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()
{
}
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.
As I said before SDL2 uses OpenGL so anything SDL2 can do, OpenGL can do, SDL2 is a wrapper of OpenGL.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With