OpenGL正射投影被破坏
Posted
技术标签:
【中文标题】OpenGL正射投影被破坏【英文标题】:OpenGL ortho projection is broken 【发布时间】:2019-01-20 17:36:08 【问题描述】:所以我只是在我的渲染中添加了正射投影,一切都停止了渲染......如果我删除它,它会再次工作。这是我的矩阵代码:
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
matrix4x4 init_matrix4x4()
matrix4x4 m = calloc(16, sizeof(float));
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
return m;
void translate_matrix4x4(matrix4x4* matrix, float x, float y, float z)
matrix4x4 m = (*matrix);
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
void ortho_matrix4x4(matrix4x4* matrix, float left, float right, float bottom, float top, float near, float far)
matrix4x4 m = (*matrix);
m[0] = 2 / (right-left);
m[1] = 0;
m[2] = 0;
m[3] = 0;
m[4] = 0;
m[5] = 2 / (top - bottom);
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = 1 / (far - near);
m[11] = 0;
m[12] = (left + right) / (left - right);
m[13] = (top + bottom) / (bottom - top);
m[14] = near / (near - far);
m[15] = 1;
void mat4_identity(matrix4x4* matrix)
matrix4x4 out = (*matrix);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
void mat4_lookAtf(matrix4x4* matrix, float eye[3], float center[3], float up[3])
matrix4x4 out = (*matrix);
float x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2],
centerx = center[0],
centery = center[1],
centerz = center[2];
if (fabs(eyex - centerx) < 0.000001 &&
fabs(eyey - centery) < 0.000001 &&
fabs(eyez - centerz) < 0.000001)
mat4_identity(&out);
return;
z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;
len = 1 / sqrt/*f*/(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len)
x0 = 0;
x1 = 0;
x2 = 0;
else
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len)
y0 = 0;
y1 = 0;
y2 = 0;
else
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;
;
这里是 main.c
,我渲染的地方:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include "include/matrix.h"
#include "include/io.h"
const int WIDTH = 640;
const int HEIGHT = 480;
// called when user resizes window
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
glViewport(0, 0, width, height);
// called when we receive input
void processInput(GLFWwindow *window)
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, 1);
GLuint get_checker_texture()
unsigned char texDat[64];
for (int i = 0; i < 64; ++i)
texDat[i] = ((i + (i / 8)) % 2) * 128 + 127;
//upload to GPU texture
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, texDat);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
return tex;
//void render_box(renderable* this, unsigned int vbo, unsigned int vao, unsigned int ebo)
// draw_texture(this->texture, this->x, this->y, this->z, vbo, vao, ebo);
//
int main(int argc, char* argv[])
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // only on MACOS
#endif
// creating the window
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL App", NULL, NULL);
if (window == NULL)
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
glfwMakeContextCurrent(window);
// hook on window resize
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
printf("Failed to initialize GLAD");
return -1;
printf("OpenGL %d.%d\n", GLVersion.major, GLVersion.minor);
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, WIDTH, HEIGHT);
unsigned int tex = get_checker_texture();
const char* vertex_shader_src = read_file("res/shaders/textured_and_positioned.vs.glsl");
unsigned int vertex_shader;
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL);
glCompileShader(vertex_shader);
int success;
char infoLog[512];
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success)
glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
printf("%s\n", infoLog);
const char* fragment_shader_src = read_file("res/shaders/textured_and_positioned.fs.glsl");
unsigned int fragment_shader;
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL);
glCompileShader(fragment_shader);
int success0;
char infoLog0[512];
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success0);
if (!success0)
glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog0);
printf("%s\n", infoLog0);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertex_shader);
glAttachShader(shaderProgram, fragment_shader);
glLinkProgram(shaderProgram);
unsigned uniform_sampler_ourTexture = glGetUniformLocation(shaderProgram, "ourTexture");
unsigned uniform_mat4_model = glGetUniformLocation(shaderProgram, "model");
unsigned uniform_mat4_view = glGetUniformLocation(shaderProgram, "view");
unsigned uniform_mat4_perspective = glGetUniformLocation(shaderProgram, "perspective");
int success1;
char infoLog1[512];
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success1);
if(!success1)
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog1);
printf("%s\n", infoLog1);
float vertices[] =
// positions // colors // texture coords
0.1f, 0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.1f, -0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.1f, -0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.1f, 0.1f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0 // top left
;
unsigned elements[] =
0, 1, 2, // triangle
2, 3, 0 // triangle
;
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
matrix4x4 model = init_matrix4x4();
matrix4x4 view = init_matrix4x4();
translate_matrix4x4(&view, 0.0f, 0.0f, 0.0f);
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
matrix4x4 perspective = calloc(16, sizeof(float));
ortho_matrix4x4(&perspective, 0.0f, 640.0f, 0.0f, 480.0f, 0.1f, 100.0f);
unsigned int vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(0 * sizeof(float)));
glEnableVertexAttribArray(0);
// colors
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coords
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
unsigned int ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glUseProgram(shaderProgram);
glUniformMatrix4fv(uniform_mat4_view, 1, GL_FALSE, view);
glUniformMatrix4fv(uniform_mat4_perspective, 1, GL_FALSE, perspective);
// render loop
while(!glfwWindowShouldClose(window))
processInput(window);
// render here
glClearColor(
0, 0, 0, 0
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(uniform_sampler_ourTexture, 0);
translate_matrix4x4(&model, x, y, z);
glUniformMatrix4fv(uniform_mat4_model, 1, GL_FALSE, model);
//x += 0.0001f;
//y += 0.0001f;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
glfwTerminate();
return 0;
这是顶点着色器:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 perspective;
out vec3 ourColor;
out vec2 TexCoord;
void main()
gl_Position = perspective * view * model * vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
这是片段着色器:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
FragColor = vec4(vec3(texture(ourTexture, TexCoord).r), 1.);
现在,如果我从着色器(即正交矩阵)中删除 perspective
值,则方格纹理将按应有的方式渲染。
这里有什么问题?
是我的着色器还是矩阵正交函数?
【问题讨论】:
m[10]
看起来很可疑 - glOrtho
矩阵不应该是 -2 / (F - N)
吗?弄错 Z 的符号会让一切都“看不见”。
【参考方案1】:
您的矩阵存储在行优先中,将它们提交给制服而不进行转置,并在着色器中进行左关联计算。
你可以
按列主要顺序存储或
加载到制服时转置或
在着色器中切换到左关联乘法每个效果都一样。
【讨论】:
以上是关于OpenGL正射投影被破坏的主要内容,如果未能解决你的问题,请参考以下文章