2011-03-23 4 views
0

오렌지 북 벽돌 쉐이더를 OpenGL ES 2.0으로 이식하려고하는데 조명에 문제가 있습니다. 조명을 통해 벽돌을 보았지만 모양이 검은 색이었습니다. enter image description hereenter image description hereOpenGL ES 2.0으로 오렌지 북 쉐이더 포팅

는 수직

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; 
} 

파편

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); 
} 

여기 내 자바

@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.glGetAttribLocation(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()); 
} 
입니다

답변

3

문제는 내 NormalMatrix에 대해 잘못된 값을 전달하고 있다는 것이 었습니다. NormalMatrix는 ModelViewMatrix의 Inverse의 Transpose의 왼쪽 위 3x3입니다. 이를 위해이 코드했다 :

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

4 × 4 매트릭스에 나 섰으나 내 쉐이더에서 I는 mat3로 한이 약의 값을 이동하고 실패했다.