OpenGL中的透视投影矩阵

时间:2014-08-17 16:51:34

标签: c opengl matrix perspectivecamera

我一直在研究来自open.gl的转换教程,并且无法使我的透视投影矩阵工作。本教程使用了GLM,但我选择使用自己的矩阵数学函数来尝试更好地学习数学。一切都编译得很好(gcc-Wall),我的旋转和外观矩阵函数工作得很好,但我的透视投影矩阵导致黑屏没有OpenGL错误。

投影矩阵(我认为)应该是

/ cot(fovy/2)/aspect 0.0         0.0                                0.0 \
| 0.0                cot(fovy/2) 0.0                                0.0 |
| 0.0                0.0         (zfar + znear)/(znear - zfar)     -1.0 |
\ 0.0                0.0         (2 * zfar * znear)/(znear - zfar)  0.0 /

有趣的是,我可以用矩阵

提供预期的效果
/ cot(fovy/2)/aspect 0.0         0.0                            0.0 \
| 0.0                cot(fovy/2) 0.0                            0.0 |
| 0.0                0.0         (zfar + znear)/(znear - zfar) -1.0 |
\ 0.0                0.0         0.4                            1.0 /

Here are the necessary source files.您需要GLFW3和SOIL来编译代码 - 我一直在使用gcc -Wall -Werror -std=c99 -lGL -lGLEW -lglfw -lm -lSOIL transform.c -o transform。我已经尝试在下面提供更短(非编译)的源代码,以防有任何明显的错误。

transform.c:

#include <math.h>
#define M_PI (3.14159265358979323846)

#include <stdio.h>
#include <stdlib.h>

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <SOIL/SOIL.h>

typedef struct mat4_t {
    float arr[16];
} mat4_t;

typedef struct vec3_t {
    float arr[3];
} vec3_t;

/* forward declarations... */

/* return a 4x4 'lookat' matrix to be multiplied by model space coords        */
mat4_t mat4mklook(const vec3_t eye, const vec3_t center, const vec3_t up) {
    /* check out the OpenGL gluLookAt documentation for an explanation */
    vec3_t f = vec3norm(vec3sub(center, eye));
    vec3_t up_ = vec3norm(up);
    vec3_t s = vec3cross(f, up_);
    vec3_t u = vec3cross(s, f);

    return (mat4_t) { { 
        s.arr[0],  s.arr[1],  s.arr[2], 0.0f,
        u.arr[0],  u.arr[1],  u.arr[2], 0.0f,
       -f.arr[0], -f.arr[1], -f.arr[2], 0.0f,
        0.0f,      0.0f,      0.0f,     1.0f
    } };
}

/* return a 4x4 persp. projection matrix to be multiplied by camera coords    */
mat4_t mat4mkproj(const float fovy, const float aspect, const float znear, const float zfar) {
    float f = 1 / tan(fovy / 2.0f);

    return (mat4_t){ {
        f/aspect, 0.0f,  0.0f,                      0.0f,
        0.0f,     f,     0.0f,                      0.0f,
        0.0f,     0.0f,  (zfar+znear)/(znear-zfar), (2*zfar*znear)/(znear-zfar),
        0.0f,     0.0f, -1.0f,                      0.0f
    } };
}

/* returns a 4x4 rotation matrix of magnitude 'th' about unit vector 'axis'   */
mat4_t mat4mkrot(const vec3_t axis, const float th) {
    const float uX = axis.arr[0];
    const float uY = axis.arr[1];
    const float uZ = axis.arr[2];
    const float sinth = sin(th);
    const float costh = cos(th);

    return (mat4_t) { {
        costh+pow(uX,2)*(1-costh), uX*uY*(1-costh)-uZ*sinth,  uX*uZ*(1-costh)+uY*sinth,  0.0,
        uY*uX*(1-costh)+uZ*sinth,  costh+pow(uY,2)*(1-costh), uY*uZ*(1-costh)-uX*sinth,  0.0,
        uZ*uX*(1-costh)-uY*sinth,  uZ*uY*(1-costh)+uX*sinth,  costh+pow(uZ,2)*(1-costh), 0.0,
        0.0,                       0.0,                       0.0,                       1.0
    } };
}

/* returns the product of matrices 'a' and 'b'                                */
mat4_t mat4mult(const mat4_t a, const mat4_t b) {
    mat4_t result;
    for(int i = 0; i < 16; ++i) {
        result.arr[i] = 0.0f;
        for(int j = 0; j < 4; ++j) {
            result.arr[i] += a.arr[i / 4 + j] * b.arr[i % 4 + j * 4];
        }
    }
    return result;
}

