OpenGL black textures - c++

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

Related

opengl won't overlap more than 1 texture

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);

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.

Texture units overlap? Rendered the wrong texture

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);

Viewing depth buffer in OpenGL

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.

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.