首页 > 解决方案 > OpenGL 纹理几乎不可见(非常暗)

问题描述

我已经开始在 opengl 中处理纹理,并且在渲染我的第一个纹理时,我看到了一个黑屏。然后我意识到屏幕不是黑色的,而是纹理非常暗淡。为什么会这样?这是代码:

纹理类(.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;
}

纹理类声明(如果需要):

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

着色器:顶点着色器:

#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;
}

片段着色器:

#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;
}

渲染器类声明(你不需要实现,但如果你想要它,我很乐意添加它,只是问):

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

主要应用(简化):

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

标签: c++openglglslshaderglfw

解决方案


纹理的每个颜色通道都以一个字节编码。因此,颜色值在 [0, 255] 范围内。更改 的值t[16]

unsigned char t[16] = {
    255, 0,   0,   255,
    255, 255, 255, 255,
    255, 255, 255, 255,
    255, 0,   0,   255
  };

注意,在指定二维纹理图像时,像素数据的数据类型由 指定GL_UNSIGNED_BYTE

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, this->width, this->height, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, data);


推荐阅读