I'm trying to get shadow mapping working on my project. I followed the tutorial at Learn OpenGL Tutorial. For some reason, I can't see the shadows though, only the specularity from the lighting code in the fragment shader.
Image from render.
Here's how I do the framebuffer setup (Where frameBuffer and DepthMap are two global GLuint):
void createFrameBuffer()
{
glGenFramebuffers(1, &frameBuffer);
glGenTextures(1, &DepthMap);
glBindTexture(GL_TEXTURE_2D, DepthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
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);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, DepthMap, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Then I proceed to setup the geometry
glGenVertexArrays(1, &shadowVertexAttribute);
glBindVertexArray(shadowVertexAttribute);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
//Texture Map
glUniform1i(glGetUniformLocation(sShaderProgram, "DepthMap"), 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, DepthMap);
//Normal Map
glUniform1i(glGetUniformLocation(sShaderProgram, "DiffuseMap"), 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureMap);
glUniform3fv(glGetUniformLocation(sShaderProgram, "lightPos"), 1, glm::value_ptr(lightPos));
GLuint shadowVertBuffer;
GLuint shadowUVBuffer;
GLuint shadowNormalBuffer;
for (int i = 0; i < objmesh.size(); i++) {
glGenBuffers(1, &shadowVertBuffer);
glBindBuffer(GL_ARRAY_BUFFER, shadowVertBuffer);
glBufferData(GL_ARRAY_BUFFER, objmesh[i]->vertices.size() * sizeof(glm::vec3), &objmesh[i]->vertices[0], GL_STATIC_DRAW);
GLuint svertexPos = glGetAttribLocation(sShaderProgram, "vertex_position");
glVertexAttribPointer(svertexPos, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glGenBuffers(1, &shadowUVBuffer);
glBindBuffer(GL_ARRAY_BUFFER, shadowUVBuffer);
glBufferData(GL_ARRAY_BUFFER, objmesh[i]->uvs.size() * sizeof(glm::vec2), &objmesh[i]->uvs[0], GL_STATIC_DRAW);
GLuint svertexUV = glGetAttribLocation(sShaderProgram, "vertex_UV");
glVertexAttribPointer(svertexUV, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glGenBuffers(1, &shadowNormalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, shadowNormalBuffer);
glBufferData(GL_ARRAY_BUFFER, objmesh[i]->normals.size() * sizeof(glm::vec3), &objmesh[i]->normals[0], GL_STATIC_DRAW);
GLuint svertexNormal = glGetAttribLocation(sShaderProgram, "vertex_normal");
glVertexAttribPointer(svertexNormal, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
}
Finally, I render the shadows (or at least try):
if (shadows == true) {
glUseProgram(sShaderProgram);
glBindVertexArray(shadowVertexAttribute);
glm::mat4 lightProjection = glm::ortho(-3000.0f, 3000.0f, -3000.0f,
3000.0f, NEARPLANE, FARPLANE);
glm::mat4 lightView = glm::lookAt(lightPos, glm::vec3(0.0),
glm::vec3(0.0, 1.0, 0.0));
glm::mat4 lightSpaceMatrix = lightProjection * lightView;
glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "lightSpaceMatrix"),
1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
glUniformMatrix4fv(glGetUniformLocation(sShaderProgram, "modelMatrix"),
1, GL_FALSE, glm::value_ptr(mesh.modelMatrix));
//rendering to depthmap
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glClear(GL_DEPTH_BUFFER_BIT);
GLuint texLocation = glGetUniformLocation(sShaderProgram, "DepthMap");
glUniform1i(texLocation, 0);
texLocation = glGetUniformLocation(sShaderProgram, "DiffuseMap");
glUniform1i(texLocation, 1);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, DepthMap);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, textureMap);
glDrawArrays(GL_TRIANGLES, 0, mesh.vertices.size());
glBindFramebuffer(GL_FRAMEBUFFER, 0);
setViewPort();
}
Here's also the Shadow Vertex and Shadow Fragment shader if needed.
Vertex:
//Vertex Shader
#version 440
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec2 vertex_UV;
layout(location = 2) in vec3 vertex_normal;
uniform mat4 modelMatrix;
uniform mat4 lightSpaceMatrix;
out vec3 outVertex;
out vec2 outTexCoords;
out vec3 outNormals;
out vec4 outVertexLightSpace;
layout(binding = 3 , std140) uniform uniformBlock
{
vec3 camPos;
mat4 world;
mat4 LookAt;
mat4 projection;
mat4 MVP;
};
layout(binding = 4 , std140) uniform materials
{
vec3 Diffuse;
vec3 Ambient;
vec3 Translucency;
//char texturePath[128];
float refraction;
vec3 Specular;
float PhongSpecular;
};
void main()
{
outVertex = vec3(modelMatrix * vec4(vertex_position, 1.0));
outTexCoords = vertex_UV;
outNormals = transpose(inverse(mat3(modelMatrix))) * vertex_normal;
outVertexLightSpace = lightSpaceMatrix * vec4(vertex_position, 1.0f);
gl_Position = projection * LookAt * modelMatrix * vec4(vertex_position ,
1.0);
}
Fragment:
//Fragment Shader
#version 440
out vec4 fragment_color;
uniform sampler2D DepthMap;
uniform sampler2D DiffuseMap;
uniform vec3 lightPos;
in vec3 outVertex;
in vec2 outTexCoords;
in vec3 outNormals;
in vec4 outVertexLightSpace;
layout(binding = 3 , std140) uniform uniformBlock
{
vec3 camPos;
mat4 world;
mat4 LookAt;
mat4 projection;
mat4 MVP;
};
float CalculateShadow(vec4 fragPos){
vec3 projCoords = outVertexLightSpace.xyz / outVertexLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
float closestDepth = texture(DepthMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float shadow;
if(currentDepth > closestDepth) {
shadow = 1.0;
}
else {
shadow = 0.0;
}
return shadow;
}
void main()
{
vec3 color = texture(DiffuseMap, outTexCoords).rgb;
vec3 normal = normalize(outNormals);
vec3 lightColor = vec3(1.0);
vec3 ambient = 0.4 * color;
vec3 lightDir = normalize(lightPos - outVertex);
float diff = max(dot(lightDir, normal), 0.0);
vec3 diffuse = diff * lightColor;
vec3 viewDir = normalize(camPos - outVertex);
vec3 halfWayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(normal, halfWayDir), 0.0), 64.0);
vec3 specular = spec * lightColor;
float shadowValue = CalculateShadow(outVertexLightSpace);
vec3 lighting = (ambient + (1.0 - shadowValue) * (diffuse + specular)) * color;
fragment_color = vec4(lighting, 1.0);
}
If you have any pointers to what could be wrong I'd be happy to hear them. Thank you for all your help in advance :D
Related
I'm trying to use a framebuffer as a Geometry Buffer for deferred shading. I'm having issues with writing and reading from the framebuffer's color attachments.
All I am trying to do is verify that my framebuffer's color attachments have some data. I do this by binding one of the color attachments and drawing a fullscreen quad. Each color attachment results in a fully black screen even though I've verified that my uniform variables are receiving the data they need.
My framebuffer is setup as follows:
glGenFramebuffers(1, &FBOID);
glBindFramebuffer(GL_FRAMEBUFFER, FBOID);
int WIDTH = windowDetails->width;
int HEIGHT = windowDetails->height;
glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, WIDTH, HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
glGenTextures(1, &gAlbedo);
glBindTexture(GL_TEXTURE_2D, gAlbedo);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gAlbedo, 0);
glGenTextures(1, &gNormal);
glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, WIDTH, HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gNormal, 0);
glGenTextures(1, &gEffects);
glBindTexture(GL_TEXTURE_2D, gEffects);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, WIDTH, HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gEffects, 0);
GLuint attachments[4] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
glDrawBuffers(4, attachments);
glGenRenderbuffers(1, &zBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, zBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WIDTH, HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zBuffer);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "Framebuffer not complete !" << std::endl;
}
Every frame, I will bind this framebuffer and draw to it using my geometry shader. Then I will bind a test shader to check if the contents of the color attachements have some data by binding all of the color attachments to their own texture unit and passing one of them to the test shader:
glDisable(GL_BLEND); // No blend for deffered rendering
glEnable(GL_DEPTH_TEST); // Enable depth testing for scene render
glBindFramebuffer(GL_FRAMEBUFFER, FBOID); // Start drawing to FBO
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(gShader);
SubmittedGeometry& geometry = defferedGeometry[0];
glm::mat4 projViewModel = projection * view * geometry.transform;
glm::mat4& prevProjViewModel = prevProjViewModels.count(geometry.handle) <= 0 ? projViewModel : prevProjViewModels.at(geometry.handle);
prevProjViewModels.insert({ geometry.handle, projViewModel });
glUniformMatrix4fv(matModelLoc, geometry.transform);
glUniformMatrix4fv(matProjViewLoc, projViewModel);
glUniformMatrix4fv(matPrevProjeViewLoc, prevProjViewModel);
// Bind albedo textures
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, albedoTexID);
glUniform1i(albedoLoc, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normalTexID);
glUniform1i(normalLoc, 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, roughnessTexID);
glUniform1i(rougnessLoc, 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, metalnessTexID);
glUniform1i(metalnessLoc, 3);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, aoTexID);
glUniform1i(aoLoc, 4);
glBindVertexArray(geometry.vaoID);
glDrawElements(GL_TRIANGLES, geometry.indices, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Done drawing to FBO
// Test FBO color attachments
glUseProgram(testShaderID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gAlbedo);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, gEffects);
glUniform1i(testTextureLoc, 1);
quad->Draw();
Assigning the testTexture sampler with 0, 1, 2, or 3 all result in a black screen.
Geometry Shader:
VERTEX SHADER
#version 420
layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec3 vNormal;
layout (location = 2) in vec2 vTextureCoordinates;
layout (location = 3) in vec3 vBiNormal;
layout (location = 4) in vec3 vTangent;
uniform mat4 uMatModel;
uniform mat4 uMatView;
uniform mat4 uMatProjection;
uniform mat4 uMatProjViewModel;
uniform mat4 uMatPrevProjViewModel;
out vec3 mViewPosition;
out vec2 mTextureCoordinates;
out vec3 mNormal;
out vec4 mFragPosition;
out vec4 mPrevFragPosition;
void main()
{
// Translate to view space
vec4 viewFragmentPosition = uMatView * uMatModel * vec4(vPosition, 1.0f);
mViewPosition = viewFragmentPosition.xyz;
mTextureCoordinates = vTextureCoordinates;
// Apply transformation to normal
mat3 matNormal = transpose(inverse(mat3(uMatView * uMatModel)));
mNormal = matNormal * vNormal;
mFragPosition = uMatProjViewModel * vec4(vPosition, 1.0f);
mPrevFragPosition = uMatPrevProjViewModel * vec4(vPosition, 1.0f);
gl_Position = uMatProjection * viewFragmentPosition;
};
FRAGMENT SHADER
#version 420
layout (location = 0) out vec4 gPosition;
layout (location = 1) out vec4 gAlbedo;
layout (location = 2) out vec4 gNormal;
layout (location = 3) out vec3 gEffects;
in vec3 mViewPosition;
in vec2 mTextureCoordinates;
in vec3 mNormal;
in vec4 mFragPosition;
in vec4 mPrevFragPosition;
uniform sampler2D uAlbedoTexture1;
uniform sampler2D uNormalTexture;
uniform sampler2D uRoughnessTexture;
uniform sampler2D uMetalnessTexture;
uniform sampler2D uAmbientOcculsionTexture;
const float nearPlane = 1.0f;
const float farPlane = 1000.0f;
float LinearizeDepth(float depth);
vec3 ComputeTextureNormal(vec3 viewNormal, vec3 textureNormal);
void main()
{
vec3 normal = normalize(texture(uNormalTexture, mTextureCoordinates).rgb * 2.0f - 1.0f); // Sample normal texture and convert values in range from -1.0 to 1.0
vec2 fragPos = (mFragPosition.xy / mFragPosition.w) * 0.5f + 0.5f;
vec2 prevFragPos = (mPrevFragPosition.xy / mPrevFragPosition.w) * 0.5f + 0.5f;
gPosition = vec4(mViewPosition, LinearizeDepth(gl_FragCoord.z)); // Set position with adjusted depth
gAlbedo.rgb = vec3(texture(uAlbedoTexture1, mTextureCoordinates)); // Sample and assign albedo rgb colors
gAlbedo.a = vec3(texture(uRoughnessTexture, mTextureCoordinates)).r; // Sample and assign roughness value
gNormal.rgb = ComputeTextureNormal(mNormal, normal); // Assign normal
gNormal.a = vec3(texture(uMetalnessTexture, mTextureCoordinates)).r; // Sample and assign metalness value
gEffects.r = vec3(texture(uAmbientOcculsionTexture, mTextureCoordinates)).r;
gEffects.gb = fragPos - prevFragPos;
}
float LinearizeDepth(float depth)
{
float z = depth * 2.0f - 1.0f;
return (2.0f * nearPlane * farPlane) / (farPlane + nearPlane - z * (farPlane - nearPlane));
}
vec3 ComputeTextureNormal(vec3 viewNormal, vec3 textureNormal)
{
// Get partial derivatives
vec3 dPosX = dFdx(mViewPosition);
vec3 dPosY = dFdy(mViewPosition);
vec2 dTexX = dFdx(mTextureCoordinates);
vec2 dTexY = dFdy(mTextureCoordinates);
// Convert normal to tangent space
vec3 normal = normalize(viewNormal);
vec3 tangent = normalize(dPosX * dTexY.t - dPosY * dTexX.t);
vec3 binormal = -normalize(cross(normal, tangent));
mat3 TBN = mat3(tangent, binormal, normal);
return normalize(TBN * textureNormal);
}
And my test shader code is:
VERTEX SHADER
#version 420
layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec2 vTextureCoordinates;
out vec2 mTextureCoordinates;
void main()
{
mTextureCoordinates = vTextureCoordinates; // Pass out texture coords
gl_Position = vec4(vPosition, 1.0f);
};
FRAGMENT SHADER
#version 420
in vec2 mTextureCoordinates;
out vec4 oColor;
uniform sampler2D testTexture;
void main()
{
vec3 color = texture(testTexture, mTextureCoordinates).rgb;
oColor = vec4(color, 1.0f);
}
I've made sure that glCheckFramebufferStatus is always complete and that all of my uniform variables are being passed correctly in to the shader
Turns out my code here is correct. My issue was that I was crossing the wrong vectors so my camera's view matrix was wrong.
I am trying to make a simple deferred lighting scene in OpenGL, but the problem after the implementation of a 1 point light I got a 180 degree lighted surface :
screenshot 1 :
screenshot 2 :
Here is my code :
Material shaderGeometryPass("Shaders/deff_shader.vers", "Shaders/deff_shader.frags");
Material shaderLightingPass("Shaders/deff_light.vers", "Shaders/deff_light.frags");
shaderLightingPass.Use();
shaderLightingPass.setInt("gPosition", 0);
shaderLightingPass.setInt("gNormal", 1);
shaderLightingPass.setInt("gAlbedoSpec", 2);
// configure g-buffer framebuffer
// ------------------------------
unsigned int gBuffer;
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
unsigned int gPosition, gNormal, gAlbedoSpec;
// position color buffer
glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_weight, SCR_height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
// normal color buffer
glGenTextures(1, &gNormal);
glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_weight, SCR_height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
// color + specular color buffer
glGenTextures(1, &gAlbedoSpec);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_weight, SCR_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gAlbedoSpec, 0);
// tell OpenGL which color attachments we'll use (of this framebuffer) for rendering
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
// create and attach depth buffer (renderbuffer)
unsigned int rboDepth;
glGenRenderbuffers(1, &rboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_weight, SCR_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
// finally check if framebuffer is complete
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "Framebuffer not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
while (!glfwWindowShouldClose(window) == 0)
{
camera.ComputeMatrices();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1. geometry pass: render scene's geometry/color data into gbuffer
// -----------------------------------------------------------------
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (size_t i = 0; i < mScene.all_children.size(); i++)
{
if (mScene.all_children[i]->Get_component_id(Comp_Mesh) >= 0)
{
bool get_suc = false;
RMesh &get_mesh = meshs.GetMesh(mScene.all_children[i]->Get_component_id(Comp_Mesh), get_suc);
if (get_suc)
{
if (!get_mesh.mesh_available) continue;
get_mesh.UseVertex();
shaderGeometryPass.Use();
glm::mat4 ModelMatrix = glm::scale(translate(mat4(1.0), mScene.all_children[i]->transform.Position), mScene.all_children[i]->transform.Scale);
shaderGeometryPass.SetMat4("projection", camera.GetProjectionMatrix());
shaderGeometryPass.SetMat4("view", camera.GetViewMatrix());
shaderGeometryPass.SetMat4("model", ModelMatrix);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1));
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2));
// Set our "myTextureSampler" sampler to use Texture Unit 0
glUniform1i(shaderGeometryPass.GetUniform("texture_diffuse"), 0);
glUniform1i(shaderGeometryPass.GetUniform("texture_specular"), 1);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, get_mesh.vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, get_mesh.uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, get_mesh.normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, get_mesh.elementbuffer);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, get_mesh.indices.size(), GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
get_mesh.EndVertex();
}
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 2. lighting pass: calculate lighting by iterating over a screen filled quad pixel-by-pixel using the gbuffer's content.
// -----------------------------------------------------------------------------------------------------------------------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderLightingPass.Use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
// send light relevant uniforms
for (size_t i = 0; i < mScene.all_children.size(); i++)
{
if (mScene.all_children[i]->Get_component_id(Comp_PointLight) >= 0)
{
int g;
if (Point_lights.GetLight(mScene.all_children[i]->Get_component_id(Comp_PointLight), &g))
{
if (Point_lights.lights[g].light_id == mScene.all_children[i]->Get_component_id(Comp_PointLight))
{
Point_lights.lights[g].Position = mScene.all_children[i]->transform.Position;
}
}
}
if (Point_lights.lights.size() > 0)
{
shaderLightingPass.SetVec3("lights[0].Position", Point_lights.lights[0].Position);
shaderLightingPass.SetVec3("lights[0].Color", Point_lights.lights[0].Color);
// update attenuation parameters and calculate radius
const float constant = 1.0;
const float linear = Point_lights.lights[0].Range;
const float quadratic = 1.8;
shaderLightingPass.SetFloat("lights[0].Linear", linear);
shaderLightingPass.SetFloat("lights[0].Quadratic", quadratic);
// then calculate radius of light volume/sphere
const float maxBrightness = Point_lights.lights[0].Energy; //std::fmaxf(std::fmaxf(Point_lights.lights[0].Color.r, Point_lights.lights[0].Color.g), Point_lights.lights[0].Color.b);
float radius = (-linear + std::sqrt(linear * linear - 4 * quadratic * (constant - (256.0f ) * maxBrightness))) / (2.0f * quadratic);
shaderLightingPass.SetFloat("lights[0].Radius", radius);
}
}
shaderLightingPass.SetVec3("viewPos", camera.transform.Position);
renderQuad();
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
"deff_light.vers" shader :
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos, 1.0);
}
"deff_light.frags" shader :
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;
struct Light {
vec3 Position;
vec3 Color;
float Linear;
float Quadratic;
float Radius;
};
const int NR_LIGHTS = 1;
uniform Light lights[NR_LIGHTS];
uniform vec3 viewPos;
void main()
{
// retrieve data from gbuffer
vec3 FragPos = texture(gPosition, TexCoords).rgb;
vec3 Normal = texture(gNormal, TexCoords).rgb;
vec3 Diffuse = texture(gAlbedoSpec, TexCoords).rgb;
float Specular = texture(gAlbedoSpec, TexCoords).a;
// then calculate lighting as usual
vec3 lighting = Diffuse * 0.1; // hard-coded ambient component
vec3 viewDir = normalize(viewPos - FragPos);
for(int i = 0; i < NR_LIGHTS; ++i)
{
// calculate distance between light source and current fragment
float distance = length(lights[i].Position - FragPos);
if(distance < lights[i].Radius)
{
// diffuse
vec3 lightDir = normalize(lights[i].Position - FragPos);
vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lights[i].Color;
// specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0);
vec3 specular = lights[i].Color * spec * Specular;
// attenuation
float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);
diffuse *= attenuation;
specular *= attenuation;
lighting += diffuse + specular;
}
}
FragColor = vec4(lighting, 1.0);
}
"deff_shader.vers" shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec2 TexCoords;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
vec4 worldPos = model * vec4(aPos, 1.0);
FragPos = worldPos.xyz;
TexCoords = aTexCoords;
mat3 normalMatrix = transpose(inverse(mat3(model)));
Normal = normalMatrix * aNormal;
gl_Position = projection * view * worldPos;
}
"deff_shader.frags" shader:
#version 330 core
layout (location = 0) out vec3 gPosition;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec4 gAlbedoSpec;
in vec2 TexCoords;
in vec3 FragPos;
in vec3 Normal;
uniform sampler2D texture_diffuse1;
uniform sampler2D texture_specular1;
void main()
{
// store the fragment position vector in the first gbuffer texture
gPosition = FragPos;
// also store the per-fragment normals into the gbuffer
gNormal = normalize(Normal);
// and the diffuse per-fragment color
gAlbedoSpec.rgb = texture(texture_diffuse1, TexCoords).rgb;
// store specular intensity in gAlbedoSpec's alpha component
gAlbedoSpec.a = texture(texture_specular1, TexCoords).r;
}
What I am doing wrong ?
Any help please ?
I'm trying to draw texture2 partly (the textures have different position-coordinates) on top of texture1. The textures is supposed have different images.
The code below works fine except that texture1 gets in front of texture2, but it should be the other way around.
If I change the drawing order, texture2 get in front of texture1 as desired but texture2 gets the same image as texture1.
What am I doing wrong here?
In my init function:
glBindAttribLocation(shaderProgram, 0, "position");
glBindAttribLocation(shaderProgram, 1, "color");
glBindAttribLocation(shaderProgram, 2, "texCoordIn");
glBindFragDataLocation(shaderProgram, 0, "fragmentColor");
linkShaderProgram(shaderProgram);
texture = ilutGLLoadImage("image1.jpg");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
texture2 = ilutGLLoadImage("image2.png");
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUseProgram(shaderProgram);
int texLoc = glGetUniformLocation(shaderProgram, "colortexture");
glUniform1i(texLoc, 0);
My vertex-shader:
in vec3 position;
in vec3 color;
out vec3 outColor;
in vec2 texCoordIn;
out vec2 texCoord;
uniform mat4 projectionMatrix;
void main()
{
gl_Position = projectionMatrix * vec4(position, 1);
outColor = color;
texCoord = texCoordIn;
}
My fragment-shader:
in vec3 outColor;
uniform sampler2D colortexture;
in vec2 texCoord;
out vec4 fragmentColor;
void main()
{
fragmentColor = texture2D(colortexture, texCoord.xy);
}
In my draw-function: (If I draw in the order below, the textures get their desired images. But if I change the order, both textures get image1)
glBindVertexArray(vertexArrayObject2);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(vertexArrayObject);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
I am following the shadow tutorial on http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/ and I can view the depth value in the depth texture when rendered to a screen aligned quad. The problem is when I sample from this depth texture I get only one value.
This is how I setup the depth texture FBO; the size of the texture is set to the window size. I'm not sure if this is part of the problem, but if I half the dimensions of the depth texture and try to view that, I end up seeing a corner quarter of the view. I thought textures are always accessed from [0,1]?
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0,
GL_DEPTH_COMPONENT,
fbWidth,
fbHeight,
0,
GL_DEPTH_COMPONENT,
GL_FLOAT,
0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, renderedTexture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
assert(false && "framebuffer NOT OK");
1st pass vertex shader
#version 150 core
in vec3 position;
uniform mat4 model;
void main(){
gl_Position = model * vec4(position,1.0);
}
1st pass fragment shader
#version 150 core
void main(){ //letting the default gl_FragDepth assignment happen
}
2nd pass vertex shader
#version 150 core
in vec3 position;
out vec4 shadowCoord;
uniform mat4 model;
uniform mat4 camera;
uniform mat4 DepthBiasMVP;
void main() {
gl_Position = camera * model * vec4(position, 1.0);
shadowCoord = DepthBiasMVP * vec4(position, 1.0);
}
2nd pass fragment shader: the stuck at 1 or 0 problems are in the comments, along with the variations I've tried
#version 150 core
in vec4 shadowCoord;
uniform mat4 model;
out vec4 outColor;
//tried both types
//uniform sampler2D shadowMap;
uniform sampler2DShadow shadowMap;
void main() {
vec3 finalColor = ...
float visibility = 1.0;
vec3 P = shadowCoord.xyz / shadowCoord.w; //doesn't work
// vec3 P =vec3(shadowCoord.x, shadowCoord.y, shadowCoord.z); //no difference
// vec3 P = vec3(shadowCoord.xy, shadowCoord.z / shadowCoord.w); //also no difference
visibility = texture( shadowMap, P); // always 1
// //when shadowMap is set to sampler2D
// vec3 textureCoord = shadowCoord.xyz/ shadowCoord.w;
// if (texture(shadowMap, shadowCoord.xy).z ==0) //always 0
// if (texture(shadowMap, shadowCoord.xy).x ==0) //always 1
// if (shadowCoord.z == 0) //always 0
// visibility = 0.06; //
finalColor *= visibility;
outColor = vec4(finalColor, 1.0);
}
This is how I call the passes, the object I am looking at is located at the origin
glm::vec3 srcPerspective(0,0,-4);
glm::mat4 depthProjectionMatrix = glm::ortho<float>(-1,1,-1,1,-10,10);
glm::mat4 depthViewMatrix = glm::lookAt(srcPerspective, glm::vec3(0,0,0), glm::vec3(0,1,0));
//pass 1
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shadowMap.shaderProgram);
depthMVP = depthProjectionMatrix * depthViewMatrix * modelMatrix;
shadowMap.drawIndexed(world, camera, depthMVP, shapes[shipIdx].mesh.indices.data());
//pass 2
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
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
);
glm::mat4 depthBiasMVP = biasMatrix * depthMVP;
glUniformMatrix4fv(loc, 1, GL_FALSE, &depthBiasMVP[0][0]);
ship.drawIndexed(world, camera, lightPos, mvp, shipColor, shapes[shipIdx].mesh.indices.data());
I made an application which renders skybox and particles over it. I want to add some effects and i need to use framebuffers to render skybox, particles color, depth and position to separate textures. Then i want to use simple shader to use values from these textures and mix them in a proper way. I wrote helper classes for textures, framebuffers and screen quad (simple rectangle to render) but unfortunately - nothing renders when i try to use it.
When binding framebuffers is commented out, my scene looks like this:
Modifying shader shows that depth and position values are calculated properly. Therefore problem lays in texture and framebuffers way of using. Time for some code:
Framebuffer helper class (only important methods):
void Framebuffer::init(){
// unbind all textures from openGL
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &framebuffer);
}
void Framebuffer::bind(){
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}
void Framebuffer::unbind(){
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Framebuffer::attachTexture(GLuint texture, GLenum attachmentType){
glBindTexture(GL_TEXTURE_2D, texture);
glFramebufferTexture(GL_FRAMEBUFFER, attachmentType, texture, 0);
}
void Framebuffer::drawBuffers(GLsizei n, const GLenum *buffers){
glDrawBuffers(n, buffers);
}
Texture helper class:
void Texture::init(GLuint windowWidth, GLuint windowHeight, GLint internalFormat, GLenum format, GLenum type){
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D( GL_TEXTURE_2D, 0, internalFormat , windowWidth, windowHeight, 0, format, type, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Texture::bind(){
glBindTexture(GL_TEXTURE_2D, texture);
}
void Texture::unbind(){
glBindTexture(GL_TEXTURE_2D, 0);
}
GLuint Texture::getId(){
return texture;
}
ScreenQuad class:
void ScreenQuad::init(void){
vao.createVAO();
vao.bindVAO();
vbo.createVBO();
vbo.addData(vertices, 8*sizeof(GLfloat));
vbo.bindVBO(GL_ARRAY_BUFFER);
vbo.uploadDataToGPU(GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)3, 2, GL_FLOAT, GL_FALSE, 0, NULL);
loadShaders("shaders/basicPostShader.vp", "shaders/basicPostShader.fp");
}
void ScreenQuad::loadShaders(string vsPath, string fsPath){
shaderProgram.createProgram();
shaderProgram.loadVertexShader(vsPath);
shaderProgram.loadFragmentShader(fsPath);
glBindAttribLocation(shaderProgram.getProgramID(), 3, "v_coord");
shaderProgram.linkProgram();
}
void ScreenQuad::draw(GLuint depthTexture, GLuint colorTexture, GLuint positionTexture, GLuint backgroundTexture){
shaderProgram.bindProgram();
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthTexture);
shaderProgram.setUniform("u_depthtex", 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, colorTexture);
shaderProgram.setUniform("u_colortex", 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, positionTexture);
shaderProgram.setUniform("u_positiontex", 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
shaderProgram.setUniform("u_backgroundtex", 3);
glEnableVertexAttribArray(3);
vbo.bindVBO();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
vbo.unbindVBO();
glDisableVertexAttribArray(3);
shaderProgram.unbindProgram();
}
and methods for initialization and rendering scene:
void OpenGLContext::setupScene(void) {
glClearColor(0.4f, 0.6f, 0.9f, 1.0f);
//FRAMEBUFFERS:
skyboxFramebuffer.init();
skyboxTexture.init(windowWidth, windowHeight, GL_RGBA32F, GL_RGBA, GL_FLOAT);
skyboxFramebuffer.bind();
skyboxFramebuffer.attachTexture(skyboxTexture.getId(), GL_COLOR_ATTACHMENT0);
const GLenum skyboxDrawBuffers[1] = { GL_COLOR_ATTACHMENT0};
skyboxFramebuffer.drawBuffers(1, skyboxDrawBuffers);
skyboxFramebuffer.validate();
skyboxFramebuffer.unbind();
mainFramebuffer.init();
mainColorTexture.init(windowWidth, windowHeight, GL_RGBA32F, GL_RGBA, GL_FLOAT);
mainPositionTexture.init(windowWidth, windowHeight, GL_RGBA32F, GL_RGBA, GL_FLOAT);
mainDepthTexture.init(windowWidth, windowHeight, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT);
mainFramebuffer.bind();
mainFramebuffer.attachTexture(mainColorTexture.getId(), GL_COLOR_ATTACHMENT0);
mainFramebuffer.attachTexture(mainPositionTexture.getId(), GL_COLOR_ATTACHMENT1);
mainFramebuffer.attachTexture(mainDepthTexture.getId(), GL_DEPTH_ATTACHMENT);
const GLenum mainDrawBuffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
mainFramebuffer.drawBuffers(2, mainDrawBuffers);
mainFramebuffer.validate();
mainFramebuffer.unbind();
//SKYBOX:
skybox->init("resources/skybox/default/",
"pos_x.tga",
"neg_x.tga",
"pos_y.tga",
"neg_y.tga",
"pos_z.tga",
"neg_z.tga");
//PARTICLES:
particles->init(scene);
//SCREENQUAD:
screenQuad.init();
}
void OpenGLContext::renderScene() {
glfwGetFramebufferSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
fpsCounter->calcFPS(1.0, windowName);
if(mode==INPUT_ENABLED_MODE){
updateInputs();
}
projectionMatrix = controls->getProjectionMatrix();
viewMatrix = controls->getViewMatrix();
modelMatrix = glm::mat4(1.0f);
glm::mat4 mvpMatrix = projectionMatrix*viewMatrix*modelMatrix;
//SKYBOX:
skyboxFramebuffer.bind();
skybox->render(mvpMatrix);
skyboxFramebuffer.unbind();
//PARTICLES:
if(scene->tryLockScene()){
if(scene->isSceneUpdated()){
particles->updateParticlesPosition(scene);
scene->setSceneUpdated(false);
}
scene->unlockScene();
}
mainFramebuffer.bind();
particles->draw(modelMatrix, viewMatrix, projectionMatrix);
mainFramebuffer.unbind();
//SCREENQUAD:
screenQuad.draw(mainDepthTexture.getId(), mainColorTexture.getId(), mainPositionTexture.getId(), skyboxTexture.getId());
glfwSwapBuffers(window);
glfwPollEvents();
}
plus screenQuad shaders:
vertex:
#version 430
layout (location = 3) in vec2 v_coord;
layout (binding = 0) uniform sampler2D u_depthtex;
layout (binding = 1) uniform sampler2D u_colortex;
layout (binding = 2) uniform sampler2D u_positiontex;
layout (binding = 3) uniform sampler2D u_backgroundtex;
out vec2 fs_texcoord;
void main(void) {
gl_Position = vec4(v_coord, 0.0, 1.0);
fs_texcoord = (v_coord + 1.0) / 2.0;
}
and fragment:
#version 430
layout (binding = 0) uniform sampler2D u_depthtex;
layout (binding = 1) uniform sampler2D u_colortex;
layout (binding = 2) uniform sampler2D u_positiontex;
layout (binding = 3) uniform sampler2D u_backgroundtex;
layout (location = 0) out vec4 out_Color;
in vec2 fs_texcoord;
void main(void) {
float exp_depth = texture(u_depthtex,fs_texcoord).r;
if(exp_depth>0.99f){
out_Color = vec4(texture(u_backgroundtex,fs_texcoord).xyz,1.0f);
return;
}
out_Color = vec4(texture(u_colortex,fs_texcoord).xyz, 1.0f);
}
Shader helper classes, vao and vbo helper classes are fine for sure. No errors occurs in logs.
UPDATE:
particles vertex shader:
#version 430
uniform mat4x4 modelViewMatrix;
uniform mat4x4 projectionMatrix;
uniform float pointRadius; // point size in world space
uniform float pointScale; // scale to calculate size in pixels
layout (location = 0) in vec3 in_Position;
layout (location = 1) in vec4 in_Color;
out vec3 fs_PosEye;
out vec4 fs_Position;
out vec4 fs_Color;
void main(void) {
vec3 posEye = (modelViewMatrix * vec4(in_Position.xyz, 1.0f)).xyz;
float dist = length(posEye);
gl_PointSize = pointRadius * (pointScale/dist);
fs_PosEye = posEye;
fs_Position = modelViewMatrix * vec4(in_Position.xyz, 1.0f);
fs_Color = in_Color;
gl_Position = projectionMatrix * modelViewMatrix * vec4(in_Position.xyz, 1.0f);
}
fragment shader:
#version 430
uniform mat4x4 modelViewMatrix;
uniform mat4x4 projectionMatrix;
uniform float pointRadius; // point size in world space
uniform float pointScale; // scale to calculate size in pixels
in vec4 fs_Position;
in vec3 fs_PosEye;
in vec4 fs_Color;
layout (location = 0) out vec4 out_Color;
layout (location = 1) out vec4 out_Position;
void main(void)
{
// calculate normal from texture coordinates
vec3 normal;
normal.xy = gl_PointCoord.xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
float r = dot(normal.xy, normal.xy);
if(r>1.0)
discard;
normal.z = sqrt(1.0-r);
//calculate depth
vec4 pixelPos = vec4(fs_PosEye + normalize(normal)*pointRadius,1.0f);
vec4 clipSpacePos = projectionMatrix * pixelPos;
gl_FragDepth = (clipSpacePos.z / clipSpacePos.w);
out_Color = fs_Color;
out_Position = pixelPos;
}
and Particles.draw() method:
void CParticles::draw(glm::mat4 modelMatrix, glm::mat4 viewMatrix, glm::mat4 projectionMatrix){
shaderProgram.bindProgram();
glm::mat4 modelViewMatrix = viewMatrix*modelMatrix;
shaderProgram.setUniform("projectionMatrix", &projectionMatrix);
shaderProgram.setUniform("modelViewMatrix", &modelViewMatrix);
shaderProgram.setUniform("pointRadius", &pointRadius);
shaderProgram.setUniform("pointScale", &pointScale);
glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
glEnable(GL_POINT_SPRITE);
glEnable(GL_PROGRAM_POINT_SIZE);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_POINTS, 0, n);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisable(GL_PROGRAM_POINT_SIZE);
glDisable(GL_POINT_SPRITE);
shaderProgram.unbindProgram();
}
UPDATE2:
The problem is that textures filled by a particle shader are empty when I try to sample data from them in a screenQuad shader. Each depth, position and color texture samplers return zeros. I use same classes and same methods as with a skybox, but skybox texture works fine.
UPDATE3:
Random code changes showed me that if I comment line with attaching depth texture to framebuffer, particle color is finally passed to a texture and i can see it on a screen quad (but without any depth test. Red particles (drawed last) are always on the front).
I guess there is a problem with connecting particle shader with depth texture. But still I can't find an exact bug. I hope my sugestion will be helpful.
I haven't studied the entire code, but one problem jumps out immediately:
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, colorTexture);
shaderProgram.setUniform("u_colortex", colorTexture);
The value of a uniform for a texture sampler is not the texture id (aka name). It's the texture unit the texture is bound to. So in this case, since you're using texture unit 1 for this texture, it should be:
shaderProgram.setUniform("u_colortex", 1);
The problem was that glDepthMask() was disabled when i invoked glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);.
It needs to be enabled in order to glClear(GL_DEPTH_BUFFER_BIT) took any effect.
Plus I needed to add cleaning framebuffers in a proper way as well.