[ADD] custom rendering system
This commit is contained in:
118
src/renderEngine/Loader.cpp
Normal file
118
src/renderEngine/Loader.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "../stb_image.h"
|
||||
#include "Loader.h"
|
||||
|
||||
namespace renderEngine
|
||||
{
|
||||
namespace loader
|
||||
{
|
||||
static GLuint createVAO();
|
||||
static void storeDataInAttributeList(int attributeNumber, int coordinateSize, std::vector<float>& data);
|
||||
static void bindIndicesBuffer(std::vector<unsigned int>& indices);
|
||||
|
||||
static std::vector<GLuint> vaos;
|
||||
static std::vector<GLuint> vbos;
|
||||
static std::vector<GLuint> textures;
|
||||
|
||||
/*
|
||||
This function will generate a Model from vertex positions, textureCoordinates and indices.
|
||||
*/
|
||||
struct models::RawModel LoadToVAO(std::vector<float>& positions, std::vector<float>& textureCoords, std::vector<unsigned int>& indices)
|
||||
{
|
||||
GLuint vaoID = createVAO();
|
||||
bindIndicesBuffer(indices);
|
||||
storeDataInAttributeList(0, 3, positions);
|
||||
storeDataInAttributeList(1, 2, textureCoords);
|
||||
glBindVertexArray(0);
|
||||
return { vaoID, static_cast<int>(indices.size()) };
|
||||
}
|
||||
|
||||
/*
|
||||
Loads an image as texture into openGL
|
||||
*/
|
||||
GLuint LoadTexture(std::string fileName)
|
||||
{
|
||||
int width, height, bpp;
|
||||
unsigned char* imgData = stbi_load(fileName.c_str(), &width, &height, &bpp, 4);
|
||||
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(imgData);
|
||||
textures.push_back(textureID);
|
||||
return textureID;
|
||||
}
|
||||
|
||||
/*
|
||||
This function will delete all the vectors declared at the top of this file from openGL.
|
||||
*/
|
||||
void CleanUp()
|
||||
{
|
||||
glDeleteVertexArrays(static_cast<GLsizei>(vaos.size()), &vaos[0]);
|
||||
glDeleteBuffers(static_cast<GLsizei>(vbos.size()), &vbos[0]);
|
||||
glDeleteTextures(static_cast<GLsizei>(textures.size()), &textures[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
This function will create a new VAO for a new mesh.
|
||||
*/
|
||||
static GLuint createVAO()
|
||||
{
|
||||
GLuint vaoID;
|
||||
glGenVertexArrays(1, &vaoID);
|
||||
vaos.push_back(vaoID);
|
||||
glBindVertexArray(vaoID);
|
||||
return vaoID;
|
||||
}
|
||||
|
||||
/*
|
||||
This function can store data (vbo) in a vao.
|
||||
*/
|
||||
static void storeDataInAttributeList(int attributeNumber, int coordinateSize, std::vector<float>& data)
|
||||
{
|
||||
GLuint vboID;
|
||||
glGenBuffers(1, &vboID);
|
||||
vbos.push_back(vboID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboID);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * data.size(), &data[0], GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(attributeNumber, coordinateSize, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
This functions loads a indices buffer and binds it to a vao.
|
||||
(Using this method of rendering is way more effici<63>nt with large/complex meshes.
|
||||
This way you won't have to specify double or more occuring vertices. You just use sort of a lookup table
|
||||
to choose which vertex to get)
|
||||
|
||||
Example:
|
||||
std::vector<float> vertices =
|
||||
{
|
||||
-0.5f, 0.5f, 0,
|
||||
-0.5f, -0.5f, 0,
|
||||
0.5f, -0.5f, 0,
|
||||
0.5f, 0.5f, 0
|
||||
};
|
||||
|
||||
std::vector<int> indices =
|
||||
{
|
||||
0,1,3,
|
||||
3,1,2
|
||||
};
|
||||
*/
|
||||
static void bindIndicesBuffer(std::vector<unsigned int>& indices)
|
||||
{
|
||||
GLuint vboID;
|
||||
glGenBuffers(1, &vboID);
|
||||
vbos.push_back(vboID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * indices.size(), &indices[0], GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/renderEngine/Loader.h
Normal file
26
src/renderEngine/Loader.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../models/Model.h"
|
||||
|
||||
namespace renderEngine
|
||||
{
|
||||
namespace loader
|
||||
{
|
||||
/*
|
||||
This function generates a model from model data.
|
||||
*/
|
||||
struct models::RawModel LoadToVAO(std::vector<float>& positions, std::vector<float>& textureCoords, std::vector<unsigned int>& indices);
|
||||
|
||||
/*
|
||||
Loads a texture from a file into openGL using stb_image.h
|
||||
*/
|
||||
GLuint LoadTexture(std::string fileName);
|
||||
|
||||
/*
|
||||
Call this function when cleaning up all the meshes (when exiting the program).
|
||||
*/
|
||||
void CleanUp();
|
||||
}
|
||||
}
|
||||
134
src/renderEngine/ObjLoader.cpp
Normal file
134
src/renderEngine/ObjLoader.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "Loader.h"
|
||||
#include "ObjLoader.h"
|
||||
|
||||
/*
|
||||
* Grotendeels van deze functies zijn gemaakt door:
|
||||
* https://github.com/Hopson97/ThinMatrix-OpenGL-Engine/blob/master/Source/Render_Engine/OBJLoader.cpp
|
||||
*/
|
||||
|
||||
static void split(const std::string& s, char delim, std::vector<std::string>& elems)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.str(s);
|
||||
std::string item;
|
||||
while (getline(ss, item, delim)) {
|
||||
elems.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> split(const std::string& s, char delim)
|
||||
{
|
||||
std::vector<std::string> elems;
|
||||
split(s, delim, elems);
|
||||
return elems;
|
||||
}
|
||||
|
||||
static void processVertex(const std::vector<std::string>& vertexData,
|
||||
const std::vector<glm::vec3>& normals,
|
||||
const std::vector<glm::vec2>& textures,
|
||||
std::vector<GLuint>& indices,
|
||||
std::vector<GLfloat>& textureArray,
|
||||
std::vector<GLfloat>& normalArray)
|
||||
{
|
||||
GLuint currentVertexPointer = std::stoi(vertexData.at(0)) - 1;
|
||||
indices.push_back(currentVertexPointer);
|
||||
|
||||
glm::vec2 currentTexture = textures.at(std::stoi(vertexData.at(1)) - 1);
|
||||
textureArray[(currentVertexPointer * 2) % textureArray.size()] = currentTexture.x;
|
||||
textureArray[(currentVertexPointer * 2 + 1) % textureArray.size()] = 1 - currentTexture.y;
|
||||
|
||||
glm::vec3 currentNorm = normals.at(std::stoi(vertexData.at(2)) - 1);
|
||||
normalArray[currentVertexPointer * 3] = currentNorm.x;
|
||||
normalArray[currentVertexPointer * 3 + 1] = currentNorm.y;
|
||||
normalArray[currentVertexPointer * 3 + 2] = currentNorm.z;
|
||||
}
|
||||
|
||||
models::RawModel LoadObjModel(std::string fileName)
|
||||
{
|
||||
std::ifstream inFile (fileName);
|
||||
if ( !inFile.is_open() )
|
||||
{
|
||||
throw std::runtime_error ( "Could not open model file " + fileName + ".obj!" );
|
||||
}
|
||||
std::vector<glm::vec3> vertices;
|
||||
std::vector<glm::vec3> normals;
|
||||
std::vector<glm::vec2> textures;
|
||||
std::vector<GLuint> indices;
|
||||
std::vector<GLfloat> vertexArray;
|
||||
std::vector<GLfloat> normalArray;
|
||||
std::vector<GLfloat> textureArray;
|
||||
std::string line;
|
||||
|
||||
try
|
||||
{
|
||||
while (std::getline(inFile, line))
|
||||
{
|
||||
std::vector<std::string> splitline = split(line, ' ');
|
||||
if (splitline.at(0) == "v")
|
||||
{
|
||||
glm::vec3 vertex;
|
||||
vertex.x = std::stof(splitline.at(1));
|
||||
vertex.y = std::stof(splitline.at(2));
|
||||
vertex.z = std::stof(splitline.at(3));
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
else if (splitline.at(0) == "vt")
|
||||
{
|
||||
glm::vec2 texture;
|
||||
texture.x = std::stof(splitline.at(1));
|
||||
texture.y = std::stof(splitline.at(2));
|
||||
textures.push_back(texture);
|
||||
}
|
||||
else if (splitline.at(0) == "vn")
|
||||
{
|
||||
glm::vec3 normal;
|
||||
normal.x = std::stof(splitline.at(1));
|
||||
normal.y = std::stof(splitline.at(2));
|
||||
normal.z = std::stof(splitline.at(3));
|
||||
normals.push_back(normal);
|
||||
}
|
||||
else if (splitline.at(0) == "f")
|
||||
{
|
||||
normalArray = std::vector<GLfloat>(vertices.size() * 3);
|
||||
textureArray = std::vector<GLfloat>(textures.size() * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::vector<std::string> splitline = split(line, ' ');
|
||||
std::vector<std::string> vertex1 = split(splitline.at(1), '/');
|
||||
std::vector<std::string> vertex2 = split(splitline.at(2), '/');
|
||||
std::vector<std::string> vertex3 = split(splitline.at(3), '/');
|
||||
processVertex(vertex1, normals, textures, indices, textureArray, normalArray);
|
||||
processVertex(vertex2, normals, textures, indices, textureArray, normalArray);
|
||||
processVertex(vertex3, normals, textures, indices, textureArray, normalArray);
|
||||
if (!std::getline(inFile, line))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e)
|
||||
{
|
||||
// Always go in here
|
||||
}
|
||||
|
||||
inFile.close();
|
||||
|
||||
vertexArray = std::vector<GLfloat>( vertices.size() * 3 );
|
||||
int p = 0;
|
||||
for ( auto& vertex : vertices )
|
||||
{
|
||||
vertexArray[p++] = vertex.x;
|
||||
vertexArray[p++] = vertex.y;
|
||||
vertexArray[p++] = vertex.z;
|
||||
}
|
||||
|
||||
return renderEngine::loader::LoadToVAO( vertexArray, textureArray, indices);
|
||||
}
|
||||
6
src/renderEngine/ObjLoader.h
Normal file
6
src/renderEngine/ObjLoader.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "../models/Model.h"
|
||||
|
||||
models::RawModel LoadObjModel(std::string fileName);
|
||||
68
src/renderEngine/Renderer.cpp
Normal file
68
src/renderEngine/Renderer.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <GL/glew.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <iostream>
|
||||
#include "../models/Model.h"
|
||||
#include "Renderer.h"
|
||||
#include "../toolbox/Toolbox.h"
|
||||
|
||||
namespace renderEngine
|
||||
{
|
||||
namespace renderer
|
||||
{
|
||||
static const float FOV = 70.0f;
|
||||
static const float NEAR_PLANE = 0.01f;
|
||||
static const float FAR_PLANE = 1000.0f;
|
||||
|
||||
/*
|
||||
This function will load the projectionMatrix into the shader
|
||||
*/
|
||||
void Init(shaders::StaticShader& shader)
|
||||
{
|
||||
const glm::mat4 projectionMatrix =
|
||||
glm::perspective(glm::radians(FOV), (WINDOW_WIDTH / WINDOW_HEIGT), NEAR_PLANE, FAR_PLANE);
|
||||
|
||||
shader.start();
|
||||
shader.loadProjectionMatrix(projectionMatrix);
|
||||
shader.stop();
|
||||
}
|
||||
|
||||
/*
|
||||
This function will clear the screen.
|
||||
*/
|
||||
void Prepare()
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClearColor(0.3f, 0.4f, 0.6f, 1.0f);
|
||||
}
|
||||
|
||||
/*
|
||||
This function will Render a Model on the screen.
|
||||
*/
|
||||
void Render(entities::Entity& entity, shaders::StaticShader& shader)
|
||||
{
|
||||
const models::TexturedModel model = entity.getModel();
|
||||
const models::RawModel rawModel = model.rawModel;
|
||||
|
||||
// Enable the model
|
||||
glBindVertexArray(rawModel.vaoID);
|
||||
|
||||
// Enable the inputs for the vertexShader
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
// Load the transformation of the model into the shader
|
||||
const glm::mat4 modelMatrix = toolbox::createModelMatrix(entity.getPosition(), entity.getRotation(), entity.getScale());
|
||||
shader.loadModelMatrix(modelMatrix);
|
||||
|
||||
// Draw the model
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, model.texture.textureID);
|
||||
glDrawElements(GL_TRIANGLES, rawModel.vertexCount, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/renderEngine/Renderer.h
Normal file
25
src/renderEngine/Renderer.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "../entities/Entity.h"
|
||||
#include "../shaders/StaticShader.h"
|
||||
|
||||
namespace renderEngine
|
||||
{
|
||||
namespace renderer
|
||||
{
|
||||
/*
|
||||
Call this function when starting the program
|
||||
*/
|
||||
void Init(shaders::StaticShader& shader);
|
||||
|
||||
/*
|
||||
Call this function before rendering.
|
||||
*/
|
||||
void Prepare();
|
||||
|
||||
/*
|
||||
Call this function when wanting to Render a mesh to the screen.
|
||||
*/
|
||||
void Render(entities::Entity& entity, shaders::StaticShader& shader);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user