开发者

Porting Orange Book shaders to OpenGL ES 2.0

I am trying to port the Orange Book brick shader to OpenGL ES 2.0 and I am running into problems with the lighting. With out the lighting I see the bricks, but with it the shape is just black.

Porting Orange Book shaders to OpenGL ES 2.0

Porting Orange Book shaders to OpenGL ES 2.0

Vert

const float ZERO = 0.0;
const float ONE = 1.0;

// Should be built in, but this is GLES
uniform mat4 ModelViewMatrix;
uniform mat4 ModelViewProjectionMatrix;
uniform mat3 NormalMatrix;
attribute vec4 Vertex;
attribute vec3 Normal;

// Other variables
uniform vec3 LightPosition;

const float SpecularContribution = 0.3;
const float DiffuseContribution = 1.0 - SpecularContribution;

varying float LightIntensity;
varying vec2 MCPosition;

void main()
{
    vec3 ecPosition = vec3(ModelViewMatrix * Vertex);
    vec3 tnorm      = normalize(NormalMatrix * Normal);
    vec3 lightVec   = normalize(LightPosition - ecPosition);
    vec3 reflectVec = reflect(-lightVec, tnorm);
    vec3 viewVec    = normalize(-ecPosition);
    float diffuse   = max(dot(lightVec, tnorm), ZERO);
    float spec      = ZERO;

        if(diffuse > ZERO)
    {
        spec = max(dot(reflectVec, viewVec), ZERO);
        spec = pow(spec, 16.0);
    }

    LightIntensity  = DiffuseContribution * diffuse +
              SpecularContribution * spec;

    MCPosition  = Vertex.xy;
    gl_Position = ModelViewProjectionMatrix * Vertex;
}

Frag

precision mediump float;

const float ONE = 1.0;
const float HALF = 0.5;

uniform vec3 BrickColor, MortarColor;
uniform vec2 BrickSize, BrickPercent;

varying float LightIntensity;
varying vec2 MCPosition;

void main()
{
    vec3 color;
    vec2 position, useBrick;

    position = MCPosition / BrickSize;

    if(fract(position.y * HALF) > HALF)
        position.x += HALF;

    position = fract(position);

    useBrick = step(position, BrickPercent);

    color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);
    color *= LightIntensity;
    gl_FragColor = vec4(color, ONE);
}

Here's my Java

@Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
{
    GLES20.glClearColor(0.3922f, 0.5843f, 0.9294f, 1.0f);
    GLES20.glEnable(GLES20.GL_DEPTH_TEST);

    try
    {
        mTorus.genTorus(60, 1.25f, 0.5f);
        mAngle = 45.0f;

        mProgramObject = ESShader.loadProgram(mContext, "cube.vert", "cube.frag");

        mModelViewLoc = GLES20.glGetUniformLocation(mProgramObject, "ModelViewMatrix");
        mMVPLoc = GLES20.glGetUniformLocation(mProgramObject, "ModelViewProjectionMatrix");
        mNormalMatrixLoc = GLES20.glGetUniformLocation(mProgramObject, "NormalMatrix");
        mLightPositionLoc = GLES20.glGetUniformLocation(mProgramObject, "LightPosition");

        mBrickColorLoc = GLES20.glGetUniformLocation(mProgramObject, "BrickColor");
        mMortarColorLoc = GLES20.glGetUniformLocation(mProgramObject, "MortarColor");
        mBrickSizeLoc = GLES20.glGetUniformLocation(mProgramObject, "BrickSize");
        mBrickPercentLoc = GLES20.glGetUniformLocation(mProgramObject, "BrickPercent");

        mPositionLoc = GLES20.glGetAttribLocation(mProgramObject, "Vertex");
            mNormalLoc = GLES20.glGetAttribLoca开发者_运维百科tion(mProgramObject, "Normal");
    }
    catch(IOException ioe)
    {
        System.err.println("Failed to load shaders");
    }
}

@Override
public void onSurfaceChanged(GL10 glUnused, int width, int height)
{
    mWidth = width;
    mHeight = height;

    mProjection.loadIdentity();
    mProjection.perspective(60.0f, (float)mWidth / (float)mHeight, 1.0f, 20.0f);

    GLES20.glViewport(0, 0, mWidth, mHeight);
}

private void update()
{
    if(mLastTime == 0) mLastTime = SystemClock.uptimeMillis();
    long curTime = SystemClock.uptimeMillis();
    long elapsedTime = curTime - mLastTime;
    float deltaTime = elapsedTime / 1000.0f;
    mLastTime = curTime;

    // Compute a rotation angle based on time to rotate the cube
    mAngle += (deltaTime * 40.0f);
    if(mAngle >= 360.0f) mAngle -= 360.0f;
}

@Override
public void onDrawFrame(GL10 glUnused)
{
    update();
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    // Use the program object
    GLES20.glUseProgram(mProgramObject);

    mModelView.loadIdentity();
    mModelView.translate(0.0f, 0.0f, -5.0f);
    mModelView.rotate(mAngle, 1.0f, 0.0f, 0.75f);

    mNormalMatrix.load(mModelView);
    mNormalMatrix.invert();
    mNormalMatrix.transpose();

    mMVPMatrix.multiply(mModelView, mProjection);

    GLES20.glUniformMatrix4fv(mModelViewLoc, 1, false, mModelView.getAsFloatBuffer());
    GLES20.glUniformMatrix4fv(mMVPLoc, 1, false, mMVPMatrix.getAsFloatBuffer());
    GLES20.glUniformMatrix4fv(mNormalMatrixLoc, 1, false, mNormalMatrix.getAsFloatBuffer());
    GLES20.glUniform3f(mLightPositionLoc, 5.0f, 5.0f, 5.0f);

    GLES20.glUniform3f(mBrickColorLoc, 0.549f, 0.239f, 0.271f);
    GLES20.glUniform3f(mMortarColorLoc, 0.8f, 0.8f, 0.8f);
    GLES20.glUniform2f(mBrickSizeLoc, 0.3f, 0.15f);
    GLES20.glUniform2f(mBrickPercentLoc, 0.9f, 0.85f);

    GLES20.glVertexAttribPointer(mPositionLoc, 3, GLES20.GL_FLOAT, false, 0, mTorus.getVertices());
    GLES20.glEnableVertexAttribArray(mPositionLoc);

    GLES20.glVertexAttribPointer(mNormalLoc, 3, GLES20.GL_FLOAT, false, 0, mTorus.getNormals());
    GLES20.glEnableVertexAttribArray(mNormalLoc);

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, mTorus.getNumIndices(), GLES20.GL_UNSIGNED_SHORT, mTorus.getIndices());
}


The problem was that I was passing in the wrong values for my NormalMatrix. The NormalMatrix is the Upper-Left 3x3 of the Transpose of the Inverse of the ModelViewMatrix. For that I had this code:

mNormalMatrix.load(mModelView);
mNormalMatrix.invert();
mNormalMatrix.transpose();

Which resulted in a 4x4 Matrix, but in my shader I had it as a mat3, this shifted the values around and made it fail.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