diff --git a/src/Renderer.cpp b/src/Renderer.cpp index 50c820b..de9d6d3 100755 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -115,8 +115,14 @@ void Renderer::LoadContent() m_FirstPassProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/First_pass.vert.glsl"))); m_FirstPassProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/First_pass.frag.glsl"))); m_FirstPassProgram.Compile(); + BindFragDataLocation(); m_FirstPassProgram.Link(); + m_SecondPassProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/Second_pass.vert.glsl"))); + m_SecondPassProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/Second_pass.frag.glsl"))); + m_SecondPassProgram.Compile(); + m_SecondPassProgram.Link(); + m_Skybox = std::make_shared("Textures/Skybox/Sunset", "jpg"); m_DebugAABB = CreateAABB(); @@ -538,137 +544,125 @@ void Renderer::ClearStuff() void Renderer::FrameBufferTextures() { m_fb = 0; - + m_fDepthBuffer = 0; + glGenFramebuffers(1, &m_fb); - GLERROR("GLERROR: Failed to generate frame buffer"); - glGenTextures(1, &m_fb_PositionTexture); - GLERROR("GLERROR: Failed to generate Position texture"); - glBindTexture(GL_TEXTURE_2D, m_fb_PositionTexture); - GLERROR("GLERROR: Failed to bind Position texture"); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB16F, - WIDTH, - HEIGHT, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - NULL - ); - GLERROR("GLERROR: Failed to generate Position texture image"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glGenRenderbuffers(1, &m_fDepthBuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, m_fDepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, WIDTH, HEIGHT); + + //Generate and bind diffuse texture + glGenTextures(1, &m_fDiffuseTexture); + glBindTexture(GL_TEXTURE_2D, m_fDiffuseTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + 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_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - GLERROR("GLERROR: Failed to generate Position Parameters"); - glGenTextures(1, &m_fb_NormalsTexture); - GLERROR("GLERROR: Failed to generate Normal texture"); - glBindTexture(GL_TEXTURE_2D, m_fb_NormalsTexture); - GLERROR("GLERROR: Failed to bind Normal texture"); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB16F, - WIDTH, - HEIGHT, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - NULL - ); - GLERROR("GLERROR: Failed to generate Normal texture image"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //Generate and bind position texture + glGenTextures(1, &m_fPositionTexture); + glBindTexture(GL_TEXTURE_2D, m_fPositionTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + 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_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - GLERROR("GLERROR: Failed to generate Normals Parameters"); + //Generate and bind normal texture + glGenTextures(1, &m_fNormalsTexture); + glBindTexture(GL_TEXTURE_2D, m_fNormalsTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + 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_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + //Generate and bind blend texture + glGenTextures(1, &m_fBlendTexture); + glBindTexture(GL_TEXTURE_2D, m_fBlendTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + 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_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + //Bind fb glBindFramebuffer(GL_FRAMEBUFFER, m_fb); - GLERROR("GLERROR: Failed to bind framebuffer"); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fb_PositionTexture, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_fb_NormalsTexture, 0); - GLERROR("GLERROR: Failed to FrameBufferTexture2D"); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_fDepthBuffer); - m_rb = 0; - glGenRenderbuffers(1, &m_rb); - GLERROR("GLERROR: Failed to generate RenderBuffer"); - glBindRenderbuffer(GL_RENDERBUFFER, m_rb); - GLERROR("GLERROR: Failed to bind RenderBuffer"); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WIDTH, HEIGHT); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rb); - - draw_bufs[1] = GL_COLOR_ATTACHMENT0; - draw_bufs[2] = GL_COLOR_ATTACHMENT1; - + //Attach textures to the FB + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fDiffuseTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_fPositionTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, m_fNormalsTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, m_fBlendTexture, 0); + GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if(fbStatus != GL_FRAMEBUFFER_COMPLETE) + { + printf("DeferredLighting:Init: FrameBuffer incomplete: 0x%x\n", fbStatus); + exit(1); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::DrawFBO() { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb); + + GLenum windowBuffClear[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; + glDrawBuffers(4, windowBuffClear); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glBindFramebuffer(GL_FRAMEBUFFER, m_fb); - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); -#ifdef DEBUG - glDisable(GL_CULL_FACE); - glPolygonMode(GL_BACK, GL_LINE); -#endif - // Draw models - glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)) * glm::translate(-m_Camera->Position() * glm::vec3(1, 0, 0)); - glm::mat4 depthCamera = m_SunProjection * depthViewMatrix; - glm::mat4 biasMatrix( - 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.5, 0.5, 0.5, 1.0 - ); + // Execute the first render stage which will fill out the internal buffers with data(??) + //EnableRenderProgramStage1; + GLenum windowBuffOpaque[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_NONE }; + glDrawBuffers(4, windowBuffOpaque); + //DrawTheWorld(); - m_ShaderProgram.Bind(); - if (m_DrawWireframe) - { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * m_Camera->ViewMatrix(); - glm::mat4 depthCameraMatrix = biasMatrix * depthCamera; - glm::mat4 MVP; - glm::mat4 depthMVP; - for (auto tuple : ModelsToRender) - { - Model* model; - glm::mat4 modelMatrix; - bool visible; - std::tie(model, modelMatrix, visible, std::ignore) = tuple; - if (!visible) - continue; + GLenum windowBuffTransp[] = { GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3 }; + glDrawBuffers(4, windowBuffTransp); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + //Depth buffer shall not be updated + glDepthMask(GL_FALSE); + //DrawTransparent items + glDepthMask(GL_TRUE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - MVP = cameraMatrix * modelMatrix; - depthMVP = depthCameraMatrix * modelMatrix; - glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix)); - glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr( m_Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); - glBindVertexArray(model->VAO); -// for (auto texGroup : model->TextureGroups) -// { -// glActiveTexture(GL_TEXTURE0); -// glBindTexture(GL_TEXTURE_2D, *texGroup.Texture); -// glDrawArrays(GL_TRIANGLES, texGroup.StartIndex, texGroup.EndIndex - texGroup.StartIndex + 1); -// } - } + //Probably means to use the second_pass shader + //EnableRenderProgramDeferredStage(); -#ifdef DEBUG - // Debug draw model normals - if (m_DrawNormals) - { - m_ShaderProgramNormals.Bind(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - DrawModels(m_ShaderProgramNormals); - } -#endif + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + //SetupDefferedStageUniforms(); // Probably what we do in FrameBufferTextures(); + //glEnableVertexAttribArray(fVertexIndex); // VertexIndex? + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, m_fBlendTexture); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, m_fNormalsTexture); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_fPositionTexture); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_fDiffuseTexture); + + //DrawSimpleSquare(); //I guess this draw a square and put the textures on it + + //glDisableVertexAttribArray(fVertexIndex); //VertexIndex? - //glDrawBuffers(2, draw_bufs); } +void Renderer::BindFragDataLocation() +{ + glBindFragDataLocation(m_FirstPassProgram.GetHandle(), 0, "diffuseOutput"); + glBindFragDataLocation(m_FirstPassProgram.GetHandle(), 1, "posOutput"); + glBindFragDataLocation(m_FirstPassProgram.GetHandle(), 2, "normOutput"); + glBindFragDataLocation(m_FirstPassProgram.GetHandle(), 3, "blendOutput"); +} diff --git a/src/Renderer.h b/src/Renderer.h index 3243eef..d915c9c 100755 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -88,16 +88,19 @@ private: GLuint m_ShadowFrameBuffer; GLuint m_ShadowDepthTexture; - GLuint m_fb_PositionTexture; - GLuint m_fb_NormalsTexture; + GLuint m_fDiffuseTexture; + GLuint m_fPositionTexture; + GLuint m_fNormalsTexture; + GLuint m_fBlendTexture; GLuint m_fb; - GLuint m_rb; + GLuint m_fDepthBuffer; GLenum draw_bufs[2]; std::shared_ptr m_Camera; ShaderProgram m_ShaderProgram; ShaderProgram m_FirstPassProgram; + ShaderProgram m_SecondPassProgram; ShaderProgram m_ShaderProgramNormals; ShaderProgram m_ShaderProgramShadows; ShaderProgram m_ShaderProgramShadowsDrawDepth; @@ -111,6 +114,7 @@ private: void CreateShadowMap(int resolution); void FrameBufferTextures(); void DrawFBO(); + void BindFragDataLocation(); GLuint CreateQuad(); void DrawDebugShadowMap(); diff --git a/src/Shaders/First_pass.frag.glsl b/src/Shaders/First_pass.frag.glsl index df66547..2f3405b 100644 --- a/src/Shaders/First_pass.frag.glsl +++ b/src/Shaders/First_pass.frag.glsl @@ -1,4 +1,27 @@ -#version 400 +#version 130 +uniform sampler2D firstTexture; +in vec3 fragmentNormal; +in vec2 fragmentTexCoord; +in vec3 position; +layout (location = 0) out vec4 diffuseOutput; +layout (location = 1) out vec4 posOutput; +layout (location = 2) out vec4 normOutput; +layout (location = 3) out vec4 blendOutput; + +void main(void) +{ + posOutput.xyz = position; + normOutPut = vec4(fragmentNormal, 0); + vec4 clr = texture(firstTexture, fragmentTexCoord); + float alpha = clr.a; + if(alpha < 0.1) + discard; //Some optimizing + blendOutput.rgb = clr.rgb * clr.a; //Pre multiplied alpha + blendOutput.a = clr.a; + diffuseOutput = clr; +} + +/*#version 400 in vec3 p_eye; in vec3 n_eye; @@ -9,4 +32,4 @@ layout (location = 1) out vec4 def_n; // "go to GL_COLOR_ATTACHMENT1" void main () { def_p = vec4(p_eye, 1.0); def_n = vec4(n_eye, 1.0); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Shaders/First_pass.vert.glsl b/src/Shaders/First_pass.vert.glsl index f6cd49c..832c0d8 100644 --- a/src/Shaders/First_pass.vert.glsl +++ b/src/Shaders/First_pass.vert.glsl @@ -1,4 +1,34 @@ -#version 400 +#version 130 + +precision mediump float; +uniform mat4 projectionMatrix; +uniform mat4 modelMatrix; +uniform mat4 viewMatrix; + +in vec3 normal; +in vec2 texCoord; +in vec3 vertex; + +in float intensity; +in float ambientLight; + +out vec3 fragmentNormal; +out vec2 fragmentTexCoord; +out float extIntensity; +out float extAmbientLight; + +void main(void) +{ + fragmentTexCoord = texCoord; + fragmentNormal = normalize((modelMatrix*vec4(normal, 0.0).xyz); + gl_Position = vec3(modelMatrix * vertex); //Copy position to the fragment shader + extIntensity = intensity/255.0; + extAmbientLight = ambientLight/255.0; +} + + + +/*#version 400 layout(location = 0) in vec3 vp; layout(location = 1) in vec3 vn; @@ -13,4 +43,4 @@ void main () { p_eye = (V * M * vec4 (vp, 1.0)).xyz; n_eye = (V * M * vec4 (vn, 0.0)).xyz; gl_Position = P * vec4 (p_eye, 1.0); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Shaders/Second_pass.frag.glsl b/src/Shaders/Second_pass.frag.glsl index 5792748..3591f9b 100644 --- a/src/Shaders/Second_pass.frag.glsl +++ b/src/Shaders/Second_pass.frag.glsl @@ -1,24 +1,32 @@ -#version 430 +#version 130 -uniform sampler2D tDiffuse; -uniform sampler2D tPosition; -uniform sampler2D tNormals; -uniform vec3 cameraPosition; +uniform sampler2D diffuseTex; // The color information +uniform sampler2D posTex; // World position +uniform sampler2D normalTex; // Normals +uniform sampler2D blendTex; // A bitmap with colors to blend with. +uniform vec3 camera; // The coordinate of the camera +in vec2 position; // The world position +layout (location = 0) out vec4 fragColor; -void main( void ) +void main(void) { - vec4 image = texture2D( tDiffuse, gl_TexCoord[0].xy ); - vec4 position = texture2D( tPosition, gl_TexCoord[0].xy ); - vec4 normal = texture2D( tNormals, gl_TexCoord[0].xy ); - - vec3 light = vec3(50,100,50); - vec3 lightDir = light - position.xyz ; - - normal = normalize(normal); - lightDir = normalize(lightDir); - - vec3 eyeDir = normalize(cameraPosition-position.xyz); - vec3 vHalfVector = normalize(lightDir.xyz+eyeDir); - - gl_FragColor = max(dot(normal,lightDir),0) * image + pow(max(dot(normal,vHalfVector),0.0), 100) * 1.5; -} + // Load data, stored in textures, from the first stage rendering. + vec4 diffuse = texture2D(diffuseTex, position.xy); + vec4 blend = texture2D(blendTex, position.xy); + vec4 worldPos = texture2D(posTex, position.xy); + vec4 normal = texture2D(normalTex, position.xy); + // Use information about lamp coordinate (not shown here), the pixel + // coordinate (worldpos.xyz), the normal of this pixel (normal.xyz) + // to compute a lighting effect. + // Use this lighting effect to update 'diffuse' + vec4 preBlend = diffuse * lamp + specularGlare; + // manual blending, using premultiplied alpha. + fragColor = blend + preBlend*(1-blend.a); +// Some debug features. Enable any of them to get a visual representation +// of an internal buffer. +// fragColor = (normal+1)/2; +// fragColor = diffuse; +// fragColor = blend; +// fragColor = worldPos; // Scaling may be needed to range [0,1] +// fragColor = lamp*vec4(1,1,1,1); +} \ No newline at end of file diff --git a/src/Shaders/Second_pass.vert.glsl b/src/Shaders/Second_pass.vert.glsl index 23a3280..3845ced 100644 --- a/src/Shaders/Second_pass.vert.glsl +++ b/src/Shaders/Second_pass.vert.glsl @@ -1,9 +1,9 @@ -#version 430 +#version 130 +in vec4 vertex; out vec2 position; -void main( void ) +void main(void) { - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - gl_TexCoord[0] = gl_MultiTexCoord0; - - gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0); -} + gl_Position = vertex*2-1; + gl_Position.z = 0.0; + position = vertex.xy; +} \ No newline at end of file