I have two textures with same size attached to one fbo, and I want to render another texture into one of the attached textures, and I want to render a blue shape of the figure of the input texture to the other fbo attached texture.
the (updated) vertex shader:
#version 330
in vec2 coord;
out vec2 f_coord;
void main() {
gl_Position = vec4(coord, 0.0, 1.0);
f_coord = (1.0+coord)/2.0;
}
the (updated) fragment shader:
#version 330
uniform sampler2D my_texture;
in vec2 f_coord;
out vec4 FragData[2];
void main() {
if(texture(my_texture,f_coord).a == 0.0)
discard;
FragData[0]=texture(my_texture,f_coord);
FragData[1]=vec4(0.5, 0.5, 1.0, 1.0);
}
With this fragment shader everything works fine. The texture and the blue stamp of the texture contures are rendered properly.
Here is a screenshot:
http://s14.directupload.net/file/d/3487/kvkqdbl7_png.htm
But if I want to render the texture into gl_FragData[1] and the blue conture stamp into gl_FragData[0]
#version 330
uniform sampler2D my_texture;
in vec2 f_coord;
out vec4 FragData[2];
void main() {
if(texture(my_texture,f_coord).a == 0.0)
discard;
FragData[0]=vec4(0.5, 0.5, 1.0, 1.0);
FragData[1]=texture(my_texture,f_coord);
}
than I get two totally blue textures. The strange thing is: Both target textures are totally blue, but I have set the glViewport just to a part of the texture.
Here a screenshot:
http://s1.directupload.net/file/d/3487/9loqibdc_png.htm
The fbo attachments have the half screen size
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glutGet(GLUT_WINDOW_WIDTH)/2, glutGet(GLUT_WINDOW_HEIGHT), 0, GL_RGBA, GL_BYTE, 0);
So I can render both textures to the screen for checking.
This is how I created the framebufferobject
void init_fbo()
{
glGenTextures(1, &fbo.texture0);
glBindTexture(GL_TEXTURE_2D, fbo.texture0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glutGet(GLUT_WINDOW_WIDTH)/2, glutGet(GLUT_WINDOW_HEIGHT), 0, GL_RGBA, GL_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenTextures(1, &fbo.texture1);
glBindTexture(GL_TEXTURE_2D, fbo.texture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glutGet(GLUT_WINDOW_WIDTH)/2, glutGet(GLUT_WINDOW_HEIGHT), 0, GL_RGBA, GL_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &fbo.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo.fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
fbo.texture0, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
fbo.texture1, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
I use those global struct variables
struct
{
GLuint fbo;
GLuint texture0;
GLuint texture1;
} fbo;
struct
{
GLuint program;
GLint uni_texture;
GLint att_coord;
} shader_fbo;
struct
{
GLuint program;
GLint uni_texture;
GLint att_coord;
} shader_screen;
And this is my render function
void render()
{
GLenum buffers[2];
GLfloat vertices[] = { -1.0, -1.0,
-1.0, 1.0,
1.0, -1.0,
1.0, 1.0 };
GLubyte indices[] = { 0, 1, 2,
1, 2, 3 };
/*render to mrt fbo*/
glUseProgram(shader_fbo.program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.texID);
glUniform1i(shader_fbo.uni_texture, 0);
glEnableVertexAttribArray(shader_fbo.att_coord);
glVertexAttribPointer(shader_fbo.att_coord,
2,
GL_FLOAT,
GL_FALSE,
0,
vertices);
glBindFramebuffer(GL_FRAMEBUFFER, fbo.fbo);
buffers[0] = GL_COLOR_ATTACHMENT0;
buffers[1] = GL_COLOR_ATTACHMENT1;
glDrawBuffers(2, buffers);
glViewport(0, 0,
texture.width, texture.height);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.texID);
glUniform1i(shader_fbo.uni_texture, 0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
glDisableVertexAttribArray(shader_fbo.att_coord);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
/*render both textures now to screen*/
glUseProgram(shader_screen.program);
glEnableVertexAttribArray(shader_screen.att_coord);
glVertexAttribPointer(shader_screen.att_coord,
2,
GL_FLOAT,
GL_FALSE,
0,
vertices);
/*render the first texture to the left side of the screen*/
glViewport(0, 0,
glutGet(GLUT_WINDOW_WIDTH)/2, glutGet(GLUT_WINDOW_HEIGHT));
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, fbo.texture0);
glUniform1i(shader_screen.uni_texture, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
/*render the second texture to the right side of the screen*/
glViewport(glutGet(GLUT_WINDOW_WIDTH)/2, 0,
glutGet(GLUT_WINDOW_WIDTH)/2, glutGet(GLUT_WINDOW_HEIGHT));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, fbo.texture1);
glUniform1i(shader_screen.uni_texture, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
glutSwapBuffers();
}
Related
I am trying to put either a color or an image to the background of the rectangle I draw using OpenGL 3.3.
I'm trying to generate the image color myself for testing, but it seems something is wrong with my code and I only see a single color.
Vertex shader:
#version 330 core
layout(location = 0) in vec2 VertexPosition;
layout(location = 1) in vec2 VertexUV;
out vec2 UV;
void main() {
gl_Position = vec4(VertexPosition.x, VertexPosition.y, 0.0, 1.0);
UV = VertexUV;
}
Fragment Shader:
#version 330 core
in vec2 UV;
out vec3 Color;
uniform sampler2D TextureSampler;
void main() {
Color = texture(TextureSampler, UV).rgb;
}
The way I generate textures:
GLuint data[3] = {64, 128, 192};
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
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_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
The way I draw my elements:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(TextureSamplerID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, UVBuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindTexture(GL_TEXTURE_2D, 0);
The way I generate buffers:
glGenBuffers(1, &VertexBuffer);
glGenBuffers(1, &UVBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
const GLfloat uv_coordinates[] = {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f
};
glBindBuffer(GL_ARRAY_BUFFER, UVBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coordinates), uv_coordinates, GL_STATIC_DRAW);
When I create and draw a rectangle using these, I see this:
I try to generate texture data with these:
GLuint data2[192];
for(int i = 0; i < 192; i++) data2[i] = i;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, data2);
and I see this:
Since the type which enumerator which is passed to glTexImage2D is GL_UNSIGNED_BYTE, the data typo of the array of pixel data has to be GLubyte (which corresponds to GL_UNSIGNED_BYTE) instead of GLuint:
GLubyte data2[192];
for(int i = 0; i < 192; i++) data2[i] = i;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, data2);
There's some Artifacts on my FrameBuffer Depth Texture I can't get rid off:
The Code used to init the FrameBuffer:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &color);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color, 0);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, depth, 0);
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, attachments);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
std::cout << "FBO FEHLER" << std::endl;
}
Code used to draw the FrameBuffer:
shader->bind();
// Bind Textures
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, color);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depth);
glUniform1i(shader->getUniform("tex"), 0);
glUniform1i(shader->getUniform("depth"), 1);
glUniformMatrix4fv(shader->getUniform("matrix"), 1, GL_FALSE, glm::value_ptr(ortho));
// Draw Call
glBindBuffer(GL_ARRAY_BUFFER,fbovbo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, (void*)12);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Unbind
shader->unbind();//*/
FragmentShader of the actual rendering:
#version 330 core
layout(location = 0) out vec4 out_color;
layout(location = 1) out vec4 out_depth;
in float temp;
void main(void){
out_color = vec4(1,0.0,0.0,1.0);
out_depth = vec4(gl_FragCoord.z);
}
FragmentShader of the FrameBuffer rendering:
#version 330 core
in vec2 fuv;
out vec4 color;
uniform sampler2D tex;
uniform sampler2D depth;
void main(){
vec4 d = texture2D(depth, fuv);
gl_FragDepth = d.a;
vec4 c = texture2D(tex,fuv);
if(c.a<0.1){
discard;
}
color = c;
//color = vec4(texture2D(depth, fuv).zzz,1.0);
//color.a = 0.8;
//color = vec4(1,0,0,0.5);
}
The red "Mesh" is behind the brown surface, but its borders still appear. thats the problem
The problem might come from the limited precision of the depth buffer. Basically, the range between near and farplane has to be represented by the depth-buffer. In your case, the depth-buffer has 8 bit, thus there are only 256 different depth values that can be represented. When two objects are closer together than this, they will be mapped to the same value in the depth buffer.
To overcome this, you can try to increase the precision of the depth buffer, for example, by using
glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL);
Side-note: I'm not sure why the depth texture has four channels. If you don't need them, I would change this to a one channel format.
I'm currently working in a deferred shading and I created a class which manages the FBOs and draw the buffers on the screen.
This is how it looks so far:
FBORender::FBORender(float screenWidth, float screenHeight) :
_screenWidth(screenWidth),
_screenHeight(screenHeight),
ProgramManager("defVertexShader.txt", "defFragShader.txt")
{
CreateProgram();
_vbo[0] = 0;
_vbo[1] = 0;
_vao = 0;
BuildQuad();
BuildVAO();
glGenFramebuffers(1, &_fbo);
glGenRenderbuffers(1, &_depthBuffer);
// Bind the depth buffer
glBindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, (int)_screenWidth, (int)_screenHeight);
// Generate and bind the texture for diffuse
glGenTextures(1, &_diffuseBuffer);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Generate and bind the texture for positions
glGenTextures(1, &_positionBuffer);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Generate and bind the texture for normals
glGenTextures(1, &_normalBuffer);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Bind the FBO so that the next operations will be bound to it.
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
// Attach the textures to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _diffuseBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _positionBuffer, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _normalBuffer, 0);
GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
{
printf("DeferredLighting::Init: FrameBuffer incomplete: 0x%x\n", fboStatus);
exit(1);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
FBORender::~FBORender()
{
glDeleteTextures(1, &_normalBuffer);
glDeleteTextures(1, &_positionBuffer);
glDeleteTextures(1, &_diffuseBuffer);
glDeleteFramebuffers(1, &_fbo);
glDeleteVertexArrays(1, &_vao);
glDeleteBuffers(2, _vbo);
}
void FBORender::Start()
{
// Bind the FBO and set the viewport to the proper size
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glViewport(0, 0, (int)_screenWidth, (int)_screenWidth);
// Clear the render targets
GLenum windowBuffClear[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, windowBuffClear);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLenum windowBuffOpaque[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, windowBuffOpaque);
}
void FBORender::Draw(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_ModelViewProjection = Projection * ModelView;
_ModelView = ModelView;
glDisable(GL_DEPTH_TEST);
Bind();
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
glBindVertexArray(_vao);
LoadUniformVariables();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
UnBind();
}
void FBORender::Stop()
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void FBORender::BuildQuad()
{
_coordinates[0] = 1.0f;
_coordinates[1] = 1.0f;
_coordinates[2] = 0.0f;
_coordinates[3] = -1.0f;
_coordinates[4] = 1.0f;
_coordinates[5] = 0.0f;
_coordinates[6] = 1.0;
_coordinates[7] = -1.0f;
_coordinates[8] = 0.0f;
_coordinates[9] = -1.0f;
_coordinates[10] = -1.0f;
_coordinates[11] = 0.0f;
_uv[0] = 1.0f;
_uv[1] = 1.0f;
_uv[2] = 0.0f;
_uv[3] = 1.0f;
_uv[4] = 1.0f;
_uv[5] = 0.0f;
_uv[6] = 0.0f;
_uv[7] = 0.0f;
}
void FBORender::BuildVAO()
{
// Generate and bind the vertex array object
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
// Generate and bind the vertex buffer object
glGenBuffers(2, _vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), _coordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), _uv, GL_STATIC_DRAW);
LoadAttributeVariables();
glBindVertexArray(0);
}
void FBORender::LoadUniformVariables()
{
// OpenGL Matrices
GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvMatrix");
glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(_ModelView));
// Texture buffers
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
GLint Diffuse_location = glGetUniformLocation(GetProgramID(), "tDiffuse");
glUniform1i(Diffuse_location, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _positionBuffer);
GLint Position_location = glGetUniformLocation(GetProgramID(), "tPosition");
glUniform1i(Position_location, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, _normalBuffer);
GLint Normal_location = glGetUniformLocation(GetProgramID(), "tNormals");
glUniform1i(Normal_location, 0);
}
void FBORender::LoadAttributeVariables()
{
// Vertex Attributes
GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
glEnableVertexAttribArray(VertexPosition_location);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "uvCoord");
printf("%d \n", TextureCoord_Location);
glEnableVertexAttribArray(TextureCoord_Location);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
And those are my shaders:
#version 410 core
uniform mat4 mvMatrix;
in vec4 vPosition;
in vec2 uvCoord;
smooth out vec2 texCoord;
void main(void)
{
texCoord = uvCoord;
gl_Position = vPosition * mvMatrix;
}
#version 410 core
uniform sampler2D tDiffuse;
uniform sampler2D tPosition;
uniform sampler2D tNormals;
in vec2 texCoord;
out vec4 fragColor;
void main( void )
{
vec4 image = texture( tDiffuse, texCoord.st );
vec4 position = texture( tPosition, texCoord.st );
vec4 normal = texture( tNormals, texCoord.st );
fragColor.xyz = vec3(0.5f, 0.5f, 0.5f);
}
The problems is that when I try to set the attribute variables the one called uvCoord is not found. I think this may be due to an optimization, however, if that's so, what am I'm doing wrong or how should I do it? The uvCoord is used in the fragment shader.
The uvCoord is used in the fragment shader.
No it is not. Your output is a constant color. As a result, the texture fetches before are all eliminated by a decent compiler, as is the texCoord varying. This ultimately results in the elimination of the input attribute, which simply does not affect the output of the program in any way. This is allowed by the GL spec. Your attribute is just not considered active, but only active attributes have locations.
I am trying to use deferred shading to implement SSAO and I have problems to access my textures in the deferred fragment shader. The code is in C++/Qt5 and makes use of Coin3D to generate the rest of the UI (but this shouldn't really matter here).
The fragment shader of the deferred pass is:
#version 150 compatibility
uniform sampler2D color;
uniform sampler2D position;
uniform sampler2D normal;
uniform vec3 dim;
uniform vec3 camPos;
uniform vec3 camDir;
void main()
{
// screen position
vec2 t = gl_TexCoord[0].st;
// the color
vec4 c = texture2D(color, t);
gl_FragColor = c + vec4(1.0, t.x, t.y, 1.0);
}
The code for running the deferred pass is
_geometryBuffer.Unbind();
// push state
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glPushAttrib(GL_DEPTH_BUFFER_BIT |
GL_COLOR_BUFFER_BIT |
GL_LIGHTING_BIT |
GL_SCISSOR_BIT |
GL_POLYGON_BIT |
GL_CURRENT_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_CULL_FACE);
}
// bind shader
// /!\ IMPORTANT to do before specifying locations
_deferredShader->bind();
_CheckGLErrors("deferred");
// specify positions
_deferredShader->setUniformValue("camPos", ...);
_deferredShader->setUniformValue("camDir", ...);
_geometryBuffer.Bind(GBuffer::TEXTURE_TYPE_NORMAL, 2);
_deferredShader->setUniformValue("normal", GLint(2));
_geometryBuffer.Bind(GBuffer::TEXTURE_TYPE_POSITION, 1);
_deferredShader->setUniformValue("position", GLint(1));
_geometryBuffer.Bind(GBuffer::TEXTURE_TYPE_DIFFUSE, 0);
_deferredShader->setUniformValue("color", GLint(0));
_CheckGLErrors("bind");
// draw screen quad
{
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glColor3f(0, 0, 0);
glVertex2f(-1, -1);
glTexCoord2f(1, 0);
glColor3f(0, 0, 0);
glVertex2f( 1, -1);
glTexCoord2f(1, 1);
glColor3f(0, 0, 0);
glVertex2f( 1, 1);
glTexCoord2f(0, 1);
glColor3f(0, 0, 0);
glVertex2f(-1, 1);
glEnd();
}
_deferredShader->release();
// for debug
_geometryBuffer.Unbind(2);
_geometryBuffer.Unbind(1);
_geometryBuffer.Unbind(0);
_geometryBuffer.DeferredPassBegin();
_geometryBuffer.DeferredPassDebug();
// pop state
{
glPopAttrib();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
I know that the textures have been correctly processed in the geometry buffer creation because I can dump them into files and get the expected result.
The deferred pass doesn't work. The shader compiled correctly and I get the following result on screen:
And the last part of my code (DeferredPassBegin/Debug) is to draw the FBO to the screen (as shown in screenshot) as a proof that the GBuffer is correct.
The current result seems to mean that the textures are not correctly bound to their respective uniform, but I know that the content is valid as I dumped the textures to files and got the same results as shown above.
My binding functions in GBuffer are:
void GBuffer::Unbind()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
void GBuffer::Bind(TextureType type, uint32_t idx)
{
glActiveTexture(GL_TEXTURE0 + idx);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textures[static_cast<uint32_t>(type)]);
}
void GBuffer::Unbind(uint32_t idx)
{
glActiveTexture(GL_TEXTURE0 + idx);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
Finally, the textures are 512/512, and I created them in my GBuffer with:
WindowWidth = WindowHeight = 512;
// Create the FBO
glGenFramebuffers(1, &_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
const uint32_t NUM = static_cast<uint32_t>(NUM_TEXTURES);
// Create the gbuffer textures
glGenTextures(NUM, _textures);
glGenTextures(1, &_depthTexture);
for (unsigned int i = 0 ; i < NUM; i++) {
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WindowWidth, WindowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i + _firstIndex, GL_TEXTURE_2D, _textures[i], 0);
}
// depth
glBindTexture(GL_TEXTURE_2D, _depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, WindowWidth, WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
GLenum buffers[NUM];
for(uint32_t i = 0; i < NUM; ++i){
buffers[i] = GLenum(GL_COLOR_ATTACHMENT0 + i + _firstIndex);
}
glDrawBuffers(NUM, buffers);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
printf("FB error, status: 0x%x\n", status);
return _valid = false;
}
// unbind textures
glBindTexture(GL_TEXTURE_2D, 0);
// restore default FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
How can I debug farther at this stage?
I know that the texture data is valid, but I can't seem to bind it to the shader correctly (but I have other shaders that use textures loaded from files and which work fine).
--- Edit 1 ---
As asked, the code for DeferredPassBegin/Debug (mostly coming from this tutorial )
void GBuffer::DeferredPassBegin() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo);
}
void GBuffer::DeferredPassDebug() {
GLsizei HalfWidth = GLsizei(_texWidth / 2.0f);
GLsizei HalfHeight = GLsizei(_texHeight / 2.0f);
SetReadBuffer(TEXTURE_TYPE_POSITION);
glBlitFramebuffer(0, 0, _texWidth, _texHeight,
0, 0, HalfWidth, HalfHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
SetReadBuffer(TEXTURE_TYPE_DIFFUSE);
glBlitFramebuffer(0, 0, _texWidth, _texHeight,
0, HalfHeight, HalfWidth, _texHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
SetReadBuffer(TEXTURE_TYPE_NORMAL);
glBlitFramebuffer(0, 0, _texWidth, _texHeight,
HalfWidth, HalfHeight, _texWidth, _texHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
Arghk!!!
So I expected that texture parameters were not mandatory, but as I looked at some code, I just tried to specify my texture parameters. When generating the FBO textures, I use now
for (unsigned int i = 0 ; i < NUM; i++) {
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WindowWidth, WindowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i + _firstIndex, GL_TEXTURE_2D, _textures[i], 0);
}
And with this change, I get the expected result (with only c in the fragment shader, and similar correct results if I switch to visualizing the normal / position).
Conclusion: one must specify the texture parameters for deferred shading to work (at least with the graphics setup of my application / machine).
I'm drawing a lot of points to the screen, and I am trying to get them to render to a texture for post processing before then rendering the texture back to the screen. Currently I'm trying to just pass through and get the texture rendering but it appears to be rendering nothing.
My fragment shader works (without render to texture - used bellow in mEllipseTextureProgram) and the only change I have made is to include
out vec3 color;
to render to the texture itself (and obviously change to color= rather than gl_FragColor=). The second program referenced below (mScreenProgram) is as follows:
Vertex Shader:
#version 330 compatibility
in vec2 vUV;
out vec2 UV;
void main()
{
gl_Position = gl_Vertex;
UV = vUV;
}
Fragment Shader:
#version 330 core
in vec2 UV;
out vec3 color;
uniform sampler2D renderedTexture;
void main(){
color = texture( renderedTexture, UV ).xyz;
}
I set up my render to texture stuff like this:
glGenFramebuffers(1, &mGaussianFrameBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mGaussianFrameBuffer);
glGenTextures(1, &mGaussianRenderTexture);
glBindTexture(GL_TEXTURE_2D, mGaussianRenderTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1024,
768,
0, GL_RGBA, GL_UNSIGNED_BYTE,
NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mGaussianRenderTexture, 0);
glGenTextures(1, &mGaussianDepthBuffer);
glBindTexture(GL_TEXTURE_2D, mGaussianDepthBuffer);
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_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
1024,
768,
0, GL_DEPTH_COMPONENT, GL_FLOAT,
NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mGaussianDepthBuffer, 0);
which returns a successful GL_FRAMEBUFFER_COMPLETE.
Here are the three concerning rendering functions:
void Draw()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(45, 1024.0/768.0, 3.0, 20000);
perspectiveGL(45, 1024.0/768.0, 1.0, 20000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
gluLookAt(cameraData[0],cameraData[1], cameraData[2],
cameraData[3],cameraData[4], cameraData[5],
0,1,0);
glEnable(GL_DEPTH_TEST);
glClearColor( 0.2f, 0.2f, 0.9f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// OTHER STUFF POTENTIALLY DRAW HERE IN DIFFERENT WAYS
glUseProgram(mEllipseTextureProgram);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mGaussianFrameBuffer);
GLuint attachments[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, attachments);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
DrawEllipseToTexture();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glUseProgram(mScreenProgram);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
DrawTextureToScreen();
}
void DrawEllipseToTexture()
{
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, mVBO);
glVertexPointer(3, GL_FLOAT, 0, 0);
glEnable(GL_PROGRAM_POINT_SIZE);
glEnable(GL_POINT_SPRITE);
glEnable( GL_TEXTURE_2D );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mBMP);
glProgramUniform1i(mEllipseTextureProgram, mTextureLocation, 0);
glBindBuffer(GL_ARRAY_BUFFER, mUV);
glEnableVertexAttribArray(mTexCoordLocation);
glVertexAttribPointer(mTexCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, mSpacial);
glEnableVertexAttribArray(mSpacialLocation);
glVertexAttribPointer(mSpacialLocation, 1, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, mNormals);
glEnableVertexAttribArray(mNormalLocation);
glVertexAttribPointer(mNormalLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, mVerticalSpat);
glEnableVertexAttribArray(mMajorLocation);
glVertexAttribPointer(mMajorLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, mHorizontalSpat);
glEnableVertexAttribArray(mMinorLocation);
glVertexAttribPointer(mMinorLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );
glDrawArrays(GL_POINTS, 0, mNumberPoints);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisable( GL_TEXTURE_2D );
glDisableVertexAttribArray(mSpacialLocation);
glDisable(GL_POINT_SPRITE);
glDisable( GL_POINT_SMOOTH );
glDisable(GL_PROGRAM_POINT_SIZE);
glDisableClientState(GL_VERTEX_ARRAY);
}
void DrawTextureToScreen()
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnable( GL_TEXTURE_2D );
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mGaussianRenderTexture);
glProgramUniform1i(mScreenProgram, mGaussianTextureLocation, 0);
GLfloat vertices[] = { -1, -1, 2,
1, -1, 2,
1, 1, 2,
-1, 1, 2 };
GLfloat uv[] = { 0, 0,
1, 0,
1, 1,
0, 1,};
glVertexPointer(3, GL_FLOAT, 0, vertices);
glEnableVertexAttribArray(mGaussianUV);
glVertexAttribPointer(mGaussianUV, 2, GL_FLOAT, GL_FALSE, 0, uv);
glDrawArrays(GL_TRIANGLES, 0, 4);
glDisable ( GL_TEXTURE_2D );
glDisableClientState(GL_VERTEX_ARRAY);
}
I still don't know what was wrong with my solution above (to which I tried a lot of variations) - but following this tutorial got it working: Tutorial
I usually use `out vec4 color', I am not sure whether it will work after you setting your texture type is GL_RGBA and then return vec3 for each fragment.
And I didnt see you set glViewport() in your code which means there is no specify affine transformation to mapping the screen position (x,y) from NDC to Screen space. If you don't have a viewport during fbo render, that definitely gives you nothing.
I am same as you struggling in the similar situation. Read the functions you don't know from GL documentation instead of blog is a much better way to understand things correctly...
: )