#include "MyEngine.h"
int main() {
MyEngine myEngine;
myEngine.run();
return 0;
}
MyEngine.h
#pragma once
#include "MyWindow.h"
#include "MyShaders.h"
#include "MyShapes.h"
class MyEngine
{
private:
GLFWwindow * myWindowHandle;
MyWindow * myWindow;
public:
MyEngine();
~MyEngine();
void run();
};
MyEngine.cpp
#include "MyEngine.h"
MyEngine::MyEngine()
{
MyWindow myWindow(800, 600, "My Game Engine");
this->myWindow = &myWindow;
myWindow.createWindow();
this->myWindowHandle = myWindow.getWindowHandle();
// Load all OpenGL function pointers for use
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
}
MyEngine::~MyEngine()
{
this->myWindow->destroyWindow();
}
void MyEngine::run() {
MyShaders myShaders("VertexShader.glsl", "FragmentShader.glsl");
MyShapes myShapes;
GLuint vertexArrayObjectHandle;
float coordinates[] = { 0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f };
vertexArrayObjectHandle = myShapes.drawTriangle(coordinates);
while (!glfwWindowShouldClose(this->myWindowHandle)) {
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw something
glUseProgram(myShaders.getShaderProgram());
glBindVertexArray(vertexArrayObjectHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(this->myWindowHandle);
glfwPollEvents();
}
}
MyShaders.h
#pragma once
#include <glad\glad.h>
#include <GLFW\glfw3.h>
#include "MyFileHandler.h"
class MyShaders
{
private:
const char * vertexShaderFileName;
const char * fragmentShaderFileName;
const char * vertexShaderCode;
const char * fragmentShaderCode;
GLuint vertexShaderHandle;
GLuint fragmentShaderHandle;
GLuint shaderProgram;
void compileShaders();
public:
MyShaders(const char * vertexShaderFileName, const char * fragmentShaderFileName);
~MyShaders();
GLuint getShaderProgram();
const char * getVertexShaderCode();
const char * getFragmentShaderCode();
};
MyShaders.cpp
#include "MyShaders.h"
MyShaders::MyShaders(const char * vertexShaderFileName, const char * fragmentShaderFileName)
{
this->vertexShaderFileName = vertexShaderFileName;
this->fragmentShaderFileName = fragmentShaderFileName;
// Load shaders from files
MyFileHandler myVertexShaderFileHandler(this->vertexShaderFileName);
this->vertexShaderCode = myVertexShaderFileHandler.readFile();
MyFileHandler myFragmentShaderFileHandler(this->fragmentShaderFileName);
this->fragmentShaderCode = myFragmentShaderFileHandler.readFile();
// Compile shaders
this->compileShaders();
}
MyShaders::~MyShaders()
{
}
void MyShaders::compileShaders() {
this->vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER);
this->fragmentShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this->vertexShaderHandle, 1, &(this->vertexShaderCode), NULL);
glShaderSource(this->fragmentShaderHandle, 1, &(this->fragmentShaderCode), NULL);
glCompileShader(this->vertexShaderHandle);
glCompileShader(this->fragmentShaderHandle);
this->shaderProgram = glCreateProgram();
glAttachShader(this->shaderProgram, this->vertexShaderHandle);
glAttachShader(this->shaderProgram, this->fragmentShaderHandle);
glLinkProgram(this->shaderProgram);
return;
}
GLuint MyShaders::getShaderProgram() {
return this->shaderProgram;
}
const char * MyShaders::getVertexShaderCode() {
return this->vertexShaderCode;
}
const char * MyShaders::getFragmentShaderCode() {
return this->fragmentShaderCode;
}
MyWindow.h
#pragma once
#include <glad\glad.h>
#include <GLFW\glfw3.h>
class MyWindow
{
private:
GLFWwindow * windowHandle;
int windowWidth;
int windowHeight;
const char * windowTitle;
public:
MyWindow(int windowWidth, int windowHeight, const char * windowTitle);
~MyWindow();
GLFWwindow * getWindowHandle();
void createWindow();
void MyWindow::destroyWindow();
};
MyWindow.cpp
#include "MyWindow.h"
MyWindow::MyWindow(int windowWidth, int windowHeight, const char * windowTitle)
{
this->windowHandle = NULL;
this->windowWidth = windowWidth;
this->windowWidth = windowWidth;
this->windowHeight = windowHeight;
this->windowTitle = windowTitle;
glfwInit();
}
MyWindow::~MyWindow()
{
}
GLFWwindow * MyWindow::getWindowHandle() {
return this->windowHandle;
}
void MyWindow::createWindow() {
// Use OpenGL 3.3 and GLSL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
// Limit backwards compatibility
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Prevent resizing window
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create window
this->windowHandle = glfwCreateWindow(this->windowWidth, this->windowHeight, this->windowTitle, NULL, NULL);
glfwMakeContextCurrent(this->windowHandle);
}
void MyWindow::destroyWindow() {
glfwTerminate();
}
MyShapes.h
#pragma once
#include <glad\glad.h>
#include <GLFW\glfw3.h>
class MyShapes
{
public:
MyShapes();
~MyShapes();
GLuint & drawTriangle(float coordinates[]);
};
MyShapes.cpp
#include "MyShapes.h"
MyShapes::MyShapes()
{
}
MyShapes::~MyShapes()
{
}
GLuint & MyShapes::drawTriangle(float coordinates[]) {
GLuint vertexBufferObject{};
GLuint vertexArrayObject{};
// Create a VAO
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
// Send vertices to the GPU
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(coordinates), coordinates, GL_STATIC_DRAW);
// Dertermine the interpretation of the array buffer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
// Unbind the buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return vertexArrayObject;
}
MyFileHandler.h
#pragma once
#include <cstdio>
#include <cstdlib>
class MyFileHandler
{
private:
const char * fileName;
unsigned long fileSize;
void setFileSize();
public:
MyFileHandler(const char * fileName);
~MyFileHandler();
unsigned long getFileSize();
const char * readFile();
};
MyFileHandler.cpp
#include "MyFileHandler.h"
MyFileHandler::MyFileHandler(const char * fileName)
{
this->fileName = fileName;
this->setFileSize();
}
MyFileHandler::~MyFileHandler()
{
}
void MyFileHandler::setFileSize() {
FILE * fileHandle = NULL;
fopen_s(&fileHandle, this->fileName, "rb");
fseek(fileHandle, 0L, SEEK_END);
this->fileSize = ftell(fileHandle);
rewind(fileHandle);
fclose(fileHandle);
return;
}
unsigned long MyFileHandler::getFileSize() {
return (this->fileSize);
}
const char * MyFileHandler::readFile() {
char * buffer = (char *)malloc((this->fileSize)+1);
FILE * fileHandle = NULL;
fopen_s(&fileHandle, this->fileName, "rb");
fread(buffer, this->fileSize, sizeof(char), fileHandle);
fclose(fileHandle);
buffer[this->fileSize] = '\0';
return buffer;
}
VertexShader.glsl
#version 330 core
layout (location = 0) vec3 VertexPositions;
void main() {
gl_Position = vec4(VertexPositions, 1.0f);
}
FragmentShader.glsl
#version 330 core
out vec4 FragmentColor;
void main() {
FragmentColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
I am attempting to create a simple engine/graphics utility using some object-oriented paradigms. My first goal is to get some output from my engine, namely, a simple red triangle.
For this goal, the MyShapes class will be responsible for defining shapes such as triangles, polygons etc. Currently, there is only a drawTriangle() method implemented, because I first wanted to see whether it works or not before attempting to code other shape drawing methods.
The constructor of the MyEngine class creates a GLFW window (GLAD is also initialized here to load all OpenGL functionality), and the myEngine.run() method in Main.cpp is responsible for firing up the engine. In this run() method, the shaders get loaded from files via the help of my FileHandler class. The vertices for the triangle are processed by the myShapes.drawTriangle() method where a vertex array object, a vertex buffer object and vertrex attributes are set for this purpose.
The while loop in the run() method should be outputting me the desired red triangle, but all I get is a grey window area. Why?
Note: The shaders are compiling and linking without any errors.
(Note: I am aware that this code is not using any good software engineering practices (e.g. exceptions, error handling). I am planning to implement them later, once I get the hang of OpenGL.)
↧