【问题标题】:glDrawElementsInstanced getting only one vertex position and texture coordinateglDrawElementsInstanced 只获取一个顶点位置和纹理坐标
【发布时间】:2021-02-10 04:17:44
【问题描述】:

我正在尝试使用实例化渲染在一次绘制调用中多次渲染一个简单的网格(由 2 个三角形组成的纹理四边形)。渲染时,我看不到我的实例化网格,并且在使用 renderdoc 分析帧时,所有顶点位置都设置为网格的第一个顶点的位置,对于纹理坐标也是如此,所以我倾向于认为我有问题有顶点数据上传,但我不知道是什么。

我对实例渲染的主要灵感来源是this tutorialthe OpenGL documentation

以下是我的代码的相关部分:

  // This is part of the instanced mesh object initialization code.
  // VAO, VBO, and EBO are unsigned int private members of the object.

  glGenVertexArrays(1, &VAO);
  glGenBuffers(1, &VBO);
  glGenBuffers(1, &EBO);

  glBindVertexArray(VAO);
  glBindBuffer(GL_ARRAY_BUFFER, VBO);

  // I could confirm in a debug session that vertices contains the data I expect it to contain
  glBufferData(GL_ARRAY_BUFFER,
               static_cast<GLsizeiptr>(sizeof(float) * vertices.size()),
               vertices.data(),
               GL_STATIC_DRAW);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

  // Same as vertices, I could confirm indices contains the data I expect.
  glBufferData(GL_ELEMENT_ARRAY_BUFFER,
               static_cast<GLsizeiptr>(sizeof(unsigned int) * indices.size()),
               indices.data(),
               GL_STATIC_DRAW);

  GLsizei vertexStride = static_cast<GLsizei>(7 * sizeof(float));

  // vertex coordinates (only x and y, so the size of 2 is ok here)
  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, vertexStride, 0);
  glVertexAttribDivisor(0, 1);
  glEnableVertexAttribArray(0);

  // color
  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, 2);
  glVertexAttribDivisor(1, 1);
  glEnableVertexAttribArray(1);

  // texture coordinates
  glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertexStride, 5);
  glVertexAttribDivisor(2, 1);
  glEnableVertexAttribArray(2);

  glBindVertexArray(0);
  // This is the rendering code.

  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, texture.id);
  glActiveTexture(GL_TEXTURE1);
  glBindTexture(GL_TEXTURE_1D, palette.id);

  glBindVertexArray(VAO);

  // As advised by learnopengl.com, 4th argument is set to 0 since I'm using an element buffer
  glDrawElementsInstanced(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0, instances.size());
  glBindVertexArray(0);

  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, 0);
  glActiveTexture(GL_TEXTURE1);
  glBindTexture(GL_TEXTURE_1D, 0);
// vertex shader
#version 330 core
layout (location = 0) in vec2 vertex_pos;
layout (location = 1) in vec3 vertex_color;
layout (location = 2) in vec2 vertex_tex_coord;

out vec2 tex_coord;
out vec3 color;

uniform mat4 viewproj;

void main()
{
  gl_Position = viewproj * vec4(vertex_pos, 0.0, 1.0);
  tex_coord = vertex_tex_coord;
  color = vertex_color;
}

// fragment shader
#version 330 core
out vec4 fragment_color;

in vec2 tex_coord;
in vec3 color;

uniform sampler2D tex;
uniform sampler1D palette;

void main()
{
  float base_index = texture(tex, tex_coord).r;
  fragment_color = texture(palette, base_index) * vec4(color, 1);
}

这是我得到的: 我有正确数量的顶点,索引也可以,颜色也可以(代码前面的颜色设置为glm:vec3(1.0f, 1.0f, 1.0f)。但是,vertex_posvertex_tex_coord 值都是相同的。值是一致的,但都一样。

我会期待这样的事情:

考虑到我得到了正确的索引值,我认为 EBO 没问题,但我的 VBO 可能有问题,因为在上传之前我的 vertices 向量中的数据是正确的,而之前不正确渲染它,我迷路了^^',我不知道从哪里开始。

【问题讨论】:

    标签: c++ opengl


    【解决方案1】:

    你误解了glVertexAttribDivisor 的作用。 glVertexAttribDivisor 用于实例属性。实例属性是随实例而变化的属性,而不是实例的顶点。顶点坐标、颜色和纹理坐标不是实例属性,而是顶点属性。因此,您必须删除对 glVertexAttribDivisor 的调用(或将 divisor 参数设置为 0):

    glVertexAttribDivisor(0, 1);


    如果命名缓冲区对象绑定到GL_ARRAY_BUFFER 目标,则glVertexAttribPointer 的最后一个参数将被视为缓冲区对象数据存储的字节 偏移量。所以颜色和纹理坐标属性的偏移量必须是2*sizeof(float)5*sizeof(float),而不是2和5:

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, 2);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, (void*)(2*sizeof(float)));
    

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, 5);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, (void*)(5*sizeof(float)));
    

    【讨论】:

    • 谢谢你的回答:),你是对的,这里有一个错误。我修复了它,但得到了相同的结果,我会相应地更新问题。
    • @aTom 如果你更新问题,我的回答将毫无用处。
    • 我理解,但由于它不能解决我的实际问题...您指出的错误在我的实际代码库中不存在,这是我在尝试最小化数量时犯的错误我将分享的源代码
    • @aTom 我已经扩展了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多