Hello!
Im having a curious problem with my textures that a searched literally in all related topics and can’t solve by myself. Im really new to opengl and want some help, because i really want to solve this problem before continue going on my code.
My rendering seems to put a white texture instead of the desired textures at some camera rotations. The textures im using are the checkerboard and the stairs.
See: https://media.giphy.com/media/Kccb4nH3Xcd4PTK84j/giphy.gif
Vertex shader code:
#version 450 core
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec4 a_color;
layout(location = 2) in vec2 a_textureCoord;
layout(location = 3) in float a_textureIndex;
layout(location = 4) in float a_tilingFactor;
uniform mat4 u_viewProjection;
out vec2 v_textureCoord;
out vec4 v_color;
out float v_textureIndex;
out float v_tilingFactor;
void main()
{
v_textureCoord = a_textureCoord;
v_color = a_color;
v_textureIndex = a_textureIndex;
v_tilingFactor = a_tilingFactor;
gl_Position = u_viewProjection * vec4(a_position, 1.0);
}
Fragment shader code:
#version 450 core
layout(location = 0) out vec4 color;
uniform sampler2D u_textures[32];
in vec2 v_textureCoord;
in vec4 v_color;
in float v_textureIndex;
in float v_tilingFactor;
void main()
{
color = texture(u_textures[int(v_textureIndex)], v_textureCoord * v_tilingFactor) * v_color;
}
Looking at the fragment shader, you can see that Im doing some multiplications. When I’m not using a texture (just want to render single color), the texture will be a default created white texture (1x1). When I’m using textures, v_color can be used as a tint (the checkerboard is being colored in red).
The transformation matrix, passed as a uniform, seems fine, since que vertex positions are fine all the time. The problem is that at some specific rotations, the texture component of the multiplication in the fragment shader is just a white color.
The texture binding values seem fine too.
I really don’t know what’s wrong with my code. Maybe it can be the texture creation/settings (glTextureParameteri)?
Texture2D::Texture2D(const std::string& filepath)
: internalFormat(0), dataFormat(0)
{
NT_PROFILE_FUNCTION();
// stbi_load uses signed Int
Int width, height, channels;
stbi_set_flip_vertically_on_load(1); // flip the image loaded vertically
auto data = stbi_load(filepath.c_str(), &width, &height, &channels, 0);
NT_CORE_ASSERT(data, "Failed to load texture image!");
// Converts to unsigned because OpenGL uses UInt
this->width = width;
this->height = height;
if (channels == 4)
{
this->internalFormat = GL_RGBA8;
this->dataFormat = GL_RGBA;
}
else if (channels == 3)
{
this->internalFormat = GL_RGB8;
this->dataFormat = GL_RGB;
}
NT_CORE_ASSERT(this->internalFormat & this->dataFormat,
"Color channel format not supported!");
glCreateTextures(GL_TEXTURE_2D, 1, &this->rendererID);
// Alocates storage on the gpu for the texture
glTextureStorage2D(
this->rendererID, 1, this->internalFormat, this->width, this->height);
// Set linear interpolation (integer parameter) for resizing
// (expansion or contraction) the texture in the geometry
glTextureParameteri(this->rendererID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(this->rendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(this->rendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(this->rendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTextureSubImage2D(
this->rendererID, 0, 0, 0, this->width, this->height,
this->dataFormat, GL_UNSIGNED_BYTE, data);
// Deallocates the memory
stbi_image_free(data);
}
The white default texture is created using constructor + setData, and is working fine to rendering the single color quads:
Texture2D::Texture2D(Int width, Int height)
: width(width), height(height), internalFormat(GL_RGBA8), dataFormat(GL_RGBA)
{
NT_PROFILE_FUNCTION();
NT_CORE_ASSERT(this->internalFormat & this->dataFormat,
"Color channel format not supported!");
glCreateTextures(GL_TEXTURE_2D, 1, &this->rendererID);
// Alocates storage on the gpu for the texture
glTextureStorage2D(
this->rendererID, 1, this->internalFormat, this->width, this->height);
// Set linear interpolation (integer parameter) for resizing
// (expansion or contraction) the texture in the geometry
glTextureParameteri(this->rendererID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(this->rendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTextureParameteri(this->rendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(this->rendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
void Texture2D::setData(void* data, UInt size)
{
NT_PROFILE_FUNCTION();
glTextureSubImage2D(
this->rendererID, 0, 0, 0, this->width, this->height,
this->dataFormat, GL_UNSIGNED_BYTE, data);
}
For rendering, im using batching, so that’s why im using a lot of input at vertex shader.
I would be very grateful if someone can give me some insight about what’s going on.
Thanks!