#include <GL/glew.h>
#include <iostream>
#include <SFML/Graphics.hpp>
#include <thread>
using namespace std;
//Forward Declarations
void renderingThread(sf::RenderWindow* window);
void rThread(sf::RenderWindow* window);
std::chrono::milliseconds timespan(1000);
bool openGLInitialized = false;
GLuint shader_program = 0;
GLuint vbo = 0;
GLuint vao = 0;
void GLAPIENTRY
MessageCallback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam)
{
fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
type, severity, message);
}
int main() {
// Create the window
sf::RenderWindow gameWindow(sf::VideoMode(1920, 1080), "Game", sf::Style::Fullscreen);
// Enable Glew
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit()) {
cerr << "Failed to initialize GLEW";
exit(-1);
}
else {
cout << " > OpenGL Version: " << (const char*)glGetString(GL_VERSION) << endl;
cout << " > GLSL Version: " << (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
cout << " > OpenGL Vendor: " << (const char*)glGetString(GL_VENDOR) << endl;
cout << " > OpenGL Renderer: " << (const char*)glGetString(GL_RENDERER) << endl << endl;
// During init, enable debug output
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(MessageCallback, 0);
}
// Set some stuff for the window
gameWindow.setKeyRepeatEnabled(false);
gameWindow.setMouseCursorVisible(false);
gameWindow.setActive(false);
// Being the rendering thread
sf::Thread thread(&renderingThread, &gameWindow);
thread.launch();
// Poll Events
while (gameWindow.isOpen()) {
sf::Event evnt;
while (gameWindow.pollEvent(evnt)) {
if (evnt.type == sf::Event::Closed) {
gameWindow.close();
}
// Easy ESC kill command
if (evnt.type == sf::Event::KeyPressed) {
if (evnt.key.code == sf::Keyboard::Escape) {
exit(0);
}
}
}
}
return 0;
}
void renderingThread(sf::RenderWindow* gameWindow) {
// Do rendering here
// Set screen renderer to active in this thread
gameWindow->setActive(true);
// Load a font
sf::Font basicFont;
if (!basicFont.loadFromFile("Fonts/HonyaJi-Re.ttf")) {
cerr << "Error loading font" << endl;
exit(0);
}
// Render loop
while (gameWindow->isOpen()) {
cout << "SFML - BEFORE" << endl;
// Draw some basic text on screen using SFML
sf::Text countdownText;
countdownText.setCharacterSize(36);
countdownText.setFillColor(sf::Color::White);
countdownText.setFont(basicFont);
countdownText.setPosition(500.f, 500.f);
for (int i = 3; i > 0; i--) {
gameWindow->clear();
countdownText.setString("SFML-Before | " + to_string(i));
gameWindow->draw(countdownText);
gameWindow->display();
this_thread::sleep_for(timespan);
}
// Switch over to OpenGL rendering in a different thread
gameWindow->clear();
gameWindow->setActive(false);
sf::Thread thread(&rThread, gameWindow);
thread.launch();
thread.wait();
cout << "SFML - AFTER" << endl;
// After returning back, draw in SFML again
gameWindow->setActive(true);
sf::Text countdownText2;
countdownText2.setCharacterSize(36);
countdownText2.setFillColor(sf::Color::White);
countdownText2.setFont(basicFont);
countdownText2.setPosition(500.f, 500.f);
for (int i = 3; i > 0; i--) {
gameWindow->clear();
countdownText2.setString("SFML-After | " + to_string(i));
gameWindow->draw(countdownText2);
gameWindow->display();
this_thread::sleep_for(timespan);
}
}
}
void rThread(sf::RenderWindow* window) {
window->setActive(true);
if (!openGLInitialized) {
openGLInitialized = true;
// Triangle vertices
float points[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
// Pass vertices into VBO
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
// Build VAO
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// Vertex Shader
const char* vertex_shader =
"#version 400\n"
"in vec3 vp;"
"void main() {"
" gl_Position = vec4(vp, 1.0);"
"}";
// Fragment Shader
const char* fragment_shader =
"#version 400\n"
"out vec4 frag_colour;"
"void main() {"
" frag_colour = vec4(0.5, 0.0, 0.5, 1.0);"
"}";
// Compile shaders
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
// Link and attach shaders
shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
}
cout << "OpenGL" << endl;
int i = 3;
while (i > 0) {
// Draw OpenGL
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
glBindVertexArray(vao);
// Draw points 0-3 from the currently bound VAO with
// current in-use shader
glDrawArrays(GL_TRIANGLES, 0, 3);
window->display();
i--;
this_thread::sleep_for(timespan);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
window->setActive(false);
}