Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw a triangle with SDL2 and OpenGL?

Tags:

c++

opengl

I'm developing a simple application with SDL2 and OpenGL in C++.

The problem is that my program doesn't draw the triangle.

Rect.hpp (The class that draw the triangle):

#ifndef Rect_hpp
#define Rect_hpp

#include <stdio.h>
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include "Shaders.hpp"

using namespace std;

extern GLfloat vertices[];

class Rect
{

public:
 Rect();
 ~Rect();
 void init();
void draw();

private:
 void bind();

 GLuint VAO;
 GLuint VBO;
 GLuint vertexShader;
 GLuint fragmentShader;
 GLuint shaderProgram;
 Shaders shaders;

};

#endif /* Rect_hpp */

Rect.cpp:

#include "Rect.hpp"

GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
};

Rect::Rect()
{
VBO = NULL;
vertexShader = NULL;
fragmentShader = NULL;
shaderProgram = NULL;
}

Rect::~Rect()
{
glDeleteShader(vertexShader);
vertexShader = NULL;
glDeleteShader(fragmentShader);
fragmentShader = NULL;
}

void Rect::bind()
{
glBindVertexArray(VAO);

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

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

glBindVertexArray(0);
}

void Rect::init()
{
//VAO
glGenVertexArrays(1, &VAO); //VAO creation

//VBO
glGenBuffers(1, &VBO); //VBO creation

//SHADER
vertexShader = glCreateShader(GL_VERTEX_SHADER); //vertex shader
glShaderSource(vertexShader, 1, &shaders.vertexSource, NULL);
glCompileShader(vertexShader);

fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //fragment shader
glShaderSource(fragmentShader, 1, &shaders.fragmentSource, NULL);
glCompileShader(fragmentShader);

shaderProgram = glCreateProgram(); //shader program
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

bind();
}

void Rect::draw()
{
 glUseProgram(shaderProgram);
 glBindVertexArray(VAO);
 glDrawArrays(GL_TRIANGLES, 0, 3);
 glBindVertexArray(0);
}

Game.hpp:

#ifndef Game_hpp
#define Game_hpp

#include <stdio.h>
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <OpenGL/gl3.h>
#include "glm/glm.hpp"
#include "Rect.hpp"

  using namespace glm;
  using namespace std;

  class Game
{

public:
Game(int width, int height);
~Game();
void run();

private:
int _width, _height;

void init();
void loop();
void input();
void draw();

SDL_Window* window;
SDL_GLContext context;
bool isRunning;
SDL_Event e;
Rect* rect;

};

#endif /* Game_hpp */

Game.cpp:

#include "Game.hpp"

Game::Game(int width, int height)
{
 _width = width;
 _height = height;

window = NULL;
context = NULL;

rect = new Rect();

 isRunning = true;
}

 Game::~Game()
 {
 SDL_GL_DeleteContext(context);
 context = NULL;
 SDL_DestroyWindow(window);
 window = NULL;
 SDL_Quit();
 }

void Game::run()
{
 init();
 loop();
}

void Game::init()
{
 //SDL INIT
 SDL_Init(SDL_INIT_EVERYTHING);

 //OPENGL ATTRIBUTES
 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,  SDL_GL_CONTEXT_PROFILE_CORE);
 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);

  //WINDOW INIT
  window = SDL_CreateWindow("OpenGL_GAME_TEST",
                          SDL_WINDOWPOS_CENTERED,
                          SDL_WINDOWPOS_CENTERED,
                          _width,
                          _height,
                          SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
glViewport(0, 0, _width, _height);

//OPENGL CONTEXT INIT
context = SDL_GL_CreateContext(window);

//GLEW INIT
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
    cout << "ERROR: GLEW initialization failed!" << endl;

//CLASSES INIT
rect->init();

}

void Game::loop()
{
while(isRunning)
{
    input();
    draw();
}
}

void Game::input()
{
if(SDL_PollEvent(&e))
{

    if(e.type == SDL_QUIT) isRunning = false;
    if(e.type == SDL_KEYDOWN)
        if(e.key.keysym.sym == SDLK_ESCAPE) isRunning = false;

}
}

