glReadPixels is not working with GL_FLOAT - opengl

I'm using OpenGL shader and trying to print the color values.
So, I used glReadPixels function. It is working with GL_UNSIGNED_BYTE but not with GL_FLOAT.
Is there anything else should I do?
This is my code.
void settingFrameBuffers()
{
glGenFramebuffers(NUM_FBO, fbo);
glGenTextures(NUM_FBO, tex);
for (int i = 0; i < NUM_FBO; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
glBindTexture(GL_TEXTURE_2D, tex[i]);
if (i == 0) glActiveTexture(GL_TEXTURE0);
else if (i == 1) glActiveTexture(GL_TEXTURE1);
else if (i == 2) glActiveTexture(GL_TEXTURE2);
else if (i == 3) glActiveTexture(GL_TEXTURE3);
else if (i == 4) glActiveTexture(GL_TEXTURE4);
else if (i == 5) glActiveTexture(GL_TEXTURE5);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[i], 0);
GLuint dbo;
glGenRenderbuffers(1, &dbo);
glBindRenderbuffer(GL_RENDERBUFFER, dbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, dbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
}
void printWholeMassToConsole()
{
GLfloat* data =new GLfloat[4 * width*height];
glBindFramebuffer(GL_FRAMEBUFFER, fbo[otFb]);
//glReadPixels(0, 0, width, height, GL_RGBA, GL_FLOAT, data);
glReadnPixels(0, 0, width, height, GL_RGBA, GL_FLOAT, sizeof(data), data);
float sumR = 0;
float sumG = 0;
float sumB = 0;
for (int i = 0; i < 4 * width*height; i += 4)
{
if (i > 0) break;
sumR += data[i];
sumG += data[i + 1];
sumB += data[i + 2];
}
float sum = sumR + sumG + sumB;
float possibleDiff = 3.0*width*height*0.5;
//if (abs(wholeMass - sum) <= possibleDiff) cout << "O - ";
//else cout << "X - ";
printf("mass : %d\t %d\t %d\t %d\n", sum, sumR, sumG, sumB);
free(data);
}
This is the first shader.
// vertex shader
#version 450
in vec4 position;
in vec2 texCoord;
out vec2 fragTexCoord;
void main()
{
gl_Position = position;
fragTexCoord = texCoord;
}
// fragment shader
#version 450
in vec2 fragTexCoord;
out vec4 FragColor;
void main()
{
FragColor = vec4(0.5, 0.0, 0.0, 1.0);
}
This is the second shader.
// vertex shader
#version 450
in vec4 position;
in vec2 texCoord;
out vec2 fragTexCoord;
void main()
{
gl_Position = position;
fragTexCoord = texCoord;
}
// fragment shader
#version 450
in vec2 fragTexCoord;
uniform sampler2D tex;
out vec4 FragColor;
void main()
{
FragColor = texture(tex, fragTexCoord);
}
It draws something on otFb framebuffer through the first shader and then otFb texture is mapped on the main framebuffer.
When I use glReadPixels with GL_FLOAT, the program is terminated by itself, when glReadnPixels with GL_FLOAT, the program print garbage values.
I used so many times to search, but I could not find the solutions.
Or is there any different way that I can try?

Try changing the first parameter of the framebuffer binding function call(the second line of code in your printWholeMassToConsole function) i.e.:
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[otFb]);
Hope it works.

Related

Issues writing to Framebuffer (Color attachments always black)

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 facing a glTextureStorage2D error. Opengl

