我到处寻找同样的问题,所有解决方案都无法正常工作。如果我拿出我的投影/透视矩阵,它会呈现正确的,但是当我把它放入时,它会混乱起来。我似乎无法找到它。另外,我正在使用JOML 1.9.9。
创建投影矩阵
public static Matrix4f createProjectionMatrix(float fov, float width, float height, float zNear, float zFar) {
float aspectRatio = width / height;
float yScale = (float) ((1f / Math.tan(Math.toRadians(fov / 2f))) * aspectRatio);
float xScale = yScale / aspectRatio;
float frustumLength = zFar - zNear;
Matrix4f projectionMatrix = new Matrix4f();
projectionMatrix.m00(xScale);
projectionMatrix.m11(yScale);
projectionMatrix.m22(-((zFar + zNear) / frustumLength));
projectionMatrix.m32(-1);
projectionMatrix.m23(-((2 * zFar * zNear) / frustumLength));
projectionMatrix.m33(0);
return projectionMatrix;
}
着色器类
package engine.shaders;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.FloatBuffer;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
public abstract class Shader {
private int programID, vertexShaderID, fragmentShaderID;
private String vertexFile, fragmentFile;
public Shader(String vertexFile, String fragmentFile){
this.vertexFile = vertexFile;
this.fragmentFile = fragmentFile;
}
public void create() {
vertexShaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(vertexShaderID, readFile(vertexFile));
GL20.glCompileShader(vertexShaderID);
if (GL20.glGetShaderi(vertexShaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE){
System.err.println("Error: Vertex Shader - " + GL20.glGetShaderInfoLog(vertexShaderID));
System.exit(-1);
}
fragmentShaderID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
GL20.glShaderSource(fragmentShaderID, readFile(fragmentFile));
GL20.glCompileShader(fragmentShaderID);
if (GL20.glGetShaderi(fragmentShaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE){
System.err.println("Error: Fragment Shader - " + GL20.glGetShaderInfoLog(fragmentShaderID));
System.exit(-1);
}
programID = GL20.glCreateProgram();
GL20.glAttachShader(programID, vertexShaderID);
GL20.glAttachShader(programID, fragmentShaderID);
bindAttributes();
GL20.glLinkProgram(programID);
if (GL20.glGetProgrami(programID, GL20.GL_LINK_STATUS) == GL11.GL_FALSE){
System.err.println("Error: Program Linking - " + GL20.glGetProgramInfoLog(programID));
System.exit(-1);
}
GL20.glValidateProgram(programID);
if (GL20.glGetProgrami(programID, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE){
System.err.println("Error: Program Validating - " + GL20.glGetProgramInfoLog(programID));
System.exit(-1);
}
}
public void bind() {
GL20.glUseProgram(programID);
}
public void remove() {
GL20.glUseProgram(0);
GL20.glDetachShader(programID, vertexShaderID);
GL20.glDetachShader(programID, fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
GL20.glDeleteProgram(programID);
}
protected abstract void bindAttributes();
protected void bindAttribute(int attribute, String variableName) {
GL20.glBindAttribLocation(programID, attribute, variableName);
}
protected abstract void getAllUniforms();
protected int getUniform(String name) {
return GL20.glGetUniformLocation(programID, name);
}
protected void loadFloatUniform(int location, float value) {
GL20.glUniform1f(location, value);
}
protected void loadIntUniform(int location, int value) {
GL20.glUniform1i(location, value);
}
protected void loadVectorUniform(int location, Vector3f value) {
GL20.glUniform3f(location, value.x, value.y, value.z);
}
protected void loadMatrixUniform(int location, Matrix4f value) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
value.get(buffer);
GL20.glUniformMatrix4fv(location, false, buffer);
}
private String readFile(String file) {
StringBuilder string = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null){
string.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
System.err.println("Error: Couldn't find file");
System.exit(-1);
}
return string.toString();
}
}
导入矩阵
package engine.shaders;
import org.joml.Matrix4f;
public class BasicShader extends Shader {
private static final String VERTEX_FILE = "src/engine/shaders/basicVertexShader.glsl";
private static final String FRAGMENT_FILE = "src/engine/shaders/basicFragmentShader.glsl";
private int transformationLocation, projectionLocation;
public BasicShader() {
super(VERTEX_FILE, FRAGMENT_FILE);
}
@Override
protected void bindAttributes() {
super.bindAttribute(0, "position");
super.bindAttribute(1, "textCoords");
}
@Override
protected void getAllUniforms() {
transformationLocation = super.getUniform("transformation");
projectionLocation = super.getUniform("projection");
}
public void loadTransformationMatrix(Matrix4f matrix) {
super.loadMatrixUniform(transformationLocation, matrix);
}
public void loadProjectionMatrix(Matrix4f matrix) {
super.loadMatrixUniform(projectionLocation, matrix);
}
}
渲染器类
package engine.rendering;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import engine.maths.MatrixMaths;
import engine.rendering.models.ModelEntity;
import engine.rendering.models.TexturedModel;
import engine.rendering.models.UntexturedModel;
import engine.shaders.BasicShader;
public class Renderer {
private BasicShader shader;
public Renderer(BasicShader shader) {
this.shader = shader;
shader.create();
shader.bind();
shader.loadProjectionMatrix(MatrixMaths.createProjectionMatrix(70.0f, 800.0f, 600.0f, 0.01f, 1000.0f));
}
public void renderModel(UntexturedModel model){
GL30.glBindVertexArray(model.getVertexArrayID());
GL20.glEnableVertexAttribArray(0);
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
public void renderTexturedModel(TexturedModel model){
GL30.glBindVertexArray(model.getVertexArrayID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getMaterial().getTextureID());
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL30.glBindVertexArray(0);
}
public void renderModelEntity(ModelEntity entity){
GL30.glBindVertexArray(entity.getModel().getVertexArrayID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
shader.loadTransformationMatrix(entity.getTransformationMatrix());
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, entity.getModel().getMaterial().getTextureID());
GL11.glDrawElements(GL11.GL_TRIANGLES, entity.getModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL30.glBindVertexArray(0);
}
}
顶点着色器
#version 150
in vec3 position;
in vec2 textCoords;
out vec2 passTextCoords;
uniform mat4 transformation;
uniform mat4 projection;
void main(void) {
vec4 worldPos = transformation * vec4(position, 1.0);
gl_Position = projection * worldPos;
passTextCoords = textCoords;
}
发布于 2018-06-12 10:54:17
设置一个列 - 主要顺序矩阵。有三种可能的解决方案:
无论是m23
和m32
必须交换:
Matrix4f projectionMatrix = new Matrix4f();
projectionMatrix.m00(xScale);
projectionMatrix.m11(yScale);
projectionMatrix.m22(-((zFar + zNear) / frustumLength));
projectionMatrix.m32(-((2 * zFar * zNear) / frustumLength));
projectionMatrix.m23(-1);
projectionMatrix.m33(0);
或者矩阵必须在设置时转置:
GL20.glUniformMatrix4fv(location, true, buffer); // focus on "true"
当然,也可以在顶点着色器中将向量从左边乘以矩阵,因为将左边的向量乘以矩阵对应于将它从右边乘以转置矩阵:
gl_Position = worldPos * projection;
要通过指定向量或标量来初始化矩阵,这些分量将按列 - 主次序分配给矩阵元素。
mat4(float, float, float, float, // first column float, float, float, float, // second column float, float, float, float, // third column float, float, float, float); // fourth column
请注意,相比之下,一般的数学矩阵以行优先顺序表示。如果一个矩阵以列为主,那么轴或转换的x,y,z分量直接在存储器中连续存在。访问轴向量或矩阵的平移向量时,这是一个很大的优势。
这意味着一个OpenGL的persepctive投影矩阵看起来像这样:
r = right, l = left, b = bottom, t = top, n = near, f = far
2*n/(r-l) 0 0 0
0 2*n/(t-b) 0 0
(r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1
0 0 -2*f*n/(f-n) 0
其中:
a = w / h
ta = tan( fov_y / 2 );
2 * n / (r-l) = 1 / (ta * a)
2 * n / (t-b) = 1 / ta
如果投影是对称的,那么视线是对称轴的平截头体,那么可以简化矩阵:
1/(ta*a) 0 0 0
0 1/ta 0 0
0 0 -(f+n)/(f-n) -1
0 0 -2*f*n/(f-n) 0
https://stackoverflow.com/questions/-100001666
复制相似问题