2016-09-22 10 views
1

私はキューブを作成して変更するプログラムを持っています。私がそうする一つの方法は、私のLightCubeクラスのシェーダを通して照明を追加することです。私はthis tutorialに従っており、すべて正常に動作しています。私の質問はなぜdrawLight()メソッドが必要なのでしょうか? drawLightを呼び出さずに、すべてのライトがシェーダだけで視覚的に実装されます。私はdrawLightが一見明るいピクセルを作成するのを見ることができますが、私は小さなキューブを扱っているので、単一のピクセルが本当に際立っています。それは単に大きなオブジェクトの陰影を強調する方法ですか、それとも私が無視している大きな目的がありますか?ここでAndroidのOpenGL拡散照明

は私MyGLRendererです:ここでは

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です: パブリッククラス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

関連する問題