/* returns the cross product of vectors 'a' and 'b'                           */
vec3_t vec3cross(const vec3_t a, const vec3_t b) {
    return (vec3_t){ {
        a.arr[1] * b.arr[2] - a.arr[2] * b.arr[1],
        a.arr[2] * b.arr[0] - a.arr[0] * b.arr[2],
        a.arr[0] * b.arr[1] - a.arr[1] * b.arr[0]
    } };
}

/* returns a unit vector derived from vector 'v'                              */
vec3_t vec3norm(const vec3_t a) {
    vec3_t result;

    float mag;
    if((mag = sqrt(pow(a.arr[0], 2) + pow(a.arr[1], 2) + pow(a.arr[2], 2))) == 0.0f) {
        result = (vec3_t) {{0}};
    } else {
        for(int i = 0; i < 3; ++i) {
            result.arr[i] = a.arr[i] / mag;
        }
    }
    return result;
}

/* return the vector difference 'a' - 'b'                                     */
vec3_t vec3sub(const vec3_t a, const vec3_t b) {
    vec3_t result;
    for(int i = 0; i < 3; ++i) {
        result.arr[i] = a.arr[i] - b.arr[i];
    }
    return result;
}

/* returns the dot product of vectors 'a' and 'b'                             */
float vec3dot(const vec3_t a, const vec3_t b) {
    return a.arr[0] * b.arr[0] +
           a.arr[1] * b.arr[1] +
           a.arr[2] * b.arr[2];
}

GLfloat vertices[] = {
  /* position       texture */
    -0.5f,  0.5f,   0.0f, 0.0f,
     0.5f,  0.5f,   1.0f, 0.0f,
     0.5f, -0.5f,   1.0f, 1.0f,
    -0.5f, -0.5f,   0.0f, 1.0f
};

GLuint elements[] = {
    0, 1, 2,
    2, 3, 0
};

int main() {
    glfwInit();

    /* context settings */

    /* window & context creation */
    GLFWwindow * const window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
    glfwMakeContextCurrent(window);

    /* glew initialization -- generates harmless error */
    glewExperimental = GL_TRUE;
    glewInit();
    glGetError();

    /* vertex setup */

    /* shader setup */

    /* vertex attribute setup */

    /* texture setup */

    GLint modeluni;
    { /* matrix uniform setup */
        modeluni = glGetUniformLocation(shaderProgram, "model");

        mat4_t viewmat = mat4mklook((vec3_t){{1.2f, 1.2f, 1.2f}}, (vec3_t){{0.0f, 0.0f, 0.0f}}, (vec3_t){{0.0f, 0.0f, 1.0f}});
        GLint viewuni = glGetUniformLocation(shaderProgram, "view");
        glUniformMatrix4fv(viewuni, 1, GL_TRUE, viewmat.arr);

        mat4_t projmat = mat4mkproj(M_PI / 4.0f, 800.0f / 600.0f, 1.0f, 10.0f);
        GLint projuni = glGetUniformLocation(shaderProgram, "proj");
        glUniformMatrix4fv(projuni, 1, GL_TRUE, projmat.arr);
    }

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    while(!glfwWindowShouldClose(window)) {
        const GLuint error = glGetError();
        if(error) {
            fprintf(stderr, "%d\n", error);
        }

        glClear(GL_COLOR_BUFFER_BIT); 

        mat4_t modmat = mat4mkrot((vec3_t){{0.0f, 0.0f, 1.0f}}, (glfwGetTime() / 2.0) * M_PI);
        glUniformMatrix4fv(modeluni, 1, GL_TRUE, modmat.arr);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 

        glfwSwapBuffers(window); 
        glfwPollEvents();
    }

    /* delete opengl ids */

    glfwTerminate();
    return 0;
}

vert.glsl:

#version 330

in vec2 position;
in vec3 color;
in vec2 texcoord;

out vec3 Color;
out vec2 Texcoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;

void main() {
    Color = color;
    Texcoord = texcoord;
    gl_Position = proj * view * model * vec4(position.x, position.y, 0.0, 1.0);
}

frag.glsl:

#version 330

in vec3 Color;
in vec2 Texcoord;

out vec4 outColor;

uniform sampler2D texKitten;
uniform sampler2D texPuppy;

void main() {
    vec4 colKitten = texture(texKitten, Texcoord);
    vec4 colPuppy = texture(texPuppy, Texcoord);
    outColor = mix(colKitten, colPuppy, 0.5);
}

0 个答案:

没有答案