簡體   English   中英

使用使用freeimage加載的紋理時,OpenGL Quad顯示為黑色

[英]OpenGL quad appears black when using textures loaded with freeimage

我正在使用OpenGL 4.3,並且試圖繪制一個要在其上應用此紋理的四邊形(即“ textures / dickbutt.png”)。 紋理的尺寸為654x654。

雞巴

但是,每種可能的指令組合總是使我具有黑色的紋理,有時在右下角還帶有一些人工制品。

黑色四邊形 人工制品特寫

這是繪圖發生的主要功能的代碼。

void Run() {
  shader::factory::CompileShaderFile("shaders/test.vert", GL_VERTEX_SHADER);
  shader::factory::CompileShaderFile("shaders/test.frag", GL_FRAGMENT_SHADER);
  GLuint m_shaderProgram = shader::factory::CreateProgram();

  // Set up vertex data (and buffer(s)) and attribute pointers
  GLfloat vertices[] = {
    -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    0.5f,  0.5f, 0.0f,
    -0.5f, 0.5f, 0.0f
  };

 GLfloat texcoords[] = {
    0.0f, 0.0f,
    1.0f, 0.0f,
    1.0f, 1.0f,
    0.0f, 1.0f
  };

  GLuint VBO, VAO;
  glGenVertexArrays(1, &VAO);
  glBindVertexArray(VAO);

  glGenBuffers(1, &VBO);
  glBindBuffer(GL_ARRAY_BUFFER, VBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

  // Position attribute
  glEnableVertexAttribArray(0);
  glBindVertexBuffer(0, VBO, 0, 3*sizeof(GL_FLOAT));
  glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0);
  glVertexAttribBinding(0, 0);

  GLuint texVBO;
  glGenBuffers(1, &texVBO);
  glBindBuffer(GL_ARRAY_BUFFER, texVBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW);

  glEnableVertexAttribArray(1);
  glBindVertexBuffer(1, texVBO, 0, 2 * sizeof(GL_FLOAT));
  glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, 0);
  glVertexAttribBinding(1, 1);

  glBindVertexArray(0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);


  GLuint m_textureID = 
    texture::factory::Create2DTexture("textures/dickbutt.png");

  shader::module::RegisterUniform("mytexture", m_shaderProgram);

  while (!graphic_context->PollWindowClosedEvent()) {
    double dt = timer::chrono::GetTimeElapsedInSeconds();

    glActiveTexture(GL_TEXTURE0);
    shader::module::Use(m_shaderProgram);
    glUniform1i(shader::module::GetUniformLocation("mytexture", m_shaderProgram), 0);
    glBindTexture(GL_TEXTURE_2D, m_textureID);

    glBindVertexArray(VAO);
    glDrawArrays(GL_QUADS, 0, 4);
    glBindVertexArray(0);

    // Next line renders the XYZ axes in separated shader program, commenting it out changes nothing in the texture display.
    scene::Render(); 

    graphic_context->Update();
    timer::chrono::Update();
  }
}

這是Texture :: factory的代碼,在該代碼中加載圖像,並創建和設置OpenGL緩沖區。

GLuint Create2DTexture(const std::string& a_sFileName) {
  GLsizei wWidth, wHeight;
  unsigned char *wImage = nullptr;
  void *wBitMapHandle = nullptr;

  if (!LoadImage(a_sFileName, wImage, wWidth, wHeight, wBitMapHandle)) {
    std::cerr << "texture_factory::Create2DTexture -> Loading image failed. " << std::endl
      << "Returning 0xFFFFFFFF..." << std::endl;
    return 0xFFFFFFFF;
  }

  // Generate texture
  GLuint wTexture;
  glGenTextures(1, &wTexture);
  // Create texture
  glBindTexture(GL_TEXTURE_2D, wTexture);

  glTexImage2D(
    GL_TEXTURE_2D,    // 2D texture target
    0,                // Base mipmap level
    GL_RGBA,           // RGBA color components
    wWidth, wHeight,  // Dimensions
    0,                // Must be 0...
    GL_RGBA,           // Pixel data format
    GL_UNSIGNED_BYTE, // Depends on what the LoadImage function return type
    wImage);          // Loaded image

  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_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);          

  // Commenting-out the next line make the artefacts appear on the quad
  //  glGenerateMipmap(GL_TEXTURE_2D);

  // Free image
  FreeImage(wBitMapHandle);
  //glBindTexture(GL_TEXTURE_2D, 0);

  return wTexture;
}

