opengl - 黑色纹理,如何在缓冲区上使用 glm::vec*?

Posted

技术标签:

【中文标题】opengl - 黑色纹理,如何在缓冲区上使用 glm::vec*?【英文标题】:opengl - black textures, how to use glm::vec* on buffers? 【发布时间】:2014-02-22 15:49:49 【问题描述】:

我目前正在学习一些 opengl 的东西。过去,我将顶点数据、纹理位置数据等存储在使用 malloc 创建的数组中。 现在我正在尝试使用一些 std::vector 来实现这一点。我还使用本教程 http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading 创建了一个简单的 .obj 加载器。 但由于某种原因,我的纹理保持黑色。我在“对象”类中有这些东西。

我会发布所有我认为重要的代码,但是如果您想查看整个源代码,我会发布。

Object.hpp:

class Object 
public:
  Object(std::string objName);
  ~Object(void);

  bool loadTexture(std::string textureName);

  void setPos(glm::vec3 pos);
  void setDir(glm::vec3 dir);

  void draw(GLfloat time);

private:
  std::vector<glm::vec3> vertexData;
  std::vector<glm::vec3> elementData;
  std::vector<glm::vec2> texturePosData;
  std::vector<glm::vec3> vertexNormalData;

  GLuint vertexArrayObject;
  GLuint vertexBufferObject;
  GLuint elementBufferObject;
  GLuint texturePosBufferObject;

  ShaderProgram *shader;
  GLuint shaderProgram ;

  GLuint textureObject;
  GLuint textureUnit;
  static GLuint globalTextureCount;

  glm::vec3 position;
  glm::vec3 direction;

  //Uniforms
  GLint model, uniView, uniProj, overrideColor;
;

目前有一些我将在纹理工作后立即使用的未使用的东西(如 setPos() 或 setDir() )

Object.cpp: 我知道构造函数和对象加载器工作正常,因为顶点数据和纹理位置数据在向量中

bool Object::loadTexture(std::string textureName) 
  textureUnit = globalTextureCount;
  globalTextureCount++;

  glBindVertexArray(vertexArrayObject);

  //Create texuture Pos Buffer
  glGenBuffers(1, &texturePosBufferObject);
  glBindBuffer(GL_ARRAY_BUFFER, texturePosBufferObject);
  glBufferData(GL_ARRAY_BUFFER, texturePosData.size() * sizeof(glm::vec2), &texturePosData[0], GL_STATIC_DRAW);

  glGenTextures(1, &textureObject);
  glActiveTexture(GL_TEXTURE0 + textureUnit);
  glBindTexture(GL_TEXTURE_2D, textureObject);

  int width, height;
  unsigned char *image = NULL;
  image = SOIL_load_image(textureName.c_str(), &width, &height, 0, SOIL_LOAD_RGB);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
  SOIL_free_image_data(image);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  glUniform1i(glGetUniformLocation(shaderProgram, "texKitten"), textureUnit);

  GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
  glEnableVertexAttribArray(texAttrib);
  glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);

  return true;

这是正确的方法吗,我正在使用 glBufferData 和这些向量? 纹理可能有什么问题? glError() 不会抛出错误。 感谢您的帮助!

大卫

【问题讨论】:

我解决了这个问题,问题出在 Object::draw() 中。我没有初始化制服。 【参考方案1】:

问题是您在将纹理加载到矢量之前调用了 glBufferData。对 glBufferData 的调用正在将向量的内容复制到 GPU 内存中,但是您的向量尚未将纹理加载到其中,因此它可能充满了零(刚刚初始化)。

我的建议是等到 SOIL_load_image 返回后调用 glBufferData。

[编辑] 我在那里的回答太离谱了。我也没有看到您对您的问题的评论,您找到了根本原因。让我失望的是,您正在 loadTexture 方法中创建和加载顶点数组缓冲区。顶点数组缓冲区实际上与纹理或加载它没有任何关系。在 loadTexture 之外的某个地方处理顶点数组缓冲区可能更有意义,并使您的代码更具可读性。阅读您的代码时,它确实让我失望! :)

【讨论】:

以上是关于opengl - 黑色纹理,如何在缓冲区上使用 glm::vec*?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 在单色上混合颜色

模板的OpenGL修剪/内联轮廓

OpenGL ES 2.0 Framebuffer 渲染到纹理 iOS:没有显示

帧缓冲区和在opengl中使用着色器

OpenGL 多重渲染目标 - 黑色输出

关于 OpenGL 纹理、帧缓冲区和 UV 坐标的问题 [关闭]