Hi Guys,
I'm struggling to draw some sf::Text to the sf::RenderWindow when used alongside OpenGL glDraw commands.
I've tried working through the resolution in
http://en.sfml-dev.org/forums/index.php?topic=14622.0, however I think a few crucial lines of code and their order may be omitted from the solution.
I think the issue is in the draw procedure towards the bottom of the code, more specifically :
window.pushGLStates();
window.draw(instructions);
window.popGLStates();
Any pointers as to where I'm going wrong?
Wall of text incoming :
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include <vector>
// globals
int screenWidth = 600;
int screenHeight = 600;
bool running = true;
sf::Font ambleFont;
sf::Text instructions;
GLuint
vaoId,
vboId,
indexBufferId[1],
vertexShaderId,
fragmentShaderId,
programId,
currentIndexBuffer = 0;
const GLchar* vertexShader = {
"#version 400\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n"
};
const GLchar* FragmentShader =
{
"#version 400\n"\
"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\
"void main(void)\n"\
"{\n"\
" out_Color = ex_Color;\n"\
"}\n"
};
sf::RenderWindow window;
bool init();
bool load();
void unload();
bool createBuffers();
void destroyBuffers();
bool createShaders();
void destroyShaders();
void handleEvents();
void draw();
typedef struct {
float XYZW[4];
float RGBA[4];
} Vertex;
// helper to check and display for shader compiler errors
bool check_shader_compile_status(GLuint obj) {
GLint status;
glGetShaderiv(obj, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint length;
glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
std::vector<char> log(length);
glGetShaderInfoLog(obj, length, &length, &log[0]);
std::cerr << &log[0];
return false;
}
return true;
}
// helper to check and display for shader linker error
bool check_program_link_status(GLuint obj) {
GLint status;
glGetProgramiv(obj, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint length;
glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
std::vector<char> log(length);
glGetProgramInfoLog(obj, length, &length, &log[0]);
std::cerr << &log[0];
return false;
}
return true;
}
int main() {
if (!init()) running = false;
while (running) {
handleEvents();
draw();
}
unload();
return 0;
}
bool init() {
window.create(sf::VideoMode(800, 600), "OpenGL Test", sf::Style::Default, sf::ContextSettings(24U, 8U, 4U, 4U, 0U));
window.setVerticalSyncEnabled(true);
std::cout << "Initializing OpenGL v" << window.getSettings().majorVersion << "." << window.getSettings().minorVersion << std::endl;
glewExperimental = GL_TRUE;
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
std::cout << "Error initializing an OpenGL context with the current window." << std::endl;
return false;
}
GLenum ret = glewInit();
if (ret != GLEW_NO_ERROR) {
std::cout << "Error, couldn't initialize Glew." << std::endl;
return false;
}
if (!load()) return false;
glClearColor(0.f, 0.f, 0.f, 255.f);
return true;
}
bool load() {
if (!createShaders()) return false;
if (!createBuffers()) return false;
return true;
}
void unload() {
destroyShaders();
destroyBuffers();
}
bool createBuffers() {
ambleFont.loadFromFile("../resources/Amble-Bold.ttf");
instructions.setFont(ambleFont);
instructions.setString("Press 'T' to swap indices.");
instructions.setPosition(50, 50);
instructions.setColor(sf::Color::White);
Vertex vertices[] = {
{ { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
// Top
{ { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
{ { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
{ { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
// Bottom
{ { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
{ { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
{ { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
{ { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
// Left
{ { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
{ { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
{ { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
{ { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
// Right
{ { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
{ { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
{ { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
{ { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }
};
GLubyte indices[] = {
// Top
0, 1, 3,
0, 3, 2,
3, 1, 4,
3, 4, 2,
// Bottom
0, 5, 7,
0, 7, 6,
7, 5, 8,
7, 8, 6,
// Left
0, 9, 11,
0, 11, 10,
11, 9, 12,
11, 12, 10,
// Right
0, 13, 15,
0, 15, 14,
15, 13, 16,
15, 16, 14
};
GLubyte alternateIndices[] = {
// Outer square border:
3, 4, 16,
3, 15, 16,
15, 16, 8,
15, 7, 8,
7, 8, 12,
7, 11, 12,
11, 12, 4,
11, 3, 4,
// Inner square
0, 11, 3,
0, 3, 15,
0, 15, 7,
0, 7, 11
};
GLenum errCheckVal = glGetError();
glGenVertexArrays(1, &vaoId);
glBindVertexArray(vaoId);
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (char*)0 + 0 * sizeof(GLfloat));
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (void*)sizeof(vertices[0].XYZW));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glGenBuffers(2, indexBufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(alternateIndices), alternateIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[0]); // rebind to the first
errCheckVal = glGetError();
if (errCheckVal != GL_NO_ERROR) {
std::cout << "Error: Couldn't create a VBO:" << gluErrorString(errCheckVal) << std::endl;
return false;
}
return true;
}
void destroyBuffers() {
GLenum errCheckVal = glGetError();
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(0, &vboId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(2, indexBufferId);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vaoId);
errCheckVal = glGetError();
if (errCheckVal != GL_NO_ERROR) {
std::cout << "Error: Couldn't destroy the VBO:" << gluErrorString(errCheckVal) << std::endl;
}
}
bool createShaders() {
GLenum errCheckVal = glGetError();
vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderId, 1, &vertexShader, nullptr);
glCompileShader(vertexShaderId);
if (!check_shader_compile_status(vertexShaderId)) {
return false;
}
fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderId, 1, &FragmentShader, nullptr);
glCompileShader(fragmentShaderId);
if (!check_shader_compile_status(fragmentShaderId)) {
return false;
}
programId = glCreateProgram();
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
glLinkProgram(programId);
if (!check_program_link_status(programId)) {
return false;
}
glUseProgram(programId);
errCheckVal = glGetError();
if (errCheckVal != GL_NO_ERROR) {
std::cout << "Error: Couldn't create the shaders:" << gluErrorString(errCheckVal) << std::endl;
return false;
}
return true;
}
void destroyShaders() {
GLenum errCheckVal = glGetError();
//glUseProgram(0);
glDetachShader(programId, vertexShaderId);
glDetachShader(programId, fragmentShaderId);
glDeleteShader(vertexShaderId);
glDeleteShader(fragmentShaderId);
glDeleteProgram(programId);
errCheckVal = glGetError();
if (errCheckVal != GL_NO_ERROR) {
std::cout << "Error: Couldn't destroy the shaders:" << gluErrorString(errCheckVal) << std::endl;
}
}
void handleEvents() {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
running = false;
break;
case sf::Event::Resized:
glViewport(0, 0, event.size.width, event.size.height);
break;
case sf::Event::KeyPressed:
switch (event.key.code) {
case sf::Keyboard::Escape:
running = false;
break;
case sf::Keyboard::T:
currentIndexBuffer = !currentIndexBuffer;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[currentIndexBuffer]);
break;
}
}
}
}
void draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programId);
glBindVertexArray(vaoId);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (currentIndexBuffer == 0) {
glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, nullptr);
}
else {
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, nullptr);
}
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glDisableVertexAttribArray(1);
//glDisableVertexAttribArray(0);
window.pushGLStates();
window.draw(instructions);
window.popGLStates();
window.display();
}