0
votes

I am trying to implement the reflection mapping in OpenGL ES 2.0 for 'sphere'. I have done the skybox. For sphere rendering, the reflection shaders i have used are:

Environment mapping (Sphere) vertex shader::

precision highp float;
uniform mat4    u_mvMatrix; // ModelView Matrix
uniform mat4    u_mvpMatrix; // ModelViewProjection Matrix

attribute vec4 a_position;
attribute vec3 a_envmapNormal;

varying vec3 v_eyecoordEyeReflection;

vec3 v_eyecoordPosition;
vec3 v_eyecoordNormal;

void main()
 {
    // position and normal in model coordinates
    vec4 modelCoordPosition = a_position;
    vec3 modelCoordNormal   = a_envmapNormal;

    // Calculate position in eye space
    v_eyecoordPosition = vec3(u_mvMatrix * modelCoordPosition);

    // Calculate and normalize eye space normal
    vec3 eyecoordNormal    = vec3(u_mvMatrix * vec4(modelCoordNormal, 0.0));
    v_eyecoordNormal        = normalize(eyecoordNormal);
    // Calculate reflection vector
    v_eyecoordEyeReflection = reflect(v_eyecoordPosition, v_eyecoordNormal);

    gl_Position = u_mvpMatrix * a_position;
}

Environment mapping (Sphere) Fragment shader

precision highp float;
uniform lowp samplerCube baseCubeMapTexture;
varying vec3 v_eyecoordEyeReflection;

void main()
{
    gl_FragColor  = textureCube(baseCubeMapTexture, v_eyecoordEyeReflection);
}

But i am not getting correct output. When the sphere is rotated, the texture is not changing.

what is the error in the shader?



Thanks Andon... I used your shader code. But i am getting white sphere.

Sphere Normals are calculated using:

    #define ANGLE_STEP      ((2.0f * OGLES_PI) / ((float) NUM_OF_SLICES))
    for ( iCnti = 0; iCnti < NUM_OF_PARALLELS + 1; iCnti++ )    {
        for ( iCntj = 0; iCntj < NUM_OF_SLICES + 1; iCntj++ )   {
            pSphereNormals[iNormalIndex + 0] = sin(ANGLE_STEP * (FLOAT) iCnti )* sin (ANGLE_STEP *(FLOAT)iCntj);
            pSphereNormals[iNormalIndex + 1] = cos(ANGLE_STEP * (FLOAT) iCnti );
            pSphereNormals[iNormalIndex + 2] = sin(ANGLE_STEP * (FLOAT) iCnti )* cos (ANGLE_STEP *(FLOAT)iCntj);
            iNormalIndex += 3;
        }
    }

My View Matrix "matViewMatrix" is derived from (http://www.learnopengles.com/tag/linmath-h/ mat4x4_look_at()) MyCameraLookAt(matViewMatrix, 0.0f , 0.0f, -2.0f, 0.0f , 0.0f, -1.0f, 0.0f , 1.0f, 0.0f);

The Inverse matrix InvViewMat is // inverse() function is taken from http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp

    InvViewMat[0][0] = -1.000000   InvViewMat[1][0] = -0.000000   InvViewMat[2][0] = 0.000000    InvViewMat[3][0] = -0.000000
    InvViewMat[0][1] = -0.000000   InvViewMat[1][1] = 1.000000    InvViewMat[2][1] = -0.000000   InvViewMat[3][1] = -0.000000
    InvViewMat[0][2] =  0.000000   InvViewMat[1][2] = -0.000000   InvViewMat[2][2] = -1.000000   InvViewMat[3][2] = -2.000000
    InvViewMat[0][3] = -0.000000   InvViewMat[1][3] = 0.000000    InvViewMat[2][3] = 0.000000    InvViewMat[3][3] = 1.000000

Is there any problem with my matrix values or any of my calculations?

1

1 Answers

0
votes

If you have a sphere centered at the camera's origin (eye-space), then no matter how you rotate it the position and normals in eye-space are always going to be the same at any location on screen. That is the definition of a sphere - every vertex is the same distance (radius) from the center.

You actually need to do this in world-space (that position will vary as you rotate the sphere).

Now, this brings up an issue - you only have a ModelView matrix (which transforms from object-space to eye-space). You are going to need to split your Model and View matrices to do this and for convenience you should pass the inverse of the View matrix to GLSL.

Below is a modified Vertex Shader that does what you want:

precision highp float;
uniform mat4    u_vInvMatrix; // Inverse View Matrix -- NEW
uniform mat4    u_mvMatrix;   // ModelView Matrix
uniform mat4    u_mvpMatrix;  // ModelViewProjection Matrix

attribute vec4 a_position;
attribute vec3 a_envmapNormal;

//varying vec3 v_eyecoordEyeReflection; // YOU DO NOT WANT EYE-SPACE
varying vec3 v_worldReflection;         // Use world-space instead -- MODIFIED

vec3 v_eyecoordPosition;
vec3 v_eyecoordNormal;

void main()
 {
    // position and normal in model coordinates
    vec4 modelCoordPosition = a_position;
    vec3 modelCoordNormal   = a_envmapNormal;

    // Calculate position in eye space
    v_eyecoordPosition   = vec3(u_mvMatrix * modelCoordPosition);

    // Calculate and normalize eye space normal
    vec3 eyecoordNormal  = vec3(u_mvMatrix * vec4(modelCoordNormal, 0.0));
    v_eyecoordNormal     = normalize(eyecoordNormal);

    // Calculate reflection vector (eye-space)
    vec3 eyeReflection   = reflect(v_eyecoordPosition, v_eyecoordNormal);

    // Transform the reflection into world-space -- NEW
    v_worldReflection    = vec3 (u_vInvMatrix * vec4 (eyeReflection, 0.0f));

    gl_Position = u_mvpMatrix * a_position;
}