Java LWJGL投影矩阵-不发生任何情况
目前,我正试图在LWJGL中创建一个Camera类,但我遇到了投影矩阵的问题。出于某种原因,当我尝试用投影矩阵乘以顶点时,屏幕上根本没有显示任何内容 摄像机等级Java LWJGL投影矩阵-不发生任何情况,java,lwjgl,vbo,opengl-3,projection-matrix,Java,Lwjgl,Vbo,Opengl 3,Projection Matrix,目前,我正试图在LWJGL中创建一个Camera类,但我遇到了投影矩阵的问题。出于某种原因,当我尝试用投影矩阵乘以顶点时,屏幕上根本没有显示任何内容 摄像机等级 public class Camera { private Vector3f position, rotation; private Matrix4f view; private final Vector3f xAxis, yAxis, zAxis; private float fov, aspect, zNear, zFar;
public class Camera {
private Vector3f position, rotation;
private Matrix4f view;
private final Vector3f xAxis, yAxis, zAxis;
private float fov, aspect, zNear, zFar;
private Matrix4f projection;
public Camera(float fov, float aspect, float zNear, float zFar){
this.fov = fov;
this.aspect = aspect;
this.zNear = zNear;
this.zFar = zFar;
projection = createPerspectiveProjection(fov, aspect, zNear, zFar);
position = new Vector3f();
rotation = new Vector3f();
view = new Matrix4f();
view.setIdentity();
xAxis = new Vector3f(1, 0, 0);
yAxis = new Vector3f(0, 1, 0);
zAxis = new Vector3f(0, 0, 1);
}
public void addRotation(float x, float y, float z){
rotation.x += x;
rotation.y += y;
rotation.z += z;
apply();
}
public void move(float x, float y, float z){
position.x += x;
position.y += y;
position.z += z;
apply();
}
public Matrix4f getView(){
return view;
}
public Matrix4f getProjection(){
return projection;
}
private void apply(){
view.setIdentity();
view.rotate(rotation.x, xAxis);
view.rotate(rotation.y, yAxis);
view.rotate(rotation.z, zAxis);
view.translate(position);
}
private Matrix4f createPerspectiveProjection(float fov, float aspect, float zNear, float zFar){
Matrix4f mat = new Matrix4f();
float yScale = (float) (1 / (Math.tan(Math.toRadians(fov / 2))));
float xScale = yScale / aspect;
float frustrumLength = zFar - zNear;
mat.m00 = xScale;
mat.m11 = yScale;
mat.m22 = -((zFar + zNear) / frustrumLength);
mat.m23 = -1;
mat.m32 = -((2 * zFar * zNear) / frustrumLength);
mat.m33 = 0;
return mat;
}
}
public class Game implements Runnable {
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static final DisplayMode dm = new DisplayMode(WIDTH, HEIGHT);
int vaoID;
ShaderProgram program;
Camera camera;
Model model;
public Game(){
new Thread(this).start();
}
public void run(){
init();
while(true){
if(Display.isCloseRequested())
break;
update(Timer.getElapsedTime());
render();
Display.sync(60);
Display.update();
}
Display.destroy();
}
public void init(){
try{
Display.setTitle("Ludum Dare!");
Display.setDisplayMode(dm);
Display.create();
}catch(LWJGLException e){
e.printStackTrace();
System.exit(1);
}
Timer.start();
camera = new Camera(60.0f, WIDTH / HEIGHT, 0.1f, 100.0f);
program = new ShaderProgram("res/shader/defaultshader.vert", "res/shader/defaultshader.frag");
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
model = new Model(new float[] {
-1, -1, 1,
1, -1, 1,
0, 1, 1
});
}
public void update(float delta){
}
public void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program.bind();
program.setUniform("model_matrix", model.getModel());
program.setUniform("view_matrix", camera.getView());
program.setUniform("projection_matrix", camera.getProjection());
model.render();
program.unbind();
}
public static void main(String[] args){
new Game();
}
}
public class ShaderProgram {
private int vertexShaderID, fragmentShaderID;
private int programID;
public ShaderProgram(String vertPath, String fragPath){
programID = glCreateProgram();
vertexShaderID = attachShader(vertPath, GL_VERTEX_SHADER);
fragmentShaderID = attachShader(fragPath, GL_FRAGMENT_SHADER);
link();
}
private int attachShader(String path, int type){
StringBuilder shaderSource = new StringBuilder();
try{
BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
String line;
while((line = reader.readLine()) != null){
shaderSource.append(line).append("\n");
}
reader.close();
}catch(IOException e){
e.printStackTrace();
System.out.println("Error reading from shader " + path);
System.exit(1);
}
System.out.println("Compiling shader " + path);
int id = glCreateShader(type);
glShaderSource(id, shaderSource);
glCompileShader(id);
if(glGetShaderi(id, GL_COMPILE_STATUS) == GL_FALSE){
System.out.println(glGetShaderInfoLog(id, 1000));
System.exit(1);
}
return id;
}
private void link(){
System.out.println("Linking program...");
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
}
public void bind(){
glUseProgram(programID);
}
public void unbind(){
glUseProgram(0);
}
public void setUniform(String name, Matrix4f value){
FloatBuffer matrix = BufferUtils.createFloatBuffer(16);
value.store(matrix); matrix.flip();
glUniformMatrix4(glGetUniformLocation(programID, name), false, matrix);
}
}
主类
public class Camera {
private Vector3f position, rotation;
private Matrix4f view;
private final Vector3f xAxis, yAxis, zAxis;
private float fov, aspect, zNear, zFar;
private Matrix4f projection;
public Camera(float fov, float aspect, float zNear, float zFar){
this.fov = fov;
this.aspect = aspect;
this.zNear = zNear;
this.zFar = zFar;
projection = createPerspectiveProjection(fov, aspect, zNear, zFar);
position = new Vector3f();
rotation = new Vector3f();
view = new Matrix4f();
view.setIdentity();
xAxis = new Vector3f(1, 0, 0);
yAxis = new Vector3f(0, 1, 0);
zAxis = new Vector3f(0, 0, 1);
}
public void addRotation(float x, float y, float z){
rotation.x += x;
rotation.y += y;
rotation.z += z;
apply();
}
public void move(float x, float y, float z){
position.x += x;
position.y += y;
position.z += z;
apply();
}
public Matrix4f getView(){
return view;
}
public Matrix4f getProjection(){
return projection;
}
private void apply(){
view.setIdentity();
view.rotate(rotation.x, xAxis);
view.rotate(rotation.y, yAxis);
view.rotate(rotation.z, zAxis);
view.translate(position);
}
private Matrix4f createPerspectiveProjection(float fov, float aspect, float zNear, float zFar){
Matrix4f mat = new Matrix4f();
float yScale = (float) (1 / (Math.tan(Math.toRadians(fov / 2))));
float xScale = yScale / aspect;
float frustrumLength = zFar - zNear;
mat.m00 = xScale;
mat.m11 = yScale;
mat.m22 = -((zFar + zNear) / frustrumLength);
mat.m23 = -1;
mat.m32 = -((2 * zFar * zNear) / frustrumLength);
mat.m33 = 0;
return mat;
}
}
public class Game implements Runnable {
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static final DisplayMode dm = new DisplayMode(WIDTH, HEIGHT);
int vaoID;
ShaderProgram program;
Camera camera;
Model model;
public Game(){
new Thread(this).start();
}
public void run(){
init();
while(true){
if(Display.isCloseRequested())
break;
update(Timer.getElapsedTime());
render();
Display.sync(60);
Display.update();
}
Display.destroy();
}
public void init(){
try{
Display.setTitle("Ludum Dare!");
Display.setDisplayMode(dm);
Display.create();
}catch(LWJGLException e){
e.printStackTrace();
System.exit(1);
}
Timer.start();
camera = new Camera(60.0f, WIDTH / HEIGHT, 0.1f, 100.0f);
program = new ShaderProgram("res/shader/defaultshader.vert", "res/shader/defaultshader.frag");
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
model = new Model(new float[] {
-1, -1, 1,
1, -1, 1,
0, 1, 1
});
}
public void update(float delta){
}
public void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program.bind();
program.setUniform("model_matrix", model.getModel());
program.setUniform("view_matrix", camera.getView());
program.setUniform("projection_matrix", camera.getProjection());
model.render();
program.unbind();
}
public static void main(String[] args){
new Game();
}
}
public class ShaderProgram {
private int vertexShaderID, fragmentShaderID;
private int programID;
public ShaderProgram(String vertPath, String fragPath){
programID = glCreateProgram();
vertexShaderID = attachShader(vertPath, GL_VERTEX_SHADER);
fragmentShaderID = attachShader(fragPath, GL_FRAGMENT_SHADER);
link();
}
private int attachShader(String path, int type){
StringBuilder shaderSource = new StringBuilder();
try{
BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
String line;
while((line = reader.readLine()) != null){
shaderSource.append(line).append("\n");
}
reader.close();
}catch(IOException e){
e.printStackTrace();
System.out.println("Error reading from shader " + path);
System.exit(1);
}
System.out.println("Compiling shader " + path);
int id = glCreateShader(type);
glShaderSource(id, shaderSource);
glCompileShader(id);
if(glGetShaderi(id, GL_COMPILE_STATUS) == GL_FALSE){
System.out.println(glGetShaderInfoLog(id, 1000));
System.exit(1);
}
return id;
}
private void link(){
System.out.println("Linking program...");
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
}
public void bind(){
glUseProgram(programID);
}
public void unbind(){
glUseProgram(0);
}
public void setUniform(String name, Matrix4f value){
FloatBuffer matrix = BufferUtils.createFloatBuffer(16);
value.store(matrix); matrix.flip();
glUniformMatrix4(glGetUniformLocation(programID, name), false, matrix);
}
}
顶点着色器
#version 330 core
layout(location = 0) in vec3 vertex_modelspace;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
void main(){
mat4 modelviewprojection_matrix = projection_matrix * view_matrix * model_matrix;
vec4 vertex = vec4(vertex_modelspace, 1.0);
gl_Position = modelviewprojection_matrix * vertex;
}
着色器程序类
public class Camera {
private Vector3f position, rotation;
private Matrix4f view;
private final Vector3f xAxis, yAxis, zAxis;
private float fov, aspect, zNear, zFar;
private Matrix4f projection;
public Camera(float fov, float aspect, float zNear, float zFar){
this.fov = fov;
this.aspect = aspect;
this.zNear = zNear;
this.zFar = zFar;
projection = createPerspectiveProjection(fov, aspect, zNear, zFar);
position = new Vector3f();
rotation = new Vector3f();
view = new Matrix4f();
view.setIdentity();
xAxis = new Vector3f(1, 0, 0);
yAxis = new Vector3f(0, 1, 0);
zAxis = new Vector3f(0, 0, 1);
}
public void addRotation(float x, float y, float z){
rotation.x += x;
rotation.y += y;
rotation.z += z;
apply();
}
public void move(float x, float y, float z){
position.x += x;
position.y += y;
position.z += z;
apply();
}
public Matrix4f getView(){
return view;
}
public Matrix4f getProjection(){
return projection;
}
private void apply(){
view.setIdentity();
view.rotate(rotation.x, xAxis);
view.rotate(rotation.y, yAxis);
view.rotate(rotation.z, zAxis);
view.translate(position);
}
private Matrix4f createPerspectiveProjection(float fov, float aspect, float zNear, float zFar){
Matrix4f mat = new Matrix4f();
float yScale = (float) (1 / (Math.tan(Math.toRadians(fov / 2))));
float xScale = yScale / aspect;
float frustrumLength = zFar - zNear;
mat.m00 = xScale;
mat.m11 = yScale;
mat.m22 = -((zFar + zNear) / frustrumLength);
mat.m23 = -1;
mat.m32 = -((2 * zFar * zNear) / frustrumLength);
mat.m33 = 0;
return mat;
}
}
public class Game implements Runnable {
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static final DisplayMode dm = new DisplayMode(WIDTH, HEIGHT);
int vaoID;
ShaderProgram program;
Camera camera;
Model model;
public Game(){
new Thread(this).start();
}
public void run(){
init();
while(true){
if(Display.isCloseRequested())
break;
update(Timer.getElapsedTime());
render();
Display.sync(60);
Display.update();
}
Display.destroy();
}
public void init(){
try{
Display.setTitle("Ludum Dare!");
Display.setDisplayMode(dm);
Display.create();
}catch(LWJGLException e){
e.printStackTrace();
System.exit(1);
}
Timer.start();
camera = new Camera(60.0f, WIDTH / HEIGHT, 0.1f, 100.0f);
program = new ShaderProgram("res/shader/defaultshader.vert", "res/shader/defaultshader.frag");
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
model = new Model(new float[] {
-1, -1, 1,
1, -1, 1,
0, 1, 1
});
}
public void update(float delta){
}
public void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program.bind();
program.setUniform("model_matrix", model.getModel());
program.setUniform("view_matrix", camera.getView());
program.setUniform("projection_matrix", camera.getProjection());
model.render();
program.unbind();
}
public static void main(String[] args){
new Game();
}
}
public class ShaderProgram {
private int vertexShaderID, fragmentShaderID;
private int programID;
public ShaderProgram(String vertPath, String fragPath){
programID = glCreateProgram();
vertexShaderID = attachShader(vertPath, GL_VERTEX_SHADER);
fragmentShaderID = attachShader(fragPath, GL_FRAGMENT_SHADER);
link();
}
private int attachShader(String path, int type){
StringBuilder shaderSource = new StringBuilder();
try{
BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
String line;
while((line = reader.readLine()) != null){
shaderSource.append(line).append("\n");
}
reader.close();
}catch(IOException e){
e.printStackTrace();
System.out.println("Error reading from shader " + path);
System.exit(1);
}
System.out.println("Compiling shader " + path);
int id = glCreateShader(type);
glShaderSource(id, shaderSource);
glCompileShader(id);
if(glGetShaderi(id, GL_COMPILE_STATUS) == GL_FALSE){
System.out.println(glGetShaderInfoLog(id, 1000));
System.exit(1);
}
return id;
}
private void link(){
System.out.println("Linking program...");
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
}
public void bind(){
glUseProgram(programID);
}
public void unbind(){
glUseProgram(0);
}
public void setUniform(String name, Matrix4f value){
FloatBuffer matrix = BufferUtils.createFloatBuffer(16);
value.store(matrix); matrix.flip();
glUniformMatrix4(glGetUniformLocation(programID, name), false, matrix);
}
}
当我运行此操作时,我创建的VBO(三角形)不会出现,但当我在顶点着色器中将投影矩阵排除在乘法之外时,它运行得很好。我遗漏了什么吗?我假设
model.getModel()
将返回标识矩阵(就像视图矩阵是标识一样)。在这种情况下,会出现以下情况:在平面z=1.0中绘制一个三角形。如果还将标识用作投影矩阵,则直接在剪辑空间中绘制,并且试验将位于远平面上,因此它是可见的
然而,您的createPerspectiveProjection
函数似乎是按照标准的OpenGL约定编写的,所以它几乎和您的一样。(您的代码缺少该手册页中标记为A和B的部分,因此您只能使用对称的平截头体,但在大多数情况下这是可以的。)
该矩阵使用的约定是,相机正朝-z方向看,并且实际映射了
zNear
和zFar
参数,使得z_eye=-zNear
处的点投影到近平面(z_ndc=-1
),而z_eye=-zFar
处的点投影到远平面(z_ndc=1
)。如果你应用投影矩阵,那么你在z=1处的三角形就在相机后面。你的zNear和zFar值看起来有点奇怪。真不敢相信我没有捕捉到!谢谢!