# Custom vertex/fragment shader for radial geometery

1. A concise explanation of the problem you’re experiencing.

I’m trying to implement a customized shader for a simple pano ground projection 3d object. I have one 720 pano image and I need to get the ground projection.

I’v created some triangles to form a circle to construct the geometery. Then I use vertex/fragment shader to display the texture. But there are some transformation/location problems that the texture is not displaying correctly. The texture supposed to be fixed on the circle turns out changes with camera.

Somebody please guide me the way to get the correct texture coordinate in fragment shader. I believe there is something wrong with my code. I’m new to gl.

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

geometery

``````var GroundProjectGeometry = function(){
//
var total_triangles = 500;
var dtheta = 2.0 * Math.PI / total_triangles;
var curtheta = 0.0;
var radius = 9;

var positions = new Float64Array((total_triangles + 1) * 3);

// position 0
positions[0] = 0.0;
positions[1] = 0.0;
positions[2] = 0.0;

for(var i=0;i<total_triangles;i++){

positions[3*(i+1)] = radius * Math.cos(curtheta);
positions[3*(i+1) + 1] = radius * Math.sin(curtheta);
positions[3*(i+1) + 2] = 0.0;
curtheta += dtheta;
// console.log("v",positions[3*(i+1)],positions[3*(i+1) + 1],positions[3*(i+1) + 2]);
}

var attributes = new Cesium.GeometryAttributes({
position : new Cesium.GeometryAttribute({
componentDatatype : Cesium.ComponentDatatype.DOUBLE,
componentsPerAttribute : 3,
values : positions
}),
st:null
});

//顶点索引
var indices = new Uint16Array(total_triangles * 3);

var index = 1;
for(i=0;i<total_triangles;i++){
var next = ((index+1)%(total_triangles+1)) != (index+1) ? 1: index+1;
indices[3*i] = 0;
indices[3*i + 1] = next;
indices[3*i + 2] = index;
// console.log("r",0,next,index);
index++;
}

this.attributes = attributes;
this.indices = indices;
this.primitiveType = Cesium.PrimitiveType.TRIANGLES;
this.boundingSphere = Cesium.BoundingSphere.fromVertices(positions);

// this.vertexFormat = Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT;
};

function customGround() {

var scene = viewer2D.scene;

//模型矩阵
var modelMatrix = new Cesium.Matrix4();
Cesium.Matrix4.multiply(
panoENU,
Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(panooffset.x,  panooffset.y,  20)),
modelMatrix);

var instance = new Cesium.GeometryInstance({
geometry : new GroundProjectGeometry(),
modelMatrix : modelMatrix,
attributes : {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE)
}
});

var im = new Image();
im.src = '../../SampleData/Cesium3DTiles/Tilesets/' + pathname + '/pano.jpg';
im.onload = function () {
ground = scene.primitives.add(new Cesium.Primitive({
geometryInstances : instance,
// appearance : new Cesium.PerInstanceColorAppearance({
//     flat : true,
//     translucent : false
// })
appearance : new Cesium.MaterialAppearance({
material: new Cesium.Material({
fabric: {
type: 'Image',
uniforms: {
// image: '../../SampleData/Cesium3DTiles/Tilesets/' + pathname + '/thumbnail_f.jpg',
// image: '../../SampleData/Cesium3DTiles/Tilesets/' + pathname + '/pano.png',
// image: '../../SampleData/Cesium3DTiles/Tilesets/' + pathname + '/pano.jpg',
image: im,
},
components: {
alpha: 0.5
// alpha: 0.99
},
// source : document.getElementById( 'materialSource' ).textContent
},
}),
flat : true,
translucent : false,
vertexShaderSource: document.getElementById( 'vertexShader' ).textContent,
fragmentShaderSource: document.getElementById( 'fragmentShader' ).textContent
}),
}));
};
}

``````

shader

``````<script id="vertexShader" type="x-shader/x-vertex">
#define PI 3.1415926535897
#define DPI 6.2831853071794

attribute vec3 position3DHigh;
attribute vec3 position3DLow;
attribute vec3 normal;
attribute vec3 tangent;
attribute vec3 bitangent;
attribute vec2 st;
attribute float batchId;

varying vec3 v_positionMC;
varying vec4 v_positionEC;
varying vec3 v_normalEC;
varying vec3 v_tangentEC;
varying vec3 v_bitangentEC;
varying vec2 v_st;
varying vec3 v_position_cpd;

attribute vec4 position3DAndHeight;
attribute vec3 u_center3D;

void main()
{
vec4 p = czm_computePosition();

v_positionEC = czm_modelViewRelativeToEye * p;      // position in eye coordinates
v_normalEC = czm_normal * normal;                         // normal in eye coordinates
v_tangentEC = czm_normal * tangent;                       // tangent in eye coordinates
v_bitangentEC = czm_normal * bitangent;                   // bitangent in eye coordinates

gl_Position = czm_modelViewProjectionRelativeToEye * p;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
#define PI 3.1415926535897
#define DPI 6.2831853071794
varying vec4 v_positionEC;
varying vec4 v_positionWC;
varying vec3 v_positionMC;
varying vec3 v_normalEC;
uniform sampler2D u_diffuse;
uniform vec2 screenSize;
uniform vec2 u_resolution;
varying vec2 v_st;

void main()
{
vec2 pst = v_positionEC.xy;
float r = sqrt(pow(pst.x,2.0) + pow(pst.y,2.0));
float phi = atan(r/1.5);
float theta = atan(pst.y, pst.x);

if(theta > DPI){
theta = theta - DPI;
}
if(theta < 0.0){
theta = theta + DPI;
}

vec2 nst = vec2(theta / PI / 2.0, phi / PI);

vec3 normalEC = normalize(v_normalEC);
vec3 positionToEyeEC = -v_positionEC.xyz;

czm_materialInput materialInput;
//materialInput.normalEC = normalEC;
//materialInput.positionToEyeEC = positionToEyeEC;
materialInput.st = nst;
//materialInput.st = v_st;
czm_material material = czm_getMaterial(materialInput);

gl_FragColor = vec4(material.diffuse + material.emission, 0.5);
//gl_FragColor=vec4(1.0,1.0,1.0,0.5);
}
</script>
``````

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

4. The Cesium version you’re using, your operating system and browser.

1.52

This is a screenshot of what the problem is.
And the expected result is a very normal texture on the circle geometry.

The issue should go away if you uncomment this line:

materialInput.st = v_st;

``

Which is how the basic textured material works:

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Source/Shaders/Appearances/TexturedMaterialAppearanceFS.glsl#L17

You might want to start with that, and then do your projection on the vertex positions.

Let me know if that helps.