使用SDL2和OpenGL旋转相机和三角形绘制不会显示任何内容?

时间:2018-12-09 18:28:01

标签: c++ opengl sdl-2 glm-math gl-matrix

我只是想在中心创建一个三角形,然后围绕中心旋转相机。 tmux:4: substring expression: -1 < 0。该代码是从多个教程源中提取的,我怀疑在三角形绘制调用之前问题可能出在(0,0,0)glm::perspective/lookat的某个地方。 因为那是我现在普遍的困惑所在。 任何帮助将不胜感激,因此我可以继续我的生活。预先谢谢你。

gl:projection/model matrix

1 个答案:

答案 0 :(得分:1)

请注意,自几十年来,不赞成使用glBegin / glEnd序列进行绘制以及使用固定功能管线矩阵堆栈。 阅读有关mobile的信息,并参阅Fixed Function PipelineVertex Specification了解最新的渲染方式。

如果要使用不赞成使用的绘图方式,则必须使用兼容性配置文件上下文而不是核心配置文件上下文(请参阅Shader):

SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);


还要注意,OpenGL Contextglm::lookAt不会设置任何OpenGL状态,甚至不会设置固定功能的点线矩阵。 glm::perspective是一个数学库,用于进行与OpenGL相关的计算。这两个函数都返回4 * 4矩阵。

您可以使用glm - OpenGL Mathematics glm 函数的矩阵返回值加载到OpenGL固定函数管道矩阵堆栈:

#include <glm/glm.hpp>
#include "glm/gtc/matrix_transform.hpp"
#include <glm/gtc/type_ptr.hpp>
void Calculate()
{
    float radius = 2.0f;
    float camX = sin(SDL_GetTicks()*0.001) * radius;
    float camZ = cos(SDL_GetTicks()*0.001) * radius;

    glm::mat4 perspecive_mat = glm::perspective(
        45.0f, 1.0f / 1.0f, 0.1f, 100.0f );

    glm::mat4 view_mat = glm::lookAt(
        glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0) );

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(glm::value_ptr(perspecive_mat));

    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(glm::value_ptr(view_mat));
}

如果要使用核心配置文件,则必须创建一个简单的glLoadMatrixf程序:

#include <string>

std::string sh_vert = R"(
#version 150 core

in vec3 v_pos;
in vec4 v_col;

out vec4 color;

uniform mat4 projection;
uniform mat4 view;

void main()
{
    color = v_col;                    
    gl_Position = projection * view * vec4(v_pos, 1.0);
} 
)";

std::string sh_frag = R"(
#version 150 core

in vec4 color;

void main()
{
    gl_FragColor = color;
} 
)";

编译并链接程序:

#include <vector>

GLuint CreateShader(GLenum type, const char *code)
{
    GLuint shaderObj = glCreateShader(type);
    glShaderSource(shaderObj, 1, &code, nullptr);
    glCompileShader(shaderObj);

    GLint status = GL_TRUE;
    glGetShaderiv(shaderObj, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint logLen;
        glGetShaderiv(shaderObj, GL_INFO_LOG_LENGTH, &logLen);
        std::vector< char >log(logLen);
        GLsizei written;
        glGetShaderInfoLog(shaderObj, logLen, &written, log.data());
        std::cout << "compile error:" << std::endl << log.data() << std::endl;
    }
    return shaderObj;
}

GLuint CreateProgram()
{
    GLuint vShObj = CreateShader(GL_VERTEX_SHADER, sh_vert.c_str());
    GLuint fShObj = CreateShader(GL_FRAGMENT_SHADER, sh_frag.c_str());

    GLuint progObj = glCreateProgram();
    glAttachShader(progObj, vShObj);
    glAttachShader(progObj, fShObj);
    glLinkProgram(progObj);

    GLint status = GL_TRUE;
    glGetProgramiv(progObj, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint logLen;
        glGetProgramiv(progObj, GL_INFO_LOG_LENGTH, &logLen);
        std::vector< char >log(logLen);
        GLsizei written;
        glGetProgramInfoLog(progObj, logLen, &written, log.data());
        std::cout << "link error:" << std::endl << log.data() << std::endl;
    }
    return progObj;
}

获取属性和统一位置:

GLuint prog;
GLint pos_attr, col_attr, proj_loc, view_loc;

void Init()
{
    prog = CreateProgram();
    pos_attr = glGetAttribLocation(prog, "v_pos");
    col_attr = glGetAttribLocation(prog, "v_col");
    proj_loc = glGetUniformLocation(prog, "projection");
    view_loc = glGetUniformLocation(prog, "view");

    // ....

 }

创建一个Shader

GLuint vao;

void Init()
{
    // ....

    const std::vector<float> varray
    {
    // x      y     z     red   green blue
      -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f,
       0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
       0.0f,  0.5f, 0.0f, 0.0f, 0.0f, 1.0f
    };

    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, varray.size()*sizeof(float), varray.data(), GL_STATIC_DRAW);

    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glVertexAttribPointer(pos_attr, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), 0);
    glEnableVertexAttribArray(pos_attr);
    glVertexAttribPointer(col_attr, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float)));
    glEnableVertexAttribArray(col_attr);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

将程序对象安装为当前渲染状态的一部分,并设置统一变量:

void Calculate()
{
    float radius = 2.0f;
    float camX = sin(SDL_GetTicks()*0.001) * radius;
    float camZ = cos(SDL_GetTicks()*0.001) * radius;

    glm::mat4 perspecive_mat = glm::perspective(
        45.0f, 1.0f / 1.0f, 0.1f, 100.0f );

    glm::mat4 view_mat = glm::lookAt(
        glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0) );

    glUseProgram(prog);
    glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(perspecive_mat));
    glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(view_mat));
}

最后绘制三角形:

void Render()
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);

    SDL_GL_SwapWindow(mainWindow);
}

bool Loop()
{
    Init();

    while (true) {
        // ....

        Calculate();
        Render();
    }
}