2016-09-22 2 views
1

나는 큐브를 만들고 변경하는 프로그램이 있습니다. 내가하는 한 가지 방법은 LightCube 클래스의 쉐이더를 통해 조명을 추가하는 것입니다. 나는 this tutorial을 따르고 있으며 모든 것이 잘 작동합니다. 내 질문에 왜 drawLight() 메서드가 필요한 것입니다? drawLight를 호출하지 않고도 쉐이더만으로 모든 조명을 시각적으로 구현할 수 있습니다. drawLight는 뚜렷하게 점등 된 픽셀을 생성하지만, 작은 큐브를 다루고 있기 때문에 단일 픽셀이 실제로 두드러집니다. 그것은 더 큰 물체에서 음영을 강조하는 단순한 방법입니까, 아니면 제가 무시하고있는 더 큰 목적이 있습니까?Android에서 OpenGL 확산 조명

다음
public class MyGLRenderer implements GLSurfaceView.Renderer { 

private static final String TAG = "MyGLRenderer"; 
private Context context; 
static MainActivity x = null; 
private Cube mCube; 
private TexturedCube tCube; 
private LightCube lCube; 

private final float[] mMVPMatrix = new float[16]; 
private final float[] mProjectionMatrix = new float[16]; 
private final float[] mViewMatrix = new float[16]; 
private float[] mRotationMatrix = new float[16]; 
private float mCubeRotation; 
private static long mLastUpdateMillis; 
private static final float CUBE_ROTATION_INCREMENT = 1.6f; 

public static int limitx = 0; 
public static int limity = 0; 
long startTime = System.nanoTime(); 
int frames = 0; 
static int output=0; 

public static int cubeType = 1; 
public static int blendSwitch = 1; 
private float[] mLightModelMatrix = new float[16]; 
private final float[] mLightPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f}; 

/** Used to hold the current position of the light in world space (after transformation via model matrix). */ 
public static final float[] mLightPosInWorldSpace = new float[4]; 

/** Used to hold the transformed position of the light in eye space (after transformation via modelview matrix) */ 
public static final float[] mLightPosInEyeSpace = new float[4]; 

/* The refresh rate, in frames per second. */ 
public static final int REFRESH_RATE_FPS = 60; 
/* The duration, in milliseconds, of one frame. */ 
static final float FRAME_TIME_MILLIS = TimeUnit.SECONDS.toMillis(1)/REFRESH_RATE_FPS; 

public MyGLRenderer(Context context) { 
    this.context=context; 
} 

public static int loadShader(int type, String shaderCode){ 
    //create a vertex shader type (GLES30.GL_VERTEX_SHADER) 
    //or a fragment shader type (GLES30.GL_FRAGMENT_SHADER) 
    int shader = GLES30.glCreateShader(type); 

    //add the source code to the shader and compile it 
    GLES30.glShaderSource(shader, shaderCode); 
    GLES30.glCompileShader(shader); 


    return shader; 
} 




public void onSurfaceCreated(GL10 unused, EGLConfig config) { 
    // Set the background frame color 
    GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
    GLES30.glClearDepthf(1.0f); 
    GLES30.glEnable(GLES30.GL_DEPTH_TEST); 
    GLES30.glDepthFunc(GLES30.GL_LEQUAL); 


    switch(blendSwitch) { 

     case 1 : 
      GLES30.glDisable(GLES20.GL_BLEND); 
      break; 

     case 2 : 
      GLES30.glEnable(GLES20.GL_BLEND); 
      GLES30.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE); 
      //Enable Blending 
      break; 
    } 

    mCube = new Cube(); 
    tCube = new TexturedCube(); 
    lCube = new LightCube(); 

    //cubeList.add(new Cube()); If you would like to generate new cubes via array 
    // cubeList.add(new Cube()); 

    TexturedCube.mTextureDataHandle = TexturedCube.loadTexture(context, R.drawable.app_icon_your_company); 

} 


public void logFPS() { 
    frames++; 
    if(System.nanoTime() - startTime >= 1000000000) { 
     // Log.d("FPSCounter", "fps: " + frames); for testing - send info to log 
     output=frames; 
     frames = 0; 
     startTime = System.nanoTime(); 
    } 
} 

