Box/Quad clone methods

Phong lighting shaders
using multi draw indirect rendering
This commit is contained in:
devZoGok
2026-06-26 09:40:46 +03:00
parent 02c0c3b3fc
commit cc59f9160c
22 changed files with 873 additions and 168 deletions
+317 -47
View File
@@ -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]){