mirror of
https://github.com/devZoGok/vb01.git
synced 2026-08-27 12:03:25 +00:00
Box/Quad clone methods
Phong lighting shaders using multi draw indirect rendering
This commit is contained in:
@@ -4,17 +4,23 @@
|
||||
#include "shader.h"
|
||||
#include "box.h"
|
||||
#include "quad.h"
|
||||
#include "camera.h"
|
||||
#include "lineRenderer.h"
|
||||
#include "assetManager.h"
|
||||
#include "animationController.h"
|
||||
|
||||
#include "glad.h"
|
||||
#include <glfw3.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <glfw3.h>
|
||||
|
||||
#include <glm.hpp>
|
||||
#include <ext.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace glm;
|
||||
|
||||
namespace vb01{
|
||||
static Root *root = nullptr;
|
||||
@@ -49,12 +55,111 @@ namespace vb01{
|
||||
this->height = height;
|
||||
this->libPath = libPath;
|
||||
|
||||
AssetManager::getSingleton()->load(Root::getSingleton()->getLibPath());
|
||||
AssetManager::getSingleton()->load(libPath);
|
||||
|
||||
initWindow(name);
|
||||
|
||||
brdfLutPlane = new Quad(Vector3(1, 1, 1) * 2);
|
||||
iblBox = new Box(Vector3::VEC_IJK);
|
||||
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &NUM_MAX_TEXTURE_ARRAY_SIZE);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &NUM_MAX_TEXTURE_UNITS);
|
||||
|
||||
glGenBuffers(1, &drawCmdBuffer);
|
||||
glGenBuffers(1, &objVertBuffer);
|
||||
glGenBuffers(1, &objFragBuffer);
|
||||
|
||||
initMeshRendering(meshVAO, meshVBO, meshEBO);
|
||||
initParticleRendering();
|
||||
initGuiRendering();
|
||||
initPostProcessing();
|
||||
initMainFramebuffer(pingPongTextures[0], nullptr);
|
||||
initGuiPlane();
|
||||
}
|
||||
|
||||
void Root::initMeshRendering(u32 &VAO, u32 &VBO, u32 &EBO){
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenBuffers(1, &EBO);
|
||||
|
||||
u32 size = sizeof(MeshData::GpuVertex);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, size, (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, norm)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, uv)));
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, tan)));
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, biTan)));
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, weights)));
|
||||
glEnableVertexAttribArray(5);
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, boneIndices)));
|
||||
glEnableVertexAttribArray(6);
|
||||
|
||||
/*
|
||||
for(int i = 0; i < MAX_NUM_SHAPE_KEYS; i++){
|
||||
glVertexAttribPointer(7 + i, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, shapeKeyOffsets) + 3 * i * sizeof(float)));
|
||||
cout << glGetError() << "\n";
|
||||
glEnableVertexAttribArray(7 + i);
|
||||
cout << glGetError() << "\n";
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Root::initVertexDataOnGpu(MeshData &meshData, u32 &VAO, u32 &VBO, u32 &EBO, bool updateDrawCommands){
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
|
||||
vector<MeshData::GpuVertex> glVertData = meshData.toGpuVerts();
|
||||
u32 vertSize = sizeof(MeshData::GpuVertex), indexSize = sizeof(u32);
|
||||
|
||||
if(updateDrawCommands){
|
||||
DrawElementsIndirectCommand drawCmd;
|
||||
drawCmd.count = 3 * meshData.numTris;
|
||||
drawCmd.instanceCount = 0;
|
||||
drawCmd.firstIndex = currentIndices.size();
|
||||
drawCmd.baseVertex = currentGpuVertices.size();
|
||||
drawCmd.baseInstance = 0;
|
||||
drawCmds.push_back(drawCmd);
|
||||
drawCmdMeshes.push_back(&meshData);
|
||||
|
||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawCmdBuffer);
|
||||
glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand) * drawCmds.size(), drawCmds.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
int currNumIndices = currentIndices.size();
|
||||
|
||||
for(int i = 0; i < 3 * meshData.numTris; i++)
|
||||
currentIndices.push_back(meshData.indices[i] + currNumIndices);
|
||||
|
||||
currentGpuVertices.insert(currentGpuVertices.end(), glVertData.begin(), glVertData.end());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, currentGpuVertices.size() * vertSize, currentGpuVertices.data(), GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, currentIndices.size() * indexSize, currentIndices.data(), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
else{
|
||||
u32 numVerts = 3 * meshData.numTris, numIndexes = 3 * meshData.numTris;
|
||||
glBufferData(GL_ARRAY_BUFFER, numVerts * vertSize, glVertData.data(), GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndexes * indexSize, meshData.indices, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
void Root::initParticleRendering(){
|
||||
}
|
||||
|
||||
void Root::initGuiRendering(){
|
||||
}
|
||||
|
||||
void Root::initPostProcessing(){
|
||||
//brdfLutPlane = new Quad(Vector3(1, 1, 1) * 2);
|
||||
//iblBox = new Box(Vector3::VEC_IJK);
|
||||
|
||||
blurShader = new Shader(libPath + "blur");
|
||||
shader = new Shader(Root::getSingleton()->getLibPath() + "line3D");
|
||||
@@ -64,9 +169,18 @@ namespace vb01{
|
||||
|
||||
Texture *fragTexture = new Texture(width, height, false);
|
||||
Texture *brightTexture = new Texture(width, height, false);
|
||||
}
|
||||
|
||||
initMainFramebuffer(fragTexture, nullptr);
|
||||
initGuiPlane(fragTexture, brightTexture);
|
||||
void Root::addMeshes(Node *rootNode){
|
||||
vector<Node*> descendants;
|
||||
rootNode->getDescendants(descendants);
|
||||
|
||||
vector<Mesh*> meshes;
|
||||
|
||||
for(Node *desc : descendants){
|
||||
vector<Mesh*> m = desc->getMeshes();
|
||||
meshes.insert(meshes.end(), m.begin(), m.end());
|
||||
}
|
||||
}
|
||||
|
||||
void Root::toggleHDR(bool hdr){
|
||||
@@ -156,11 +270,15 @@ namespace vb01{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void Root::initGuiPlane(Texture *fragTexture, Texture *brightTexture){
|
||||
void Root::initGuiPlane(){
|
||||
guiPlane = new Quad(Vector3(width, height, -1), false);
|
||||
|
||||
initMeshRendering(guiPlaneVAO, guiPlaneVBO, guiPlaneEBO);
|
||||
initVertexDataOnGpu(guiPlane->getMeshBase(), guiPlaneVAO, guiPlaneVBO, guiPlaneEBO, false);
|
||||
|
||||
Material *mat = new Material(libPath + "postProcess");
|
||||
mat->addTexUniform("frag", fragTexture, false);
|
||||
mat->addTexUniform("bright", brightTexture, false);
|
||||
mat->addTexUniform("frag", pingPongTextures[0], false);
|
||||
mat->addTexUniform("bright", pingPongTextures[1], false);
|
||||
guiPlane->setMaterial(mat);
|
||||
}
|
||||
|
||||
@@ -174,16 +292,29 @@ namespace vb01{
|
||||
if(skybox){
|
||||
glDepthMask(GL_FALSE);
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
skybox->update();
|
||||
renderMesh(skybox, meshVAO);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
|
||||
AnimationController::getSingleton()->update();
|
||||
|
||||
updateNodeTree(rootNode, false);
|
||||
Vector3 camPos = camera->getPosition();
|
||||
|
||||
LineRenderer::getSingleton()->drawLines();
|
||||
Vector3 dir = camera->getDirection(), up = camera->getUp();
|
||||
mat4 view = lookAt(vec3(camPos.x, camPos.y, camPos.z), vec3(camPos.x + dir.x, camPos.y + dir.y, camPos.z + dir.z), vec3(up.x, up.y, up.z));
|
||||
|
||||
float fov = camera->getFov(), nearPlane = camera->getNearPlane(), farPlane = camera->getFarPlane();
|
||||
mat4 proj = perspective(radians(fov), (float)width / height, nearPlane, farPlane);
|
||||
|
||||
mat4 projView = proj * view;
|
||||
|
||||
updateNodeTree(rootNode, projView, false);
|
||||
|
||||
//LineRenderer::getSingleton()->drawLines();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
@@ -196,60 +327,199 @@ namespace vb01{
|
||||
updateGuiPlane();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
updateNodeTree(guiNode, true);
|
||||
//updateNodeTree(guiNode, true);
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
void Root::renderMesh(Mesh *mesh, u32 &vao){
|
||||
MeshData meshData = mesh->getMeshBase();
|
||||
glBindVertexArray(vao);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, mesh->isWireframe() ? GL_LINE : GL_FILL);
|
||||
glDrawElements(GL_TRIANGLES, 3 * meshData.numTris, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
void Root::renderMeshes(){
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, objVertBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(ObjectVertexData) * objVertData.size(), objVertData.data(), GL_DYNAMIC_DRAW);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, objVertBuffer);
|
||||
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, objFragBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(ObjectFragmentData) * objFragData.size(), objFragData.data(), GL_DYNAMIC_DRAW);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, objFragBuffer);
|
||||
|
||||
/*
|
||||
glNamedBufferSubData(objFragBuffer, 0, sizeof(ObjectFragmentData) * objFragData.size(), objFragData.data());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, objFragBuffer);
|
||||
*/
|
||||
|
||||
glBindVertexArray(meshVAO);
|
||||
|
||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawCmdBuffer);
|
||||
glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand) * drawCmds.size(), drawCmds.data(), GL_DYNAMIC_DRAW);
|
||||
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, NULL, drawCmds.size(), 0);
|
||||
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Root::renderParticles(vector<ParticleEmitter*> &particleEmitters){
|
||||
}
|
||||
|
||||
void Root::renderGui(vector<Mesh*> &meshes){
|
||||
}
|
||||
|
||||
void Root::updateNode(Node *node, mat4 &proj, mat4 &view, bool gui){
|
||||
Quaternion orient = Quaternion::QUAT_W;
|
||||
Vector3 pos = Vector3::VEC_ZERO, scale = Vector3::VEC_IJK;
|
||||
|
||||
if(!gui){
|
||||
pos = node->localToGlobalPosition(Vector3::VEC_ZERO);
|
||||
orient = node->localToGlobalOrientation(Quaternion::QUAT_W);
|
||||
scale = node->getScale();
|
||||
}
|
||||
|
||||
Vector3 rotAxis = orient.getAxis();
|
||||
|
||||
if(rotAxis == Vector3::VEC_ZERO)
|
||||
rotAxis = Vector3::VEC_I;
|
||||
|
||||
mat4 model = mat4(1.);
|
||||
model = translate(model, vec3(pos.x, pos.y, pos.z));
|
||||
model = rotate(model, orient.getAngle(), vec3(rotAxis.x, rotAxis.y, rotAxis.z));
|
||||
model = glm::scale(model, vec3(scale.x, scale.y, scale.z));
|
||||
|
||||
vector<Mesh*> mesh = node->getMeshes();
|
||||
vector<ParticleEmitter*> pe = node->getParticleEmitters();
|
||||
|
||||
/*
|
||||
for(Mesh *m : mesh){
|
||||
}
|
||||
*/
|
||||
|
||||
//meshes.insert(meshes.end(), mesh.begin(), mesh.end());
|
||||
//particleEmitters.insert(particleEmitters.end(), pe.begin(), pe.end());
|
||||
|
||||
node->update();
|
||||
}
|
||||
|
||||
//TODO replace sorting algorithm
|
||||
//TODO specify differentiation of nodes with translucent meshes AND texts
|
||||
void Root::updateNodeTree(Node *node, bool gui){
|
||||
vector<Node*> descendants, opaqueNodes, transparentNodes;
|
||||
node->getDescendants(descendants);
|
||||
void Root::updateNodeTree(Node *node, mat4 &projView, bool gui){
|
||||
objVertData.clear();
|
||||
objFragData.clear();
|
||||
|
||||
for(Node *desc : descendants){
|
||||
if(!desc->getMeshes().empty())
|
||||
for(Mesh *mesh : desc->getMeshes()){
|
||||
(mesh->getMaterial()->isTransparent() ? transparentNodes : opaqueNodes).push_back(desc);
|
||||
break;
|
||||
}
|
||||
else if(!desc->getTexts().empty())
|
||||
transparentNodes.push_back(desc);
|
||||
else
|
||||
opaqueNodes.push_back(desc);
|
||||
}
|
||||
for(DrawElementsIndirectCommand &cmd : drawCmds)
|
||||
cmd.instanceCount = 0;
|
||||
|
||||
for(Node *node : opaqueNodes)
|
||||
node->update();
|
||||
vector<Node*> descendants, opaqueNodes, transparentNodes;
|
||||
node->getDescendants(descendants);
|
||||
|
||||
int numNodes = transparentNodes.size();
|
||||
for(Node *desc : descendants){
|
||||
if(!desc->isVisible()) continue;
|
||||
|
||||
for(int i = 0; i < numNodes; i++){
|
||||
float d1 = transparentNodes[i]->getPosition().z;
|
||||
if(!desc->getMeshes().empty()){
|
||||
Quaternion orient = Quaternion::QUAT_W;
|
||||
Vector3 pos = Vector3::VEC_ZERO, scale = Vector3::VEC_IJK;
|
||||
|
||||
if(!gui){
|
||||
Vector3 v1 = transparentNodes[i]->getPosition() - camera->getPosition();
|
||||
float a1 = v1.norm().getAngleBetween(camera->getDirection());
|
||||
d1 = v1.getLength() * cos(a1);
|
||||
pos = desc->localToGlobalPosition(Vector3::VEC_ZERO);
|
||||
orient = desc->localToGlobalOrientation(Quaternion::QUAT_W);
|
||||
scale = desc->getScale();
|
||||
}
|
||||
|
||||
for(int j = i; j < numNodes; j++){
|
||||
float d2 = transparentNodes[j]->getPosition().z;
|
||||
Vector3 rotAxis = orient.getAxis();
|
||||
|
||||
if(!gui){
|
||||
Vector3 v2 = transparentNodes[j]->getPosition() - camera->getPosition();
|
||||
float a2 = v2.norm().getAngleBetween(camera->getDirection());
|
||||
d2 = v2.getLength() * cos(a2);
|
||||
if(rotAxis == Vector3::VEC_ZERO)
|
||||
rotAxis = Vector3::VEC_I;
|
||||
|
||||
mat4 model = mat4(1.);
|
||||
model = translate(model, vec3(pos.x, pos.y, pos.z));
|
||||
model = rotate(model, orient.getAngle(), vec3(rotAxis.x, rotAxis.y, rotAxis.z));
|
||||
model = glm::scale(model, vec3(scale.x, scale.y, scale.z));
|
||||
|
||||
for(Mesh *mesh : desc->getMeshes()){
|
||||
if(mesh->getMaterial()->isTransparent()){
|
||||
transparentNodes.push_back(desc);
|
||||
}
|
||||
else{
|
||||
mesh->getMaterial()->getShader()->use();
|
||||
ObjectVertexData ovd;
|
||||
ovd.viewProj = projView;
|
||||
ovd.model = model;
|
||||
//ovd.animated = 0;
|
||||
//ovd.bones[0];
|
||||
MeshData &meshData = mesh->getMeshBase();
|
||||
|
||||
if(d1 > d2)
|
||||
swap(transparentNodes[i], transparentNodes[j]);
|
||||
for(int i = 0; i < drawCmdMeshes.size(); i++)
|
||||
if(*(drawCmdMeshes[i]) == meshData)
|
||||
drawCmds[i].instanceCount++;
|
||||
/*
|
||||
*/
|
||||
|
||||
//for(int i = 0; i < meshData.numShapeKeys; i++) ovd.shapeKeyFactors[i] = meshData.shapeKeys[i].value;
|
||||
|
||||
objVertData.push_back(ovd);
|
||||
|
||||
ObjectFragmentData ofd;
|
||||
ofd.diffuseColor = Vector4::VEC_IJKL;
|
||||
ofd.specularColor;
|
||||
ofd.shinyness;
|
||||
ofd.specularStrength;
|
||||
ofd.lightingEnabled = false,
|
||||
ofd.constLightingEnabled = false,
|
||||
ofd.texturingEnabled = false,
|
||||
ofd.normalMapEnabled = false,
|
||||
ofd.specularMapEnabled = false,
|
||||
ofd.castShadow = false,
|
||||
ofd.environmentMapEnabled = false;
|
||||
objFragData.push_back(ofd);
|
||||
|
||||
//updateNode(desc, projView, gui);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(!desc->getTexts().empty())
|
||||
transparentNodes.push_back(desc);
|
||||
else{
|
||||
//updateNode(desc, proj, view, gui);
|
||||
//opaqueNodes.push_back(desc);
|
||||
}
|
||||
}
|
||||
|
||||
for(Node *node : transparentNodes)
|
||||
node->update();
|
||||
int numNodes = transparentNodes.size();
|
||||
|
||||
for(int i = 0; i < numNodes; i++){
|
||||
float d1 = transparentNodes[i]->getPosition().z;
|
||||
|
||||
if(!gui){
|
||||
Vector3 v1 = transparentNodes[i]->getPosition() - camera->getPosition();
|
||||
float a1 = v1.norm().getAngleBetween(camera->getDirection());
|
||||
d1 = v1.getLength() * cos(a1);
|
||||
}
|
||||
|
||||
for(int j = i; j < numNodes; j++){
|
||||
float d2 = transparentNodes[j]->getPosition().z;
|
||||
|
||||
if(!gui){
|
||||
Vector3 v2 = transparentNodes[j]->getPosition() - camera->getPosition();
|
||||
float a2 = v2.norm().getAngleBetween(camera->getDirection());
|
||||
d2 = v2.getLength() * cos(a2);
|
||||
}
|
||||
|
||||
if(d1 > d2)
|
||||
swap(transparentNodes[i], transparentNodes[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if(gui){} //renderGui();
|
||||
else{
|
||||
renderMeshes();
|
||||
//renderParticles(particleEmitters);
|
||||
}
|
||||
}
|
||||
|
||||
void Root::updateBloomFramebuffer(){
|
||||
@@ -266,7 +536,7 @@ namespace vb01{
|
||||
else
|
||||
pingPongTextures[!horizontal]->select();
|
||||
|
||||
guiPlane->render();
|
||||
renderMesh(guiPlane, guiPlaneVAO);
|
||||
horizontal = !horizontal;
|
||||
}
|
||||
|
||||
@@ -292,7 +562,7 @@ namespace vb01{
|
||||
((Material::TextureUniform*)material->getUniform("bright"))->value->select(1);
|
||||
}
|
||||
|
||||
guiPlane->render();
|
||||
renderMesh(guiPlane, guiPlaneVAO);
|
||||
}
|
||||
|
||||
void Root::createSkybox(string paths[6]){
|
||||
|
||||
Reference in New Issue
Block a user