From adc4756094112ca3dda7d23d6c4c8e6549b62d9e Mon Sep 17 00:00:00 2001 From: Engin Manap Date: Tue, 11 Dec 2018 01:43:43 +0300 Subject: [PATCH] Add basic SSAO It is not working as it should, consider it experimental at best. --- Engine/Shaders/Model/fragment.glsl | 61 +++++++++++++++++-- Engine/Shaders/Model/vertex.glsl | 2 + Engine/Shaders/Model/vertexAnimated.glsl | 2 + Engine/Shaders/SSAO/fragment.glsl | 6 ++ Engine/Shaders/SSAO/vertex.glsl | 43 ++++++++++++++ src/GLHelper.cpp | 74 ++++++++++++++++++++++-- src/GLHelper.h | 14 ++++- src/GameObjects/Model.cpp | 38 ++++++++++++ src/GameObjects/Model.h | 1 + src/World.cpp | 35 +++++++++++ src/World.h | 4 +- 11 files changed, 265 insertions(+), 15 deletions(-) create mode 100644 Engine/Shaders/SSAO/fragment.glsl create mode 100644 Engine/Shaders/SSAO/vertex.glsl diff --git a/Engine/Shaders/Model/fragment.glsl b/Engine/Shaders/Model/fragment.glsl index ccc35f16..00d13125 100644 --- a/Engine/Shaders/Model/fragment.glsl +++ b/Engine/Shaders/Model/fragment.glsl @@ -7,7 +7,9 @@ layout (std140) uniform PlayerTransformBlock { mat4 camera; mat4 projection; mat4 cameraProjection; + mat4 inverseTransposeProjection; vec3 position; + vec2 noiseScale; } playerTransforms; struct LightSource @@ -44,6 +46,8 @@ out vec4 finalColor; uniform sampler2DArray shadowSamplerDirectional; uniform samplerCubeArray shadowSamplerPoint; +uniform sampler2D ssaoSampler; +uniform sampler2D ssaoNoiseSampler; uniform sampler2D ambientSampler; uniform sampler2D diffuseSampler; @@ -51,7 +55,7 @@ uniform sampler2D specularSampler; uniform sampler2D opacitySampler; uniform sampler2D normalSampler; -uniform vec3 pointSampleOffsetDirections[20] = vec3[] +vec3 pointSampleOffsetDirections[20] = vec3[] ( vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1), vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1), @@ -60,6 +64,9 @@ uniform vec3 pointSampleOffsetDirections[20] = vec3[] vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1) ); +uniform vec3 ssaoKernel[128]; +uniform int ssaoSampleCount; + float ShadowCalculationDirectional(vec4 fragPosLightSpace, float bias, float lightIndex){ // perform perspective divide vec3 projectedCoordinates = fragPosLightSpace.xyz / fragPosLightSpace.w; @@ -112,6 +119,13 @@ float ShadowCalculationPoint(vec3 fragPos, float bias, float viewDistance, int l return shadow; } +vec3 calcViewSpacePos(vec3 screen) { + vec4 temp = vec4(screen.x, screen.y, screen.z, 1); + temp *= playerTransforms.inverseTransposeProjection; + vec3 camera_space = temp.xyz / temp.w; + return camera_space; +} + void main(void) { vec4 objectColor; if((material.isMap & 0x0004)!=0) { @@ -132,16 +146,51 @@ void main(void) { objectColor = vec4(material.diffuse, 1.0); } - vec3 lightingColorFactor = material.ambient; - if((material.isMap & 0x0008)!=0) { - lightingColorFactor = vec3(texture(ambientSampler, from_vs.textureCoord)); - } - vec3 normal = from_vs.normal; + if((material.isMap & 0x0010) != 0) { normal = -1 * vec3(texture(normalSampler, from_vs.textureCoord)); } + float occlusion = 0.0; + + if(length(playerTransforms.position - from_vs.fragPos) < 100) { + vec3 randomVec = texture(ssaoNoiseSampler, from_vs.fragPos.xy * playerTransforms.noiseScale).xyz; + + vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 TBN = mat3(tangent, bitangent, normal); + + float uRadius = 0.5f; + for(int i = 0; i < ssaoSampleCount; ++i){ + // get sample position + vec3 samplePosition = TBN * ssaoKernel[i]; // From tangent to view-space + samplePosition = samplePosition * uRadius; + samplePosition += vec3(from_vs.fragPos); + + vec4 offset = vec4(samplePosition, 1.0); + offset = playerTransforms.cameraProjection * offset; // from view to clip-space + offset.xyz /= offset.w; // perspective divide + offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0 + + float sampleDepth = texture(ssaoSampler, offset.xy).r; + + vec3 realElement = calcViewSpacePos(vec3(offset.xy, sampleDepth)); + vec3 kernelElement = calcViewSpacePos(offset.xyz); + + float rangeCheck= abs(realElement.z - kernelElement.z) < 1 ? 1.0 : 0.0; + occlusion += (realElement.z >= kernelElement.z ? 1.0 : 0.0) * rangeCheck; + } + + occlusion = occlusion / ssaoSampleCount; + } + occlusion = 1 - occlusion; + + vec3 lightingColorFactor = (material.ambient) * occlusion; + if((material.isMap & 0x0008)!=0) { + lightingColorFactor = vec3(texture(ambientSampler, from_vs.textureCoord)); + } + float shadow; for(int i=0; i < NR_POINT_LIGHTS; ++i){ if(LightSources.lights[i].type != 0) { diff --git a/Engine/Shaders/Model/vertex.glsl b/Engine/Shaders/Model/vertex.glsl index 13eb3b88..43f99cf2 100644 --- a/Engine/Shaders/Model/vertex.glsl +++ b/Engine/Shaders/Model/vertex.glsl @@ -19,7 +19,9 @@ layout (std140) uniform PlayerTransformBlock { mat4 camera; mat4 projection; mat4 cameraProjection; + mat4 inverseTransposeProjection; vec3 position; + vec2 noiseScale; } playerTransforms; struct LightSource diff --git a/Engine/Shaders/Model/vertexAnimated.glsl b/Engine/Shaders/Model/vertexAnimated.glsl index 7aae0a37..64f0dfeb 100644 --- a/Engine/Shaders/Model/vertexAnimated.glsl +++ b/Engine/Shaders/Model/vertexAnimated.glsl @@ -23,7 +23,9 @@ layout (std140) uniform PlayerTransformBlock { mat4 camera; mat4 projection; mat4 cameraProjection; + mat4 inverseTransposeProjection; vec3 position; + vec2 noiseScale; } playerTransforms; struct LightSource diff --git a/Engine/Shaders/SSAO/fragment.glsl b/Engine/Shaders/SSAO/fragment.glsl new file mode 100644 index 00000000..31bb7b76 --- /dev/null +++ b/Engine/Shaders/SSAO/fragment.glsl @@ -0,0 +1,6 @@ +#version 330 core +#define NR_POINT_LIGHTS 4 + +void main() { + //gl_FragDepth = FragPos.z; +} \ No newline at end of file diff --git a/Engine/Shaders/SSAO/vertex.glsl b/Engine/Shaders/SSAO/vertex.glsl new file mode 100644 index 00000000..58613df9 --- /dev/null +++ b/Engine/Shaders/SSAO/vertex.glsl @@ -0,0 +1,43 @@ +#version 330 core + +#define NR_POINT_LIGHTS 4 +#define NR_BONE 128 +#define NR_MAX_MODELS 1000 + + +layout (location = 2) in vec4 position; +layout (location = 5) in uvec4 boneIDs; +layout (location = 6) in vec4 boneWeights; + +layout (std140) uniform PlayerTransformBlock { + mat4 camera; + mat4 projection; + mat4 cameraProjection; + mat4 inverseTransposeProjection; + vec3 position; + vec2 noiseScale; +} playerTransforms; + +layout (std140) uniform ModelInformationBlock { + mat4 worldTransform[NR_MAX_MODELS]; +} model; + +layout (std140) uniform ModelIndexBlock { + uvec4 models[NR_MAX_MODELS]; +} instance; + +uniform mat4 boneTransformArray[NR_BONE]; +uniform int isAnimated; + +void main() { + if(isAnimated==1) { + mat4 BoneTransform = mat4(1.0); + BoneTransform = boneTransformArray[boneIDs[0]] * boneWeights[0]; + BoneTransform += boneTransformArray[boneIDs[1]] * boneWeights[1]; + BoneTransform += boneTransformArray[boneIDs[2]] * boneWeights[2]; + BoneTransform += boneTransformArray[boneIDs[3]] * boneWeights[3]; + gl_Position = playerTransforms.cameraProjection * (model.worldTransform[instance.models[gl_InstanceID].x] * (BoneTransform * vec4(vec3(position), 1.0))); + } else { + gl_Position = playerTransforms.cameraProjection * (model.worldTransform[instance.models[gl_InstanceID].x] * position); + } +} \ No newline at end of file diff --git a/src/GLHelper.cpp b/src/GLHelper.cpp index 5d7cdb25..a06fb46e 100644 --- a/src/GLHelper.cpp +++ b/src/GLHelper.cpp @@ -2,6 +2,7 @@ // Created by Engin Manap on 10.02.2016. // +#include #include "GLHelper.h" #include "GLSLProgram.h" @@ -222,6 +223,9 @@ void GLHelper::attachGeneralUBOs(const GLuint program){//Attach the light block GLHelper::GLHelper(Options *options): options(options) { + + this->screenHeight = options->getScreenHeight(); + this->screenWidth = options->getScreenWidth(); GLenum rev; error = GL_NO_ERROR; glewExperimental = GL_TRUE; @@ -389,8 +393,48 @@ GLHelper::GLHelper(Options *options): options(options) { glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + checkErrors("Constructor bf ssao"); + + //create depth buffer for SSAO + glGenFramebuffers(1, &depthOnlyFrameBufferSSAO); + glGenTextures(1, &depthMapSSAO); + glBindTexture(GL_TEXTURE_2D, depthMapSSAO); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + glBindTexture(GL_TEXTURE_2D, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferSSAO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMapSSAO, 0); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0); + /****************************** SSAO KERNEL AND NOISE **************************************/ + std::uniform_real_distribution randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0 + std::default_random_engine generator; + // generate noise texture + // ---------------------- + std::vector ssaoNoise; + for (unsigned int i = 0; i < 16; i++) + { + glm::vec3 noise(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, 0.0f); // rotate around z-axis (in tangent space) + ssaoNoise.push_back(noise); + } + glGenTextures(1, &noiseTexture); + glBindTexture(GL_TEXTURE_2D, noiseTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, 4, 4, 0, GL_RGB, GL_FLOAT, &ssaoNoise[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + /****************************** SSAO KERNEL AND NOISE **************************************/ + frustumPlanes.resize(6); checkErrors("Constructor"); @@ -573,6 +617,14 @@ void GLHelper::switchRenderToShadowMapPoint() { checkErrors("switchRenderToShadowMapPoint"); } +void GLHelper::switchRenderToSSAO() { + glViewport(0, 0, screenWidth, screenHeight); + glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferSSAO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMapSSAO, 0); + + glCullFace(GL_BACK); + checkErrors("switchRenderToSSAO"); +} void GLHelper::switchRenderToDefault() { glViewport(0, 0, screenWidth, screenHeight); @@ -580,8 +632,10 @@ void GLHelper::switchRenderToDefault() { //we bind shadow map to last texture unit state->attach2DTextureArray(depthMapDirectional, maxTextureImageUnits - 1); state->attachCubemapArray(depthCubemapPoint, maxTextureImageUnits - 2); + state->attachTexture(depthMapSSAO, maxTextureImageUnits - 3); + state->attachTexture(noiseTexture, maxTextureImageUnits - 4); + glCullFace(GL_BACK); - //glEnable(GL_CULL_FACE); checkErrors("switchRenderToDefault"); } @@ -722,7 +776,11 @@ GLHelper::~GLHelper() { deleteBuffer(1, playerUBOLocation); deleteBuffer(1, allMaterialsUBOLocation); deleteBuffer(1, depthMapDirectional); + deleteBuffer(1, depthCubemapPoint); + deleteBuffer(1, depthMapSSAO); glDeleteFramebuffers(1, &depthOnlyFrameBufferDirectional); //maybe we should wrap this up too + glDeleteFramebuffers(1, &depthOnlyFrameBufferPoint); + glDeleteFramebuffers(1, &depthOnlyFrameBufferSSAO); //state->setProgram(0); } @@ -732,7 +790,8 @@ void GLHelper::reshape() { this->screenWidth = options->getScreenWidth(); glViewport(0, 0, options->getScreenWidth(), options->getScreenHeight()); aspect = float(options->getScreenHeight()) / float(options->getScreenWidth()); - perspectiveProjectionMatrix = glm::perspective(options->PI/3.0f, 1.0f / aspect, 0.01f, 1000.0f); + perspectiveProjectionMatrix = glm::perspective(options->PI/3.0f, 1.0f / aspect, 0.01f, 10000.0f); + inverseTransposeProjection = glm::transpose(glm::inverse(perspectiveProjectionMatrix)); orthogonalProjectionMatrix = glm::ortho(0.0f, (float) options->getScreenWidth(), 0.0f, (float) options->getScreenHeight()); checkErrors("reshape"); } @@ -962,11 +1021,14 @@ void GLHelper::setModelIndexesUBO(std::vector &modelIndicesList) { void GLHelper::setPlayerMatrices(const glm::vec3 &cameraPosition, const glm::mat4 &cameraTransform) { this->cameraMatrix = cameraTransform; glBindBuffer(GL_UNIFORM_BUFFER, playerUBOLocation); - glBufferSubData(GL_UNIFORM_BUFFER, 0 * sizeof(glm::mat4), sizeof(glm::mat4), &cameraMatrix);//changes with camera - glBufferSubData(GL_UNIFORM_BUFFER, 1 * sizeof(glm::mat4), sizeof(glm::mat4), &perspectiveProjectionMatrix);//never changes + glBufferSubData(GL_UNIFORM_BUFFER, 0 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(cameraMatrix));//changes with camera + glBufferSubData(GL_UNIFORM_BUFFER, 1 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(perspectiveProjectionMatrix));//never changes glm::mat4 viewMatrix = perspectiveProjectionMatrix * cameraMatrix; - glBufferSubData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), sizeof(glm::mat4), &viewMatrix);//changes with camera - glBufferSubData(GL_UNIFORM_BUFFER, 3 * sizeof(glm::mat4), sizeof(glm::vec3), &cameraPosition);//changes with camera + glBufferSubData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(viewMatrix));//changes with camera + glBufferSubData(GL_UNIFORM_BUFFER, 3 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(inverseTransposeProjection));//never changes + glBufferSubData(GL_UNIFORM_BUFFER, 4 * sizeof(glm::mat4), sizeof(glm::vec3), glm::value_ptr(cameraPosition));//changes with camera + glm::vec2 noiseScale(this->screenWidth / 4, this->screenHeight / 4); + glBufferSubData(GL_UNIFORM_BUFFER, 4 * sizeof(glm::mat4)+ sizeof(glm::vec4), sizeof(glm::vec2), glm::value_ptr(noiseScale));//never changes glBindBuffer(GL_UNIFORM_BUFFER, 0); calculateFrustumPlanes(cameraMatrix, perspectiveProjectionMatrix, frustumPlanes); diff --git a/src/GLHelper.h b/src/GLHelper.h index 5c45a23e..d280efe3 100644 --- a/src/GLHelper.h +++ b/src/GLHelper.h @@ -197,15 +197,21 @@ class GLHelper { GLuint depthOnlyFrameBufferPoint; GLuint depthCubemapPoint; + GLuint depthOnlyFrameBufferSSAO; + GLuint depthMapSSAO; + + unsigned int noiseTexture; + Options *options; const uint_fast32_t lightUniformSize = (sizeof(glm::mat4) * 7) + (2 * sizeof(glm::vec4)); - const uint32_t playerUniformSize = 3 * sizeof(glm::mat4) + sizeof(glm::vec4); + const uint32_t playerUniformSize = 4 * sizeof(glm::mat4) + sizeof(glm::vec4) + sizeof(glm::vec4); int32_t materialUniformSize = 2 * sizeof(glm::vec3) + sizeof(float) + sizeof(GLuint); int32_t modelUniformSize = sizeof(glm::mat4); glm::mat4 cameraMatrix; glm::mat4 perspectiveProjectionMatrix; + glm::mat4 inverseTransposeProjection; std::vectorfrustumPlanes; glm::mat4 orthogonalProjectionMatrix; glm::mat4 lightProjectionMatrixDirectional; @@ -234,7 +240,7 @@ class GLHelper { #ifndef NDEBUG GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (fbStatus != GL_FRAMEBUFFER_COMPLETE) { - std::cerr << "FB status is " << fbStatus << std::endl; + std::cerr << "FB status while " << callerFunc << " is " << fbStatus << std::endl; } bool hasError = false; while ((error = glGetError()) != GL_NO_ERROR) { @@ -311,6 +317,8 @@ class GLHelper { glClear(GL_DEPTH_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferDirectional); glClear(GL_DEPTH_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFrameBufferSSAO); + glClear(GL_DEPTH_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, 0); renderTriangleCount = 0; @@ -382,6 +390,8 @@ class GLHelper { void switchRenderToShadowMapPoint(); + void switchRenderToSSAO(); + void switchRenderToDefault(); int getMaxTextureImageUnits() const { diff --git a/src/GameObjects/Model.cpp b/src/GameObjects/Model.cpp index 75839ed1..557414a2 100644 --- a/src/GameObjects/Model.cpp +++ b/src/GameObjects/Model.cpp @@ -4,6 +4,7 @@ #include "Model.h" #include "../AI/ActorInterface.h" +#include Model::Model(uint32_t objectID, AssetManager *assetManager, const float mass, const std::string &modelFile, bool disconnected = false) : @@ -45,6 +46,7 @@ Model::Model(uint32_t objectID, AssetManager *assetManager, const float mass, co animatedProgram = new GLSLProgram(glHelper, "./Engine/Shaders/Model/vertexAnimated.glsl", "./Engine/Shaders/Model/fragment.glsl", true); this->setSamplersAndUBOs(animatedProgram); + generateAndSetSSAOKernels(animatedProgram, 64); } //set up the program to render object meshMeta->program = animatedProgram; @@ -56,6 +58,7 @@ Model::Model(uint32_t objectID, AssetManager *assetManager, const float mass, co nonAnimatedProgram = new GLSLProgram(glHelper, "./Engine/Shaders/Model/vertex.glsl", "./Engine/Shaders/Model/fragment.glsl", true); this->setSamplersAndUBOs(nonAnimatedProgram); + generateAndSetSSAOKernels(nonAnimatedProgram, 64); } meshMeta->program = nonAnimatedProgram; } @@ -125,6 +128,33 @@ Model::Model(uint32_t objectID, AssetManager *assetManager, const float mass, co } } +void Model::generateAndSetSSAOKernels(GLSLProgram *programToSet, uint32_t kernelSize) const { +// generate sample kernel +// ---------------------- + std::vector ssaoKernel; + std::uniform_real_distribution randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0 + std::default_random_engine generator; + for (unsigned int i = 0; i < kernelSize; ++i){ + glm::vec3 sample(randomFloats(generator) * 2.0 - 1.0, randomFloats(generator) * 2.0 - 1.0, randomFloats(generator)); + sample = glm::normalize(sample); + //sample *= randomFloats(generator); + float scale = float(i) / kernelSize; + + // scale samples s.t. they're more aligned to center of kernel + scale = glm::lerp(0.1f, 1.0f, scale * scale); + sample *= scale; + ssaoKernel.push_back(sample); + //std::cout << "sampleKernel" << glm::to_string(sample) << std::endl; + } + + if(!programToSet->setUniform("ssaoKernel[0]", ssaoKernel)) { + std::cerr << "uniform variable \"ssaoKernel\" couldn't be set" << std::endl; + } + if(!programToSet->setUniform("ssaoSampleCount", (int32_t)ssaoKernel.size())) { + std::cerr << "uniform variable \"ssaoSampleCount\" couldn't be set" << std::endl; + } +} + void Model::setupForTime(long time) { if(animated && !animationLastFramePlayed) { //check if we need to blend @@ -212,6 +242,14 @@ void Model::setSamplersAndUBOs(GLSLProgram *program) { std::cerr << "Uniform \"shadowSamplerPoint\" could not be set" << std::endl; } + if (!program->setUniform("ssaoSampler", glHelper->getMaxTextureImageUnits() - 3)) { + std::cerr << "Uniform \"ssaoSampler\" could not be set" << std::endl; + } + + if (!program->setUniform("ssaoNoiseSampler", glHelper->getMaxTextureImageUnits() - 4)) { + std::cerr << "Uniform \"ssaoNoiseSampler\" could not be set" << std::endl; + } + glHelper->attachModelUBO(program->getID()); glHelper->attachModelIndicesUBO(program->getID()); } diff --git a/src/GameObjects/Model.h b/src/GameObjects/Model.h index 77ace7f4..136e8ef7 100644 --- a/src/GameObjects/Model.h +++ b/src/GameObjects/Model.h @@ -242,6 +242,7 @@ class Model : public PhysicalRenderable, public GameObject { return getAttachmentTransform(attachmentBoneID); } + void generateAndSetSSAOKernels(GLSLProgram *programToSet, uint32_t kernelSize) const; }; #endif //LIMONENGINE_MODEL_H diff --git a/src/World.cpp b/src/World.cpp index 444ea48a..107aaad2 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -72,6 +72,9 @@ World::World(const std::string &name, PlayerInfo startingPlayerType, InputHandle "./Engine/Shaders/ShadowMap/geometryPoint.glsl", "./Engine/Shaders/ShadowMap/fragmentPoint.glsl", false); + ssaoProgram = new GLSLProgram(glHelper, "./Engine/Shaders/SSAO/vertex.glsl", + "./Engine/Shaders/SSAO/fragment.glsl", false); + apiGUILayer = new GUILayer(glHelper, debugDrawer, 1); apiGUILayer->setDebug(false); @@ -626,7 +629,39 @@ void World::render() { (*animatedModelIterator)->renderWithProgramInstanced(temp,*shadowMapProgramPoint); } } + /**************** SSAO ********************************************************/ + + glHelper->switchRenderToSSAO(); + for (auto modelIterator = modelsInCameraFrustum.begin(); modelIterator != modelsInCameraFrustum.end(); ++modelIterator) { + //each iterator has a vector. each vector is a model that can be rendered instanced. They share is animated + std::set modelSet = modelIterator->second; + modelIndicesBuffer.clear(); + Model* sampleModel = nullptr; + for (auto model = modelSet.begin(); model != modelSet.end(); ++model) { + //all of these models will be rendered + modelIndicesBuffer.push_back((*model)->getWorldObjectID()); + sampleModel = *model; + } + if(sampleModel != nullptr) { + sampleModel->renderWithProgramInstanced(modelIndicesBuffer, *ssaoProgram); + } + } + + for (auto modelIterator = animatedModelsInFrustum.begin(); modelIterator != animatedModelsInFrustum.end(); ++modelIterator) { + std::vector temp; + temp.push_back((*modelIterator)->getWorldObjectID()); + (*modelIterator)->renderWithProgramInstanced(temp, *ssaoProgram); + } + + if(startingPlayer.attachedModel != nullptr && !currentPlayer->isDead()) {//don't render attched model if dead + startingPlayer.attachedModel->setupForTime(gameTime); + std::vector temp; + temp.push_back(startingPlayer.attachedModel->getWorldObjectID()); + startingPlayer.attachedModel->renderInstanced(temp); + } + + /************** END OF SSAO ********************************************************/ glHelper->switchRenderToDefault(); if(sky!=nullptr) { sky->render();//this is moved to the top, because transparency can create issues if this is at the end diff --git a/src/World.h b/src/World.h index 3cda1e8a..5e95c6d9 100644 --- a/src/World.h +++ b/src/World.h @@ -209,7 +209,9 @@ class World { glm::vec3 worldAABBMin= glm::vec3(std::numeric_limits::max()); glm::vec3 worldAABBMax = glm::vec3(std::numeric_limits::min()); - GLSLProgram *shadowMapProgramDirectional, *shadowMapProgramPoint; + GLSLProgram *shadowMapProgramDirectional = nullptr; + GLSLProgram *shadowMapProgramPoint = nullptr; + GLSLProgram *ssaoProgram = nullptr; FontManager fontManager; PlayerInfo startingPlayer;