LoadImage函數

bool LoadImage(const std::string& a_sFileName,
  unsigned char *a_pImage,
  GLsizei& a_rWidth,
  GLsizei& a_rHeight,
  void *a_pBitmapHandle) {
  const char *wFilename = a_sFileName.c_str();
  //image format
  FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
  //pointer to the image, once loaded
  FIBITMAP *dib(0);
  //pointer to the image data
  BYTE* bits(0);
  //image width and height
  unsigned int width(0), height(0);

  //check the file signature and deduce its format
  fif = FreeImage_GetFileType(wFilename, 0);
  //if still unknown, try to guess the file format from the file extension
  if (fif == FIF_UNKNOWN)
    fif = FreeImage_GetFIFFromFilename(wFilename);
  //if still unkown, return failure
  if (fif == FIF_UNKNOWN)
    return false;

  //check that the plugin has reading capabilities and load the file
  if (FreeImage_FIFSupportsReading(fif))
    dib = FreeImage_Load(fif, wFilename);
  //if the image failed to load, return failure
  if (!dib)
    return false;

  //retrieve the image data
  bits = FreeImage_GetBits(dib);
  //get the image width and height
  width = FreeImage_GetWidth(dib);
  height = FreeImage_GetHeight(dib);
  //if somehow one of these failed (they shouldn't), return failure
  if ((bits == 0) || (width == 0) || (height == 0))
    return false;

  a_pImage = bits;
  a_rWidth = width;
  a_rHeight = height;
  a_pBitmapHandle = dib;

  return true;
}

以及相關的頂點/片段着色器代碼

// test.vert
#version 430
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texcoord;

layout (std140, binding = 0) uniform CameraInfo {
  mat4  ProjectionView; 
  vec3  eye;
};

out vec2 tex_coord;

void main()
{
  vec4 vertex = vec4(position,1.0);
  gl_Position = ProjectionView*vertex;
  tex_coord = vec2(texcoord.x, 1.0 - texcoord.y);
}

//test.frag
#version 430

out vec4 color;

in vec2 tex_coord;

// Texture samplers
uniform sampler2D mytexture;

void main()
{
    //color = vec4(1.0f,0.0f,0.0f,1.0f); // Prints red quad
    color = texture2D(mytexture, tex_coord);
}

我將代碼與教程,SO上的其他帖子以及工作示例進行了數十次比較,但是我找不到我做錯了什么。

您已經傳遞了a_rWidtha_rHeight作為引用。 您必須同樣對a_pImagea_pBitmapHandle這樣做。

這全都歸結為為什么這樣的事情:

int a = 1;
test(a);
printf("%d\n", a);

假設test()的定義如下,則顯示1而不是2

void test(int a) {
    a = 2;
}

因此,您需要將LoadImage更改為此:

bool LoadImage(
    const std::string &a_sFileName,
    unsigned char **a_pImage,
    GLsizei &a_rWidth,
    GLsizei &a_rHeight,
    void **a_pBitmapHandle) {

    [...]

    *a_pImage = bits;
    a_rWidth = width;
    a_rHeight = height;
    *a_pBitmapHandle = dib;

並這樣稱呼它:

LoadImage(a_sFileName, &wImage, wWidth, wHeight, &wBitMapHandle)

另外請注意,FreeImage會將圖像解碼為BGR / BGRA格式。 因此,您必須使用GL_BGRA而不是GL_RGBA

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM