首页 文章

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

提问于
浏览
1

我只是想在中心创建一个三角形并围绕中心旋转相机 . (0,0,0) . 代码是从多个教程源中发出的,我怀疑问题可能出现在 glm::perspective/lookatgl:projection/model matrix 之前的三角绘制调用之前 . 因为那是我现在普遍困惑的地方 . 非常感谢任何帮助,所以我可以继续我的生活 . 先感谢您 .

//sudo g++ -o sdl main.cpp -lSDL2_image -lGL -lGLU -lglut -lX11 -lGLEW `sdl2-config --cflags --libs`
#include <iostream>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include "glm/gtc/matrix_transform.hpp"
#include <glm/gtc/type_ptr.hpp>
#include <SDL2/SDL.h>
#include <string>
#include <GL/gl.h>



std::string programName = "SDL2/OpenGL";
SDL_Window *mainWindow;
SDL_GLContext mainContext;

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));
}


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

    float vertexCoords[24] = {  // Coordinates for the vertices of a cube.
               1,1,1,   1,1,-1,   1,-1,-1,   1,-1,1,
              -1,1,1,  -1,1,-1,  -1,-1,-1,  -1,-1,1  };

    float vertexColors[24] = {  // An RGB color value for each vertex
               1,1,1,   1,0,0,   1,1,0,   0,1,0,
               0,0,1,   1,0,1,   0,0,0,   0,1,1  };

    int elementArray[24] = {  // Vertex numbers for the six faces.
              0,1,2,3, 0,3,7,4, 0,4,5,1,
              6,2,1,5, 6,5,4,7, 6,7,3,2  };

    glVertexPointer( 3, GL_FLOAT, 0, vertexCoords );
    glColorPointer( 3, GL_FLOAT, 0, vertexColors );

    glEnableClientState( GL_VERTEX_ARRAY );
    glEnableClientState( GL_COLOR_ARRAY );

    glDrawElements( GL_QUADS, 24, GL_UNSIGNED_INT, elementArray );


    SDL_GL_SwapWindow(mainWindow);
}

bool Loop()
{
    while (true ){
        SDL_Event event;
        while ( SDL_PollEvent( &event ) ){
            switch ( event.type ){
                case SDL_QUIT :
                SDL_Quit();
                return 0;
                case SDL_KEYDOWN : 
                    std::cout<<"Key Down"<<std::endl;
                    break;
                case SDL_KEYUP :
                    std::cout<<"Key Up"<<std::endl;
                    break;
                case SDL_MOUSEBUTTONDOWN :
                case SDL_MOUSEBUTTONUP :
                case SDL_MOUSEMOTION :
                default :
                    break;
            }
        }

        Calculate();

        Render();
    }
}


void CheckSDLError(int line = -1){
    std::string error = SDL_GetError();

    if (error != "")
    {
        std::cout << "SLD Error : " << error << std::endl;

        if (line != -1)
            std::cout << "\nLine : " << line << std::endl;

        SDL_ClearError();
    }
}


void Cleanup(){
    SDL_GL_DeleteContext(mainContext);
    SDL_DestroyWindow(mainWindow );
    SDL_Quit();
}

int main(int argc, char *argv[]){
    if (SDL_Init(SDL_INIT_VIDEO) < 0){
        std::cout << "Failed to init SDL\n";
        return false;
    }
    mainWindow = SDL_CreateWindow(programName.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
    if (!mainWindow )
    {
        std::cout << "Unable to create window\n"<< std::endl;;
        CheckSDLError(__LINE__);
        return false;
    }

    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);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    mainContext = SDL_GL_CreateContext(mainWindow );

    // This makes our buffer swap syncronized with the monitor's vertical refresh
    //      ( which means it enables v-sync)
    // Setting this to 0 will disable V-sync
    //      Which means our application could run at unlimited fps
    SDL_GL_SetSwapInterval(1);
    // Init GLEW
    glewExperimental = GL_TRUE; 
    glewInit();
    // Enable blending so that we can have transparanet object
    glEnable(GL_BLEND ) ;
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    // Enable depth testing so that closer triangles will hide the triangles farther away
    glEnable( GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    Loop();
    Cleanup();

    return 0;
}

1 回答

  • 1

    请注意, glBegin / glEnd 序列和固定功能管道矩阵堆栈的绘制几十年来已被弃用 . 阅读Fixed Function Pipeline并查看Vertex SpecificationShader以了解最先进的渲染方式 .

    如果要使用不推荐使用的绘制方式,则必须使用兼容性配置文件上下文而不是核心配置文件上下文(请参阅OpenGL Context):

    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);


    进一步注意,glm::lookAt和[ glm::perspective ]不设置任何OpenGL状态甚至固定函数pipline矩阵 . glm - OpenGL Mathematics是一个数学库,用于执行与OpenGL相关的计算 . 两个函数都返回一个4 * 4矩阵 .

    您可以使用glLoadMatrixf将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));
    }
    

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

    #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");
    
        // ....
    
     }
    

    创建一个Vertex Array Object

    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();
        }
    }
    

相关问题