Reputation: 4475
I've started messing around with textures in opengl, and when rendering my first texture, I saw a black screen. Then I realized that the screen in't black, rather the texture was very dim. Why is this happening? Here is the code:
Texture class (.cpp):
Texture::Texture(void* data, unsigned int width, unsigned int height)
:texture(0), curslot(32), width(width), height(height)
{
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
Texture::~Texture(){
glDeleteTextures(1, &texture);
}
void Texture::bind(unsigned char slot){
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, texture);
curslot = slot;
}
Texture class declaration (if you need it):
class Texture{
private:
unsigned int texture;
unsigned char curslot;
unsigned int width;
unsigned int height;
public:
Texture(void* data, unsigned int width, unsigned int height);
~Texture();
void bind(unsigned char slot=0);
};
Shaders: Vertex Shader:
#version 330 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texpos;
out vec2 texCoord;
void main(){
gl_Position = position;
texCoord = texpos;
}
Fragment Shader:
#version 330 core
layout(location=0) out vec4 color;
uniform sampler2D u_Texture;
in vec2 texCoord;
void main(){
vec4 texColor = texture(u_Texture, texCoord);
color = texColor;
}
Renderer class declaration (you won't need the implementation although if you want it, I'll be happy to add it, just ask):
class Renderer{
private:
Renderer(){}
public:
static Renderer* renderer;
Renderer(const Renderer& r) = delete;
void draw(VertexArray* va, IndexBuffer* ib, Shader* shader, void (*uniformCallback)(Shader*, void*), void* uniformCallbackParams) const; //Fourth parameter is a function pointer that executes every time the draw function is called. It enables the user of the class to declare their uniforms. First three parameters are abstracted classes. Final parameter is a void pointer that is passed into the uniform function
};
Main Application (simplified):
typedef struct{
float x;
float y;
float texCoord_x;
float texCoord_y;
} vertex_t;
static GLFWwindow* window;
static void uniformCallback(Shader* program, void* params){
program->useUniform1i("u_Texture", 0); //Setting the sampler2D uniform for the texture slot
}
int main(){
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(500, 500, "OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
VertexArray* va = new VertexArray(); //Abstracted vertex array
va->bind();
VertexBuffer* vb = new VertexBuffer(); //Abstracted vertex buffer
IndexBuffer* ib = new IndexBuffer(); //Abstracted index buffer
unsigned char t[16] = { //Texture pixels, RGBA form. Made this simple 'image' just for testing purposes
1, 0, 0, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 0, 0, 1
};
Texture* texture = new Texture(t, 2, 2); //Texture class (abstracted)
texture->bind();
Shader* program = new Shader(2, "vs.glsl", "fs.glsl"); //Abstracted shader
vertex_t data[4] = {
{-0.5, 0.5, 0.0f, 1.0f},
{ 0.5, 0.5, 1.0f, 1.0f},
{-0.5, -0.5, 0.0f, 0.0f},
{ 0.5, -0.5, 1.0f, 0.0f}
};
unsigned int indicies[6] = {
0, 1, 2,
1, 2, 3
};
vb->setBufferData(data, 4*sizeof(vertex_t));
ib->setBufferData(indicies, 6);
vb->bind();
ib->bind();
va->addAttrib(GL_FLOAT, 2); //equivalent of glEnableAttribArray and glVertexAttribPointer
va->addAttrib(GL_FLOAT, 2);
while(!glfwWindowShouldClose(window)){
glClear(GL_COLOR_BUFFER_BIT);
Renderer::renderer->draw(va, ib, program, uniformCallback, NULL); //Refer to renderer class declaration
glfwSwapBuffers(window);
glfwPollEvents();
}
//Clean-up code (freeing pointers, etc.)
glfwTerminate();
return 0;
}
Upvotes: 1
Views: 316
Reputation: 211166
Each color channel of the texture is coded in a byte. Hence, the color values are in range [0, 255]. Change the values of t[16]
:
unsigned char t[16] = {
255, 0, 0, 255,
255, 255, 255, 255,
255, 255, 255, 255,
255, 0, 0, 255
};
Note that when specifying the two-dimensional texture image, the data type of the pixel data is specified by GL_UNSIGNED_BYTE
:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
Upvotes: 3