public void onDrawFrame(GL10 unused) { 

    // mCube = cubeList.get(0); 

    logFPS(); 

    if (x != null) { 
     x.GLDisplay(); 
    } 


    float[] scratch = new float[16]; 


    // Redraw background color 
    GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT); 


    for(float xshift=-1; xshift < limitx; xshift++) { 
     for (float yshift = -1; yshift < limity; yshift++) { 


      //Set the camera position 
      Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -400, xshift, yshift, 0f, 0f, 1.0f, 0.0f); 
      //setLookAtM(float[] rm, int rmOffset, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) 
      //Defines a viewing transformation in terms of an eye point, a center of view, and an up vector. 


      //setting up light conditions. 

      Matrix.setIdentityM(mLightModelMatrix, 0); 
      Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, -5.0f); 
      // Matrix.rotateM(mLightModelMatrix, 0, mCubeRotation , 0.0f, 1.0f, 0.0f); -->incompatible with the update Cube Rotation? requires further examination 
      Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, 2.0f); 
      Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0); 
      Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0); 


      Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); 
      //multiplyMM(float[] result, int resultOffset, float[] lhs, int lhsOffset, float[] rhs, int rhsOffset) 
      //Multiplies two 4x4 matrices together and stores the result in a third 4x4 matrix. 


      //Create a rotation transformation 
      long time = SystemClock.uptimeMillis() % 4000L; 
      float angle = 0.090f * ((int) time); 


      Matrix.setRotateM(mRotationMatrix, 0, mCubeRotation, 1.0f, 1.0f, -1.0f); 

      //Calculate the projection and view transformation 
      //Combine the rotation matrix with the projection and camera view 
      //Note that the mMVPMatrix factor *must* be first in order 
      //for the matrix multiplication product to be correct 
      Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); 
      //multiplyMM(float[] result, int resultOffset, float[] lhs, int lhsOffset, float[] rhs, int rhsOffset) 
      //Multiplies two 4x4 matrices together and stores the result in a third 4x4 matrix. 


      switch(cubeType) { 
       case 1:lCube.draw(scratch); 
        // drawLight(); 
        break; 

       case 2:tCube.draw(scratch); 
        break; 
      } 

      updateCubeRotation(); 



     } 
    } 

} 

public void drawLight() 
{ 
    LightCube.mPointProgramHandle = GLES20.glCreateProgram(); 
    GLES20.glAttachShader(LightCube.mPointProgramHandle, loadShader(GLES20.GL_VERTEX_SHADER, LightCube.pointVertexShader)); 
    GLES20.glAttachShader(LightCube.mPointProgramHandle, loadShader(GLES20.GL_FRAGMENT_SHADER, LightCube.pointFragmentShader)); 
    GLES20.glLinkProgram(LightCube.mPointProgramHandle); 

    GLES20.glUseProgram(LightCube.mPointProgramHandle); 
    final int pointMVPMatrixHandle = GLES20.glGetUniformLocation(LightCube.mPointProgramHandle, "uMVPMatrix"); 
    final int pointPositionHandle = GLES20.glGetAttribLocation(LightCube.mPointProgramHandle, "vPosition"); 

    // Pass in the position. 
    GLES20.glVertexAttrib3f(pointPositionHandle, mLightPosInModelSpace[0], mLightPosInModelSpace[1], mLightPosInModelSpace[2]); 

    // Since we are not using a buffer object, disable vertex arrays for this attribute. 
    GLES20.glDisableVertexAttribArray(pointPositionHandle); 

    // Pass in the transformation matrix. 
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mLightModelMatrix, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 
    GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mMVPMatrix, 0); 

    // Draw the point. 
    GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1); 
} 


public void onSurfaceChanged(GL10 unused, int width, int height) { 

    GLES30.glViewport(0, 0, width, height); 

    Matrix.frustumM(mProjectionMatrix, 0, -1, 15, -20, 1, 100, 500); 
    //frustumM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far) 
    //the issue is one of depth - if you make it smaller than the cubes will float inwardly due to the nature of the frustrum 

} 

public static void checkGlError(String glOperation) { 
    int error; 
    while ((error = GLES30.glGetError()) != GLES30.GL_NO_ERROR) { 
     Log.e(TAG, glOperation + ": glError " + error); 
     throw new RuntimeException(glOperation + ": glError " + error); 
    } 
} 


private void updateCubeRotation() { 
    if (mLastUpdateMillis != 0) { 
     float factor = (SystemClock.elapsedRealtime() - mLastUpdateMillis)/FRAME_TIME_MILLIS; 
     mCubeRotation += CUBE_ROTATION_INCREMENT * factor; 
    } 
    mLastUpdateMillis = SystemClock.elapsedRealtime(); 

} 


} 

내 LightCube입니다 : 여기

