0
\$\begingroup\$

I have been using the website Learn OpenGL but I am using SDL as a window Library.

My code seems to builds the window correctly but no triangle appears. I am compiling my code using Visual Studio 2013. I have spent many hours looking over the code but cannot see an error. Can anyone tell me where I have gone wrong?

#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"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";

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

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("Breakout",
            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);

        //*******************************************************************
        // Define the viewport dimensions
        //*******************************************************************
        glViewport(SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
            SCREEN_WIDTH, SCREEN_HEIGHT);

        //*******************************************************************
        // 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[] = {
            -0.5f, -0.5f, 0.0f,     // Left  
            0.5f, -0.5f, 0.0f,      // Right 
            0.0f, 0.5f, 0.0f        // Top   
        };
        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);

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 
            (GLvoid*)0);

        glEnableVertexAttribArray(0);

        //*******************************************************************
        // 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();

        while (true)
        {
            //***************************************************************
            // 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)
                {
                    break;
                }
            }

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

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

    return EXIT_SUCCESS;
}
\$\endgroup\$
1
\$\begingroup\$

This line:

glViewport(SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT);

... does not really make sense. You're passing in special constants only known by SDL to an OpenGL function that expects actual coordinates. If anything, I'd expect that to be glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT).

But then, I have never actually seen or used glViewport, and it looks like it's part of the deprecated fixed-function pipeline matrix stack, which you probably don't want to use since you're using shaders and VAOs. Simply remove the line, and voilà ! Triangle.

\$\endgroup\$
  • \$\begingroup\$ Thanks Quentin, I changed the statement to glViewport(0,0 , SCREEN_WIDTH, SCREEN_HEIGHT); \$\endgroup\$ – Lord Future Oct 19 '16 at 10:16
1
\$\begingroup\$

Try adding instead of

glClear(GL_COLOR_BUFFER_BIT);

The following line:

glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

It is a pretty common issue.

Edit: Also try moving

glEnableVertexAttribArray(0);

before

glVertexAttribPointer(...);

Edit2: Also what Quentin says might be the problem. Try using

glViewPort(0, 0, width, height);

Let me know if any of these helps.

\$\endgroup\$
  • \$\begingroup\$ Using Quentin's advice above i changed the statement to \$\endgroup\$ – Lord Future Oct 19 '16 at 10:18
  • \$\begingroup\$ glViewport(0,0 , SCREEN_WIDTH, SCREEN_HEIGHT);. This fixed the problem. But I have also followed your advice amd moved some statements around. Thanks for the help. \$\endgroup\$ – Lord Future Oct 19 '16 at 10:20
  • \$\begingroup\$ Holy..... Can you explain why setting glViewport works? I had no errors at all, glClear working good, no error/warning output in the gl debug output, nothing bad(!) but ubuntu 16.04 did not draw anything except that it could glClear.... Before I set the glViewport... Most of time I develop on archlinux and it worked okay all the time there but now I spent 2 days trying to find out why does not my game draw any primitives on the ubuntu 16.04.... Thank you.. And if you can, explain why is it necessary on some OSes please. \$\endgroup\$ – Victor Polevoy Aug 23 '17 at 12:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.