void Game::draw()
{
//DRAW...
glClearColor(0.2f, 0.4f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

rect->draw();

SDL_GL_SwapWindow(window);
}

Shaders.hpp:

#ifndef Shaders_hpp
#define Shaders_hpp

#include <stdio.h>
#include <iostream>
#include <GL/glew.h>

  class Shaders
{

public:
Shaders();
~Shaders();
const GLchar* vertexSource;
const GLchar* fragmentSource;

};

#endif /* Shaders_hpp */

Shaders.cpp:

#include "Shaders.hpp"

Shaders::Shaders()
{
vertexSource = "#version 330 core \n"
               "layout (location = 0) in vec3 position; \n"
               "void main() \n"
               "{ \n"
               "    gl_Position = vec4(position, 1.0); \n"
               "} \n \0";

fragmentSource = "#version 330 core \n"
                 "out vec4 color \n"
                 "void main() \n"
                 "{ \n"
                 "  color = vec4(1.0, 0.5, 0.1, 1.0); \n"
                 "}; \n \0";
 }

Shaders::~Shaders()
{ 

}
like image 620
GADO Avatar asked Oct 15 '16 16:10

GADO


People also ask

How do you draw a triangle in OpenGL?

glBegin(GL_TRIANGLES); glColor3f(0.1, 0.2, 0.3); glVertex3f(0, 0, 0); glVertex3f(1, 0, 0); glVertex3f(0, 1, 0); glEnd(); This gives you unlit, untextured, flat-shaded triangles. You can also draw triangle strips, quadrilaterals, and general polygons by changing what value you pass to glBegin.

Does SDL2 use OpenGL?

As I said before SDL2 uses OpenGL so anything SDL2 can do, OpenGL can do, SDL2 is a wrapper of OpenGL.


1 Answers

Minimal runnable example

main.c

#include <stdio.h>

#include <SDL2/SDL.h>
#define GLEW_STATIC
#include <GL/glew.h>

static const GLuint WIDTH = 512;
static const GLuint HEIGHT = 512;
static const GLchar* vertex_shader_source =
    "#version 120\n"
    "attribute vec2 coord2d;\n"
    "void main() {\n"
    "    gl_Position = vec4(coord2d, 0.0, 1.0);\n"
    "}\n";
static const GLchar* fragment_shader_source =
    "#version 120\n"
    "void main() {\n"
    "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    "}\n";
static GLfloat vertices[] = {
     0.0,  0.8,
    -0.8, -0.8,
     0.8, -0.8,
};

GLuint common_get_shader_program(
    const char *vertex_shader_source,
    const char *fragment_shader_source
) {
    GLchar *log = NULL;
    GLint log_length, success;
    GLuint fragment_shader, program, vertex_shader;

    /* Vertex shader */
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &log_length);
    log = malloc(log_length);
    if (log_length > 0) {
        glGetShaderInfoLog(vertex_shader, log_length, NULL, log);
        printf("vertex shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("vertex shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Fragment shader */
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetShaderInfoLog(fragment_shader, log_length, NULL, log);
        printf("fragment shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("fragment shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Link shaders */
    program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = realloc(log, log_length);
        glGetProgramInfoLog(program, log_length, NULL, log);
        printf("shader link log:\n\n%s\n", log);
    }
    if (!success) {
        printf("shader link error");
        exit(EXIT_FAILURE);
    }

    /* Cleanup. */
    free(log);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return program;
}

int main(void) {
    GLint attribute_coord2d;
    GLuint program, vbo;
    SDL_Event event;
    SDL_GLContext gl_context;
    SDL_Window *window;

    SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
    window = SDL_CreateWindow(__FILE__, 0, 0,
            WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
    gl_context = SDL_GL_CreateContext(window);
    glewInit();

    /* Shader setup. */
    program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
    attribute_coord2d = glGetAttribLocation(program, "coord2d");

    /* Buffer setup. */
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    /* Global draw state */
    glUseProgram(program);
    glViewport(0, 0, WIDTH, HEIGHT);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    /* Main loop. */
    while (1) {
        glClear(GL_COLOR_BUFFER_BIT);
        glEnableVertexAttribArray(attribute_coord2d);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glDisableVertexAttribArray(attribute_coord2d);
        SDL_GL_SwapWindow(window);
        if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
            break;
    }

    /* Cleanup. */
    glDeleteBuffers(1, &vbo);
    glDeleteProgram(program);
    SDL_GL_DeleteContext(gl_context);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}

GitHub upstream.

Compile and run:

sudo apt-get install libsdl2-dev
gcc -lSDL2 -lGL -lGLEW -o main.out main.c
./main.out

A bit more information on the OpenGL specific part: What does "immediate mode" mean in OpenGL?

Tested on Ubuntu 16.04.