내 MyGLRenderer 당신이 쉽게 볼 수 있도록 공용 클래스 LightCube {

/** Cube vertices */ 
    private static final float VERTICES[] = { 
     -0.3f, -0.3f, -0.3f, //top front right 
     0.3f, -0.3f, -0.3f, //bottom front right 
     0.3f, 0.3f, -0.3f, //bottom front left 
     -0.3f, 0.3f, -0.3f, //top front left 
     -0.3f, -0.3f, 0.3f, //top back right 
     0.3f, -0.3f, 0.3f, //bottom back right 
     0.3f, 0.3f, 0.3f, //bottom back left 
     -0.3f, 0.3f, 0.3f // top back left 
}; 

/* Vertex colors. */ 
private static final float COLORS[] = { 
     0.0f, 1.0f, 1.0f, 1.0f, 
     1.0f, 0.0f, 0.0f, 1.0f, 
     1.0f, 1.0f, 0.0f, 1.0f, 
     0.0f, 1.0f, 0.0f, 1.0f, 
     0.0f, 0.0f, 1.0f, 1.0f, 
     1.0f, 0.0f, 1.0f, 1.0f, 
     1.0f, 1.0f, 1.0f, 1.0f, 
     0.0f, 1.0f, 1.0f, 1.0f, 
}; 


//Order to draw vertices as triangles. 
private static final byte INDICES[] = { 
     0, 1, 3, 3, 1, 2, // Front face. 
     0, 1, 4, 4, 5, 1, // Bottom face. 
     1, 2, 5, 5, 6, 2, // Right face. 
     2, 3, 6, 6, 7, 3, // Top face. 
     3, 7, 4, 4, 3, 0, // Left face. 
     4, 5, 7, 7, 6, 5, // Rear face. 
}; 

private static final float NORMALS[] = { 

    //set all normals to all light for testing 
     1.0f, 1.0f, 1.0f, //top front right 
     1.0f, 0.0f, 1.0f, //bottom front right 
     0.0f, 0.0f, 1.0f, //bottom front left 
     0.0f, 1.0f, 1.0f, //top front left 
     1.0f, 1.0f, 0.0f, //top back right 
     1.0f, 0.0f, 0.0f, //bottom back right 
     0.0f, 0.0f, 0.0f, //bottom back left 
     0.0f, 1.0f, 0.0f //top back left 
}; 




static final int COORDS_PER_VERTEX = 3; 

private static final int VALUES_PER_COLOR = 4; 

/** Vertex size in bytes. */ 
final int VERTEX_STRIDE = COORDS_PER_VERTEX * 4; 

/** Color size in bytes. */ 
private final int COLOR_STRIDE = VALUES_PER_COLOR * 4; 

/** Shader code for the vertex. */ 
private static final String VERTEX_SHADER_CODE = 
       "uniform mat4 uMVPMatrix;" + 
       "uniform mat4 uMVMatrix;" + 
       "uniform vec3 u_LightPos;" + 
       "attribute vec4 vPosition;" + 
       "attribute vec4 a_Color;" + 
       "attribute vec3 a_Normal;" + 
       "varying vec4 v_Color;" + 
       "void main() {" + 
       "vec3 modelViewVertex = vec3(uMVMatrix * vPosition);"+ 
       "vec3 modelViewNormal = vec3(uMVMatrix * vec4(a_Normal, 0.0));" + 
       "float distance = length(u_LightPos - modelViewVertex);" + 
       "vec3 lightVector = normalize(u_LightPos - modelViewVertex);" + 
       "float diffuse = max(dot(modelViewNormal, lightVector), 0.1);" + 
       "diffuse = diffuse * (1.0/(1.0 + (0.000000000002 * distance * distance)));" + 
       "v_Color = a_Color * diffuse;" + 
       "gl_Position = uMVPMatrix * vPosition;" + 
       "}"; 

/** Shader code for the fragment. */ 
private static final String FRAGMENT_SHADER_CODE = 
       "precision mediump float;" + 
       "varying vec4 v_Color;" + 
       "void main() {" + 
       " gl_FragColor = v_Color;" + 
       "}"; 


// Define a shader program for the position of light on screen. 
final static String pointVertexShader = 
        "uniform mat4 uMVPMatrix;  \n" 
       + "attribute vec4 vPosition;  \n" 
       + "void main()     \n" 
       + "{        \n" 
       + " gl_Position = uMVPMatrix * vPosition; \n" 
       + " gl_PointSize = 5.0;   \n" 
       + "}        \n"; 

final static String pointFragmentShader = 
        "precision mediump float;  \n" 
       + "void main()     \n" 
       + "{        \n" 
       + " gl_FragColor = vec4(1.0,1.0, 1.0, 1.0);  \n" 
       + "}        \n"; 


private final FloatBuffer mVertexBuffer; 
private final FloatBuffer mColorBuffer; 
private final FloatBuffer mNormalBuffer; 
private final ByteBuffer mIndexBuffer; 
private final int mProgram; 
private final int mPositionHandle; 
private final int mColorHandle; 
private final int mMVPMatrixHandle; 
private final int mNormalHandle; 
public static int mLightPosHandle; 
public final int mMVMatrixHandle; 
public static int mPointProgramHandle; 




public LightCube() { 
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(VERTICES.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    mVertexBuffer = byteBuffer.asFloatBuffer(); 
    mVertexBuffer.put(VERTICES); 
    mVertexBuffer.position(0); 

    byteBuffer = ByteBuffer.allocateDirect(COLORS.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    mColorBuffer = byteBuffer.asFloatBuffer(); 
    mColorBuffer.put(COLORS); 
    mColorBuffer.position(0); 



    byteBuffer = ByteBuffer.allocateDirect(NORMALS.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    mNormalBuffer = byteBuffer.asFloatBuffer(); 
    mNormalBuffer.put(NORMALS); 
    mNormalBuffer.position(0); 


    mIndexBuffer = ByteBuffer.allocateDirect(INDICES.length); 
    mIndexBuffer.put(INDICES); 
    mIndexBuffer.position(0); 

    mProgram = GLES20.glCreateProgram(); 
    GLES20.glAttachShader(mProgram, loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE)); 
    GLES20.glAttachShader(mProgram, loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE)); 
    GLES20.glLinkProgram(mProgram); 


    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
    mMVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVMatrix"); 
    mLightPosHandle = GLES20.glGetUniformLocation(mProgram, "u_LightPos"); 
    mNormalHandle = GLES20.glGetAttribLocation(mProgram, "a_Normal"); 
    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); 
    mColorHandle = GLES20.glGetAttribLocation(mProgram, "a_Color"); 

} 

/** 
* Encapsulates the OpenGL ES instructions for drawing this shape. 
* 
* @param mvpMatrix The Model View Project matrix in which to draw this shape 
*/ 
public void draw(float[] mvpMatrix) { 


    // Add program to OpenGL environment. 
    GLES20.glUseProgram(mProgram); 

    // Prepare the cube coordinate data. 
    GLES20.glEnableVertexAttribArray(mPositionHandle); 
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, VERTEX_STRIDE, mVertexBuffer); 

    // Prepare the cube color data. 
    GLES20.glEnableVertexAttribArray(mColorHandle); 
    GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, COLOR_STRIDE, mColorBuffer); 

    //Will have the same size as Vertex as we are implementing per vertex lighting 
    GLES20.glEnableVertexAttribArray(mNormalHandle); 
    GLES20.glVertexAttribPointer(mNormalHandle, 3, GLES20.GL_FLOAT, false, VERTEX_STRIDE, mNormalBuffer); 

    // Apply the projection and view transformation. 
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mvpMatrix, 0); 

    // Apply the projection and view transformation. 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 

    GLES20.glUniform3f(LightCube.mLightPosHandle, MyGLRenderer.mLightPosInEyeSpace[0], MyGLRenderer.mLightPosInEyeSpace[1], MyGLRenderer.mLightPosInEyeSpace[2]); 

    // Draw the cube. 
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, INDICES.length, GLES20.GL_UNSIGNED_BYTE, mIndexBuffer); 

    // Disable vertex arrays. 
    GLES20.glDisableVertexAttribArray(mPositionHandle); 
    GLES20.glDisableVertexAttribArray(mColorHandle); 
    GLES20.glDisableVertexAttribArray(mNormalHandle); 

} 



/** Loads the provided shader in the program. */ 
private static int loadShader(int type, String shaderCode){ 
    int shader = GLES20.glCreateShader(type); 

    GLES20.glShaderSource(shader, shaderCode); 
    GLES20.glCompileShader(shader); 

    return shader; 
} 
} 

답변

1

내가 튜토리얼에서 drawLight의 지점을 상상하는 것입니다 어디 빛이입니다.

이렇게하면 다른 조명 쉐이더가 개체의 올바른 부분을 올바르게 조명하고 있는지 쉽게 확인할 수 있습니다. 마음에 들지 않으면 제거하십시오.

+0

나는 당신이 정확하다고 생각한다. - 나는 여전히 배우고있는 것처럼 확신한다. 감사! – lexalenka