Miscolored picture during multiple video rendering - c++

I am currently working on rendering two different video streams at the same time to two different OpenGL textures. I use an implementation of QAbstractVideoSurface to prepare each frame of the video and then I pass it to my OpenGL draw method. Each frame arrives in YUV coding so in order to get the RGB values I use GLSL.
The problem is the following: every time I try to draw more than one of these videos the first one plays correctly but the other does some kinkiness with the channels.
My vertex shader:
#version 420
attribute vec2 position;
attribute vec2 texcoord;
uniform mat4 modelViewProjectionMatrix;
varying vec2 v_texcoord;
void main()
{
gl_Position = modelViewProjectionMatrix * vec4(position, 0, 1);
v_texcoord = texcoord.xy;
}
My fragment shader:
#version 420
varying vec2 v_texcoord;
uniform sampler2D s_texture_y;
uniform sampler2D s_texture_u;
uniform sampler2D s_texture_v;
uniform float s_texture_alpha;
void main(void)
{
highp float y = texture2D(s_texture_y, v_texcoord).r;
highp float u = texture2D(s_texture_u, v_texcoord).r - 0.5;
highp float v = texture2D(s_texture_v, v_texcoord).r - 0.5;
highp float r = y + 1.402 * v;
highp float g = y - 0.344 * u - 0.714 * v;
highp float b = y + 1.772 * u;
gl_FragColor = vec4(r, g, b, s_texture_alpha);
}
The result is like the following picture:
Sometimes it gets it right, sometimes it's even worse, but the first video plays correctly all the time.
After fooling around a bit with the channels I found out that sometimes the u variable gets the same value as v in the fragment shader. My texture bindig is as it follows:
uniformSamplers[0] = functions.glGetUniformLocation(program, "s_texture_y");
uniformSamplers[1] = functions.glGetUniformLocation(program, "s_texture_u");
uniformSamplers[2] = functions.glGetUniformLocation(program, "s_texture_v");
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, textRef);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, image_width, image_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (GLvoid*)(image));
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);
functions.glUniform1i(uniformSamplers[0], 0);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, textRefU);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, image_width / 2, image_height / 2, 0, GL_LUMINANCE,
GL_UNSIGNED_BYTE, (GLvoid*)(image + image_width * image_height));
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);
functions.glUniform1i(uniformSamplers[1], 1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, textRefV);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, image_width / 2, image_height / 2, 0, GL_LUMINANCE,
GL_UNSIGNED_BYTE, (GLvoid*)(image + image_height * image_width + (image_width / 2) * (image_height / 2)));
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);
functions.glUniform1i(uniformSamplers[2], 2);

The problem was quite lame, I focused on the shaders and spent several days trying to find out the problem there. However the problem was in the texture reference intialization. All three references had the same value, thus I overwrote the same texture each time. With having all three on different value it works perfectly.

Related

OpenGL Texture still interpolated even with GL_NEAREST

I'm making a 3d game using OpenGL and I have encountered a problem I can't find the answer to. For some reason, when I load the textures it is still interpolated.
My image loading:
glGenTextures(1, &chunkTex);
glBindTexture(GL_TEXTURE_2D, chunkTex);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
int width, height, chan;
stbi_set_flip_vertically_on_load(true);
unsigned char *data = stbi_load("res/images/atlas.png", &width, &height, &chan, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
data);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
My vertex shader:
#version 330 core
in vec3 aPos;
in vec3 aColor;
in vec3 aNormal;
in vec2 uv;
uniform mat4 mvp;
out vec3 ourColor;
out vec2 puv;
out vec3 pNormal;
void main()
{
gl_Position = mvp * vec4(aPos, 1.0);
ourColor = aColor;
puv = uv;
pNormal = aNormal;
}
My fragment shader:
#version 330 core
out vec4 col;
in vec3 ourColor;
in vec2 puv;
in vec3 pNormal;
uniform sampler2D tex;
uniform vec3 lightDir;
void main()
{
col = texture(tex, puv) * max(dot(pNormal, -lightDir), 0.1);
}
If you could help me fix this I would appreciate it!
Edit: Here are my window hints:
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
Here you create a nex texture object and set the texture parameters for it:
glGenTextures(1, &chunkTex);
glBindTexture(GL_TEXTURE_2D, chunkTex);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
But here you unbind it and bind texture object 0 instead:
glBindTexture(GL_TEXTURE_2D, 0);
and load the texture image to that one:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
Now, in legacy and compatibility profile GL, texture object 0 even exists (actually, there even do exist different texture objects named 0 for different texture types), and is usable. But for that one, you never have set the texture filters and will use the default ones. And it looks like you keep textur eobject 0 bound also for rendering, and not the (empty and incomplete) chunkTex one.

