Ошибка просмотра проекции LWJGL?
Итак, я не знаю, как объяснить проблему, которая у меня сейчас слишком хорошо, но я знаю, что она включает в себя матрицы модель / вид / проекция для рисования куба. Я импортировал куб из blender, и теперь я пытаюсь создать систему камер для просмотра под разными углами. Сначала я применил масштабирование, вращение и перевод к кубу, отправил эту матрицу в мой класс вершинных шейдеров, и куб появился там, где должен, с правильным размером, и вращается в любом направлении, которое я ему даю. Следующим шагом была настройка вида с камеры, поэтому я умножил текущие мировые координаты куба на матрицу вида, чтобы я мог перемещать "камеру" и смотреть с разных сторон. Так что теперь у меня есть координаты камеры, и все выглядит так, как должно. Куб все еще вращается, и когда я меняю "камеру", куб вращается в нужном направлении. Итак, наконец, когда я добавляю матрицу проекции в шейдер, все выглядит так, как будто оно работает... изначально. Тем не менее, я замечаю, что куб больше не выглядит правильным. Теперь я могу вращать / перемещать камеру, но куб выглядит измененным так, что некоторые грани не имеют квадратной формы. Теперь странно то, что, если я подойду очень близко к кубу, это почти так, как будто все цвета снаружи идут внутрь, и вы можете увидеть идеальную форму куба. Вот ссылка на то, что он делает, потому что это, вероятно, действительно трудно понять: http://youtu.be/QHY7ZVADeiQ. Ниже приведен код, который я использую для преобразования куба (ModelTransformation), код класса камеры и настройки моего вершинного шейдера. Любые идеи очень приветствуются. И я прошу прощения за огромные блоки кода.
Класс ModelTransformation:
package engine;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
public class ModelTransformation {
private static Matrix4f identity;
private static Matrix4f scaleMatrix;
private static Matrix4f rotationMatrix;
private static Matrix4f translationMatrix;
public ModelTransformation(){
scaleMatrix = new Matrix4f();
rotationMatrix = new Matrix4f();
translationMatrix = new Matrix4f();
}
public Matrix4f getScaleMatrix(){
return scaleMatrix;
}
public void setScaleMatrix(Vector3f axis){
Matrix4f.setIdentity(scaleMatrix);
Matrix4f.scale(axis, scaleMatrix, scaleMatrix);
}
public Matrix4f getRotationMatrix(){
return rotationMatrix;
}
public void setRotationMatrix(Vector3f amount){
Matrix4f.setIdentity(rotationMatrix);
if(amount.x == 0 && amount.y == 0 && amount.z == 0)
return;
else{
Matrix4f.rotate(amount.z, new Vector3f (0, 0, 1), rotationMatrix, rotationMatrix);
Matrix4f.rotate(amount.y, new Vector3f (0, 1, 0), rotationMatrix, rotationMatrix);
Matrix4f.rotate(amount.x, new Vector3f (1, 0, 0), rotationMatrix, rotationMatrix);
}
}
public Matrix4f getTranslationMatrix(){
return translationMatrix;
}
public void setTranslationMatrix(Vector3f axis) {
Matrix4f.setIdentity(translationMatrix);
Matrix4f.translate(axis, translationMatrix, translationMatrix);
}
public Matrix4f getTransformationMatrix() {
return Matrix4f.mul(translationMatrix, Matrix4f.mul(rotationMatrix, scaleMatrix, null), null);
}
}
Класс камеры:
package engine;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
public class Camera {
private float fov;
private float aspect;
private float zNear;
private float zFar;
private Vector3f position;
private Vector3f rotation;
private Vector3f xAxis;
private Vector3f yAxis;
private Vector3f zAxis;
private Matrix4f viewMatrix;
private Matrix4f viewTranslationMatrix;
private Matrix4f viewRotationMatrix;
private Matrix4f projectionMatrix;
public Camera(float fov, float aspect, float zNear, float zFar){
this.fov = fov;
this.aspect = aspect;
this.zNear = zNear;
this.zFar = zFar;
position = new Vector3f(0, 0, 0);
rotation = new Vector3f(0, 0, 0);
xAxis = new Vector3f(1, 0, 0);
yAxis = new Vector3f(0, 1, 0);
zAxis = new Vector3f(0, 0, 1);
viewMatrix = new Matrix4f();
viewTranslationMatrix = new Matrix4f();
viewRotationMatrix = new Matrix4f();
projectionMatrix = new Matrix4f();
}
public Matrix4f getViewMatrix(){
viewMatrix.setIdentity();
rotateCamera();
translateCamera();
viewMatrix = Matrix4f.mul(viewRotationMatrix, viewTranslationMatrix, null);
return viewMatrix;
}
public void rotateCamera(){
viewRotationMatrix.setIdentity();
Matrix4f.rotate((float) Math.toRadians(rotation.x), xAxis, viewRotationMatrix, viewRotationMatrix);
Matrix4f.rotate((float) Math.toRadians(rotation.y), yAxis, viewRotationMatrix, viewRotationMatrix);
Matrix4f.rotate((float) Math.toRadians(rotation.z), zAxis, viewRotationMatrix, viewRotationMatrix);
}
public void translateCamera(){
viewTranslationMatrix.setIdentity();
Matrix4f.translate(position, viewTranslationMatrix, viewTranslationMatrix);
}
public Matrix4f getProjectionMatrix(){
projectionMatrix.setIdentity();
float tanFOV = (float)Math.tan(Math.toRadians(fov / 2));
float zRange = (zFar - zNear);
projectionMatrix.m00 = ((1 / tanFOV) / aspect); projectionMatrix.m10 = 0; projectionMatrix.m20 = 0; projectionMatrix.m30 = 0;
projectionMatrix.m01 = 0; projectionMatrix.m11 = ((1 / tanFOV)); projectionMatrix.m21 = 0; projectionMatrix.m31 = 0;
projectionMatrix.m02 = 0; projectionMatrix.m12 = 0; projectionMatrix.m22 = -((zFar + zNear) / zRange); projectionMatrix.m32 = -((2 * zFar * zNear) / zRange);
projectionMatrix.m03 = 0; projectionMatrix.m13 = 0; projectionMatrix.m23 = -1; projectionMatrix.m33 = 0;
return projectionMatrix;
}
public void input() {
if (Input.isKeyDown(Keyboard.KEY_UP))
addRotation(-1f, 0, 0);
if (Input.isKeyDown(Keyboard.KEY_DOWN))
addRotation(1f, 0, 0);
if (Input.isKeyDown(Keyboard.KEY_LEFT))
addRotation(0, -1f, 0);
if (Input.isKeyDown(Keyboard.KEY_RIGHT))
addRotation(0, 1f, 0);
if (Input.isKeyDown(Keyboard.KEY_W))
move(0.01f, 1);
if (Input.isKeyDown(Keyboard.KEY_S))
move(-0.01f, 1);
if (Input.isKeyDown(Keyboard.KEY_A))
move(0.01f, 0);
if (Input.isKeyDown(Keyboard.KEY_D))
move(-0.01f, 0);
if(Input.isKeyDown(Keyboard.KEY_SPACE))
position.y -= 0.01f;
if(Input.isKeyDown(Keyboard.KEY_LSHIFT))
position.y += 0.01f;
}
private void addRotation(float rx, float ry, float rz) {
rotation.x += rx;
rotation.y += ry;
rotation.z += rz;
}
public void move(float amount, float direction){
position.z += amount * Math.sin(Math.toRadians(rotation.y + 90 * direction));
position.x += amount * Math.cos(Math.toRadians(rotation.y + 90 * direction));
}
}
Вершинный шейдер:
#version 430
in vec3 position;
out vec4 color;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
void main(){
vec4 worldCoord = modelMatrix * vec4(position.xyz, 1.0);
vec4 cameraCoord = viewMatrix * worldCoord;
vec4 homogeneousCoord = projectionMatrix * cameraCoord;
color = vec4(clamp(position, 0.0, 1.0), 1.0);
gl_Position = homogeneousCoord;
}
Изменить: Добавлено еще несколько классов, которые могут помочь, и добавлено больше тегов
Класс RenderUtility:
public class RenderUtility {
//clearScreen - clears the screen with the color buffer bit and depth buffer bit
//then loads the identity projection matrix
public static void clearScreen(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
//Determines how the game is going to run
public static void initilizeGraphics(){
glMatrixMode(GL_PROJECTION);
glClearColor(0, 0, 0, 0);
glFrontFace(GL_CW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_FRAMEBUFFER_SRGB);
}
//getOpenGLVersion - returns the currently used version of OpenGL
public static String getOpenGLVersion(){
return glGetString(GL_VERSION);
}
}
Класс игры:
public class Game {
private static ShaderProgram program;
private static Model model2;
private static ModelTransformation transformation;
private static Camera camera;
private static Transformation transform;
private static float temp = 0.0f;
// Game - creates the program for the shaders
// Creates the entities necessary for the game
public Game() {
camera = new Camera(70, Window.getWidth()/Window.getHeight(), 0.001f, 100f);
program = new ShaderProgram();
program.addVertexShaderFrom("rsc/shaders/shader.vertex");
program.addFragmentShaderFrom("rsc/shaders/shader.fragment");
program.linkAndValidateProgram();
program.addUniform("modelMatrix");
program.addUniform("viewMatrix");
program.addUniform("projectionMatrix");
transform = new Transformation();
transformation = new ModelTransformation();
model2 = new Model("rsc/box3.obj");
}
// render - renders all items used in the game
// This is where shaders are implemented
public void render() {
program.useShaders();
program.setUniform("viewMatrix", camera.getViewMatrix());
program.setUniform("modelMatrix", transformation.getTransformationMatrix());
program.setUniform("projectionMatrix", camera.getProjectionMatrix());
model2.draw();
program.stopUsingShaders();
}
// input - takes input from keyboard/mouse and do something useful
public static void input(List<Integer> currentKeys, List<Integer> currentMouseButtons, Vector2f mouseLocation) {
// TODO: Add what each input button/key should accomplish
camera.input();
}
// update - updates values using the time difference between frames
public void update(double deltaTime) {
temp += deltaTime;
float sinTemp = 90 * (float)Math.sin(Math.toRadians(temp));
float cosTemp = (float)Math.cos(Math.toRadians(temp));
transformation.setTranslationMatrix(new Vector3f(0f, 0f, -3));
transformation.setRotationMatrix(new Vector3f(sinTemp, 0, sinTemp));
transformation.setScaleMatrix(new Vector3f(1f, 1f, 1f));
}
}
1 ответ
Итак, я нашел ошибку. Я пытался отбросить заднюю грань куба, хотя на самом деле я отбрасывал переднюю часть. Вот почему куб выглядит супер триповым.