我设法使用标准的锅炉板opengl ES2编码渲染金字塔,但是在渲染过程中金字塔似乎是扭曲的,绕Y轴旋转。
我相信这与矩阵投影矩阵或摄像机视图有关,希望有人可以通过指出错误来帮助解决。谢谢
class MyGLRenderer1 implements GLSurfaceView.Renderer {
Context context; // Application's context
private pyramid1 pyramid; // (NEW)
private Circle circle; // (NEW)
private int anglePyramid = 0; // Rotational angle in degree for pyramid (NEW)
private float angleCube = 0; // Rotational angle in degree for cube (NEW)
private float speedPyramid = 1.5f; // Rotational speed for pyramid (NEW)
private float speedCube = -1.5f; // Rotational speed for cube (NEW)
private float[] mViewMatrix = new float[16];
private float[] mProjectionMatrix = new float[16];
private float[] mModelMatrix = new float[16];
private final int mBytesPerFloat = 4;
// ** This will be used to pass in the transformation matrix. */
private int mMVPMatrixHandle;
/**
* This will be used to pass in model position information.
*/
private int mPositionHandle;
/**
* This will be used to pass in model color information.
*/
private int mColorHandle;
// Constructor with global application context
private float[] mMVPMatrix = new float[16];
/**
* How many elements per vertex.
*/
private final int mStrideBytes = 7 * mBytesPerFloat;
/**
* Offset of the position data.
*/
private final int mPositionOffset = 0;
/**
* Size of the position data in elements.
*/
private final int mPositionDataSize = 3;
/**
* Offset of the color data.
*/
private final int mColorOffset = 3;
/**
* Size of the color data in elements.
*/
private final int mColorDataSize = 4;
private FloatBuffer vertexBuffer; // Buffer for vertex-array
private FloatBuffer colorBuffer; // Buffer for color-array
private ByteBuffer indexBuffer; // Buffer for index-array
private FloatBuffer textureBuffer;
private float scale_x = 0.5f;
private float[] vertices = { // 5 vertices of the pyramid in (x,y,z)
-1.0f * scale_x, -1.0f * scale_x, -1.0f * scale_x, // 0. left-bottom-back
1.0f, 0.0f, 0.0f, 1.0f, // 4. red
1.0f * scale_x, -1.0f * scale_x, -1.0f * scale_x, // 1. right-bottom-back
0.0f, 1.0f, 0.0f, 1.0f, // 1. green
1.0f * scale_x, -1.0f * scale_x, 1.0f * scale_x, // 2. right-bottom-front
0.0f, 0.0f, 1.0f, 1.0f, // 2. blue
-1.0f * scale_x, -1.0f * scale_x, 1.0f * scale_x, // 3. left-bottom-front
0.0f, 1.0f, 0.0f, 1.0f, // 3. green
0.0f, 0.5f, 0.0f, // 4. top
0.0f, 0.0f, 1.0f, 1.0f, // 0. blue
};
private byte[] indices = { // Vertex indices of the 4 Triangles
0, 3, 4,
0, 4, 1,
1, 4, 2,
2, 3, 4,
0, 1, 2,
0, 2, 3
};
public MyGLRenderer1() {
// pyramid = new pyramid1();
// circle = new Circle();
this.context = context;
}
// Call back when the surface is first created or re-created
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set color's clear-value to black
// Position the eye behind the origin.
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 1.5f;
// We are looking toward the distance
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;
// Set our up vector. This is where our head would be pointing were we holding the camera.
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
// Set the view matrix. This matrix can be said to represent the camera position.
// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
// Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix.
+ "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in.
+ "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in.
+ "varying vec4 v_Color; \n" // This will be passed into the fragment shader.
+ "void main() \n" // The entry point for our vertex shader.
+ "{ \n"
+ " v_Color = a_Color; \n" // Pass the color through to the fragment shader.
// It will be interpolated across the triangle.
+ " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position.
+ " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in
+ "} \n"; // normalized screen coordinates.
final String fragmentShader =
"precision mediump float; \n" // Set the default precision to medium. We don't // precision in the fragment shader.
+ "varying vec4 v_Color; \n" // This is the color from the vertex shader // triangle per fragment.
+ "void main() \n" // The entry point for our fragment shader.
+ "{ \n"
+ " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline.
+ "} \n";
// Load in the vertex shader.
int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if (vertexShaderHandle != 0) {
// Pass in the shader source.
GLES20.glShaderSource(vertexShaderHandle, vertexShader);
// Compile the shader.
GLES20.glCompileShader(vertexShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0) {
GLES20.glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
}
}
if (vertexShaderHandle == 0) {
throw new RuntimeException("Error creating vertex shader.");
}
// Load in the vertex shader.
int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if (fragmentShaderHandle != 0) {
// Pass in the shader source.
GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
// Compile the shader.
GLES20.glCompileShader(fragmentShaderHandle);
// Get the compilation status.
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
// If the compilation failed, delete the shader.
if (compileStatus[0] == 0) {
GLES20.glDeleteShader(fragmentShaderHandle);
fragmentShaderHandle = 0;
}
}
if (fragmentShaderHandle == 0) {
throw new RuntimeException("Error creating vertex shader.");
}
// Create a program object and store the handle to it.
int programHandle = GLES20.glCreateProgram();
if (programHandle != 0) {
// Bind the vertex shader to the program.
GLES20.glAttachShader(programHandle, vertexShaderHandle);
// Bind the fragment shader to the program.
GLES20.glAttachShader(programHandle, fragmentShaderHandle);
// Bind attributes
GLES20.glBindAttribLocation(programHandle, 0, "a_Position");
GLES20.glBindAttribLocation(programHandle, 1, "a_Color");
// Link the two shaders together into a program.
GLES20.glLinkProgram(programHandle);
// Get the link status.
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
// If the link failed, delete the program.
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
}
}
if (programHandle == 0) {
throw new RuntimeException("Error creating program.");
}
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
mColorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");
// Tell OpenGL to use this program when rendering.
GLES20.glUseProgram(programHandle);
}
// Call back after onSurfaceCreated() or whenever the window's size changes
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (height == 0) height = 1; // To prevent divide by zero
float aspect = (float) width / height;
// Set the viewport (display area) to cover the entire window
GLES20.glViewport(0, 0, width, height);
// Set the OpenGL viewport to the same size as the surface.
// GLES20.glViewport(0, 0, width, height);
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 5.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
// Call back to draw the current frame.
@Override
public void onDrawFrame(GL10 gl) {
// Clear color and depth buffers using clear-value set earlier
GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
// Do a complete rotation every 10 seconds.
long time = SystemClock.uptimeMillis() % 10000L;
float angleInDegrees = (360.0f / 10000.0f) * ((int) time);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -2f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Draw the triangle facing straight on.
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 1.0f, 0.0f);
drawTriangle();
anglePyramid += speedPyramid;
// You OpenGL|ES rendering code here
// ......
}
private void drawTriangle() {
FloatBuffer aTriangleBuffer;
vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertices); // Copy data into buffer
vertexBuffer.position(0);
// Setup index-array buffer. Indices in byte.
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
aTriangleBuffer = vertexBuffer;
// Pass in the position information
aTriangleBuffer.position(mPositionOffset);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Pass in the color information
aTriangleBuffer.position(mColorOffset);
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, aTriangleBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
// This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_BYTE,
indexBuffer);
// GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
}
}
修订图片
答案 0 :(得分:0)
你正在失去前角,因为它与近剪裁平面相交,这就是为什么看起来你有6个顶点(5个圆边,1个在彩色区域的中间)而不是实际的5个。
其余的是因为您的面对测试错误或未启用,因此金字塔的底部是可见的,而不是前面可见。