【发布时间】:2015-05-11 15:58:34
【问题描述】:
当我渲染我的应用程序时,我希望在窗口边缘看到一些矩形。相反,我看到了这个..
所有对象都将位于z == 0.0f。如果我不使用着色器渲染我的场景,所有对象都可以正常显示。所以认为它一定是矩阵计算问题?
有人知道我的矩阵设置可能出了什么问题吗?
matrices 是一个包含 3 个矩阵的自定义类 ..
public class MatrixUtils {
/* The different matrices */
private Matrix4f modelMatrix = new Matrix4f();
private Matrix4f viewMatrix = new Matrix4f();
private Matrix4f projectionMatrix = new Matrix4f();
public MatrixUtils(){
loadIdentity(modelMatrix);
}
public void loadIdentity(Matrix4f matrix) {
matrix.load(new float[][] {
new float[] { 1, 0, 0, 0 },
new float[] { 0, 1, 0, 0 },
new float[] { 0, 0, 1, 0 },
new float[] { 0, 0, 0, 1 },
});
}
}
在我的GLEventListener 中,我使用初始值设置了矩阵。调用reshape,设置投影、模型和视图矩阵..
/* (non-Javadoc)
* @see javax.media.opengl.GLEventListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int)
*/
public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height) {
setupOrtho(width, height, 0.1f, 100.0f);
}
模型和视图矩阵最初设置为标识。投影使用正交矩阵。
private void setupOrtho(float width, float height, float znear, float zfar) {
matrices.loadIdentity(matrices.getModelMatrix());
matrices.loadIdentity(matrices.getViewMatrix());
matrices.setViewMatrix(
setupViewMatrix(
new Vec3(0.0f, 0.0f, 25.0f),
new Vec3(0.0f, 0.0f, 0.0f),
new Vec3(0.0f, 1.0f, 0.0f)));
matrices.setProjectionMatrix(ortho(0, width, 0, height, znear, zfar));
}
计算正交Projection矩阵..
public Matrix4f ortho(float left, float right, float top, float bottom, float zfar, float znear) {
return new Matrix4f(new float[][] {
new float[] { 2 / (right - left), 0, 0, -((right + left) / (right - left)) },
new float[] { 0, 2 / (top - bottom), 0, -((top + bottom) / (top - bottom)) },
new float[] { 0, 0, -2 / (zfar - znear), -((zfar + znear) / (zfar - znear)) },
new float[] { 0, 0, 0, 1 },
});
}
计算View矩阵..
public Matrix4f setupViewMatrix(Vec3 position, Vec3 target, Vec3 up) {
Vec3f f = (new Vec3f(target.sub(position))).normalize();
Vec3f s = (new Vec3f(Vec3.cross(f, up))).normalize();
Vec3f u = (new Vec3f(Vec3.cross(s, f)));
return new Matrix4f(
new float[] {
s.x, s.y, s.z, -Vec3.dot(s, position),
u.x, u.y, u.z, -Vec3.dot(u, position),
-f.x, -f.y, -f.z, Vec3.dot(f, position),
0.0f, 0.0f, 0.0f, 1.0f});
}
然后在我的 display() 循环中,我将所有 3 个矩阵传递给每个对象的 draw() 函数。
public void display(GLAutoDrawable gLDrawable) {
for (CustomObject obj : customObjects.size()){
obj.draw(gl2, matrices, getShaderProgram(), obj.getPosition(), 0.0f);
}
}
这就是我的自定义对象设置vertexBuffer ..
int COORDS_PER_VERTEX = 3;
int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
ShortBuffer drawListBuffer;
short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
float squareCoordsTemp[] = {
-(getWidth() / 2 * getP2M()), (getHeight() / 2 * getP2M()), 0.0f, // top left
-(getWidth() / 2 * getP2M()), -(getHeight() / 2 * getP2M()), 0.0f, // bottom left
(getWidth() / 2 * getP2M()), -(getHeight() / 2 * getP2M()), 0.0f, // bottom right
(getWidth() / 2 * getP2M()), (getHeight() / 2 * getP2M()), 0.0f }; // top right
squareCoords = squareCoordsTemp;
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); // # of coordinate values * 4 bytes per float
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); // # of coordinate values * 2 bytes per short
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
这就是我的CustomObject 的画法..
public void draw(final GL2 gl2, MatrixUtils matrices, int shaderProgram, final Vec3 position, final float bodyAngle){
gl2.glUseProgram(shaderProgram);
// enable alpha
gl2.glEnable(GL.GL_BLEND);
gl2.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
// Set color for drawing
setmColorHandle(gl2.glGetUniformLocation(shaderProgram, "vColor"));
gl2.glUniform4fv(getmColorHandle(), 1, getColorArray(), 0);
// get handle to vertex shader's vPosition member
mPositionHandle = gl2.glGetAttribLocation(shaderProgram, "vPosition");
// Enable a handle to the triangle vertices
gl2.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
gl2.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GL2.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to shape's transformation matrix
mProj = gl2.glGetUniformLocation(shaderProgram, "mProj");
mView = gl2.glGetUniformLocation(shaderProgram, "mView");
mModel = gl2.glGetUniformLocation(shaderProgram, "mModel");
// Apply the projection and view transformation
// getP2M() == 60.0f .. pixels to meters for box2d
matrices.loadIdentity(matrices.getModelMatrix());
matrices.setModelMatrix(matrices.translate(matrices.getModelMatrix(), new Vec3(position.x * getP2M(), position.y * getP2M(), position.z * getP2M())));
matrices.setModelMatrix(matrices.rotate(matrices.getModelMatrix(), bodyAngle, 0, 0, 1));
gl2.glUniformMatrix4fv(mProj, 1, true, matrices.getProjectionMatrix().getValues(), 0);
gl2.glUniformMatrix4fv(mView, 1, true, matrices.getViewMatrix().getValues(), 0);
gl2.glUniformMatrix4fv(mModel, 1, true, matrices.getModelMatrix().getValues(), 0);
// Draw the square
gl2.glDrawElements(
GL2.GL_TRIANGLES, drawOrder.length,
GL2.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
gl2.glDisableVertexAttribArray(mPositionHandle);
gl2.glDisable(GL.GL_BLEND);
gl2.glUseProgram(0);
}
顶点着色器..
#version 120
attribute vec4 vPosition;
uniform mat4 mProj;
uniform mat4 mView;
uniform mat4 mModel;
void main() {
gl_Position = mProj * mView * mModel * vPosition;
}
片段着色器..
#version 120
uniform vec4 vColor;
void main() {
gl_FragColor = vColor;
}
Matrix4f 的定义..
public class Matrix4f {
public float[] values;
public Matrix4f() {
this.values = new float[16];
}
/**
* @param values
*/
public Matrix4f(float[] values) {
this.values = values;
}
/**
* @param values
*/
public Matrix4f(float[][] values) {
load(values);
}
/**
* @param values
*/
public void load(float[][] values) {
this.values = new float[] {
values[0][0], values[0][2], values[0][3], values[0][4],
values[1][0], values[1][5], values[1][6], values[1][7],
values[2][0], values[2][8], values[2][9], values[2][10],
values[3][0], values[3][11], values[3][12], values[3][13]
};
}
/**
* Get the values of matrix
*
* @return values
*/
public float[] getValues() {
return this.values;
}
}
矩阵函数..
public Matrix4f translate(Matrix4f matrix, Vec3 vector) {
Matrix4f transform = new Matrix4f(new float[][] {
new float[] { 1, 0, 0, vector.x },
new float[] { 0, 1, 0, vector.y },
new float[] { 0, 0, 1, vector.z },
new float[] { 0, 0, 0, 1 },
});
return multiply(matrix, transform);
}
public Matrix4f rotate(Matrix4f matrix, float angle, int x, int y, int z) {
Matrix4f transform = new Matrix4f();
float cos = (float) Math.cos(angle);
float sin = (float) Math.sin(angle);
if (z == 1) {
transform.load(new float[][] {
new float[] { cos, -sin, 0, 0 },
new float[] { sin, cos, 0, 0 },
new float[] { 0, 0, 1, 0 },
new float[] { 0, 0, 0, 1 },
});
}
//Add onto the matrix and return the result
return multiply(matrix, transform);
}
public Matrix4f add(Matrix4f matrixA, Matrix4f matrixB) {
Matrix4f matrix = new Matrix4f();
for (int a = 0; a < matrix.values.length; a++){
matrix.values[a] = matrixA.values[a] + matrixB.values[a];
}
return matrix;
}
public Matrix4f multiply(Matrix4f matrixA, Matrix4f matrixB) {
Matrix4f matrix = new Matrix4f(new float[][] {
new float[] {
(matrixA.values[0] * matrixB.values[0]) + (matrixA.values[1] * matrixB.values[4]) + (matrixA.values[2] * matrixB.values[8]) + (matrixA.values[3] * matrixB.values[12]),
(matrixA.values[0] * matrixB.values[1]) + (matrixA.values[1] * matrixB.values[5]) + (matrixA.values[2] * matrixB.values[9]) + (matrixA.values[3] * matrixB.values[13]),
(matrixA.values[0] * matrixB.values[2]) + (matrixA.values[1] * matrixB.values[6]) + (matrixA.values[2] * matrixB.values[10]) + (matrixA.values[3] * matrixB.values[14]),
(matrixA.values[0] * matrixB.values[3]) + (matrixA.values[1] * matrixB.values[7]) + (matrixA.values[2] * matrixB.values[11]) + (matrixA.values[3] * matrixB.values[15])
},
new float[] {
(matrixA.values[4] * matrixB.values[0]) + (matrixA.values[5] * matrixB.values[4]) + (matrixA.values[6] * matrixB.values[8]) + (matrixA.values[7] * matrixB.values[12]),
(matrixA.values[4] * matrixB.values[1]) + (matrixA.values[5] * matrixB.values[5]) + (matrixA.values[6] * matrixB.values[9]) + (matrixA.values[7] * matrixB.values[13]),
(matrixA.values[4] * matrixB.values[2]) + (matrixA.values[5] * matrixB.values[6]) + (matrixA.values[6] * matrixB.values[10]) + (matrixA.values[7] * matrixB.values[14]),
(matrixA.values[4] * matrixB.values[3]) + (matrixA.values[5] * matrixB.values[7]) + (matrixA.values[6] * matrixB.values[11]) + (matrixA.values[7] * matrixB.values[15])
},
new float[] {
(matrixA.values[8] * matrixB.values[0]) + (matrixA.values[9] * matrixB.values[4]) + (matrixA.values[10] * matrixB.values[8]) + (matrixA.values[11] * matrixB.values[12]),
(matrixA.values[8] * matrixB.values[1]) + (matrixA.values[9] * matrixB.values[5]) + (matrixA.values[10] * matrixB.values[9]) + (matrixA.values[11] * matrixB.values[13]),
(matrixA.values[8] * matrixB.values[2]) + (matrixA.values[9] * matrixB.values[6]) + (matrixA.values[10] * matrixB.values[10]) + (matrixA.values[11] * matrixB.values[14]),
(matrixA.values[8] * matrixB.values[3]) + (matrixA.values[9] * matrixB.values[7]) + (matrixA.values[10] * matrixB.values[11]) + (matrixA.values[11] * matrixB.values[15])
},
new float[] {
(matrixA.values[12] * matrixB.values[0]) + (matrixA.values[13] * matrixB.values[4]) + (matrixA.values[14] * matrixB.values[8]) + (matrixA.values[15] * matrixB.values[12]),
(matrixA.values[12] * matrixB.values[1]) + (matrixA.values[13] * matrixB.values[5]) + (matrixA.values[14] * matrixB.values[9]) + (matrixA.values[15] * matrixB.values[13]),
(matrixA.values[12] * matrixB.values[2]) + (matrixA.values[13] * matrixB.values[6]) + (matrixA.values[14] * matrixB.values[10]) + (matrixA.values[15] * matrixB.values[14]),
(matrixA.values[12] * matrixB.values[3]) + (matrixA.values[13] * matrixB.values[7]) + (matrixA.values[14] * matrixB.values[11]) + (matrixA.values[15] * matrixB.values[15])
}
});
return matrix;
}
编辑:
我已将制服设置为转置我的矩阵,但方块仍未居中。它们应该在屏幕周围形成一个正方形,而不是像这样显示,而且它们似乎没有正确旋转? ..
编辑:
我已经更改了旋转和平移函数来乘以矩阵,从而解决了旋转问题。我的最后一个问题是我似乎没有在看场景的中心,或者我的对象没有画在我的视野中心。方块应围绕屏幕边缘形成一个框,屏幕中心为菱形。
我的相机位置有问题吗? ..
【问题讨论】:
-
您可以使用
gl_Position = vec4(vPosition.xyz * 0.1 + 0.5, 1.0)对其进行测试,看看它是否至少可以绘制,然后尝试缩小出现故障的矩阵。也许是行/列的主要内容,但只是猜测。 -
使用你建议的线路,我只是得到一个绿屏。假设这是距离太近的正方形之一。你对那条线有什么期待?考虑到我可以看到已经绘制了正方形,它们只是被扭曲了。
-
没有任何矩阵,您将顶点直接放在标准化设备坐标中(-1 到 1)。我的 0.1 比例是这样的,如果你有很大的几何图形,它会适合屏幕。 +0.5 是一个错误,对不起,因为中心是 0 而不是 (0.5, 0.5)。接下来我要尝试的是使用投影矩阵(它不应该扭曲任何东西,因为它是正交的),看看你是否仍然得到正方形。然后放入视图和模型矩阵。
-
使用您建议的线乘以投影矩阵,我只看到绿色消耗屏幕的左下角。屏幕的其余部分是黑色的。
-
也许矩阵只是转置了。我看不到您的 Matrix4f 实现。但似乎您正在按行主要顺序构建矩阵。 OpenGL 默认采用列优先顺序。尝试将 true 传递给 glUniformMatrix4fv。