Reputation: 1949
I'm trying to create a 3D Android game using the OpenGL library. From what I can tell, the Android platform (or OpenGL) doesn't provide a camera object, so I made my own. I managed to create a square that is drawn on the screen. I also managed to get the camera to move in all 3 directions without issue. The problem I'm having is when I turn the camera either in the x or y axis, the square is displayed in a very strange way. It seems highly distorted its perspective. Here's some pictures
Camera at origin looking forward: Position [0,0,0.55f], Forward [0,0,-1], Up [0,1,0]
Camera moved to the right: Position [3,0,0.55f], Forward [0,0,-1], Up [0,1,0]
Camera turned slightly to the right: Position [0,0,0.55f], Forward [0.05f,0,-1], Up [0,1,0]
I'm not sure where the problem is getting generated. Here are the vertices of the square:
static float vertices[] = {
// Front face (CC order)
-1.0f, 1.0f, 1.0f, // top left
-1.0f, -1.0f, 1.0f, // bottom left
1.0f, -1.0f, 1.0f, // bottom right
1.0f, 1.0f, 1.0f, // top right
};
From what I've read, my matrix multiplications are in the correct order. I pass the Matrices to the vertex shader and do the multiplications there:
private final String vertexShaderCode =
"uniform mat4 uVMatrix;" +
"uniform mat4 uMMatrix;" +
"uniform mat4 uPMatrix;" +
"attribute vec4 aVertexPosition;" + // passed in
"attribute vec4 aVertexColor;" +
"varying vec4 vColor;" +
"void main() {" +
" gl_Position = uPMatrix * uVMatrix * uMMatrix * aVertexPosition;" +
" vColor = aVertexColor;" + // pass the vertex's color to the pixel shader
"}";
The Model matrix just moves it to the origin and makes it scale 1:
Matrix.setIdentityM(ModelMatrix, 0);
Matrix.translateM(ModelMatrix, 0, 0, 0, 0);
Matrix.scaleM(ModelMatrix, 0, 1, 1, 1);
I use my Camera object to update the View Matrix:
Matrix.setLookAtM(ViewMatrix, 0,
position.x, position.y, position.z,
position.x + forward.x, position.y + forward.y, position.z + forward.z,
up.x, up.y, up.z);
Here is my ProjectionMatrix:
float ratio = width / (float) height;
Matrix.frustumM(ProjectionMatrix, 0, -ratio, ratio, -1, 1, 0.01f, 10000f);
What am I missing?
Upvotes: 0
Views: 199
Reputation: 54642
With the parameters you pass to frustrumM()
:
Matrix.frustumM(ProjectionMatrix, 0, -ratio, ratio, -1, 1, 0.01f, 10000f);
you have an extremely strong perspective. This is the reason why the geometry looks very distorted as soon as you rotate it just slightly.
The left, right, bottom, and top values are distances measured at the depth of the near clip plane. So for example for your top value of 1.0, with the near value at 0.01, the top plane of the view volume will move at distance of 1.0 away from the viewing direction at a forward distance of 0.01.
Doing the math, you get atan(top / near) = atan(1.0 / 0.01) = atan(100.0) = 89.42 degrees for half the vertical view angle, or 178.85 degrees for the whole view angle, which corresponds to an extreme fish eye lense on a camera, covering almost the whole space in front of the camera.
To use a more sane level of perspective, you can calculate the values based on the desired view angle. With alpha being the vertical view angle:
float near = 0.01f;
float top = tan(0.5f * alpha) * near;
float right = top * ratio;
Matrix.frustumM(ProjectionMatrix, 0, -right, right, -top, top, near, 10000f);
Start with view angles in the range of 45 to 60 degrees for a generally pleasing amount of perspective. And remember that the tan() function used above takes angles in radian, so you'll have to convert it first if your original angle is in degrees.
Or, if you're scared of math, you can always use perspectiveM()
instead. ;)
Upvotes: 1
Reputation: 46
Depending on your setup, your vertex buffer may be wrong . Your vertices array is a vec3. And the attribute position in your shader is a vec4.
Also you projection matrix is strange , depending on the aspect ratio you want you'll get bizarre results.
You should use perspectiveM instead.
Upvotes: 1