簡體   English   中英

現代OpenGL + SDL2三角形沒有出現

[英]Modern OpenGL + SDL2 Triangle not showing up

我目前正在嘗試學習如何在使用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。 當我運行此代碼時控制台顯示沒有錯誤,我得到了我的綠色背景,但根本沒有三角形。 我已經重新編寫了幾個“着色器如何工作”的視頻,看看我是否錯過了什么,但似乎無法找到問題的根源。 我錯過了什么?

您的程序是有效的GL程序,不應生成任何錯誤。 它正確地繪制背景顏色,並且正確地不繪制任何三角形。

GL中的默認正面方向是逆時針方向( GL_CCW )。 您定義的三角形在剪輯空間中順時針定向(以及所有后續空間NDC和窗口空間)。 結果是,

glEnable(GL_CULL_FACE);

將具有在光柵化之前剔除三角形的效果。 要查看三角形,要么禁用(只是不啟用它,默認情況下是關閉的) GL_CULL_FACE ,或者通過glCullFace(GL_FRONT) glFrontFace(GL_CW)將前面約定設置為順時針,或者只需設置glCullFace(GL_FRONT)讓GL剔除相反,或者只是交換數組中的任意兩個頂點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM