首页 文章

现代OpenGL SDL2三角形没有出现

提问于
浏览
1

我目前正在尝试学习如何在使用SDL2花费一些时间后在C中使用OpenGL,并且我正努力让我的三角形显示在屏幕上 . 我一直在学习一系列教程,并试图深入了解一切是如何运作的 . 我成功地将一个简单的纯色三角形显示在屏幕上,但是当我尝试给每个顶点一个不同的颜色时,除了背景之外没有任何颜色显示出来 .

#include <iostream>
#include <string>

#include <GL/glew.h>
#include <GL/GLU.h>
#include <SDL.h>
#include <SDL_opengl.h>

//***************************************************************************
// The Width of the screen
//***************************************************************************
const GLuint SCREEN_WIDTH = 800;

//***************************************************************************
// The height of the screen
//***************************************************************************
const GLuint SCREEN_HEIGHT = 600;

bool success = GL_TRUE;

const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"layout (location = 1) in vec3 color;\n"
"out vec3 ourColor;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position, 1.0);\n"
"ourColor = color;\n"
"}\0";

const GLchar* fragmentShaderSource = "#version 330 core\n"
"in vec3 ourColor;\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(ourColor, 1.0f);\n"
"}\n\0";

bool quit;

int main(int argc, char *argv[])
{
    //***********************************************************************
    // Initialize SDL
    //***********************************************************************
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        std::cout << "SDL could not initialize!SDL Error :" <<
            std::string(SDL_GetError());

        return EXIT_FAILURE;
    }
    else
    {
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
            SDL_GL_CONTEXT_PROFILE_CORE);

        SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

        //*******************************************************************
        //The window we'll be rendering to
        //*******************************************************************
        SDL_Window *window = SDL_CreateWindow("Triangle",
            SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
            SCREEN_HEIGHT, SDL_WINDOW_SHOWN |
            SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

        if (window == NULL)
        {
            std::cout << "Window could not be created!SDL_Error: " <<
                std::string(SDL_GetError()) << std::endl;

            return EXIT_FAILURE;
        }

        //*******************************************************************
        //OpenGL context
        //*******************************************************************
        SDL_GLContext context = SDL_GL_CreateContext(window);

        //*******************************************************************
        // Set the required callback functions
        //*******************************************************************
        SDL_Event windowEvent;

        //*******************************************************************
        //Use OpenGL 3.3
        //*******************************************************************

        //*******************************************************************
        // Set this to true so GLEW knows to use a modern approach to 
        // retrieving function pointers and extensions
        //*******************************************************************
        glewExperimental = GL_TRUE;

        //*******************************************************************
        // Initialize GLEW to setup the OpenGL Function pointers
        //*******************************************************************
        GLenum glewError = glewInit();
        if (GLEW_OK != glewError)
        {
            std::cout << "Failed to initialize GLEW: " << 
                glewGetErrorString(glewError) << std::endl;

            return EXIT_FAILURE;
        }

        glEnable(GL_CULL_FACE);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


        //*******************************************************************
        // Build and compile our shader program
        // Vertex shader
        //*******************************************************************
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
        glCompileShader(vertexShader);

        //*******************************************************************
        // Check for compile time errors
        //*******************************************************************
        GLint success;
        GLchar infoLog[512];
        glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED: " << 
                infoLog << std::endl;
        }

        //*******************************************************************
        // Fragment shader
        //*******************************************************************
        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
        glCompileShader(fragmentShader);

        //*******************************************************************
        // Check for compile time errors
        //*******************************************************************
        glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED: " << 
                infoLog << std::endl;
        }

        //*******************************************************************
        // Link shaders
        //*******************************************************************
        GLuint shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
        glLinkProgram(shaderProgram);

        //*******************************************************************
        // Check for linking errors
        //*******************************************************************
        glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED: " << infoLog << std::endl;
        }
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);

        //*******************************************************************
        // Set up vertex data (and buffer(s)) and attribute pointers
        //*******************************************************************
        GLfloat vertices[] = {
            // Positions            // Colors
            0.5f, -0.5f, 0.0f,      1.0f, 0.0f, 0.0f,  // Bottom Right
            -0.5f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f,  // Bottom Left
            0.0f, 0.5f, 0.0f,       0.0f, 0.0f, 1.0f // Top
        };

        GLfloat colors[] = {
            1.0f, 0.0f, 0.0f, 1.0f,
            0.0f, 1.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f, 1.0f
        };

        GLuint VBO, VAO;
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);

        //*******************************************************************
        // Bind the Vertex Array Object first, then bind and set vertex 
        // buffer(s) and attribute pointer(s).
        //*******************************************************************
        glBindVertexArray(VAO);

        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        // Position attribute
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
        glEnableVertexAttribArray(0);
        // Color attribute
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)(3 * sizeof(GLfloat)));
        glEnableVertexAttribArray(1);

        //*******************************************************************
        // Note that this is allowed, the call to glVertexAttribPointer 
        // registered VBO as the currently bound vertex buffer object so 
        // afterwards we can safely unbind
        //*******************************************************************
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        //*******************************************************************
        // Unbind VAO (it's always a good thing to unbind any buffer/array to
        // prevent strange bugs)
        //*******************************************************************
        glBindVertexArray(0);

        //*******************************************************************
        // DeltaTime variables
        //*******************************************************************
        GLdouble deltaTime = 0.0f;
        Uint64 lastFrame = 0L;
        Uint64 currentFrame = SDL_GetPerformanceCounter();

        quit = false;

        while (!quit)
        {
            //***************************************************************
            // Calculate delta time
            //***************************************************************
            lastFrame = currentFrame;
            currentFrame = SDL_GetPerformanceCounter();

            deltaTime = ((currentFrame - lastFrame) * 1000 /
                (GLdouble)SDL_GetPerformanceFrequency());

            double tmpDeltaTime = deltaTime;

            //std::cout << "Hello 1 - deltaTime: " << std::to_string(deltaTime) <<
            //    std::endl;

            if (SDL_PollEvent(&windowEvent))
            {
                if (windowEvent.type == SDL_QUIT)
                {
                    quit = true;
                }
            }

            //***************************************************************
            // Clear the colorbuffer and render
            //***************************************************************
            glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);

            //***************************************************************
            // Draw our first triangle
            //***************************************************************
            glUseProgram(shaderProgram);
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, 3);
            glBindVertexArray(0);

            //***************************************************************
            // draw OpenGL: Swap the screen buffers
            //***************************************************************
            SDL_GL_SwapWindow(window);
        }

        //***************************************************************
        // Properly de-allocate all resources once they've outlived their 
        // purpose
        //***************************************************************
        glDeleteVertexArrays(1, &VAO);
        glDeleteBuffers(1, &VBO);
        glDeleteProgram(shaderProgram);

        SDL_GL_DeleteContext(context);
        SDL_DestroyWindow(window);
        SDL_Quit();
    }

    return EXIT_SUCCESS;
}

正如你所知,我试图在同一个项目中同时使用OpenGL和SDL2 . 当我运行此代码时,控制台显示没有错误,我得到了我的绿色背景,但根本没有三角形 . 我已经重新编写了几个“着色器如何工作”的视频,看看我是否遗漏了任何东西,但似乎无法找到问题的根源 . 我错过了什么?

1 回答

  • 3

    您的程序是一个有效的GL程序,不应该生成任何错误 . 它正确地绘制背景颜色,并且正确地不绘制任何三角形 .

    GL中的默认正面方向是逆时针方向( GL_CCW ) . 您定义的三角形在剪辑空间中顺时针定向(以及所有后续空间NDC和窗口空间) . 结果是,

    glEnable(GL_CULL_FACE);
    

    将具有在光栅化之前剔除三角形的效果 . 要查看三角形,要么禁用(只是不启用它,默认情况下它是关闭的) GL_CULL_FACE ,或者通过 glFrontFace(GL_CW) 将正面约定设置为顺时针,或者只需设置 glCullFace(GL_FRONT) 让GL剔除正面,或者只需交换数组中的任意两个顶点 .

相关问题