0
votes

I'm currently implementing a spot light in Open GL ES 2.0 on iOS. All my lighting calculations are done in world space (i.e. I pass world space coords to the shaders).

I have placed a floor mesh (very well tesselated) horizontally in the scene, and a light source at (0,250,0) i.e straight up. In my shader I hard code the light to point straight down (0,-1,0). In this situation, the spot light cone doesn't work. However, as I raise the floor position up (in the y axis, going nearer the light) at a certain point the spot-light 'appears'. Furthermore, just before it appears, a strange 'mirror image' outline of the cone appears on the floor, and at a certain threshold, there are some obvious rendering bugs (4th image below)

See screenshots in the following album, arranged with floor getting closer to the light each image. The final image shows it working correctly

http://imgur.com/a/cKOll

Furthermore - these screens were taken on an ipad mini, but on the xCode iOS Simulator it works perfectly!!

Also at 'close' range all the basic phong calculations work as expected.

Any ideas as to what might be causing the problems?

Here's my fragment shader:

// Fragment shader
precision highp float;

uniform mediump vec4 u_mat_diffuse;
uniform mediump vec4 u_mat_ambient;
uniform mediump float u_mat_specular;
uniform mediump float u_mat_shininess;
uniform mediump vec3 u_light_color;
uniform mediump float u_light_intensity;
uniform mediump vec3 u_light_spot_dir;
uniform mediump float u_light_spot_cutoff;
uniform mediump vec3 u_light_pos;
uniform mediump vec3 u_camera_eye;


varying mediump vec3 v_light_dir; 
varying mediump vec3 v_normal;
varying mediump vec3 v_pos;


void main(void)
{
    //normalize all first - v-pos is the vertex world position
    //all uniforms are in world position
    mediump vec3 E = normalize(u_camera_eye - v_pos);
    mediump vec3 L = normalize(u_light_pos - v_pos);

    mediump vec3 N = normalize(v_normal);

    mediump vec3 light_direction = vec3(0.0, -1.0, 0.0); //light direction
    mediump vec3 D = normalize(light_direction); 


    highp vec4 finalColor = vec4(0.0, 0.0, 0.0, 1.0);  

    //simple lambert
    highp float ndotl = max(dot(N, L), 0.0);
    highp vec3 DiffuseColor = vec3(1.0, 1.0, 1.0) * ndotl;


    if (dot(-L, D) > 0.9)
    {
        finalColor += vec4(DiffuseColor, 1.0) * vec4(1.0, 0.0, 0.0, 1.0);        
    }

    gl_FragColor = finalColor ;

}

Edit: if I set finalColor to be a fixed value (i.e not use the diffuse term) then it works! So there is something wrong with the way the diffuse term is calculated

SOLVED:

The answer was to make the relevant vectors and matrices all high precision (highp) in the shader.

1

1 Answers

0
votes

The answer was to make the relevant vectors and matrices all high precision (highp) in the shader.