diff --git a/box.cpp b/box.cpp index 8901662..2988ef2 100755 --- a/box.cpp +++ b/box.cpp @@ -1,13 +1,17 @@ #include "box.h" +#include "root.h" namespace vb01{ - Box::Box(Vector3 size){ - setSize(size); + Box::Box(Vector3 sz) : size(sz){ + init(); } - void Box::setSize(Vector3 size){ - this->size = size; + Box::Box(Box *b){ + size = b->getSize(); + meshBase = b->getMeshBase(); + } + void Box::init(){ Vector3 *pos = new Vector3[8]; pos[0] = Vector3(size.x / 2, size.y / 2, size.z / 2); pos[1] = Vector3(-size.x / 2, size.y / 2, size.z / 2); @@ -67,5 +71,7 @@ namespace vb01{ } meshBase = MeshData(pos, nullptr, nullptr, nullptr, 8, norm, vertices, indices, numTris); + Root *root = Root::getSingleton(); + root->initVertexDataOnGpu(meshBase, root->getMeshVAO(), root->getMeshVBO(), root->getMeshEBO(), true); } } diff --git a/box.h b/box.h index 96c7e1d..254cd7c 100755 --- a/box.h +++ b/box.h @@ -7,9 +7,13 @@ namespace vb01{ class Box : public Mesh{ public: Box(Vector3); - void setSize(Vector3); + inline Box* clone(){return new Box(this);} + inline void setSize(Vector3 size){this->size = size;} inline Vector3 getSize(){return size;} private: + Box(Box*); + void init(); + Vector3 size; }; } diff --git a/driverSample.cpp b/driverSample.cpp index d19fd29..d0764b7 100644 --- a/driverSample.cpp +++ b/driverSample.cpp @@ -121,13 +121,13 @@ int main(){ * The AnimationController plays the animations set in the AnimationChannel objects. * AnimationChannel objects require an animation and animatable objects, e.g. textures to work. */ - AnimationController *controller = AnimationController::getSingleton(); - controller->addAnimation(anim); - AnimationChannel *channel = new AnimationChannel(); - controller->addAnimationChannel(channel); - channel->addAnimatable(driver); - channel->setAnimationName(animName); - channel->setLoop(true); + //AnimationController *controller = AnimationController::getSingleton(); + //controller->addAnimation(anim); + //AnimationChannel *channel = new AnimationChannel(); + //controller->addAnimationChannel(channel); + //channel->addAnimatable(driver); + //channel->setAnimationName(animName); + //channel->setLoop(true); while(true){ root->update(); diff --git a/light.cpp b/light.cpp index b7f02bd..887ee68 100755 --- a/light.cpp +++ b/light.cpp @@ -6,7 +6,7 @@ #include "material.h" #include "mesh.h" -#include "glad.h" +#include #include #include #include @@ -174,7 +174,7 @@ namespace vb01{ else depthMapShader->setMat4(proj * view, "lightMat"); - mesh->render(); + //mesh->render(); } } } diff --git a/lineRenderer.cpp b/lineRenderer.cpp index 186ce88..7e83eab 100644 --- a/lineRenderer.cpp +++ b/lineRenderer.cpp @@ -1,4 +1,5 @@ #include "lineRenderer.h" +#include "camera.h" #include "root.h" #include "glad.h" @@ -41,10 +42,10 @@ namespace vb01{ shader->setMat4(proj, "proj"); shader->setMat4(view, "view"); - glBegin(GL_LINES); - glVertex3f(l.start.x, l.start.y, l.start.z); - glVertex3f(l.end.x, l.end.y, l.end.z); - glEnd(); + //glBegin(GL_LINES); + //glVertex3f(l.start.x, l.start.y, l.start.z); + //glVertex3f(l.end.x, l.end.y, l.end.z); + //glEnd(); } } } diff --git a/mesh.cpp b/mesh.cpp index 91cf395..ee35427 100755 --- a/mesh.cpp +++ b/mesh.cpp @@ -2,11 +2,12 @@ #include "node.h" #include "box.h" #include "quad.h" +#include "camera.h" #include "texture.h" #include "skeleton.h" #include "animation.h" -#include "glad.h" +#include #include #include #include @@ -50,11 +51,11 @@ namespace vb01{ } void Mesh::updateVerts(MeshData meshData){ - glBindBuffer(GL_ARRAY_BUFFER, meshData.VBO); + //glBindBuffer(GL_ARRAY_BUFFER, meshData.VBO); - MeshData::GpuVertex *glVertData = meshBase.toGpuVerts(); - glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(MeshData::GpuVertex) * meshBase.numTris, glVertData); - delete glVertData; + //MeshData::GpuVertex *glVertData = meshBase.toGpuVerts(); + //glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(MeshData::GpuVertex) * meshBase.numTris, glVertData); + //delete glVertData; } void Mesh::update(){ @@ -89,12 +90,12 @@ namespace vb01{ Shader *shader = material->getShader(); material->update(); - shader->setBool(castShadow, "castShadow"); - shader->setBool(skeleton, "animated"); - shader->setMat4(view, "view"); - shader->setMat4(proj, "proj"); - shader->setVec3(camPos, "camPos"); - shader->setMat4(model, "model"); + //shader->setBool(castShadow, "castShadow"); + //shader->setBool(skeleton, "animated"); + //shader->setMat4(view, "view"); + //shader->setMat4(proj, "proj"); + //shader->setVec3(camPos, "camPos"); + //shader->setMat4(model, "model"); if(skeleton) updateSkeleton(shader); @@ -111,8 +112,6 @@ namespace vb01{ if(node) shader->setVec3(pos, "pos"); } - - render(); } void Mesh::updateShapeKeys(Shader *shader){ @@ -228,7 +227,7 @@ namespace vb01{ if(skybox) { glDepthMask(GL_FALSE); glCullFace(GL_FRONT); - skybox->render(); + //root->renderMesh(skybox); glDepthMask(GL_TRUE); glCullFace(GL_BACK); } @@ -261,7 +260,7 @@ namespace vb01{ glDepthMask(GL_FALSE); glCullFace(GL_FRONT); - root->getIblBox()->render(); + //root->renderMesh(root->getIblBox()); glDepthMask(GL_TRUE); glCullFace(GL_BACK); } @@ -301,7 +300,7 @@ namespace vb01{ glDepthMask(GL_FALSE); glCullFace(GL_FRONT); - root->getIblBox()->render(); + //root->getIblBox()->renderMesh(); glDepthMask(GL_TRUE); glCullFace(GL_BACK); } @@ -326,7 +325,7 @@ namespace vb01{ brdfIntegrationShader->setUnsignedInt(numSamples, "numSamples"); Root *root = Root::getSingleton(); - root->getBrdfLutPlane()->render(); + //root->renderMesh(root->getBrdfLutPlane()); glBindRenderbuffer(GL_RENDERBUFFER, *root->getRBO()); glBindFramebuffer(GL_FRAMEBUFFER, *root->getFBO()); @@ -356,12 +355,6 @@ namespace vb01{ postfilterMap->select(postFilterId); } - void Mesh::render(){ - glBindVertexArray(meshBase.VAO); - glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL); - glDrawElements(GL_TRIANGLES, 3 * meshBase.numTris, GL_UNSIGNED_INT, 0); - } - void Mesh::setReflect(bool reflect){ this->reflect = reflect; diff --git a/mesh.h b/mesh.h index 099f259..b043428 100755 --- a/mesh.h +++ b/mesh.h @@ -22,12 +22,12 @@ namespace vb01{ ~Mesh(); void updateVerts(MeshData); virtual void update(); - void render(); void setReflect(bool); inline void setMaterial(Material *mat){this->material = mat;} inline void setCastShadow(bool castShadow){this->castShadow = castShadow;} inline void setReflective(bool r){this->reflective = r;} inline void setWireframe(bool w){this->wireframe = w;} + inline bool isWireframe(){return wireframe;} inline void setSkeleton(Skeleton *sk){this->skeleton = sk;} inline Material* getMaterial(){return material;} inline bool isReflective(){return reflective;} @@ -38,7 +38,7 @@ namespace vb01{ inline Texture* getIrradianceMap(){return irradianceMap;} inline Texture* getPostfilterMap(){return postfilterMap;} inline Texture* getBrdfIntegrationMap(){return brdfIntegrationMap;} - inline MeshData getMeshBase(){return meshBase;} + inline MeshData& getMeshBase(){return meshBase;} private: void initFramebuffer(u32&, u32&, int); void updateSkeleton(Shader*); @@ -61,6 +61,7 @@ namespace vb01{ Skeleton *skeleton = nullptr; protected: Mesh(){} + virtual void init(){} MeshData meshBase; int numShapeKeys = 0; diff --git a/meshData.cpp b/meshData.cpp index 4e384ce..da92040 100644 --- a/meshData.cpp +++ b/meshData.cpp @@ -1,6 +1,7 @@ #include "meshData.h" +#include "root.h" -#include "glad.h" +#include #include #include #include @@ -40,43 +41,7 @@ namespace vb01{ fullSkeletonName(fsn), shapeKeys(sk), numShapeKeys(nsk) - { - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - glGenBuffers(1, &EBO); - - u32 size = sizeof(MeshData::GpuVertex); - - glBindVertexArray(VAO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - - MeshData::GpuVertex *glVertData = toGpuVerts(); - glBufferData(GL_ARRAY_BUFFER, 3 * numTris * size, glVertData, GL_DYNAMIC_DRAW); - delete glVertData; - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * numTris * sizeof(u32), indices, GL_STATIC_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 < numShapeKeys; i++){ - glVertexAttribPointer(7 + i, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, shapeKeyOffsets) + 3 * i * sizeof(float))); - glEnableVertexAttribArray(7 + i); - } - } + {} void MeshData::ShapeKey::animate(float value, KeyframeChannel keyframeChannel){ switch(keyframeChannel.type){ @@ -92,29 +57,45 @@ namespace vb01{ } } - MeshData::GpuVertex* MeshData::toGpuVerts(){ + //TODO replace number of max bone influences literal + vector MeshData::toGpuVerts(){ int numVertices = 3 * numTris; - GpuVertex *vertData = new GpuVertex[numVertices]; + vector vertData; for(int i = 0; i < numVertices; i++){ - vertData[i].pos = *vertices[i].pos; - vertData[i].norm = *vertices[i].norm; - vertData[i].tan = vertices[i].tan; - vertData[i].biTan = vertices[i].biTan; - vertData[i].uv = vertices[i].uv; + MeshData::GpuVertex gpuVert; + gpuVert.pos = *vertices[i].pos; + gpuVert.norm = *vertices[i].norm; + gpuVert.tan = vertices[i].tan; + gpuVert.biTan = vertices[i].biTan; + gpuVert.uv = vertices[i].uv; if(weights){ for(int j = 0; j < 4; j++){ - vertData[i].weights[j] = vertices[i].weights[j]; - vertData[i].boneIndices[j] = vertices[i].boneIndices[j]; + gpuVert.weights[j] = vertices[i].weights[j]; + gpuVert.boneIndices[j] = vertices[i].boneIndices[j]; } } + /* - if(shapeKeyOffsets) - for(int j = 0; j < 100; j++) - vertData[i].shapeKeyOffsets[j] = vertices[i].shapeKeyOffsets[j]; + */ + if(shapeKeyOffsets){ + const int MAX_NUM_SHAPE_KEYS = Root::getSingleton()->getMaxNumShapeKeys(); + + for(int j = 0; j < MAX_NUM_SHAPE_KEYS; j++) + gpuVert.shapeKeyOffsets[j] = vertices[i].shapeKeyOffsets[j]; + } + + vertData.push_back(gpuVert); } return vertData; } + + bool MeshData::operator==(MeshData &meshData){ + bool samePos = (positions == meshData.positions); + bool sameNorm = (normals == meshData.normals); + bool sameSkOffsets = (shapeKeyOffsets == meshData.shapeKeyOffsets); + return samePos && sameNorm && sameSkOffsets; + } } diff --git a/meshData.h b/meshData.h index add53c6..f71cc07 100644 --- a/meshData.h +++ b/meshData.h @@ -24,7 +24,7 @@ namespace vb01{ Vector2 uv; float weights[4]{0, 0, 0, 0}; int boneIndices[4]{-1, -1, -1, -1}; - Vector3 shapeKeyOffsets[100]; + Vector3 shapeKeyOffsets[5]; }; struct Vertex{ @@ -35,7 +35,7 @@ namespace vb01{ Vector3 *shapeKeyOffsets = nullptr; }; - GpuVertex* toGpuVerts(); + std::vector toGpuVerts(); Vector3 *positions = nullptr, *normals = nullptr, **shapeKeyOffsets = nullptr; float **weights = nullptr; @@ -43,12 +43,13 @@ namespace vb01{ Vertex *vertices; std::string *vertexGroups = nullptr; ShapeKey *shapeKeys = nullptr; - u32 *indices, VAO, VBO, EBO; + u32 *indices; int numPos, numTris, numVertexGroups = 0, numShapeKeys = 0; std::string attachableName = "", fullSkeletonName = ""; MeshData(){} MeshData(Vector3*, float**, int**, Vector3**, int, Vector3*, Vertex*, u32*, int, std::string = "", std::string *vg = nullptr, int = 0, std::string = "", ShapeKey *sk = nullptr, int = 0); + bool operator==(MeshData&); }; } diff --git a/node.cpp b/node.cpp index 4b0fbac..46a9e7e 100755 --- a/node.cpp +++ b/node.cpp @@ -62,8 +62,7 @@ namespace vb01{ l->update(render); if(render){ - for(Mesh *m : meshes) - m->update(); + //for(Mesh *m : meshes) m->update(); for(Text *t : texts) t->update(); diff --git a/node.h b/node.h index 59924c7..82cecd2 100755 --- a/node.h +++ b/node.h @@ -54,6 +54,7 @@ namespace vb01{ inline std::vector& getTexts(){return texts;} inline std::vector& getMeshes(){return meshes;} inline std::vector& getSkeletons(){return skeletons;} + inline std::vector& getParticleEmitters(){return emitters;} inline Mesh* getMesh(int i){return meshes[i];} inline int getNumMeshes(){return meshes.size();} inline ParticleEmitter* getParticleEmitter(int i){return emitters[i];} diff --git a/particleEmitter.cpp b/particleEmitter.cpp index fdf78e7..f6fca7d 100755 --- a/particleEmitter.cpp +++ b/particleEmitter.cpp @@ -1,5 +1,5 @@ #include -#include "glad.h" +#include #include #include #include diff --git a/phong4.frag b/phong4.frag new file mode 100755 index 0000000..56e393f --- /dev/null +++ b/phong4.frag @@ -0,0 +1,196 @@ +#version 460 core +const int numLights=1; +const bool checkLights=false; + +in flat int drawId, instanceId; +in vec3 fragPos; +in vec3 tan; +in vec3 biTan; +in vec3 norm; +in vec2 texCoords; +in vec4 lightSpaceFragPos; + +layout (location = 0) out vec4 FragColor; +layout (location = 1) out vec4 BrightColor; + +//0-POINT,1-DIRECTIONAL,2-SPOT + +struct Light{ + bool useAngle, additive, render; + int type, attenuation; + vec3 pos, color, direction; + float innerAngle, outerAngle; + float a, b, c, near, far, radius; + //sampler2D depthMap; + //samplerCube depthMapCube; + mat4 lightMat; +}; + +struct Texture{ + float mixRatio; + sampler2D pastTexture, nextTexture; + bool animated; +}; + +layout(std430, binding = 2) readonly buffer lightsSSBO { + Light lights[]; +}; + +struct ObjectFragData{ + bool lightingEnabled, constLightingEnabled, texturingEnabled, normalMapEnabled, specularMapEnabled, castShadow, environmentMapEnabled; + vec4 diffuseColor, specularColor; + float shinyness, specularStrength; +}; + +layout(std430, binding = 1) buffer objFragSSBO { + //vec3 camPos; + ObjectFragData objData[]; +}; + +uniform Texture textures[4]; +uniform samplerCube environmentMap; + +float linDepth(float depth, int i){ + float z = depth * 2 - 1, near = lights[i].near, far = lights[i].far; + return (2 * near * far) / (far + near - z * (far - near)); +} + +float getShadow(int id){ + int type = lights[id].type; + + float shadow = 0, closestDepth = 0, currentDepth = 0, bias = .005, val = .7; + + /* + if(type == 0){ + vec3 projDir = fragPos - lights[id].pos; + closestDepth = texture(lights[id].depthMapCube, projDir).r * lights[id].far; + currentDepth = length(projDir); + shadow = (currentDepth - bias > closestDepth) ? val : 0; + } + else{ + vec4 lightSpaceFragPos = lights[id].lightMat * vec4(fragPos, 1); + vec3 projCoords = (lightSpaceFragPos.xyz / lightSpaceFragPos.w) * .5 + .5; + closestDepth = texture(lights[id].depthMap, projCoords.xy).r; + currentDepth = projCoords.z; + + if(type == 2) + closestDepth = linDepth(closestDepth, id); currentDepth = linDepth(currentDepth, id); + + shadow = (currentDepth - bias > closestDepth) ? val : 0; + + if(projCoords.z > 1) + shadow = 0; + } + */ + + return shadow; +} + +void main(){ + vec4 finalColor = objData[drawId + instanceId].diffuseColor; + + /* + if(texturingEnabled){ + vec4 textureColor = texture(textures[0].pastTexture, texCoords); + vec4 mixedTexColor = mix(textureColor, texture(textures[0].nextTexture, texCoords), textures[0].mixRatio); + finalColor = (textures[0].animated ? mix(textureColor, texture(textures[0].nextTexture, texCoords), textures[0].mixRatio) : textureColor); + } + */ + + vec3 normal = norm; + + /* + if(lightingEnabled){ + if(normalMapEnabled){ + vec3 n = normalize(vec3(texture(textures[1].pastTexture, texCoords)) * 2 - 1); + + if(textures[1].animated) + n = mix(n, normalize(texture(textures[1].nextTexture, texCoords).rgb * 2 - 1), textures[1].mixRatio); + + normal = mat3(tan, biTan, norm) * n; + } + + vec3 diffuseCol = vec3(0), specularCol = vec3(0); + + if(checkLights){ + bool addedLighting = false; + + for(int i = 0; i < numLights; i++){ + if(!lights[i].render) continue; + + vec3 lightDir = vec3(0), viewDir = normalize(camPos - fragPos); + float attenuation = 1, coef = 1; + float factor = 0; + bool canAdd = false; + + if(lights[i].type == 0){ + lightDir = normalize(lights[i].pos - fragPos); + float dist = length(lights[i].pos - fragPos), radius = lights[i].radius; + + if(lights[i].attenuation == 0){ + float a = lights[i].a, b = lights[i].b, c = lights[i].c; + attenuation = 1.0 / (a * dist * dist + b * dist + c); + factor = (lights[i].useAngle ? max(dot(lightDir, normalize(normal)), 0.) : 1) * attenuation; + } + else if(lights[i].attenuation == 1 && dist < radius && radius > 0){ + canAdd = !lights[i].additive; + factor = 1.0 - dist / lights[i].radius; + } + else if(lights[i].attenuation == 2 && dist < radius && radius > 0){ + canAdd = !lights[i].additive; + factor = 1; + } + } + else if(lights[i].type == 1){ + lightDir = -normalize(lights[i].direction); + factor = max(dot(lightDir, normalize(normal)), 0.) * attenuation; + } + else if(lights[i].type == 2){ + lightDir = normalize(lights[i].pos - fragPos); + float innerAngle = lights[i].innerAngle; + float angle = acos(dot(-lightDir, lights[i].direction)); + float outerAngle = lights[i].outerAngle; + + if(lights[i].innerAngle <= angle && angle <= lights[i].outerAngle) + coef = (angle - outerAngle) / (innerAngle - outerAngle); + + if(angle > lights[i].outerAngle) + continue; + + factor = max(dot(lightDir, normalize(normal)), 0.) * attenuation * coef; + } + else factor = 1; + + + if(lights[i].additive) + diffuseCol += lights[i].color * factor; + else if(!lights[i].additive && constLightingEnabled && !addedLighting && canAdd){ + addedLighting = true; + diffuseCol += lights[i].color * factor; + } + + if(specularMapEnabled){ + float specularSample = texture(textures[2].pastTexture, texCoords).r; + vec3 halfwayVec = normalize(lightDir + viewDir); + float spec = pow(max(dot(normal, halfwayVec), 0), shinyness); + specularCol += specularStrength * spec * specularSample * lights[i].color; + } + + if(castShadow) + diffuseCol *= (1.0 - getShadow(i)); + } + } + + finalColor *= vec4(diffuseCol + specularCol, 1); + } + */ + + float brightness = dot(finalColor.rgb, vec3(0.2126, 0.7152, 0.0722)); + + if(brightness > 1) + BrightColor = vec4(finalColor.rgb, 1); + + //FragColor = vec4(fragPos,1); + FragColor = vec4(1,1,0,1); + //FragColor = finalColor; +} diff --git a/phong4.geo b/phong4.geo new file mode 100644 index 0000000..826ad1a --- /dev/null +++ b/phong4.geo @@ -0,0 +1,39 @@ +#version 430 core + +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; + +in VS_OUT{ + vec2 tCoords; +}gs_in[]; + +out vec4 FragPos; +out vec2 texCoords; + +uniform mat4 shadowMat[6]; +uniform bool environment; + +void main(){ +/* + if(environment) + for(int i = 0; i < 6; i++){ + gl_Layer = i; + for(int j = 0; j < 3; j++){ + FragPos = gl_in[j].gl_Position; + gl_Position = shadowMat[i] * FragPos; + EmitVertex(); + } + EndPrimitive(); + } +*/ +gl_Position = gl_in[0].gl_Position; +texCoords = gs_in[0].tCoords; +EmitVertex(); +gl_Position = gl_in[1].gl_Position; +texCoords = gs_in[1].tCoords; +EmitVertex(); +gl_Position = gl_in[2].gl_Position; +texCoords = gs_in[2].tCoords; +EmitVertex(); +EndPrimitive(); +} diff --git a/phong4.vert b/phong4.vert new file mode 100755 index 0000000..c7f6a9f --- /dev/null +++ b/phong4.vert @@ -0,0 +1,153 @@ +#version 460 core + +const int numBones = 1; +const int numVertGroups = 0; +const int numMaxInfluences = 4; +const int numShapeKeys = 4; + +mat4 transform[numBones]; +mat4 poseTransform[numBones]; + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNorm; +layout (location = 2) in vec2 aTexCoords; +layout (location = 3) in vec3 aTan; +layout (location = 4) in vec3 aBiTan; +layout (location = 5) in vec4 aWeight; +layout (location = 6) in ivec4 aBoneIndices; +//layout (location = 7) in vec3 aShapeKeyOffsets[numShapeKeys]; + +out vec3 fragPos, norm, tan, biTan; +out vec2 texCoords; +out int drawId, instanceId; + +struct Bone{ + float angle; + vec3 pos, trans, rotAxis, scale; + int vertGroup, parent; +}; + +struct ObjectVertData{ + float shapeKeyFactors[24]; + mat4 viewProj, model, bones[256]; + //bool animated; +}; + +layout(std430, binding = 0) readonly restrict buffer objVertSSBO { + ObjectVertData objData[]; +}; + +mat4 createTranslationMatrix(vec3 trans){ + mat4 transMat; + transMat[0] = vec4(1, 0, 0, trans.x); + transMat[1] = vec4(0, 1, 0, trans.y); + transMat[2] = vec4(0, 0, 1, trans.z); + transMat[3] = vec4(0, 0, 0, 1); + return transpose(transMat); +} + +mat4 createRotationMatrix(float angle, vec3 axis){ + mat4 rotMat; + + float s = sin(-angle); + float c = cos(-angle); + float oc = 1.0 - c; + + rotMat[0] = vec4(oc * axis.x * axis.x + c,oc * axis.x * axis.y + axis.z * s,oc * axis.z * axis.x - axis.y * s, 0.0); + rotMat[1] = vec4(oc * axis.x * axis.y - axis.z * s,oc * axis.y * axis.y + c,oc * axis.y * axis.z + axis.x * s, 0.0); + rotMat[2] = vec4(oc * axis.z * axis.x + axis.y * s,oc * axis.y * axis.z - axis.x * s,oc * axis.z * axis.z + c, 0.0); + rotMat[3] = vec4(0, 0, 0, 1); + + return transpose(rotMat); +} + +mat4 createScaleMatrix(vec3 scale){ + mat4 scaleMat; + scaleMat[0] = vec4(scale.x, 0, 0, 0); + scaleMat[1] = vec4(0, scale.y, 0, 0); + scaleMat[2] = vec4(0, 0, scale.z, 0); + scaleMat[3] = vec4(0, 0, 0, 1); + return scaleMat; +} + +float getWeight(Bone bone){ + float weight = 0; + for(int i = 0; i < numMaxInfluences; i++){ + if(bone.vertGroup == aBoneIndices[i]) + weight = aWeight[i]; + } + return weight; +} + +void main(){ + vec4 vertPos = vec4(aPos, 1); + bool anyWeights = false; + + //int id = 0; + int id = gl_DrawID + gl_InstanceID; + mat4 model = objData[id].model; + mat3 normalMat = mat3(transpose(inverse(model))); + norm = (normalMat * aNorm); + tan = (normalMat * aTan); + biTan = (normalMat * aBiTan); + + for(int i = 0; i < numMaxInfluences; i++) + if(aWeight[i] > 0) + anyWeights = true; + /* + + for(int i = 0; i < numShapeKeys; i++){ + vertPos.xyz += aShapeKeyOffsets[i] * shapeKeyFactors[i]; + } + if(animated && anyWeights){ + for(int i = 0; i < numBones; i++){ + transform[i] = createTranslationMatrix(bones[i].pos); + vec3 trans = bones[i].trans; + float angle = bones[i].angle; + vec3 axis = bones[i].rotAxis; + vec3 scale = bones[i].scale; + mat4 animTransform = createTranslationMatrix(trans) * createRotationMatrix(angle, axis) * createScaleMatrix(scale); + poseTransform[i] = transform[i] * animTransform; + } + + for(int i = 1; i < numBones; i++){ + mat4 localTransform = inverse(transform[bones[i].parent]) * poseTransform[i]; + poseTransform[i] = poseTransform[bones[i].parent] * localTransform; + } + + vec3 v0 = vec3(0), n0 = vec3(0), t0 = vec3(0), b0 = vec3(0); + for(int i = 0; i < numBones; i++){ + float weight = getWeight(bones[i]); + mat4 inverseTransform = inverse(transform[i]); + vec4 boneLocalVert = inverseTransform * vertPos; + vec4 boneLocalNorm = inverseTransform * vec4(aNorm, 0); + vec4 boneLocalTan = inverseTransform * vec4(aTan, 0); + vec4 boneLocalBiTan = inverseTransform * vec4(aBiTan, 0); + + v0 += (weight * poseTransform[i] * boneLocalVert).xyz; + mat4 normalPoseTrans = transpose(inverse(poseTransform[i])); + n0 += (weight * normalPoseTrans * boneLocalNorm).xyz; + t0 += (weight * normalPoseTrans * boneLocalTan).xyz; + b0 += (weight * normalPoseTrans * boneLocalBiTan).xyz; + + } + vertPos.xyz = v0; + norm = n0; + tan = t0; + biTan = b0; + } + */ + + norm = normalize(normalMat * norm); + tan = normalize(normalMat * tan); + biTan = normalize(normalMat * biTan); + + mat4 viewProj = objData[id].viewProj; + mat4 rotMat = createRotationMatrix(.3, normalize(vec3(1,1,1))); + + gl_Position = viewProj * model * vertPos; + fragPos = vec3(model * vertPos); + texCoords = aTexCoords; + drawId = gl_DrawID; + instanceId = gl_InstanceID; +} diff --git a/quad.cpp b/quad.cpp index 57508df..9d02e47 100755 --- a/quad.cpp +++ b/quad.cpp @@ -1,21 +1,23 @@ #include "quad.h" +#include "root.h" #include namespace vb01{ using namespace std; - Quad::Quad(Vector3 size, bool spatial, int numVertDiv, int numHorDiv){ - this->spatial = spatial; - this->numVertDiv = numVertDiv; - this->numHorDiv = numHorDiv; + Quad::Quad(Vector3 sz, bool sp, int nvd, int nhd) : size(sz), spatial(sp), numVertDiv(nvd), numHorDiv(nhd){ + init(); + } - setSize(size); + Quad::Quad(Quad *q){ + size = q->getSize(); + numVertDiv = q->getNumVertSubquads() - 1; + numHorDiv = q->getNumHorSubquads() - 1; + meshBase = q->getMeshBase(); } - void Quad::setSize(Vector3 size){ - this->size = size; - + void Quad::init(){ const int numHorQuads = numVertDiv + 1, numVertQuads = numHorDiv + 1; const int numVertPos = (numHorQuads + 1) * (numVertQuads + 1), numTris = 2 * numHorQuads * numVertQuads, numVerts = 3 * numTris; Vector2 subQuadSize = Vector2(size.x / numHorQuads, size.y / numVertQuads); @@ -84,6 +86,7 @@ namespace vb01{ } meshBase = MeshData(faceVertPos, nullptr, nullptr, nullptr, 6, norm, vertices, indices, numTris); + //Root::getSingleton()->initVertexDataOnGpu(meshBase); } //TODO improve functionality for GUI quads diff --git a/quad.h b/quad.h index 6d93dda..1a68d78 100755 --- a/quad.h +++ b/quad.h @@ -8,14 +8,18 @@ namespace vb01{ class Quad : public Mesh{ public: Quad(Vector3, bool = true, int numVertDiv = 0, int numHorDiv = 0); - void setSize(Vector3); Vector3 getSubquadCorner(int, int, int, int, bool, bool); Vector2 getSubquadIds(int, int, Vector3, Vector3); + inline Quad* clone(){return new Quad(this);} + inline void setSize(Vector3 size){this->size = size;} inline Vector3 getSize(){return size;} inline Vector2 getSubquadSize(){return Vector2(size.x / (numHorDiv + 1), size.y / (numVertDiv + 1));} inline int getNumHorSubquads(){return numHorDiv + 1;} inline int getNumVertSubquads(){return numVertDiv + 1;} private: + Quad(Quad*); + void init(); + Vector3 size; bool spatial; int numVertDiv, numHorDiv; diff --git a/root.cpp b/root.cpp index f097bf5..b5a9e86 100755 --- a/root.cpp +++ b/root.cpp @@ -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 -#include +#include + +#include +#include + +#include #include 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 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 descendants; + rootNode->getDescendants(descendants); + + vector meshes; + + for(Node *desc : descendants){ + vector 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 &particleEmitters){ + } + + void Root::renderGui(vector &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 = node->getMeshes(); + vector 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 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 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]){ diff --git a/root.h b/root.h index 614a76c..a300723 100755 --- a/root.h +++ b/root.h @@ -1,9 +1,16 @@ #ifndef ROOT_H #define ROOT_H -#include "camera.h" #include "util.h" +#include "meshData.h" +#include + +#include + +#include + +#include #include #include @@ -12,19 +19,31 @@ class GLFWwindow; namespace vb01{ void foo(); + class Camera; class Mesh; class Box; class Quad; class Node; class Texture; class Shader; + class ParticleEmitter; class Root{ public: + static Root* getSingleton(); void update(); void start(int, int, std::string, std::string); void toggleHDR(bool); void toggleBloom(bool); + void addMeshes(Node*); + void createSkybox(std::string[6]); + void createSkybox(vb01::Texture*); + void removeSkybox(); + void initVertexDataOnGpu(MeshData&, u32&, u32&, u32&, bool); + inline u32& getMeshVAO(){return meshVAO;} + inline u32& getMeshVBO(){return meshVBO;} + inline u32& getMeshEBO(){return meshEBO;} + inline const int getMaxNumShapeKeys(){return MAX_NUM_SHAPE_KEYS;} inline Camera* getCamera(){return camera;} inline Node* getRootNode(){return rootNode;} inline Node* getGuiNode(){return guiNode;} @@ -39,38 +58,69 @@ namespace vb01{ inline Box* getSkybox(){return skybox;} inline Box* getIblBox(){return iblBox;} inline Quad* getBrdfLutPlane(){return brdfLutPlane;} - void createSkybox(std::string[6]); - void createSkybox(vb01::Texture*); - void removeSkybox(); - static Root* getSingleton(); inline void shiftNumLights(bool increase){numLights += (increase ? 1 : -1);} inline int getNumLights(){return numLights;} inline std::string getLibPath(){return libPath;} private: - int numLights = 0; + struct DrawElementsIndirectCommand { + u32 count = 0; + u32 instanceCount = 0; + u32 firstIndex = 0; + int baseVertex = 0; + u32 baseInstance = 0; + }; + struct ObjectVertexData { + float shapeKeyFactors[24]; + glm::mat4 viewProj, model, bones[256]; + //bool animated; + }; + struct ObjectFragmentData { + Vector4 diffuseColor, specularColor; + float shinyness, specularStrength; + bool lightingEnabled, constLightingEnabled, texturingEnabled, normalMapEnabled, specularMapEnabled, castShadow, environmentMapEnabled; + }; + + const int MAX_NUM_SHAPE_KEYS = 5; + int NUM_MAX_TEXTURE_UNITS = 0, NUM_MAX_TEXTURE_ARRAY_SIZE = 0, numLights = 0, width, height, blurLevel = 10, currNumVerts = 0, currNumIndexes = 0; + u32 meshVAO, meshVBO, meshEBO, particleVAO, particleVBO, guiPlaneVAO, guiPlaneVBO, guiPlaneEBO, FBO, RBO, pingpongBuffers[2], drawCmdBuffer = -1, objVertBuffer = -1, objFragBuffer = -1; bool bloom = false, hdr = false; float exposure = 1, gamma = 1; Box *skybox = nullptr, *iblBox = nullptr; Quad *guiPlane = nullptr, *brdfLutPlane = nullptr; - int width, height, blurLevel = 10; - u32 FBO, RBO, pingpongBuffers[2]; GLFWwindow *window; Node *rootNode, *guiNode; Camera *camera; Shader *blurShader; Texture *pingPongTextures[2]; + std::vector drawCmdMeshes; + std::vector currentGpuVertices; + std::vector currentIndices; std::vector meshes; + std::vector drawCmds; + std::vector objVertData; + std::vector objFragData; std::string libPath; - void framebuffer_size_callback(GLFWwindow*, int, int); Root(); + void framebuffer_size_callback(GLFWwindow*, int, int); + void renderMeshes(); + void renderParticles(std::vector&); + void renderGui(std::vector&); void initWindow(std::string); void initMainFramebuffer(Texture*, Texture*); void initBloomFramebuffer(); - void initGuiPlane(Texture*, Texture*); + void initGuiPlane(); void updateBloomFramebuffer(); void updateGuiPlane(); - void updateNodeTree(vb01::Node*, bool); + void updateNodeTree(vb01::Node*, glm::mat4&, bool); + void updateNode(vb01::Node*, glm::mat4&, glm::mat4&, bool); + void renderMesh(Mesh*, u32&); + protected: + virtual void initMeshRendering(u32 &vao, u32 &vbo, u32 &ebo); + virtual void initParticleRendering(); + virtual void initGuiRendering(); + virtual void initPostProcessing(); + virtual void postProcess(){} }; } diff --git a/shader.cpp b/shader.cpp index 6779cd2..b98b45d 100755 --- a/shader.cpp +++ b/shader.cpp @@ -1,4 +1,4 @@ -#include "glad.h" +#include #include #include diff --git a/texture.cpp b/texture.cpp index 503e822..3956104 100755 --- a/texture.cpp +++ b/texture.cpp @@ -8,7 +8,7 @@ #include "assetManager.h" #include "imageAsset.h" -#include "glad.h" +#include #include #include diff --git a/xmlModelReader.cpp b/xmlModelReader.cpp index 1e77a36..cb771bf 100644 --- a/xmlModelReader.cpp +++ b/xmlModelReader.cpp @@ -207,6 +207,9 @@ namespace vb01{ shapeKeys, numShapeKeys ); + + Root *root = Root::getSingleton(); + root->initVertexDataOnGpu(meshData, root->getMeshVAO(), root->getMeshVBO(), root->getMeshEBO(), true); Mesh *mesh = new Mesh(meshData); return mesh;