I am slightly experienced with C++, and very new to OpenGL. I have been using tutorials/books to learn and built a project up to the point of displaying a triangle on screen, and using matrices for transformations. Before I went any further I wanted to develop what I had into a state machine, and get better organized with the code. After making changes, my new code would display a flickering triangle. As I have tried to fix the issue, it now no longer displays at all. I have looked over the code repeatedly to identify the issue, and even printed out all programs following along with how they would proceed highlighting calls to match them up, and I don't see any major differences between the two (minus that I have removed some things like matrices to simplify). Could anyone please see if they can spot where the error might be, or offer any suggestions?
Source Code Below:
Original Working Project:
Start.cpp
//#define GLFW_INCLUDE_GLCOREARB
#include <gl/glew.h>
#include "gl/wglew.h"
#pragma comment(lib, "glew32.lib")
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "LoadShaders.h"
#include "TestGraphicObject.h"
TestGraphicObject testGO;
GLuint ProgramID; //shader program
GLuint MatrixID;
float ratio;
glm::mat4 Projection;
glm::mat4 View;
//GLFW Callbacks
static void error_callback(int error, const char* description) {
fputs(description, stderr);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void window_close_callback(GLFWwindow* window) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
void setCallbacks(GLFWwindow* window) {
glfwSetKeyCallback(window, key_callback);
glfwSetWindowCloseCallback(window, window_close_callback);
}
//End GLFW Callbacks
GLFWwindow* makeWindow() {
GLFWwindow* window;
glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
glfwTerminate();
return 0;
}
ratio = 640 / 480;
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
setCallbacks(window);
return window;
}
int init() {
glewExperimental = true; // Needed in core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
//Setup for displaying tri
testGO.init();
// Create and compile our GLSL program from the shaders
ProgramID = LoadShaders("shader.vert", "shader.frag");
MatrixID = glGetUniformLocation(ProgramID, "MVP");
//Enable depth testing
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
return 0;
}
void display(void) {
glClear(GL_DEPTH_BUFFER_BIT);
glUseProgram(ProgramID);
testGO.render(MatrixID, View, Projection);
}
int main(void) {
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
GLFWwindow* window = makeWindow();
if (!window || window == 0) {
glfwTerminate();
exit(EXIT_FAILURE);
}
//Initialize GLEW
if (init() < 0) {
exit(EXIT_FAILURE);
}
//Initialize matrices
Projection = glm::perspective(glm::radians(45.0f), ratio, 0.1f, 100.0f);
View = glm::lookAt(glm::vec3(4, 3, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
//Initialize Graphic Object
testGO.init();
//Begin Game Loop
while (!glfwWindowShouldClose(window)) {
display();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
TestGraphicsObject.cpp
#include "TestGraphicObject.h"
TestGraphicObject::TestGraphicObject() {
}
void TestGraphicObject::init() {
//Setup for displaying tri
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
//Vertices
GLfloat vertices[NumVertices][3] = { { -0.9f, -0.9f, 1.0f },{ 0.9f, -0.9f, 1.0f },{ 0.0f, 0.9f, 1.0f } };
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
Model = glm::mat4(1.0f);
}
void TestGraphicObject::render(GLuint matID, glm::mat4 view, glm::mat4 projection) {
glm::mat4 mvp = projection * view * Model;
glUniformMatrix4fv(matID, 1, GL_FALSE, &mvp[0][0]);
glEnableVertexAttribArray(vPosition);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glVertexAttribPointer(vPosition, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(vPosition);
}
shader.vert
#version 430 core
layout(location = 0) in vec4 vPosition;
uniform mat4 MVP;
out vec4 color;
void main() {
gl_Position = MVP * vPosition;
color = vec4((vPosition.x + 1) / 2, 0.0f, (vPosition.y + 1) / 2, 1.0f);
color.y = 1.0f - color.x;
if (color.z > color.x){
color.y = 1.0f - color.z;
}
}
shader.frag
#version 430 core
in vec4 color;
out vec4 fColor;
void main() {
fColor = color; //vec4(0.0, 0.0, 1.0, 1.0);
}
New non-working project:
Main.cpp
//Main.cpp
#include <gl/glew.h>
#pragma comment(lib, "glew32.lib")
//#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctime>
#include "zWindow.h"
#include "zStateManager.h"
#include "StateTest.h"
//GLFW error callback
static void error_callback(int error, const char* description) {
fputs(description, stderr);
}
int initGlew() {
glewExperimental = true;
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
return 0;
}
int main(void) {
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
zWindow wind;
GLFWwindow* window = wind.getWindow();
if (!window || window == 0) {
glfwTerminate();
exit(EXIT_FAILURE);
}
//Initialize GLEW
if (initGlew() < 0) {
exit(EXIT_FAILURE);
}
zStateManager stateMan; //Create State Manager
stateMan.setCallbacks(window); //Set Input Callbacks
StateTest testState;
stateMan.addState(&testState); //Add Test State
//Begin Main Loop
while (!glfwWindowShouldClose(window)) {
if (stateMan.render(window) != zState::STATERESULT_SUCCESS) {
glfwTerminate();
exit(EXIT_FAILURE);
}
//if (stateMan.update(deltaTime) != zStateManager::STATERESULT_SUCCESS) {
// glfwTerminate();
// exit(EXIT_FAILURE);
//}
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
zWindow.cpp
//zWindow.cpp
#include "zWindow.h"
zWindow::zWindow() {
int result = makeWindow(640, 480, "zWindow example", WINDOW_WINDOWED);
}
GLFWwindow* zWindow::getWindow() {
return window;
}
int zWindow::makeWindow(int width, int height, char* title, int mode) {
if (mode != WINDOW_WINDOWED && mode != WINDOW_FULLSCREEN && mode != WINDOW_WINDOWEDFULLSCREEN) {
return WINDOW_ERROR_INVALID_SCREENTYPE;
}
aspectRatio = (float)width / (float)height;
GLFWwindow* win;
glfwWindowHint(GLFW_SAMPLES, 4);
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
if (mode == WINDOW_WINDOWED) {
//glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
win = glfwCreateWindow(width, height, title, NULL, NULL);
}
else if (mode == WINDOW_WINDOWEDFULLSCREEN) {
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
aspectRatio = (float)mode->width / (float)mode->height;
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
win = glfwCreateWindow(mode->width, mode->height, title, monitor, NULL);
}
else {
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
win = glfwCreateWindow(width, height, title, monitor, NULL);
}
if (win == NULL) {
glfwTerminate();
return WINDOW_ERROR_CREATE_WINDOW;
}
if (window != NULL && window != 0) {
glfwDestroyWindow(window);
}
window = win;
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
return WINDOW_SUCCESS;
}
// Callbacks
void zWindow::window_close_callback(GLFWwindow* win) {
//Window closed
glfwSetWindowShouldClose(win, GL_FALSE);
}
void zWindow::window_size_callback(GLFWwindow* win, int width, int height) {
//Window size changed
aspectRatio = (float)width / (float)height;
}
void zWindow::framebuffer_size_callback(GLFWwindow* win, int width, int height) {
//Framebuffer size changed
}
void zWindow::window_pos_callback(GLFWwindow* win, int& x, int& y) {
//Window has moved
}
void zWindow::window_iconify_callback(GLFWwindow* win, int iconified) {
if (iconified) {
//Window minimized
}
else {
//Window restored
}
}
void zWindow::window_focus_callback(GLFWwindow* win, int focused) {
if (focused) {
//Window received focus
}
else {
//Window lost focus
}
}
zStateManager.cpp
//zStateManager.cpp
#include "zStateManager.h"
zStateManager::zStateManager() {
ProgramID = LoadShaders("shader.vert", "shader.frag");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
}
void zStateManager::addState(zState* t) {
states.push_back(t);
}
int zStateManager::removeState() {
if (states.size() > 0) {
states.pop_back();
return zState::STATERESULT_SUCCESS;
}
return zState::STATERESULT_FAILURE;
}
int zStateManager::update(double t) {
if (states.size() > 0) {
states.back()->update(t);
return zState::STATERESULT_SUCCESS;
}
return zState::STATERESULT_FAILURE;
}
int zStateManager::render(GLFWwindow* window) {
if (states.size() > 0) {
glClear(GL_DEPTH_BUFFER_BIT);
glUseProgram(ProgramID);
states.back()->render(window);
glFlush();
glfwSwapBuffers(window);
glfwPollEvents();
return zState::STATERESULT_SUCCESS;
}
glfwSwapBuffers(window);
glfwPollEvents();
return zState::STATERESULT_FAILURE;
}
void zStateManager::setCallbacks(GLFWwindow* window) {
glfwSetKeyCallback(window, key_callback);
}
void zStateManager::key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
zState.h - No CPP file
//zState.h
#pragma once
#ifndef __ZSTATE_DEFINED
#define __ZSTATE_DEFINED
#include <GLFW/glfw3.h>
//#include "zStateManager.h"
class zState {
protected:
public:
typedef enum {
STATERESULT_SUCCESS = 0,
STATERESULT_FAILURE
} errorCodes;
public:
virtual int update(double t) = 0;
virtual int render(GLFWwindow* window) = 0;
virtual void init(void) = 0;
};
#endif
StateTest.cpp
//StateTest.cpp
#include "StateTest.h"
StateTest::StateTest() {
init();
}
int StateTest::update(double t) {
return zState::STATERESULT_SUCCESS;
}
int StateTest::render(GLFWwindow* window) {
glEnableVertexAttribArray(vPosition);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glVertexAttribPointer(vPosition, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glDisableVertexAttribArray(vPosition);
//glFlush();
return zState::STATERESULT_SUCCESS;
}
void StateTest::init() {
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertices[NumVertices][3] = { { -0.9f, -0.9f, 1.0f },{ 0.9f, -0.9f, 1.0f },{ 0.0f, 0.9f, 1.0f } };
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),
vertices, GL_STATIC_DRAW);
}
shader.vert
#version 430 core
layout(location = 0) in vec3 vPosition;
//uniform mat4 MVP;
out vec4 color;
void main() {
gl_Position.xyz = vPosition;
gl_Position.w = 1.0f;
color = vec4(0.0f, 0.0f, 1.0f, 1.0f);
}
shader.frag
#version 430 core
in vec4 color;
out vec4 fColor;
void main() {
fColor = color; //vec4(0.0, 0.0, 1.0, 1.0);
}