OpenGL black textures

When trying to render a 2D label using a bitmap texture, my texture sampling returns black. I tried debugging using RenderDoc but I can't find the problem. It seems the texture loads fine and is stored in the correct register, but it still renders black.
I even tried using a full red texture to check the texture coordinates, but the texture still showed up as black.
Here is the code I use for loading/rendering the texture. It tried to render a label. (genMipMaps is false).
void Texture::CreateGLTextureWithData(GLubyte* data, bool genMipMaps) {
if (bitmap)
glDeleteTextures(1, &bitmap);
glGenTextures(1, &bitmap);
glBindTexture(GL_TEXTURE_2D, bitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (genMipMaps)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
if (genMipMaps)
glGenerateMipmap(GL_TEXTURE_2D);
}
Custom sampler:
glGenSamplers(1, &linearSampler);
glSamplerParameteri(linearSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(linearSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(linearSampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glSamplerParameteri(linearSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(linearSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(linearSampler, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
glSamplerParameterf(linearSampler, GL_TEXTURE_MIN_LOD, 0);
glSamplerParameterf(linearSampler, GL_TEXTURE_MAX_LOD, GL_TEXTURE_MAX_LOD);
glBindSampler(0, linearSampler);
Rendering:
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, texture->getBitmap());
// Set index and vertex buffers
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
if (glIsBuffer(vertBuffer) && vertBuffer != lastVertBuffer)
glBindBuffer(GL_ARRAY_BUFFER, vertBuffer);
if (glIsBuffer(indexBuffer) && indexBuffer != lastIndexBuffer)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
shader->updateLayout();
// Draw
const void* firstIndex = reinterpret_cast<const void*>(0);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, firstIndex);
glBindVertexArray(0);
Shaders:
VS:
#version 430 core
// Vertex atributes
in vec3 a_position;
in vec2 a_texture;
in vec4 a_color;
// Constant buffers
layout(std140) uniform VertexBlock
{
mat4 u_wvp;
mat4 u_world;
};
// Vertex shader outputs
out vec2 v_texture;
out vec4 v_color;
void main()
{
v_texture = a_texture;
v_color = a_color;
gl_Position = u_wvp * vec4(a_position, 1.0);
}
FS: (I tried setting the color to red without using the texture and it renders in red correctly.)
#version 430 core
in vec4 v_color;
in vec2 v_texture;
layout(binding = 0) uniform sampler2D u_texture;
out vec4 fragColor;
void main()
{
fragColor = v_color * texture(u_texture, v_texture);
}
Found out what the problem was. I was not generating mipmaps for the 2D textures but the sampler was still using them.
Texture loading:
...
if (genMipMaps)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
if (genMipMaps)
glGenerateMipmap(GL_TEXTURE_2D);
...
Sampler:
...
glSamplerParameteri(linearSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(linearSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
...
What I did to fix it is just always generate mipmaps for the textures

Fragment shader does not show any colour when compiled with vs2013

When compiled with vs2010, the fragment shader works, but when I compiled and run in vs 2013, it's grey.
My fragment shader converts the yuv texture into rgb
Below is my fragment code
const char *FProgram =
"uniform sampler2D Ytex;\n"
"uniform sampler2D Utex;\n"
"uniform sampler2D Vtex;\n"
"void main(void) {\n"
" vec4 c = vec4((texture2D(Ytex, gl_TexCoord[0]).r - 16./255.) * 1.164);\n"
" vec4 U = vec4(texture2D(Utex, gl_TexCoord[0]).r - 128./255.);\n"
" vec4 V = vec4(texture2D(Vtex, gl_TexCoord[0]).r - 128./255.);\n"
" c += V * vec4(1.596, -0.813, 0, 0);\n"
" c += U * vec4(0, -0.392, 2.017, 0);\n"
" c.a = 1.0;\n"
" gl_FragColor = c;\n"
"}\n";
glClearColor(0, 0, 0, 0);
PHandle = glCreateProgram();
FSHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FSHandle, 1, &FProgram, NULL);
glCompileShader(FSHandle);
glAttachShader(PHandle, FSHandle);
glLinkProgram(PHandle);
glUseProgram(PHandle);
glDeleteProgram(PHandle);
glDeleteProgram(FSHandle);
This is my texture code, I receive linesize and yuv frame data from ffmpeg and make into texture. Everything works fine in VS 2010 computer, but when compiled and run in vs2013 computer, it is grey (black n white), no colour
/* Select texture unit 1 as the active unit and bind the U texture. */
glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize1);
glActiveTexture(GL_TEXTURE1);
i = glGetUniformLocation(PHandle, "Utex");
glUniform1i(i, 1); /* Bind Utex to texture unit 1 */
glBindTexture(GL_TEXTURE_2D, 1);
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_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
/* Select texture unit 2 as the active unit and bind the V texture. */
glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize2);
glActiveTexture(GL_TEXTURE2);
i = glGetUniformLocation(PHandle, "Vtex");
glUniform1i(i, 2); /* Bind Vtext to texture unit 2 */
glBindTexture(GL_TEXTURE_2D, 2);
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_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame2);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
/* Select texture unit 0 as the active unit and bind the Y texture. */
glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize0);
glActiveTexture(GL_TEXTURE0);
i = glGetUniformLocation(PHandle, "Ytex");
glUniform1i(i, 0);
glBindTexture(GL_TEXTURE_2D, 0);
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_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glClear(GL_COLOR_BUFFER_BIT);
/* Draw image (again and again). */
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2i(-w / 2, h / 2);
glTexCoord2i(1, 0);
glVertex2i(w / 2, h / 2);
glTexCoord2i(1, 1);
glVertex2i(w / 2, -h / 2);
glTexCoord2i(0, 1);
glVertex2i(-w / 2, -h / 2);
glEnd();

Sample depth buffer in OpenGL compute shader

I'm trying to sample a depth texture into a compute shader and to copy it into an other texture.
The problem is that I don't get correct values when I read from the depth texture:
I've tried to check if the initial values of the depth texture were correct (with GDebugger), and they are. So it's the imageLoad GLSL function that retrieve wrong values.
This is my GLSL Compute shader:
layout (binding=0, r32f) readonly uniform image2D depthBuffer;
layout (binding=1, rgba8) writeonly uniform image2D colorBuffer;
// we use 16 * 16 threads groups
layout (local_size_x = 16, local_size_y = 16) in;
void main()
{
ivec2 position = ivec2(gl_GlobalInvocationID.xy);
// Sampling from the depth texture
vec4 depthSample = imageLoad(depthBuffer, position);
// We linearize the depth value
float f = 1000.0;
float n = 0.1;
float z = (2 * n) / (f + n - depthSample.r * (f - n));
// even if i try to call memoryBarrier(), barrier() or memoryBarrierShared() here, i still have the same bug
// and finally, we try to create a grayscale image of the depth values
imageStore(colorBuffer, position, vec4(z, z, z, 1));
}
and this is how I'm creating the depth texture and the color texture:
// generate the deth texture
glGenTextures(1, &_depthTexture);
glBindTexture(GL_TEXTURE_2D, _depthTexture);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, wDimensions.x, wDimensions.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
// generate the color texture
glGenTextures(1, &_colorTexture);
glBindTexture(GL_TEXTURE_2D, _colorTexture);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wDimensions.x, wDimensions.y, 0, GL_RGBA, GL_FLOAT, NULL);
I fill the depth texture with depth values (bind it to a frame buffer and render the scene) and then I call my compute shader this way:
_computeShader.use();
// try to synchronize with the previous pass
glMemoryBarrier(GL_ALL_BARRIER_BITS);
// even if i call glFinish() here, the result is the same
glBindImageTexture(0, _depthTexture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
glBindImageTexture(1, _colorTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
glDispatchCompute((wDimensions.x + WORK_GROUP_SIZE - 1) / WORK_GROUP_SIZE,
(wDimensions.y + WORK_GROUP_SIZE - 1) / WORK_GROUP_SIZE, 1); // we divide the compute into groups of 16 threads
// try to synchronize with the next pass
glMemoryBarrier(GL_ALL_BARRIER_BITS);
with:
wDimensions = size of the context (and of the framebuffer)
WORK_GROUP_SIZE = 16
Do you have any idea of why I don't get valid depth values?
EDIT:
This is what the color texture looks like when I render a sphere:
and it seems that glClear(GL_DEPTH_BUFFER_BIT) doesn't do anything:
Even if I call it just before the glDispatchCompute() I still have the same image...
How can this be possible?
Actually, i discovered that you cannot send a depth texture as an image to a compute shader, even with the readonly keyword.
So i've replaced:
glBindImageTexture(0, _depthTexture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
by:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _depthTexture);
and in my compute shader:
layout (binding=0, r32f) readonly uniform image2D depthBuffer;
by:
layout (binding = 0) uniform sampler2D depthBuffer;
and to sample it i just write:
ivec2 position = ivec2(gl_GlobalInvocationID.xy);
vec2 screenNormalized = vec2(position) / vec2(ctxSize); // ctxSize is the size of the depth and color textures
vec4 depthSample = texture2D(depthBuffer, screenNormalized);
and it works very well like this

Changing color using a shader

I am writing a deferred shader and as one of the first steps, to get familiar with GLSL and using shaders and the framebuffer I am trying to change the color of a mesh through a shader.
I have it linked to one of the buffers by calling glDrawBuffers with an array that holds the attachement and then binding the texture to my framebuffer:
glReadBuffer(GL_NONE);
GLint color_loc = glGetFragDataLocation(pass_prog,"out_Color");
GLenum draws [1];
draws[color_loc] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, draws);
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[color_loc], diffuseTexture, 0);
I have an out_Color variable in my fragment shader (otherwise it wouldn't even compile), but I can't manage to change the color of the mesh by setting it through that variable inside the shader.
Does anyone has any idea why and could explain that to me?
Thanks
Edit:
My shaders:
Vertex Shader
#version 330
uniform mat4x4 u_Model;
uniform mat4x4 u_View;
uniform mat4x4 u_Persp;
uniform mat4x4 u_InvTrans;
in vec3 Position;
in vec3 Normal;
out vec3 fs_Normal;
out vec4 fs_Position;
void main(void) {
fs_Normal = (u_InvTrans*vec4(Normal,0.0f)).xyz;
vec4 world = u_Model * vec4(Position, 1.0);
vec4 camera = u_View * world;
fs_Position = camera;
gl_Position = u_Persp * camera;
}
Fragment shader
#version 330
uniform float u_Far;
in vec3 fs_Normal;
in vec4 fs_Position;
out vec4 out_Normal;
out vec4 out_Position;
out vec4 out_Color;
void main(void)
{
out_Normal = vec4(normalize(fs_Normal),0.0f);
out_Position = vec4(fs_Position.xyz,1.0f); //Tuck position into 0 1 range
out_Color = vec4(1.0f, 0.0f, 0.0f, 1.0f);//first three diffuse, last specular
}
And I am not doing a deferred shader in order to learn GLSL. I am learning GLSL in order to make
a deferred shader. =)
More source code from setting up the textures:
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &depthTexture);
glGenTextures(1, &normalTexture);
glGenTextures(1, &positionTexture);
glGenTextures(1, &diffuseTexture);
//DEPTH TEXTURE
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
//NORMAL TEXTURE
glBindTexture(GL_TEXTURE_2D, normalTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0);
//POSITION TEXTURE
glBindTexture(GL_TEXTURE_2D, positionTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0);
//DIFFUSE TEXTURE
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0);
//create a framebuffer object
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
//Instruct openGL that we won't bind a color texture with the currently binded FBO
glReadBuffer(GL_NONE);
GLint normal_loc = glGetFragDataLocation(pass_prog,"out_Normal");
GLint position_loc = glGetFragDataLocation(pass_prog,"out_Position");
GLint color_loc = glGetFragDataLocation(pass_prog,"out_Color");
GLenum draws [3];
draws[normal_loc] = GL_COLOR_ATTACHMENT0;
draws[position_loc] = GL_COLOR_ATTACHMENT1;
draws[color_loc] = GL_COLOR_ATTACHMENT2;
glDrawBuffers(3, draws);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);
glBindTexture(GL_TEXTURE_2D, normalTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[normal_loc], normalTexture, 0);
glBindTexture(GL_TEXTURE_2D, positionTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[position_loc], positionTexture, 0);
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[color_loc], diffuseTexture, 0);
check FBO status
FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(FBOstatus != GL_FRAMEBUFFER_COMPLETE) {
printf("GL_FRAMEBUFFER_COMPLETE failed, CANNOT use FBO\n");
checkFramebufferStatus(FBOstatus);
}
switch back to window-system-provided framebuffer
glClear(GL_DEPTH_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
Edit:
I solved it. Thanks.
You should do something like this. I assume that out_color is declared as out vec4 out_Color:
Compile shaders and attach them to the program.
glBindFragDataLocation(program, 0, "out_Color");
glLinkProgram(program);
glUseProgram(program);
GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 }
glDrawBuffers(1, drawBuffers);
Setup FBO.
The it should work, if it doesn't, post your fragment shader and more source code. By the way, i should also say that creating a deferred renderer to learn GLSL is not a good idea. There are easier ways to learn GLSL.