Here is an image of the issue I am facing in opengl:
In the image I tagged my texture also displays weirdly.
Can someone help me figure out why the texture on the ground is incomplete and placed odd?
This is my code:
Ground.LoadModel("O_Ground.obj");
Fence.LoadModel("O_Fence.obj");
string names[] = { "Green.jpg","wood.jpg" };
glGenTextures(2, texture);
for( string name :names)
{
stbi_set_flip_vertically_on_load(true);
int iWidth, iHeight, iChannels;
unsigned char* iData = stbi_load(name.c_str(), &iWidth, &iHeight, &iChannels, 0);
for (int i=0;i<2;i++)
{
glBindTexture(GL_TEXTURE_2D, texture[i]);
glTextureStorage2D(texture[i], 1, GL_RGB8, iWidth, iHeight);
glTextureSubImage2D(texture[i], 0, 0, 0, iWidth, iHeight, GL_RGB, GL_UNSIGNED_BYTE, iData);
cout << texture[i];
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
}
}
This is my render function
for (int i = 0;i < 2; i++)
{
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, texture[i]);
GLint tex_location = glGetUniformLocation(program, "texture[i]");
glUniform1i(tex_location, i);
}
Ground.Draw();
Fence.Draw();
And my vertex and fragment shaders
vsmodel1
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 tc;
layout (location = 2) in vec3 normals;
out VS_OUT
{
vec2 tc;
vec3 normals;
} vs_out;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 proj_matrix;
void main(void)
{
gl_Position = proj_matrix * view_matrix * model_matrix * vec4(position, 1.0);
vs_out.tc = tc;
vs_out.normals = normals;
}
fsmodel1
out vec4 color;
in VS_OUT
{
vec2 tc;
vec3 normals;
}
fs_in;
layout(binding=0)uniform sampler2D tex;
void main(void)
{
color= texture(tex, fs_in.tc);
}
The functions glTextureStorage2D and glTextureSubImage2D are not part of OpenGL 4.3 which you are using here.
These functions were introduced with direct state access in OpenGL 4.5. You'll have to use the non-DSA functions glTexStorage2D and glTexSubImage2D instead, with the other semantics of course.
This part of the code is also not going to work:
for (int i = 0;i < 2; i++)
{
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, texture[i]);
GLint tex_location = glGetUniformLocation(program, "texture[i]");
glUniform1i(tex_location, i);
}
There is no uniform called texture in your shader program. And even if it were, and it were an array, texture[i] would still not work, as the i is just part of the string literal, and not the value of the variable i you declared in your code.
Since the above glGetUniformLocation() calls a guaranteed to return -1, thew glUniform call following it will have no effect.
Your shader:
// [...]
layout(binding=0)uniform sampler2D tex;
void main(void)
{
color= texture(tex, fs_in.tc);
}
is only using a tex uniform, and it is using only one texture unit at all. The tex uniform will point to unit 0. It is totally unclear why you even bind 2 different textures at once to units 0 and 1, if your shader can ever only deal with one.

openGL single channel texture always samples 0

