diff --git a/shaders/debug.frag.glsl b/shaders/debug.frag.glsl new file mode 100644 index 0000000..8f7e61c --- /dev/null +++ b/shaders/debug.frag.glsl @@ -0,0 +1,18 @@ +#version 330 core + +in vec2 varTexCoord; + +// LIGHT BUFFER + +uniform sampler2DRect debuggedBuffer; + +// OUTPUT LIGHT + +layout(location = 0)out vec4 outColor; + +// MAIN PROGRAM + +void main(void) { + vec4 texel = texture(debuggedBuffer, varTexCoord); + outColor = vec4(texel.rgb, 1.0); +} diff --git a/shaders/debug.vert.glsl b/shaders/debug.vert.glsl new file mode 100644 index 0000000..0c25364 --- /dev/null +++ b/shaders/debug.vert.glsl @@ -0,0 +1,13 @@ +#version 330 core + +layout(location = 0)in vec2 inPosition; + +uniform vec2 origin; +uniform vec2 size; + +out vec2 varTexCoord; + +void main(void) { + varTexCoord = (inPosition + vec2(1.0))/2.0; + gl_Position = vec4(origin + inPosition * size, 0.0, 1.0); +} diff --git a/shaders/lighting.frag.glsl b/shaders/lighting.frag.glsl index ccd0f61..b65d590 100644 --- a/shaders/lighting.frag.glsl +++ b/shaders/lighting.frag.glsl @@ -1,15 +1,17 @@ // G-BUFFER +#ifndef UNLIT // - Position in view space uniform sampler2DRect positionBuffer; // - Albedo + Roughness uniform sampler2DRect albedoBuffer; // - Normal buffer uniform sampler2DRect normalBuffer; -// - Emission + Metallic -uniform sampler2DRect emissionBuffer; // - depth buffer uniform sampler2DRect depthBuffer; +#endif +// - Emission + Metallic +uniform sampler2DRect emissionBuffer; // LIGHT ATTRIBUTES #ifdef AMBIENT_LIGHT @@ -17,7 +19,7 @@ uniform samplerCube ambientMap; uniform samplerCube reflectMap; uniform sampler2D brdfLUT; uniform mat3 inverseViewMatrix; -#else +#elif !defined UNLIT uniform vec3 lightColor; #endif @@ -102,7 +104,7 @@ vec3 GGX( // combining light return kD * diffuse + specular; } -#else +#elif !defined UNLIT float DistributionGGX(vec3 N, vec3 H, float roughness) { float a = roughness*roughness; @@ -153,9 +155,13 @@ vec3 GGX( // MAIN PROGRAM + void main(void) { // get fragment information from the G-Buffer ivec2 texCoord = ivec2(gl_FragCoord.xy); +#ifdef UNLIT + outColor = vec4(texelFetch(emissionBuffer, texCoord).rgb, 1); +#else vec3 normal = texelFetch(normalBuffer, texCoord).xyz; vec4 albedoTexel = texelFetch(albedoBuffer, texCoord); vec3 albedo = albedoTexel.rgb; @@ -201,4 +207,7 @@ void main(void) { vec3 light = GGX(albedo, metallic, roughness, lightColor, normal, dirLight, halfVec, viewDir); outColor = vec4(mix(vec3(0.0), light*shadow, att*att), 1); #endif + +#endif // UNLIT } + diff --git a/src/deferredpipeline.cpp b/src/deferredpipeline.cpp index 8ec894c..1538acf 100644 --- a/src/deferredpipeline.cpp +++ b/src/deferredpipeline.cpp @@ -1,18 +1,29 @@ #include "sparrowrenderer.h" #include "deferredpipeline.h" + +// renderer #include "texture.h" #include "scene.h" #include "mesh.h" #include "shader.h" -#include #include "shadersource.h" #include "pbrmaterial.h" #include "camera.h" #include "skybox.h" #include "guimesh.h" -#include + +// GLM +#include + +// Stl #include +// imgui +#include + +// resource packs +#include + RESOURCE_PACK(shaders) GBuffer::GBuffer(int width, int height) : FrameBuffer() @@ -81,7 +92,8 @@ DeferredPipeline::DeferredPipeline() : m_height(512), m_gBuffer(nullptr), m_lightingBuffer(nullptr), - m_renderTarget(nullptr) + m_renderTarget(nullptr), + m_debugGuiEnabled(false) { Resource::ResourceMap shaderMap; Resource::getResourcePack_shaders(shaderMap); @@ -97,6 +109,10 @@ DeferredPipeline::DeferredPipeline() : std::string vertSource = shaderMap["shaders/posteffects.vert.glsl"]; std::string fragSource = shaderMap["shaders/posteffects.frag.glsl"]; m_postEffectsShader = new Shader(vertSource, fragSource); + m_debugShaders = new ShaderSource(); + m_debugShaders->setSource(shaderMap["shaders/gui.vert.glsl"], ShaderSource::VERTEX); + m_debugShaders->setSource(shaderMap["shaders/gui.frag.glsl"], ShaderSource::FRAGMENT); + m_guiMesh = new GuiMesh(); m_guiMesh->initGL(); } @@ -116,6 +132,7 @@ void DeferredPipeline::renderGL(Scene *scene) std::vector mesh2D; m_gBuffer->bindFBO(); glEnable(GL_DEPTH_TEST); + glEnable(GL_STENCIL_TEST); glDepthFunc(GL_LESS); glDisable(GL_BLEND); glClearColor(0.0f, 0.0f, 0.0f, 1.f); @@ -123,7 +140,7 @@ void DeferredPipeline::renderGL(Scene *scene) glClearStencil(1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glStencilMask(0xFF); - glStencilFunc(GL_ALWAYS, 0, 0xFF); // always draw fragments (ignore the stencil buffer values for now) + glStencilFunc(GL_ALWAYS, 1, 0xFF); // always draw fragments (ignore the stencil buffer values for now) // draw skybox if(m_skybox != nullptr) { @@ -165,13 +182,28 @@ void DeferredPipeline::renderGL(Scene *scene) glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); m_gBuffer->bindTextures(); + + // draw unlit fragments +/* + Shader *shader = m_lightShaders[1 << Light::UNLIT_FLAG]; + if(shader != nullptr) + { + shader->bind(); + shader->bindInteger(shader->getLocation("emissionBuffer"), GBuffer::EMISSION); + //glStencilFunc(GL_EQUAL, 1, 0xFF); + SparrowRenderer::drawQuad(); + } +*/ + // loop on light sources + //glStencilFunc(GL_EQUAL, 0, 0xFF); for(SceneIterator* lightIt = scene->getLights(); lightIt->isValid(); lightIt->next()) { Light* light = lightIt->getItem(); Shader *shader = m_lightShaders[light->getFlags()]; - if(shader == NULL) + if(shader == nullptr) { fprintf(stderr, "no shader to render this light, please call refreshScene to generate the shader\n"); continue; @@ -196,13 +228,14 @@ void DeferredPipeline::renderGL(Scene *scene) // POST EFFECTS PASS m_renderTarget->bindFBO(); glDisable(GL_BLEND); + glDisable(GL_STENCIL_TEST); m_lightingBuffer->getTexture(0)->bind(0); m_postEffectsShader->bind(); m_postEffectsShader->bindInteger(m_postEffectsShader->getLocation("lightBuffer"), 0); SparrowRenderer::drawQuad(); m_lightingBuffer->getTexture(0)->unbind(); - // 2D GUI PASS + // 2D PASS glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -223,10 +256,73 @@ void DeferredPipeline::renderGL(Scene *scene) node->mesh->draw(shader); } + //if(m_debugGuiEnabled) + // gui(); + // IMGUI PASS m_guiMesh->drawGL(); } +struct DebugCanvas +{ + glm::ivec2 top_left; + glm::ivec2 bottom_right; + + void gui() + { + if(ImGui::Button("Left")) + { + if(top_left.x != -1) + top_left.x = -1; + else + bottom_right.x = 0; + } + if(ImGui::Button("Right")) + { + if(bottom_right.x != 1) + bottom_right.x = 1; + else + top_left.x = 0; + } + if(ImGui::Button("Up")) + { + if(top_left.y != 1) + top_left.y = 1; + else + bottom_right.y = 0; + } + if(ImGui::Button("Down")) + { + if(bottom_right.y != -1) + bottom_right.y = -1; + else + top_left.y = 0; + } + } + + void drawCanvas() + { + Shader* shader = nullptr; + shader->bind(); + shader->bindVec2(shader->getLocation("origin"), (top_left+bottom_right)/2); + shader->bindVec2(shader->getLocation("origin"), top_left-bottom_right); + SparrowRenderer::drawQuad(); + } +}; + +void DeferredPipeline::gui() +{ + ImGui::Begin("Rendering Pipeline", &m_debugGuiEnabled); + if(ImGui::Button("Add a debug canvas")) + { + + } + ImGui::End(); + + // debug render + +} + void DeferredPipeline::setSkybox(Texture* texture) { if(m_skybox != nullptr) @@ -298,6 +394,7 @@ void DeferredPipeline::refreshScene(Scene *scene) delete it.second; m_lightShaders.clear(); m_lightTypes.clear(); + m_lightTypes.push_back(1 << Light::UNLIT_FLAG); scene->getLightTypes(m_lightTypes); for(unsigned int type : m_lightTypes) m_lightShaders[type] = m_lightingSource->compile(0, type); diff --git a/src/deferredpipeline.h b/src/deferredpipeline.h index 9e90d99..dc69b7d 100644 --- a/src/deferredpipeline.h +++ b/src/deferredpipeline.h @@ -49,6 +49,7 @@ class DeferredPipeline : public Pipeline ShaderSource *m_lightingSource; ShaderSource *m_mesh2DSource; Shader *m_postEffectsShader; // TODELETE + ShaderSource *m_debugShaders; GuiMesh * m_guiMesh; @@ -57,6 +58,11 @@ class DeferredPipeline : public Pipeline LightingBuffer *m_lightingBuffer; const FrameBuffer *m_renderTarget; + // debug gui + bool m_debugGuiEnabled; + + void gui(); + public: DeferredPipeline(); @@ -70,7 +76,16 @@ public: virtual void renderGL(Scene *scene); virtual void resizeGL(int w, int h); - glm::vec4 pick(int x, int y); + /** + * @brief pick allows picking directly in the GPU buffer, this is a very heavy operation though, + * and can only be performed in the position buffer + * @param x in screen space + * @param y in screen space + * @return the position of the fragment + */ + glm::vec4 pick(int x, int y); + + void toggleDebugGui() { m_debugGuiEnabled = !m_debugGuiEnabled; } }; #endif // DEFERREDPIPELINE_H diff --git a/src/light.cpp b/src/light.cpp index f1e2999..510e74e 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -19,7 +19,8 @@ const char* Light::flagStr[] = { "POINT_LIGHT", "SPOT_LIGHT", "SHADOWMAP", - "CASCADED" + "CASCADED", + "UNLIT" }; const glm::mat4 Light::biasMatrix( @@ -63,6 +64,7 @@ DirectionnalLight::DirectionnalLight(glm::vec3 dir, glm::vec3 lightColor) : void DirectionnalLight::bindAttributes(Shader *shader, Camera *camera) { + int slot = PBRMaterial::NB_PBR_SLOTS; shader->bindVec3(shader->getLocation("lightColor"), m_color); glm::vec4 direction = glm::vec4(m_direction, 0.f); shader->bindVec3(shader->getLocation("dirLight"), glm::normalize(glm::vec3(camera->getViewMatrix()*direction))); @@ -72,16 +74,16 @@ void DirectionnalLight::bindAttributes(Shader *shader, Camera *camera) { case 1: { - m_shadowMap->getTexture(0)->bind(7); // TODO use something else than 7 - shader->bindInteger(shader->getLocation("shadowMap"), 7); + m_shadowMap->getTexture(0)->bind(slot); + shader->bindInteger(shader->getLocation("shadowMap"), slot); glm::mat4 viewToLightMatrix = Light::biasMatrix * m_projectionMatrices[0] * m_viewMatrices[0] * glm::inverse(camera->getViewMatrix()); shader->bindMat4(shader->getLocation("viewToLightMatrix"), viewToLightMatrix); } break; case 3: { - m_shadowMap->getTexture(0)->bind(7); // TODO use something else than 7 - shader->bindInteger(shader->getLocation("shadowMap"), 7); + m_shadowMap->getTexture(0)->bind(slot); + shader->bindInteger(shader->getLocation("shadowMap"), slot); glm::mat4 lightMVP; lightMVP = Light::biasMatrix * m_projectionMatrices[0] * (m_viewMatrices[0] * glm::inverse(camera->getViewMatrix())); shader->bindMat4(shader->getLocation("frontShadowMVP"), lightMVP); diff --git a/src/light.h b/src/light.h index d914a6b..672ce7f 100644 --- a/src/light.h +++ b/src/light.h @@ -29,6 +29,7 @@ public: SPOT_FLAG, SHADOWMAP_FLAG, CASCADED_FLAG, + UNLIT_FLAG, NB_FLAGS }; static const char* flagStr[]; diff --git a/src/mesh.cpp b/src/mesh.cpp index 7d4ea6d..d84fb77 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -174,9 +174,9 @@ void Mesh::initGL() void Mesh::draw(Shader* shader) { if(isWireframe) - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); else - glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); if(isDoubleSided) glDisable(GL_CULL_FACE); if(material != NULL) diff --git a/src/sparrowrenderer.cpp b/src/sparrowrenderer.cpp index fecf9e1..be9fb46 100644 --- a/src/sparrowrenderer.cpp +++ b/src/sparrowrenderer.cpp @@ -16,8 +16,11 @@ GLuint SparrowRenderer::m_quadVBO = 0; const GLfloat QUAD_VERTICES[] = { -1.0f, -1.0f, - 3.0f, -1.0f, - -1.0f, 3.0f + 1.0f, -1.0f, + -1.0f, 1.0f, + -1.0f, 1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f }; // main methods @@ -54,7 +57,7 @@ void SparrowRenderer::initGL(int w, int h) glBindVertexArray(m_quadVAO); glGenBuffers(1, &m_quadVBO); glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO); - glBufferData(GL_ARRAY_BUFFER, 3 * 2 * sizeof(GLfloat), QUAD_VERTICES, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(GLfloat), QUAD_VERTICES, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, NULL); glEnableVertexAttribArray(0); glBindVertexArray(0); @@ -97,7 +100,7 @@ void SparrowRenderer::renderGL() void SparrowRenderer::drawQuad() { glBindVertexArray(m_quadVAO); - glDrawArrays(GL_TRIANGLES, 0, 3); + glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); } diff --git a/src/sparrowrenderer.h b/src/sparrowrenderer.h index 702e033..34458f8 100644 --- a/src/sparrowrenderer.h +++ b/src/sparrowrenderer.h @@ -26,7 +26,7 @@ public: void renderGL(); // utils - static void drawQuad(); + static void drawQuad(); // draws a quad from (-1,-1) to (1,1) composed of 2 triangles // scene methods void setScene(Scene* myScene);