Search code examples
c++openglrenderingsdl-2

OpenGL rectangle inexplicably takes up entire window


So I am using GLEW & SDL2. At the moment I'm having trouble with drawing a simple rectangle. I've done this before and got it to work no problem. (I have checked my old code, but could not find any signifigant differences)

Here's what the output should look like, aside from a different background color. enter image description here

However, this is what the output looks like: enter image description here

When I check the output with Renderdoc, all the values seem to be as they should be, but for some reason the output rectangle is signifigantly larger than the viewport. (Assuming the white border in the output window represents the viewport.) enter image description here

I've googled around a bit, but could not find any solution to this issue. I'm figuring I'm just missing a single function call somewhere which is causing the program to output things in a weird way.

Here's the relevant code

game.cpp

#include "Game.h"

void Game::Game::main_loop()
{
    //Placeholder setup;
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.5f,  0.5f, 0.0f,
        -0.5f,  0.5f, 0.0f,
    };
    unsigned int indices[] = { 
        0, 1, 2,
        2, 3, 0 
    };  

    unsigned int vertex_array, vertex_buffer, element_buffer;

    glGenVertexArrays(1, &vertex_array);
    glBindVertexArray(vertex_array);

    glGenBuffers(1, &vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &element_buffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    Asset::Loader l;
    auto s = l.load_shader("res/GUI/Shaders/Textured_quad.vert", "res/GUI/Shaders/Textured_quad.frag");

    keep_going = true;
    while(keep_going)
    {
        handle_events();
        renderer.clear();

        s->use(); //Just calls 'glUseProgram' on the shader inside this object
        glBindVertexArray(vertex_array);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        renderer.show();
    }
}

void Game::Game::handle_events()
{
    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
        case SDL_MOUSEBUTTONDOWN:
        case SDL_QUIT:
            keep_going = false;
        }
    }
}

Renderer.cpp

#include "Renderer.h"

Game::Graphics::Renderer::Renderer()
{
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    window = SDL_CreateWindow(
        "GUI", 
        SDL_WINDOWPOS_CENTERED_DISPLAY(1),
        SDL_WINDOWPOS_CENTERED_DISPLAY(1),
        640,
        480,
        SDL_WINDOW_OPENGL
    );

    context = SDL_GL_CreateContext(
        window
    );

    if(!window)
    {
        std::cerr << "Window Error: " << SDL_GetError() << std::endl;
        return;
    }

    if(!context)
    {
        std::cerr << "GL Context Error: " << SDL_GetError() << std::endl;
        return;
    }

    glewInit();

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glViewport(0, 0, 640, 480);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_LIGHTING);
    glDisable(GL_BLEND);
}

Game::Graphics::Renderer::~Renderer()
{
    SDL_HideWindow(window);
    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
}

void Game::Graphics::Renderer::clear()
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void Game::Graphics::Renderer::show()
{
    SDL_GL_SwapWindow(window);
}

Shader

#version 330 core

layout (location = 0) in vec3 a_pos;

void main()
{
    gl_Position = vec4(a_pos, 0.0f);
}

//fragment
#version 330 core

out vec4 o_color;

void main()
{
    o_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}

Solution

  • gl_Position = vec4(a_pos, 0.0f);
    

    The X/Y/Z coordinates in gl_Position get divided by the W coordinate to get the screen coordinates. You are setting the W coordinate to 0, which means the X and Y coordinates become infinity and -infinity (1/0 and -1/0) and the Z coordinate becomes NaN.

    Change it to:

                              vvvv
    gl_Position = vec4(a_pos, 1.0f);