Need help about GLTF / shaders / normals

Hi All,

I’m trying to specify a simple shader set for displaying buildings - loaded from gltf file - to get something like in Cesium buildings demos (gray buildings).

I have tried to used same shaders as in Cesium demo (extracted from a gltb file), but result is very different… and I see two possibilities : either I failed in adapting the shaders (normals in these gltb file seems encoded on two values), or my normals are wrong.

Here is the code of my shaders after adaptation :

precision highp float;

uniform vec4 u_ambient;

uniform vec4 u_diffuse;

uniform vec4 u_emission;

uniform vec4 u_specular;

uniform float u_shininess;

varying vec3 v_normal;

varying vec3 v_positionEC;

void main(void) {

vec3 normal = normalize(v_normal);

vec4 color = vec4(0., 0., 0., 0.);

float diffuseIntensity = 0.0;

float specularIntensity = 0.0;

vec4 diffuse = vec4(0., 0., 0., 1.);

vec4 emission;

vec4 ambient;

vec4 specular;

diffuse = u_diffuse;

ambient = diffuse * 0.5;

emission = u_emission;

specular = u_specular;

vec3 normalizedpositionToEyeEC = normalize(-v_positionEC);

diffuseIntensity = czm_getLambertDiffuse(czm_sunDirectionEC, normal);

specularIntensity = czm_getSpecular(czm_sunDirectionEC, normalizedpositionToEyeEC, normal, u_shininess) +

 0.25 * czm_getSpecular(czm_moonDirectionEC, normalizedpositionToEyeEC, normal, u_shininess);

color.xyz += ambient.xyz;

color.xyz += diffuse.xyz * diffuseIntensity;

color.xyz += specular.xyz * specularIntensity;

color.xyz += emission.xyz;

color = vec4(color.rgb * diffuse.a, diffuse.a);

gl_FragColor = color;

}

precision highp float;

uniform vec4 u_ambient;

uniform vec4 u_diffuse;

uniform vec4 u_emission;

uniform vec4 u_specular;

uniform float u_shininess;

varying vec3 v_normal;

varying vec3 v_positionEC;

void main(void) {

vec3 normal = normalize(v_normal);

vec4 color = vec4(0., 0., 0., 0.);

float diffuseIntensity = 0.0;

float specularIntensity = 0.0;

vec4 diffuse = vec4(0., 0., 0., 1.);

vec4 emission;

vec4 ambient;

vec4 specular;

diffuse = u_diffuse;

ambient = diffuse * 0.5;

emission = u_emission;

specular = u_specular;

vec3 normalizedpositionToEyeEC = normalize(-v_positionEC);

diffuseIntensity = czm_getLambertDiffuse(czm_sunDirectionEC, normal);

specularIntensity = czm_getSpecular(czm_sunDirectionEC, normalizedpositionToEyeEC, normal, u_shininess) +

 0.25 * czm_getSpecular(czm_moonDirectionEC, normalizedpositionToEyeEC, normal, u_shininess);

color.xyz += ambient.xyz;

color.xyz += diffuse.xyz * diffuseIntensity;

color.xyz += specular.xyz * specularIntensity;

color.xyz += emission.xyz;

color = vec4(color.rgb * diffuse.a, diffuse.a);

gl_FragColor = color;

}

Note that the GLTF file use the CESIUM_RTC extension.

I saved my model as OBJ and normals seem good (in MeshLAB) :

But display in cesium is…not what I expected :

I would like to check if normals are good in the GLTF file & after loadig in Cesium.

I’m wondering if it is possible to use Cesium.createTangentSpaceDebugPrimitive on a gltf model loaded with something like :

var model = scene.primitives.add(Cesium.Model.fromGltf({

    url : 'http://xxxx'

}));

Any help appreciated,

Fred.

Hi Fred,

It looks like the problem is with your normals. It’s hard to tell from the picture you posted, but make sure all normals are normalized (have a unit length)

Also, for corners, you need a separate normal vector for each face. Otherwise the shader tries to round out the corners. Here is an example of a box model that we use for testing. You can see that each corner is duplicated so there is a normal for each face.

Best,

Hannah

Hi Hannah,

thanks - I think the problem is definitively with the normals as they were calculated before I warp coordinates from cartographic system to ECEF - and normals are not warped.

I will try to convert them to.

Just a clarification : I have one normal for each triangle - but no normals for vertices; do you confirm that this is what is expected ?

Kr,

Fred.

Hi Fred,

Having a normal for each triangle is probably okay. I would guess the obj to gltf converter will put it in the correct format.

Best,

Hannah

Hi,

I have triple checked my normals - OBJ version of my object (in ECEF system) displays fine with MeshLab and osgviewer.

If I reverse my normals ( to check that face winding is correct ), I got black face which is the expected behaviour in osgviewer for exemple.

At this point… I’m blocked. Maybe the problem comes from the shaders - my experience with GLSL is more than low.

I have just tried to copy and adapt shaders used in some buildings demos by analysis of gltb files - see at the end of history.

Maybe a shader gourou here could easily figure out if there is a problems in them.

Any help on how to :

  • check normals of loaded GLTF files,

  • writing basic shaders to display grey buildings,

  • debug shaders

will be highly appreciated.

Thanks in advance;

Fred.