私はキューブを作成して変更するプログラムを持っています。私がそうする一つの方法は、私の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;
}
}
私はあなたが正しいと思う - ちょうど私がまだ学んでいるように確かめる。ありがとう! – lexalenka