I have tried to abtract my OpenGl code into classes, which has worked fine so far. It would always render until I recently build a Game class which is a derived class of the Window2 class (which I have also only recently created). I am pretty sure that the bug is not to be found in the Mesh, Shader, PointLight or the Material class (as they have worked properly in the past). The window does appear and has the correct background color. The render function is also called in the game loop so I am not sure what the problem is. Here is the code...
Game.h
#ifndef GAME_H
#define GAME_H
#include <iostream>
#include <stdio.h>
#include <vector>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include "GameBlock.h"
#include "blocks/NormalGameBlock.h"
#include <PointLight.h>
#include <Window2.h>
#include <memory>
#include <Renderer.h>
#include <Mesh.h>
#include <Shader.h>
#include <Material.h>
#include <Utils.h>
class Game : private Window2 {
private:
Mesh* mesh;
Shader* shader;
Material* material;
PointLight* pointLight;
glm::mat4 projection;
glm::vec3 viewPosition;
glm::mat4 view;
public:
Game();
~Game();
void initialize();
void start();
void stop();
// override the functions provided by base class Window2
void input(Keys k) override;
void update() override;
void render() override;
};
#endif
Game.cpp
#include "Game.h"
Game::Game()
:
Window2((int)(1080 * 0.7f), (int)(1920 * 0.7f), "Game", false)
{
PRINT_FUNC;
pointLight = new PointLight
(
glm::vec3(0.0, 0.0, 1.0),
glm::vec3(1.0, 1.0, 1.0) * 0.0f,
glm::vec3(1.0, 1.0, 1.0) * 0.3f,
glm::vec3(1.0, 1.0, 1.0) * 1.0f,
1.0f,
0.01f,
0.01f
);
material = new Material
(
glm::vec3(0.0f, 0.0f, 1.0f) * 1.0f,
glm::vec3(0.0f, 0.0f, 1.0f) * 1.0f,
glm::vec3(0.0f, 0.0f, 1.0f) * 1.0f,
1.0f,
256.0f,
1.0f
);
}
Game::~Game() {
PRINT_FUNC;
delete mesh;
delete shader;
delete material;
delete pointLight;
}
void Game::initialize() {
PRINT_FUNC;
Window2::intitialize2();
mesh = new Mesh(Mesh::loadVertices("assets/box2.obj", false));
shader = new Shader("shaders/vertex_shader copy.glsl", "shaders/fragment_shader copy.glsl");
projection = glm::perspective(glm::radians(35.0f), 9.0f / 16.0f, 0.1f, 1000.0f);
viewPosition = glm::vec3(0, 1, 0);
view = glm::lookAt(
viewPosition, // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void Game::start() {
run();
}
void Game::stop() {
close();
}
void Game::input(Keys k) {
}
void Game::update() {
}
void Game::render() {
shader->activate();
shader->setMat4("P", projection);
shader->setMat4("V", view);
shader->setVec3("viewPos", viewPosition);
Renderer::render(mesh, shader, material, pointLight);
}
Window2.h
#ifndef WINDOW_2_H
#define WINDOW_2_H
#define GLEW_STATIC
#include <GL/glew.h> // include GLEW and new version of GL on Windows
#include <glfw3.h> // GLFW helper library
#include <iostream>
struct Keys {
bool W, A, S, D;
bool Left, Right, Up, Down;
bool N0, N1, N2, N3, N4, N5, N6, N7, N8, N9;
bool Space, Esc;
bool Shift;
};
class Window2 {
private:
GLFWmonitor* m_monitor;
unsigned int m_width;
unsigned int m_height;
int m_posX;
int m_posY;
const char* m_title;
const bool m_fullscreen;
float aspectRatio;
public:
GLFWwindow* m_window;
Window2(unsigned int width, unsigned int height, const char* title, const bool fullscreen);
~Window2();
void intitialize2();
void run();
void close();
// override functions
virtual void input(Keys k);
virtual void update();
virtual void render();
void setResizeCallback(void(*ptr)(GLFWwindow*, int, int));
void setSize(int width, int height);
float getAspectRatio();
void makeCurrent() const;
// clear window
void clear(float r, float g, float b);
// swap
void swap();
// poll events
void poll();
// get time in milliseconds
static unsigned int getTimeMS();
};
#endif
Window2.cpp
#include "Window2.h"
#include <iostream>
#include <chrono>
#include <Utils.h>
Window2::Window2
(
unsigned int width,
unsigned int height,
const char* title,
const bool fullscreen
)
:
m_width(width),
m_height(height),
m_title(title),
m_fullscreen(fullscreen)
{
PRINT_FUNC;
}
Window2::~Window2() {
PRINT_FUNC;
glfwDestroyWindow(m_window);
}
void Window2::intitialize2() {
PRINT_FUNC;
if (!glfwInit())
{
fprintf(stderr, "ERROR: could not start GLFW3\n");
return;
}
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
m_width = m_fullscreen ? mode->width : m_width;
m_height = m_fullscreen ? mode->height : m_height;
aspectRatio = (float)m_width / (float)m_height;
m_window = glfwCreateWindow(m_width, m_height, m_title, m_fullscreen ? glfwGetPrimaryMonitor() : NULL, NULL);
if (!m_window) {
fprintf(stderr, "ERROR: could not open Window2 with GLFW3\n");
glfwTerminate();
return;
}
glfwMakeContextCurrent(m_window);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
//setSize(m_width, m_height);
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER);
const GLubyte* version = glGetString(GL_VERSION);
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n\n", version);
}
void Window2::run() {
PRINT_FUNC;
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int previous = getTimeMS();
unsigned int lag = 0;
const unsigned int msPerUpdate = 1000 / 60;
while (!glfwWindowShouldClose(m_window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.8, 0.8, 0.8, 1);
unsigned int current = getTimeMS();
unsigned int elapsed = current - previous;
previous = current;
lag += elapsed;
const Keys k{
glfwGetKey(m_window, GLFW_KEY_W) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_A) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_S) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_D) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_LEFT) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_RIGHT) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_UP) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_DOWN) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_0) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_1) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_2) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_3) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_4) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_5) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_6) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_7) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_8) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_9) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_SPACE) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_ESCAPE) == GLFW_PRESS,
glfwGetKey(m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS
};
//input
input(k);
while (lag >= msPerUpdate)
{
// update
update();
lag -= msPerUpdate;
}
// render
render();
glfwSwapBuffers(m_window);
glfwPollEvents();
}
}
void Window2::input(Keys k) {
}
void Window2::update() {
}
void Window2::render() {
}
void Window2::close() {
glfwSetWindowShouldClose(m_window, GLFW_TRUE);
}
void Window2::setSize(int width, int height) {
m_width = width;
m_height = height;
aspectRatio = (float)m_width / (float)m_height;
glViewport(0, 0, width, height);
}
void Window2::setResizeCallback(void(*ptr)(GLFWwindow*, int, int)) {
glfwSetWindowSizeCallback(m_window, ptr);
}
void Window2::makeCurrent() const {
glfwMakeContextCurrent(m_window);
}
float Window2::getAspectRatio() {
return aspectRatio;
}
unsigned int Window2::getTimeMS() {
std::chrono::milliseconds mt = std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now().time_since_epoch());
return mt.count();
}
This is how the class is created in Main.cpp:
int main(int argc, char* argv[])
{
Game game;
game.initialize();
game.start();
glfwTerminate();
return 0;
}