2

I'm using a fragment shader that uses dFdy dFdx functions to calculate the normal of the face to view in a flat appearance. This shader has been running ok in gles 2.0 and 3.0. Inexplicably, shader don't work in Android 4.4 ( KitKat - gles3.0 ).

(Solved!!.. individual derivatives for each component, solve the problem).

In order check error, i prepared these shaders :

//Vertex Shader
#version 300 es
precision highp float;
precision highp int;

uniform mat4 PMatrix;  //Projection Matrix (varies according to camera)
uniform mat4 MVMatrix;  //Model View Matrix (no change)
in vec3 vPosition;
out vec3 vPos;
main()
{
      gl_Position=PMatrix * MVMatrix * vec4(vPosition.xyz,1.0);
      vPos = (MVMatrix * vec4(vPosition.xyz,1.0)).xyz;
}

// Fragment shader
#version 300 es
#extension GL_OES_standard_derivatives : enable
precision highp float;
precision highp int;
in vec3 vPos;
main()
{
    // don't run correctly
    // vec3 fdx = dFdx(vPos);
    // vec3 fdy = dFdy(vPos);

    // ***Solved!*** this run correctly in KitKat   
    vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z));    
    vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));


    vec3 N = normalize(cross(fdx,fdy)); 
    fragColor = vec4(N,1.0);
}

Drawing a cube, in Android<4.4 colors remain fixed for each side, independently of camera position (correct, the color identifies each normal-face). In Android 4.4 , colors vary if you move the camera.

Analyzing each derived separately :

1.- fragColor=vec4(normalize( fdx ), 1.0); colors are constantly changing (wrong)

2.- fragColor=vec4(normalize( fdy ), 1.0); the colors remain quasi-stable (quasi-ok)

A bug in the implementation of these features in Android 4.4? We are doing something wrong?

Buf3D
  • 77
  • 1
  • 7
  • Individual derivatives in each component solve the problem: `vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z));` `vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));` – Buf3D Jan 02 '14 at 19:06

3 Answers3

4

You said that this was originally a GLES2 shader, and you are using highp in a fragment shader unconditionally? That is a disaster waiting to happen because GLES2 implementations are not required to support highp in fragment shaders. Likewise, support for dFdx (...), dFdy (...) and fwidth (...) is optional.

You need to check for GL_OES_standard_derivatives and GL_FRAGMENT_PRECISION_HIGH in the GLES2 implementation of this fragment shader.

To that end, you might consider the accuracy hint for derivatives:

  • GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES  (GLES2, if the extension is supported)
  • GL_FRAGMENT_SHADER_DERIVATIVE_HINT          (GLES3)
Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • Yes, the shader exposed is only a "demo". Really the final sample use: `#version 300 es` `#extension GL_OES_standard_derivatives : enable` `precision highp float;` `precision highp int;`. I have not tried to activate the HINT. I test – Buf3D Nov 29 '13 at 08:36
  • Checking by `GLES30.glHint(GLES30.GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GLES30.GL_NICEST);` and `GL_FASTEST`,`GL_DONTCARE` don't solve the problem. Annotation: The Tested hardware, supports `GL_OES_standard_derivatives` and `GL_FRAGMENT_PRECISION_HIGH` extensions in 4.3 and 4.4, but in 4.4 not work properly: I Tested on S4-I9505 (4.3 and 4.4), Nexus 4 (4.3 and 4.4) and Nexus 5 (4.4) – Buf3D Nov 29 '13 at 09:16
  • Individual derivatives in each component solve the problem: `vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z));` `vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));` – Buf3D Jan 02 '14 at 19:07
4

Individual derivatives in each component solve the problem in KitKat:

// Replace vec3 fdx = dFdx(vPos)  by:
vec3 fdx = vec3(dFdx(vPos.x),dFdx(vPos.y),dFdx(vPos.z));

// Replace vec3 fdy = dFdy(vPos)  by:
vec3 fdy = vec3(dFdy(vPos.x),dFdy(vPos.y),dFdy(vPos.z));
Buf3D
  • 77
  • 1
  • 7
0

I've seen similar things on some AMD desktop setups.

Where dFdy( .xyz ) worked fine on NVIDIA/intel I had to do the derivate per-component to get it correctly for some AMD cards.

Jasper
  • 1