2016-09-22 2 views
1

Ich habe ein Programm, in dem ich Würfel erstellen und sie ändern. Eine Möglichkeit ist das Hinzufügen von Beleuchtung durch meine Shader in meiner LightCube-Klasse. Ich folge this tutorial und alles funktioniert gut. Meine Frage ist warum ist die drawLight() Methode notwendig? Alle Lichter werden sichtbar mit den Shadern implementiert, ohne drawLight aufzurufen. Ich kann sehen, dass drawLight ein scheinbar leuchtendes Pixel erzeugt, aber da es sich um kleine Würfel handelt, fällt das einzelne Pixel wirklich auf. Ist es einfach eine Art, die Schattierung in einem größeren Objekt hervorzuheben oder hat es einen größeren Zweck, den ich vernachlässige?OpenGL diffuse Beleuchtung auf Android

Hier mein MyGLRenderer ist:

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

} 


} 

Hier mein LightCube ist: public class 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; 
} 
} 

Antwort

1

Ich würde den Punkt drawLight im Tutorial vorstellen, so dass man leicht sehen können wo das Licht ist.

Damit können Sie leicht bestätigen, dass Ihre anderen Beleuchtungs-Shader den richtigen Teil Ihrer Objekte korrekt beleuchten. Wenn Sie es nicht mögen, entfernen Sie es.

+0

Ich denke, du bist richtig - nur sicher, wie ich noch lerne. Vielen Dank! – lexalenka