I'm trying to render font on screen using freetype. For that, I implemented single channel texture but it always samples 0.
cpp
unsigned char *blankData = new unsigned char[8 * 8];
for(int i = 0; i < 8 * 8; i++){
blankData[i] = 126;
}
glActiveTexture(GL_TEXTURE0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLuint m_texture2D;
glGenTextures(1, &m_texture2D);
glBindTexture(GL_TEXTURE_2D, m_texture2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, blankData);
glUniform1i(glGetUniformLocation(m_program, "texture2D"), 0);
checkGLError();
glGetError() returns GL_NO_ERROR
fragment Shader
#version 330 core
in vec2 texCoord;
in vec4 color;
uniform sampler2D texture2D;
out vec4 outColor;
void main()
{
vec4 texColor = texture(texture2D, texCoord);
outColor = vec4(texColor.r, texColor.r, texColor.r, 1.0f);
}
result
ff00ff: clear color
black: fragment shader output texcoord bottomLeft(0, 0) to topRight(1, 1)
If you are not generating mipmaps (with glGenerateMipmap) it is important to set GL_TEXTURE_MIN_FILTER. Since the default filter is GL_NEAREST_MIPMAP_LINEAR, the texture would be "Mipmap Incomplete" if you do not change the minimize function to GL_NEAREST or GL_LINEAR.
glBindTexture(GL_TEXTURE_2D, m_texture2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

OpenGL ES3 framebuffer generated is completely ignored

I create a framebuffer object to render scene as depth values to render shadow maps , after the scene initialized and all shaders compiled I add the directional light and create the FBO using this code:
glGenFramebuffers(1, &depthMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffers(1, GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
then in the render loop I render the scene on the generated framebuffer with the depth shader then render the scene again regularly on the screen after unbinding the FBO, this is the code :
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glClear(GL_DEPTH_BUFFER_BIT);
double delta = GetCurrentTime() - firstFrame;
glm::mat4 lightSpaceProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f);
glm::mat4 lightSpaceView = glm::lookAt(-sun->direction, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
lightSpaceMatrix = lightSpaceProjection * lightSpaceView;
directDepthShader.use();
GLuint lsm = glGetUniformLocation(directDepthShader.getProgramID(), "lightSpaceMatrix");
glUniformMatrix4fv(lsm, 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
for (mesh_it it = phongMeshes.begin(); it != phongMeshes.end(); it++) {
it->get()->renderDepth(directDepthShader, delta);
}
glCullFace(GL_BACK);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
the first function called before the rendering loop and the FBO generated and has an ID but the problem is the rendering function ignored it although I bind it with its ID which is not minus or even not zero to the extent that if I remove the code which create and adjust the framebuffer nothing changes in the rendering result, I am in that problem for a week !!
Edit:
Vertex shader for depth:
#version 300 es
precision mediump float;
layout (location = 0) in vec3 position;
layout (location = 4) in ivec4 BoneIDs;
layout (location = 5) in vec4 Weights;
const int MAX_BONES = 100;
uniform mat4 model;
uniform bool skinned;
uniform mat4 gBones[MAX_BONES];
uniform mat4 lightSpaceMatrix;
void main(){
vec4 nPos;
if(skinned){
mat4 BoneTransform = gBones[BoneIDs[0]] * Weights[0];
BoneTransform += gBones[BoneIDs[1]] * Weights[1];
BoneTransform += gBones[BoneIDs[2]] * Weights[2];
BoneTransform += gBones[BoneIDs[3]] * Weights[3];
nPos=BoneTransform * vec4(position, 1.0);
}
else
nPos = vec4(position, 1.0);
gl_Position = lightSpaceMatrix * model * nPos;
}
the renderDepth() for each mesh using the the depth shader program:
void Mesh::renderDepth(Shader& shader, double& delta) {
if (isSkinned) {
glUniform1i(glGetUniformLocation(shader.getProgramID(), "skinned"), 1);
vector<Matrix4f> Transforms;
BoneTransform(delta, Transforms);
for (uint j = 0; j < Transforms.size(); j++) {
Transforms[j] = Transforms[j].Transpose();
GLuint bonesLoc = glGetUniformLocation(shader.getProgramID(), (const GLchar*) ("gBones[" + ToString(j) + "]").c_str());
glUniformMatrix4fv(bonesLoc, 1, GL_FALSE, (const GLfloat*) Transforms[j]);
}
}
for (uint i = 0; i < m_Entries.size(); i++) {
glUniformMatrix4fv(glGetUniformLocation(shader.getProgramID(), "model"), 1, GL_FALSE, glm::value_ptr(m_Entries[i].matrix));
glBindVertexArray(m_Entries[i].m_VAO);
glDrawElements(GL_TRIANGLES, m_Entries[i].NumIndices, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
}
}

Strange issue with a multi pass, multi RT render in GLSL

I am seeing a strange issue with a multi pass, multi RT ping-pong render
I am using 3 shaders and an FBO, I get no errors at any stage. I am using opengl 4, so I am not using glBegin/glEnd, I use my own matrices for transformation and i am using vertex buffers for rendering
The general idea of this test is to render 3 different colours to three separate fbo attachments (I realise that it is not efficient rendering the vbo twice in the first pass but this is just to help me understand a problem in some other source) I then bind a separate set of textures to the fbo and use the first set as the samplers. The final pass is to blend the results into the back buffer
What is odd is that the output is both quads appear red, when the first should be red and the second green (as these values come from the second shader).
If i change the function SamplePix in the second shader to always take from the second sampler both appear green, and if lookups up from the third then all appears yellow, but it seems to only read from one.
For now I can't seem to explain why I can read from each sampler ok but the loop doesn't seem to lookup correctly (in shader 2)
Also if I switch to rendering the texture sampled in shader 2 i see a black quad in the second pass (image 2)
Hopefully someone can throw some light on the problem. (I have also tried adding a sync fence object after the first pass but this didn't make a difference)
Texture Sample:
// initial setup of shaders and vertex buffers ommitted for now (in separate source files)
// fbo setup like so
const int DepthLayers = 3;
bool InitFBO()
{
// width and height 768pixels
for (int j=0; j<DepthLayers; j++)
{
const int idx = j + (DepthLayers*i);
glGenTextures(1, &g_FBOManager.m_fboTex[ idx ]);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[ idx ]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//no mipmaps
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_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, GL_RGBA8, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
//depth
glGenTextures(1, &g_FBOManager.m_fboDepthTex[ idx ]);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[ idx ]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//no mipmaps
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE/* GL_COMPARE_R_TO_TEXTURE*/);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx]);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx], 0);
glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx]);
// attach a texture to FBO color attachment point
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx], 0);
// check FBO status
pglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_FBOManager.FboId(i) );
if(!CheckFramebufferStatus())
{
return false;
}
}
BindFrameBuffer(-1); // unbind fbo
if (GLGETERROR("1", fileBuf, lineBuf)) ; // check for glErrors
return true; // all ok
}
// code to init second set of textures before the render loop
const int w = g_XMLSettings->WWidth(); //res: 768 square
const int h = g_XMLSettings->WHeight();
glGenTextures(bufCount, &ttex[0]);
for (int i=0; i<bufCount; ++i)
{
glBindTexture(GL_TEXTURE_2D, ttex[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
const int bufCount = 3;
void EnableTexture1()
{
glActiveTextureARB(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, g_BackTexture);
glUniform1iARB(g_pPassAShader->m_clr_idx, 0);
}
void RenderLoop()
{
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT };
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glUseProgramObjectARB(g_pPassAShader->m_glContext);
EnableTexture1();
//... code omitted to set transform matrix and supply to shader
if (!BindFrameBuffer(0))
assert(0);
const GLuint DTex = g_FBOManager.GetDepthTexture(0);
glBindTexture(GL_TEXTURE_2D, DTex);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, DTex, 0);
for (UINT i=0; i<bufCount; ++i)
{
glBindTexture(GL_TEXTURE_2D, g_FBOManager.GetTexture(i));
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, g_FBOManager.GetTexture(i), 0);
if (!CheckFramebufferStatus())
assert(0);
}
glDrawBuffers(bufCount,buffers);
// this is very important! if we don't clear it won't get written to
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_BLEND);
EnableTexture1();
RenderVertexCache(0);
//... code omitted to set transform matrix and supply to shader
// render the second quad to other FBO tex
RenderVertexCache(0);
DisableShader(0);
BindFrameBuffer(-1); // unbinds fbo
//pass 2
if (!BindFrameBuffer(0))
assert(0);
// bind other set of textures to the fbo
for (UINT i=0; i<bufCount; ++i)
{
glBindTexture(GL_TEXTURE_2D,ttex[i]);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, ttex[i], 0);
if (!CheckFramebufferStatus())
assert(0);
}
glDrawBuffers(bufCount,buffers);
// this is very important! if we don't clear it won't get written to
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// bind our set from prev pass to the samplers as input
glUseProgramObjectARB(g_pPassBShader->m_glContext);
for (UINT i=0; i<bufCount; ++i)
{
glActiveTextureARB(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D,g_FBOManager.GetTexture(i));
glUniform1iARB(g_pPassBShader->m_intex_idx[i], i);
}
VertexBufferManager2::RenderUsingOrthoEx(g_pPassBShader); // renders a full screen quad
DisableShader(0);
BindFrameBuffer(-1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// pass 3
glUseProgramObjectARB(g_pPassCShader->m_glContext);
for (UINT i=0; i<bufCount; ++i)
{
glActiveTextureARB(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D, ttex[i]);
glUniform1iARB(g_pPassCShader->m_intex_idx[i], i);
}
VertexBufferManager2::RenderUsingOrthoEx(g_pPassCShader);
if (GLGETERROR("at1", fileBuf, lineBuf)) ; // reports any glErrors
}
// the three shaders (fragment shaders only)
// vertex shaders transfer uv's and transform vertices (version set to 410 in all)
// shader for pass1
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410
uniform sampler2D g_ClrMap;
in vec2 g_InterpUV; // supplied by vshader
out vec4 g_FBOLayers[ 3 ];
void main(void)
{
vec4 tex = texture(g_ClrMap, g_InterpUV); // if we set fbo from texture only first texture renders
g_FBOLayers[0] = vec4(1,0,0,.5);
g_FBOLayers[1] = vec4(0,1,0,1);
g_FBOLayers[2] = vec4(1,1,0,1);
}
// shader pass 2
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410
uniform sampler2D g_inLayers0;
uniform sampler2D g_inLayers1;
uniform sampler2D g_inLayers2;
in vec2 g_InterpUV ;
out vec4 g_FBOLayers[ 3 ];
vec2 fTextureSize;
vec4 SamplePix(in int buf, in vec2 tCoords, in float lod)
{
if (buf==1)
return textureLod(g_inLayers1, tCoords, lod);
else if (buf==2)
return textureLod(g_inLayers2, tCoords, lod);
return textureLod(g_inLayers0, tCoords, lod);
}
void main(void)
{
ivec2 iCoords = ivec2(int(gl_FragCoord.x),int(gl_FragCoord.y));
ivec2 iTextureSize = textureSize(g_inLayers0,0);
fTextureSize = vec2(float(iTextureSize.x), float(iTextureSize.y));
vec2 coords = vec2(gl_FragCoord.x/iTextureSize.x,gl_FragCoord.y/iTextureSize.y);
for(int i=0; i<3; ++i)
{
g_FBOLayers[i] = vec4(0.,0.,0.,0.);
}
int j = 0;
for(; j < 2; ++j)
{
g_FBOLayers[j] = SamplePix(j,coords,0);
}
}
// shader pass 3
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410
uniform sampler2D g_inLayers0;
uniform sampler2D g_inLayers1;
uniform sampler2D g_inLayers2;
in vec2 g_InterpUV ;
out vec4 g_PixColour;
vec4 tFetch(in int buf, in ivec2 tCoords, in int lod)
{
if (buf==1)
return texelFetch(g_inLayers1, tCoords, lod);
if (buf==2)
return texelFetch(g_inLayers2, tCoords, lod);
return texelFetch(g_inLayers0, tCoords, lod);
}
void main(void)
{
ivec2 iCoords = ivec2(int(gl_FragCoord.x),int(gl_FragCoord.y));
ivec2 iTextureSize = textureSize(g_inLayers0,0);
vec2 coords = vec2(gl_FragCoord.x/iTextureSize.x,gl_FragCoord.y/iTextureSize.y);
vec4 colour = vec4(0.,0.,0.,0.);
int i = 0;
for(; i <2; ++i) // 3rd texture omitted for now
{
vec4 texel = tFetch(i,iCoords,0);
if(texel.a + colour.a <= 1.0)
{
colour.rgb += (texel.rgb*texel.a);
colour.a += texel.a;
}
else
{
texel.a -= (texel.a + colour.a) - 1.0;
colour.rgb += (texel.rgb*texel.a);
colour.a += texel.a;
break;
}
}
g_PixColour = colour;
}