I am having trouble with rendering a sprite despite having copied the code from learnopengl in practice section. First I thought that nothing rendered at all, but after changing from black to sort of teal color I found out that the texture was in fact generated but it was a pitch black rectangle and not an annoying open smile of the so called "awesome face" bathed in this well-known computer green.
I tried and tried to search for a solution online. I'm using the unholy abominable combination of glew and SDL, so here's the stupid code:
SPRITE
#pragma once
#include "shader.h"
class skin2D
{
public:
unsigned int ID;
unsigned int Width, Height;
unsigned int Internal_Format;
unsigned int Image_Format;
unsigned int Wrap_S;
unsigned int Wrap_T;
unsigned int Filter_Min;
unsigned int Filter_Max;
skin2D()
{
glGenTextures(1, &this->ID);
}
void Generate(unsigned int width, unsigned int height, unsigned char* data)
{
this->Width = width;
this->Height = height;
glBindTexture(GL_TEXTURE_2D, this->ID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, this->Wrap_S);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, this->Wrap_T);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->Filter_Min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->Filter_Max);
glTexImage2D(GL_TEXTURE_2D, 0, this->Internal_Format, width, height, 0, this->Image_Format, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Bind() const
{
glBindTexture(GL_TEXTURE_2D, this->ID);
}
};
#include "resouces.h"
std::map<std::string, shader> ResourceManager::Shaders;
std::map<std::string, skin2D> ResourceManager::Textures;
skin2D ResourceManager::loadTextureFromFile(const char* file, bool alpha)
{
// create texture object
skin2D texture;
if (alpha)
{
texture.Internal_Format = GL_RGBA;
texture.Image_Format = GL_RGBA;
}
// load image
int width, height, nrChannels;
unsigned char* data = stbi_load(file, &width, &height, &nrChannels, 0);
// now generate texture
texture.Generate(width, height, data);
// and finally free image data
stbi_image_free(data);
return texture;
}
skin2D& ResourceManager::GetTexture(std::string name)
{
skin2D& skin = Textures[name];
return skin;
}
If you are not generating mipmaps (with glGenerateMipmap
) it is important to set GL_TEXTURE_MIN_FILTER
. Since the default filter is GL_NEAREST_MIPMAP_LINEAR
, the texture would be "Mipmap Incomplete" if you do not change the minimize function to GL_NEAREST
or GL_LINEAR
.
The Wrap_S
, Wrap_T
, Filter_Min
and Filter_Max
attributes of the Texture
object (class skin2D
) are never set. I suggest to set the attributes with appropriate defaults:
class skin2D
{
public:
unsigned int ID = 0;
unsigned int Width = 0,
unsigned int Height = 0;
unsigned int Internal_Format = GL_RGBA;
unsigned int Image_Format = GL_RGBA;
unsigned int Wrap_S = GL_REPEAT;
unsigned int Wrap_T = GL_REPEAT;
unsigned int Filter_Min = GL_LINEAR_MIPMAP_LINEAR;
unsigned int Filter_Max = GL_LINEAR;
skin2D()
{
glGenTextures(1, &this->ID);
}
void Generate(unsigned int width, unsigned int height, unsigned char* data)
{
this->Width = width;
this->Height = height;
glBindTexture(GL_TEXTURE_2D, this->ID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, this->Wrap_S);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, this->Wrap_T);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->Filter_Min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->Filter_Max);
glTexImage2D(GL_TEXTURE_2D, 0, this->Internal_Format, width, height, 0, this->Image_Format, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
// [...]