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.
Related
I'm trying to create an opengl program that creates a 2d square, and applies 2 textures on it.
I followed this tutorial: https://learnopengl.com/Getting-started/Textures
This is my fragment shader:
#version 330 core
//in vec3 Color;
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D Texture1;
uniform sampler2D Texture2;
void main()
{
FragColor = mix(texture(Texture1, TexCoord), texture(Texture2, TexCoord), 0.5);
}
This is the code that sends the textures and the uniforms:
GLuint Tex1, Tex2;
int TexWidth, TexHeight, TexNrChannels;
unsigned char* TexData = stbi_load("container.jpg", &TexWidth, &TexHeight, &TexNrChannels, 0);
glGenTextures(1, &Tex1);
glBindTexture(GL_TEXTURE_2D, Tex1);
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_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TexWidth, TexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, TexData);
glGenerateMipmap(GL_TEXTURE_2D);
glUniform1i(glGetUniformLocation(Program, "Texture1"), 0);
stbi_image_free(TexData);
TexData = stbi_load("awesomeface.png", &TexWidth, &TexHeight, &TexNrChannels, 0);
glGenTextures(1, &Tex2);
glBindTexture(GL_TEXTURE_2D, Tex2);
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_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, TexData);
glGenerateMipmap(GL_TEXTURE_2D);
glUniform1i(glGetUniformLocation(Program, "Texture2"), 1);
stbi_image_free(TexData);
And this is the render loop:
while (!glfwWindowShouldClose(window))
{
processInput(window);
// GL render here
glClearColor(0.05f, 0.0f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Tex1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, Tex2);
glUseProgram(Program);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
When I run it, only the first texture shows up on the square, and the a argument (last argument) of the mix function in the shader won't make a difference for any value.
I tried activating (glActiveTexture + GlBindTexture) the second texture first in the render loop, and it caused the second texture to be shown exclusively.
How can I make the textures mix together like in the tutorial?
If this approach is wrong, I would like to learn about another way to accomplish the same result.
glUniform1i set a value in the default uniform block of the currently installed program. You have to install the program with glUseProgram, before you can set the value of a uniform variable:
GLint t1_loc = glGetUniformLocation(Program, "Texture1");
GLint t2_loc = glGetUniformLocation(Program, "Texture2");
glUseProgram(Program);
glUniform1i(t1_loc, 0);
glUniform1i(t2_loc, 1);
Alternatively you can use glProgramUniform1i:
glProgramUniform1i(Program, t1_loc, 0);
glProgramUniform1i(Program, t2_loc, 1);
I wanted to use 4 textures in my fragment shader. One is a cubemap, one is a rendered texture on a framebuffer and the last two are created from images.
When I try calling them in my fragment shader, I keep getting a different one than the one I called or the same one no matter which one I call (depending on different iterations I did when I was trying to fix it).
This is how I got it
GLuint FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
GLuint renderedTexture;
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);
GLenum DrawBuffers[1]={GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers);
if ( glCheckFramebufferStatus ( GL_FRAMEBUFFER ) == GL_FRAMEBUFFER_COMPLETE )
{
glViewport(0, 0, 1024, 1024);
glClearColor( 0.4f, 0.4f, 0.4f, 1.0f );
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
ngl::ShaderLib* shader = ngl::ShaderLib::instance();
(*shader)["Normal"]->use();
m_transform.setPosition(0.0f, 0.0f, 0.0f);
loadMatricesToShader();
//drawing the quad
prim->draw("tex");
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0,1024,768);
// grab an instance of the shader manager
ngl::ShaderLib* shader = ngl::ShaderLib::instance();
( *shader )[ "PBR" ]->use();
glUniform1i(renderedTexture, 1);
//initialize environment map
initEnvironment();
initTexture(2, m_glossMapTex, "images/gloss.png");
glUniform1i(m_glossMapTex, 2);
initTexture(3, m_textMap, "images/alege.png");
glUniform1i(m_textMap, 3);
Also the initTexture and initEnvironment
void NGLScene::initTexture(const GLuint& texUnit, GLuint &texId, const char *filename) {
glActiveTexture(GL_TEXTURE0 + texUnit);
// Load up the image using NGL routine
ngl::Image img(filename);
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexImage2D (
GL_TEXTURE_2D,
0,
img.format(),
img.width(),
img.height(),
0,
GL_RGB,
GL_UNSIGNED_BYTE,
img.getPixels());
// Set up parameters for our texture
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);
}
void NGLScene::initEnvironment() {
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glActiveTexture (GL_TEXTURE0);
glGenTextures (1, &m_envTex);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_envTex);
initEnvironmentSide(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, "images/sky_zneg.png");
initEnvironmentSide(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, "images/sky_zpos.png");
initEnvironmentSide(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, "images/sky_ypos.png");
initEnvironmentSide(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, "images/sky_yneg.png");
initEnvironmentSide(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, "images/sky_xneg.png");
initEnvironmentSide(GL_TEXTURE_CUBE_MAP_POSITIVE_X, "images/sky_xpos.png");
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_AUTO_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLfloat anisotropy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
// Set our cube map texture to on the shader so we can use it
ngl::ShaderLib *shader=ngl::ShaderLib::instance();
shader->use("PBR");
shader->setUniform("envMap", 0);
}
void NGLScene::initEnvironmentSide(GLenum target, const char *filename) {
// Load up the image using NGL routine
ngl::Image img(filename);
glTexImage2D (
target,
0,
img.format(),
img.width(),
img.height(),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
img.getPixels()
);
}
I feel like I have a gap in my knowledge of texture units and setting up uniforms, or maybe there is something wrong with my uniforms in my fragment shader.
In your code there is a misunderstanding, how glUniform1i has to be used. If a values is assigned to a uniform, the the uniform has to be identified by the uniform location index. See Uniform (GLSL)
The fist parameter of glUniform1i has to be the location of the uniform and not the named texture object.
The location of a uniform can be set explicit, in shader by a Layout Qualifier
e.g.
GLSL
layout(location = 7) uniform sampler2D u_gloss;
C++
initTexture(2, m_glossMapTex, "images/gloss.png");
glUniform1i(7, 2); // uniform location 7
If the location of the uniform is not set by a layout qualifier, then the uniform location is set automatically when the program is linked. You can ask for this location by glGetUniformLocation:
e.g.
GLSL
uniform sampler2D u_gloss;
C++
GLuint program_obj = ... ; // ( *shader )[ "PBR" ]->???
GLint gloss_location = glGetUniformLocation(program_obj , "u_gloss");
initTexture(2, m_glossMapTex, "images/gloss.png");
glUniform1i(gloss_location, 2);
I am trying to create a depth map in OpenGL and for some reason the framebuffer wont write to the texture, I tried multiple things to fix it but it doesn't seem to work.
Here is what I did:
This is the generation of the framebuffer and the texture:
glGenFramebuffers(1, &_DepthMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, _DepthMapFBO);
glGenTextures(1, &_DepthMapTex);
glBindTexture(GL_TEXTURE_2D, _DepthMapTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, DEPTH_TEXTURE_WIDTH, DEPTH_TEXTURE_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_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _DepthMapTex, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _DepthMapTex, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
(In the above I tried replacing glTexImage2D with glTexStorage2D and I tried replace glFramebufferTexture with glFramebufferTexture2D, both didn't work)
Then (There is stuff before this but they work find, I checked) I rendered the framebuffer as follows:
_DepthProgram.Use();
// Setting uniforms here
glViewport(0, 0, DEPTH_TEXTURE_WIDTH, DEPTH_TEXTURE_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, _DepthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
// Rendering the scene here
glBindFramebuffer(GL_FRAMEBUFFER, 0);
These are the shaders I use:
(Vertex)
#version 410 core
layout(location = 0) in vec3 Position;
uniform mat4 LightSpaceMatrix;
uniform mat4 Model;
void main()
{
gl_Position = LightSpaceMatrix * Model * vec4(Position, 1.0);
}
(Fragment)
#version 410 core
void main()
{
// gl_FragDepth = 0.0;
}
I tried rendering the texture to a plane and it came out totally white (I Checked there was supposed to be other values), As you can see in the fragment shader, I tried to explicitly write to the gl_FragDepth but it didn't change the texture, it kept it white (1.0).
I looked all over the internet and looked at learnopengl.com and everybody seem to be doing the same as me, did I miss something?
(I double checked and I am rendering the texture to the plane right, I replaced the glBindTexture with another one and it rendered the texture)
If I am missing some information please let me know.
EDIT: By the way, I don't get any error with glGetError.
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
I am having trouble viewing depth rendered to a texture. I can view it when I render depth as RGB to texture, but when I try to render depth only I get only black. I have searched for many hours and implemented fixes from other similar questions, but to no avail. I've disabled GL_TEXTURE_COMPARE_MODE, added glDrawBuffer(GL_NONE) and glReadBuffer(GL_NONE).
I'm running on OSX 10.9 and OpenGL 4.1. I've removed gl error checking from the pasted code for conciseness.
The setup for the depth FBO/texture is this:
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_DEPTH_TEXTURE_MODE, GL_INTENSITY);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
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");
depth fragment - I can see depth when rendering RGB
#version 150 core
#if RENDER_RGB
out vec4 outColor;
void main(){
vec3 color = gl_FragCoord.z);
outColor = vec4(color, 1.0);
}
#else
void main(){
gl_FragDepth = gl_FragCoord.z;
}
#endif
Reading back the depth texture, I am using this fragment shader:
#version 150 core
in vec2 UV;
uniform sampler2D renderedTexture;
out vec4 outColor;
void main(){
vec3 color = vec3( texture(renderedTexture, UV).r );
outColor = vec4(color, 1.0);
}
Nevermind, it does work! My problem was the depth-only FBO setup for the depth texture was never called.