iDevGames Forums
Normal Mapping Precision on iOS - Printable Version

+- iDevGames Forums (
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Graphics & Audio Programming (/forum-9.html)
+--- Thread: Normal Mapping Precision on iOS (/thread-8833.html)

Normal Mapping Precision on iOS - OptimisticMonkey - Apr 13, 2011 03:31 PM

I was using ZBrush alot lately, and want to get normal mapping working on ios.

I have implemented a normal mapping glsl shader that works, but I see subtle "banding" on the lit parts of the model.

The shader works great when I run it on the mac with no banding - it's only on ios that I see the effect.

I am thinking it might be a problem with the precision of the texture sampler on ios.

Is this a known issue - should I look into encoding the normals in a more effecient fashion...

I am using the stock tangent space normal map coming out of zbrush, which I think encodes nx,ny,nz in r,g,b and ignores a.

Thanks for any advice...

RE: Normal Mapping Precision on iOS - OneSadCookie - Apr 13, 2011 04:17 PM

GLSL ES has the concept of "precision" within the shader. This allows you to potentially sacrifice precision in your results to run faster.

Long story short, the default precision for the fragment shader is "mediump"; did you change it?

RE: Normal Mapping Precision on iOS - OptimisticMonkey - Apr 13, 2011 07:54 PM

Yes - I have tried using highp for everything...
still same banding is present.

It is like the actual sampler is returning lower precision normals.
on mac:
[Image: normalmappingmac.png]
on ios:
[Image: normalmappingios.png]

Thanks again for any advice....

RE: Normal Mapping Precision on iOS - OneSadCookie - Apr 13, 2011 08:20 PM

Samplers also have associated precision, did you set the precision on the sampler? Additionally, the default precision for samplers is "lowp".

Maybe you should post your shader code.

RE: Normal Mapping Precision on iOS - arekkusu - Apr 13, 2011 10:23 PM

What texture format are you using?

RE: Normal Mapping Precision on iOS - OptimisticMonkey - Apr 13, 2011 11:21 PM

I tried it with the samplers explicitly set to highp - same issue...

I tried limiting the fragcolor to just a solid color modulated by nDotL...
and I still see the seems to be an artifact of how I am calculating nDotL.

Here are the shaders (sorry I haven't taken time to clean them up)

Vertex Shader
attribute vec4 position;
attribute vec3 normal;
attribute vec3 binormal;
attribute vec3 tangent;
attribute vec2 texcoord0;
attribute vec4 color;

varying vec4 colorVarying;
varying vec2 texOut0;
varying vec3 v_viewDirection;
varying vec3 v_lightDirection;
varying vec3 v_normal;

uniform float translate;
uniform mat4 u_mvp_matrix;
uniform mat4 Projection;
uniform mat4 Modelview;
uniform mat4 ModelviewInverse;
uniform mat3 NormalMatrix;
uniform vec3 LightPosition;
uniform vec3 EyePosition;

void main()
    vec3 vRed = vec3(1,0,0);
    gl_Position = Projection * Modelview * position;
    texOut0 = texcoord0;

    vec3 worldPosition = (Modelview * position).xyz;    
    vec3 normalWorld = normalize((NormalMatrix * normal).xyz);
    vec3 eyePositionWorld = (    ModelviewInverse *    vec4(EyePosition,1.0)).xyz;
    vec3 viewDirectionWorld = eyePositionWorld -;
    vec3 lightPositionWorld = (    ModelviewInverse *    vec4(LightPosition,1.0)).xyz;
    vec3 lightDirectionWorld = lightPositionWorld -;                
    mat3 tangentMat = mat3(tangent,binormal,;
    v_viewDirection = viewDirectionWorld * tangentMat;
    v_lightDirection = lightDirectionWorld * tangentMat;


Fragment Shader
precision highp float;
varying lowp vec4 colorVarying;
varying lowp vec2 texOut0;
varying mediump vec3 v_normal;

uniform sampler2D textureMap;
uniform sampler2D normalMap;
varying mediump vec3 v_viewDirection;
varying mediump vec3 v_lightDirection;

void main()
    highp vec3 baseColor = texture2D( textureMap,;
    //lowp vec4 baseColor = vec4(1,1,1,1);
    highp vec3 nl = texture2D( normalMap,;    
    highp vec3 normal = normalize(nl.yxz * 2.0 -1.0);
    highp vec3 lightDirection = normalize(v_lightDirection);
    highp vec3 viewDirection = normalize(v_viewDirection);
    highp float nDotL = dot(normal, lightDirection);
    highp vec3 reflection = (2.0 * normal * nDotL) - lightDirection;
    highp float rDotV = max( 0.0,dot(reflection, viewDirection));
//    mediump vec4 ambient = vec4(0.1,0.1,0.1,1.0) * baseColor;
//    mediump vec4 diffuse = vec4(0.8,0.8,0.8,1.0) * nDotL * baseColor;
//    mediump vec4 specular = vec4(1,1,1,1) * pow(rDotV, 100.0);    
    //gl_FragColor= ambient + diffuse + specular;
    highp vec3 ambient = vec3(0.1,0.1,0.1) * baseColor;
    highp vec3 diffuse = vec3(1.0,1.0,1.0) * nDotL * baseColor;
    highp vec3 specular = vec3(1,1,1) * pow(rDotV, 100.0);
    gl_FragColor= vec4(ambient + diffuse + specular,1);
    //gl_FragColor= diffuse;
    //gl_FragColor = vec4(nl,1);


Thanks again for any advice....

RE: Normal Mapping Precision on iOS - OptimisticMonkey - Apr 13, 2011 11:35 PM

arekkusu - You are Open GL master!

I was using a Texture loader that was incorrectly picking RGB565!

Once I used rgba8888 all was perfect!

Thank you - I have been struggling with this all day :-)

And thank you too OSC !