我开始认为GL ES(Android)中的z缓冲区不适用于GL_POINTS(?),但我在文档中找不到任何内容。
我正在寻找一个由点组成的立方体本色,并使用Z缓冲区将它们渲染到场景中的方法-我有一个类似的类(三角形),它渲染并使用z缓冲区?
PS:我知道我的代码很乱(对此我感到很烦),我已经整理了一下。
下面列出的代码:
class MyGLRenderer implements GLSurfaceView.Renderer {
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"uniform float vSpatical;" +
"uniform vec3 vCamPos;" +
"float vDistance;" +
"float vDisX;" +
"float vDisY;" +
"float vDisZ;" +
"float vA;" +
"void main() {" +
" gl_Position = vPosition * uMVPMatrix;" +
" vDisX = vCamPos.x-vPosition.x;" +
" vDisY = vCamPos.y-vPosition.y;" +
" vDisZ = vCamPos.z-vPosition.z;" +
" vA = 3.14159265359 * (vSpatical*vSpatical);" +
" vDistance = sqrt((vDisX*vDisX) + (vDisY*vDisY) + (vDisZ*vDisZ));" +
" gl_PointSize = 1.0 * vA / (vDistance*vDistance);" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
float[] mCamPos = {0f, 0f, 6f};
Triangle mTriangle;
Cube mCube;
int mProgram;
float mAngle = 0;
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mTriangle = new Triangle();
mCube = new Cube();
GLES20.glClearColor(0.0f, 0.4f, 0.4f, 1.0f);
GLES20.glClearDepthf(1.0f);
GLES20.glEnable(GL10.GL_DEPTH_TEST);
GLES20.glDepthFunc(GL10.GL_LEQUAL);
GLES20.glDepthMask(true);
GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
GLES10.glShadeModel(GL10.GL_SMOOTH);
}
@Override
public void onDrawFrame(GL10 unused) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.setLookAtM(mViewMatrix, 0, mCamPos[0], mCamPos[1], mCamPos[2], 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0f, 1.0f, 1.0f);
mAngle += 0.09f;
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
mTriangle.draw(mProgram, scratch);
mCube.draw(mProgram, scratch, mCamPos);
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public static int loadShader(int type, String shaderCode){
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
class Cube {
private final FloatBuffer vertexBuffer, vBuff2, vBuff3;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private int vertexCount;
private final int vertexStride = COORDS_PER_VERTEX * 4;
private float mSpaticalExtent[];
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[];
static float sides[];
static float topbottom[];
float color[] = { 0.93671875f, 0.46953125f, 0.22265625f, 1.0f };
float color2[] = { 0.43671875f, 0.96953125f, 0.22265625f, 1.0f };
float color3[] = { 0.33671875f, 0.46953125f, 0.82265625f, 1.0f };
public Cube() {
MakeCube(0, 0, 0, 10);
ByteBuffer bb = ByteBuffer.allocateDirect(
triangleCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(triangleCoords);
vertexBuffer.position(0);
ByteBuffer bb2 = ByteBuffer.allocateDirect(
sides.length * 4);
bb2.order(ByteOrder.nativeOrder());
vBuff2 = bb2.asFloatBuffer();
vBuff2.put(sides);
vBuff2.position(0);
ByteBuffer bb3 = ByteBuffer.allocateDirect(
topbottom.length * 4);
bb3.order(ByteOrder.nativeOrder());
vBuff3 = bb3.asFloatBuffer();
vBuff3.put(topbottom);
vBuff3.position(0);
}
private void MakeCube(float x, float y, float z, float width) {
triangleCoords = new float[(int)width*(int)width*6]; // Width * Width * 6 Points * 3 Float per point
sides = new float[(int)width*(int)width*6];
topbottom = new float[(int)width*(int)width*6];
vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
mSpaticalExtent = new float[1];
mSpaticalExtent[0] = width;
x -= width/2f;
y -= width/2f;
z -= width/2f;
int currentArrayPoint = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < width; j++)
{
// FRONT AND BACK WALLS- X AND Y CHANGE Z DOESN'T
//
triangleCoords[currentArrayPoint++] = (x + j) / width;
triangleCoords[currentArrayPoint++] = (y + i) / width;
triangleCoords[currentArrayPoint++] = z / width;
//
triangleCoords[currentArrayPoint++] = (x + j) / width;
triangleCoords[currentArrayPoint++] = (y + i) / width;
triangleCoords[currentArrayPoint++] = (z + width) / width;
}
}
currentArrayPoint = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < width; j++)
{
// SIDE WALLS, Y AND Z CHANGE X DOESN'T
//
sides[currentArrayPoint++] = x / width;
sides[currentArrayPoint++] = (y + i) / width;
sides[currentArrayPoint++] = (z + j) / width;
//
sides[currentArrayPoint++] = (x + width) / width;
sides[currentArrayPoint++] = (y + i) / width;
sides[currentArrayPoint++] = (z + j) / width;
}
}
currentArrayPoint = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < width; j++)
{
// TOP AND BOTTOM WALLS, X AND Z CHANGE Y DOESN'T
//
topbottom[currentArrayPoint++] = (z + j) / width;
topbottom[currentArrayPoint++] = (y) / width;
topbottom[currentArrayPoint++] = (x + i) / width;
//
topbottom[currentArrayPoint++] = (z + j) / width;
topbottom[currentArrayPoint++] = (y + width) / width;
topbottom[currentArrayPoint++] = (x + i) / width;
}
}
}
public void draw(int mProgram, float[] mvpMatrix, float[] mCamPos) {
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
int mCamHandle = GLES20.glGetUniformLocation(mProgram, "vCamPos");
GLES20.glUniform3fv(mCamHandle, 1, mCamPos, 0);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
int mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vBuff2);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color2, 0);
mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vBuff3);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color3, 0);
mSpaticalHandle = GLES20.glGetUniformLocation(mProgram, "vSpatical");
GLES20.glUniform1fv(mSpaticalHandle, 1, mSpaticalExtent, 0);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
最佳答案
在查看了您的着色器之后,我注意到了以下几点:
gl_Position = vPosition * uMVPMatrix; // D3D convention
对于OpenGL(使用列主矩阵和后乘运算),这是完全错误的。
它应该是:
gl_Position = uMVPMatrix * vPosition; // OpenGL convention
我检查了用于发送MVP矩阵的代码,它没有转置矩阵,因此您的着色器是向后的。
您也可以通过将
transpose
中的GLES20.glUniformMatrix4fv
参数设置为true来解决此问题,但是最好坚持使用传统的OpenGL约定并使用以列为主的矩阵。如果这样做,诊断这类事情要容易得多。