GLSL Instancing - 传递ModelMatrix

时间:2018-04-08 17:53:42

标签: opengl glsl

我在Google / Stackflow上进行了很多搜索,无法找到我特定问题的答案。我尝试使用修补的球体网格和以下参考文献实现实例化:

http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html

https://learnopengl.com/Advanced-OpenGL/Instancing

我试图调试我自己的代码,但似乎没有任何工作...我一直得到一个看起来像modelmatrix值已损坏或设置不正确的输出。这是在传递模型的Identity矩阵时在不同的相机旋转时的样子:

Instance Model Matrix #1

Instance Model Matrix #2

如果我将顶点着色器中的模型矩阵硬编码为Identity Matrix,那么它就可以了:

Hard-code Model Matrix

所以在我看来,模型矩阵没有被正确传递,因为我花了好几天检查我的代码并尝试不同的东西。我希望有人可以对此进行评论并发现问题..谢谢!

InstanceObject ::初始化()

for (unsigned int Level = 0; Level < Levels; Level++)
{
    FrameTicks[Level] = 0;
    VBO_SeedVector[Level] = 0;
    VBO_ModelMatrix[Level] = 0;

    //. Bind VAO for Object's Level of Detail
    glBindVertexArray(Meshes->GetMesh(Level)->GetVAO());

    //. Generate Buffers for Object's SeedVector
    glGenBuffers(1, &VBO_SeedVector[Level]);

    //. Generate Instance Array for Object's SeedVector
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Vector4f), (void*)0);
    glVertexAttribDivisor(2, 1);

    //. Generate Buffers for Object's ModelMatrix
    glGenBuffers(1, &VBO_ModelMatrix[Level]);

    //. Generate Instance Array for Object's ModelMatrix
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(0 * sizeof(Vector4f)));
    glVertexAttribDivisor(3, 1);

    glEnableVertexAttribArray(4);
    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(1 * sizeof(Vector4f)));
    glVertexAttribDivisor(4, 1);

    glEnableVertexAttribArray(5);
    glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(2 * sizeof(Vector4f)));
    glVertexAttribDivisor(5, 1);

    glEnableVertexAttribArray(6);
    glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(3 * sizeof(Vector4f)));
    glVertexAttribDivisor(6, 1);

    ObjectSeeds.push_back(std::vector<Vector4f>());
    ObjectModels.push_back(std::vector<Matrix4f>());
}

InstanceObject ::更新()

//. Load Instance Arrays into VAOs
for (unsigned int Level = 0; Level < Levels; Level++)
{
    glBindVertexArray(Meshes->GetMesh(Level)->GetVAO());

    glBindBuffer(GL_ARRAY_BUFFER, VBO_SeedVector[Level]);
    glBufferData(GL_ARRAY_BUFFER, ObjectSeeds[Level].size() * sizeof(Vector4f), &ObjectSeeds[Level], GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, VBO_ModelMatrix[Level]);
    glBufferData(GL_ARRAY_BUFFER, ObjectModels[Level].size() * sizeof(Matrix4f), &ObjectModels[Level], GL_STATIC_DRAW);
}

InstanceObject ::渲染()

//. Empty Detailed Mesh
if (Meshes == nullptr)
    return;

//. Enable VAA for Px, Py, Pz, U
glEnableVertexAttribArray(0);
glVertexAttribDivisor(0, 0);

//. Enable VAA for Nx, Ny, Nz, V
glEnableVertexAttribArray(1);
glVertexAttribDivisor(1, 0);

//. Enable VAA for Seed Vector
glEnableVertexAttribArray(2);
glVertexAttribDivisor(2, 0);

//. Enable VAA for Model Matrix
glEnableVertexAttribArray(3);
glVertexAttribDivisor(3, 1);
glEnableVertexAttribArray(4);
glVertexAttribDivisor(4, 1);
glEnableVertexAttribArray(5);
glVertexAttribDivisor(5, 1);
glEnableVertexAttribArray(6);
glVertexAttribDivisor(6, 1);

//. Render Instances For Each Ring
for (unsigned int Level = Levels - 1; Level > 0; Level--)
{
    unsigned int RingSize = ObjectModels[Level].size();

    //. Empty Ring
    if (RingSize == 0)
        continue;

    BaseMesh* Mesh = Meshes->GetMesh(Level);

    //. Empty Mesh
    if (Mesh == nullptr)
        continue;

    unsigned int VAO = Mesh->GetVAO();

    if (VAO == 0)
        continue;

    //. Render Instances
    glBindVertexArray(VAO);
    glDrawElementsInstanced(GL_TRIANGLES, Mesh->Elements.size(), GL_UNSIGNED_INT, 0, RingSize);
}

glDisableVertexAttribArray(6);
glDisableVertexAttribArray(5);
glDisableVertexAttribArray(4);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);

顶点着色器

#version 440

layout (location = 0) in vec4 Position;
layout (location = 1) in vec4 Normal;
layout (location = 2) in vec4 Seed;
layout (location = 3) in vec4 ModelCol0;
layout (location = 4) in vec4 ModelCol1;
layout (location = 5) in vec4 ModelCol2;
layout (location = 6) in vec4 ModelCol3;

//uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;

out vec3 mPosition;
out vec3 vPosition;
out vec3 vNormal;
out vec2 vSample;

void main()
{
    mPosition = Position.xyz;

    mat4 vModel = mat4(1.0);

    vModel[0] = ModelCol0;
    vModel[1] = ModelCol1;
    vModel[2] = ModelCol2;
    vModel[3] = ModelCol3;

    vPosition = (vModel * vec4(mPosition.xyz, 1.0)).xyz;
    vNormal = (vModel * vec4(Normal.xyz, 0.0)).xyz;
    vSample = vec2(Position.w, Normal.w);

    gl_Position = Projection * View * vModel * vec4(mPosition.xyz, 1.0);
}

04/09/18更新:

我更新了InstanceObject :: Init()以在VAA调用之前绑定VBO,如下所示:

for (unsigned int Level = 0; Level < Levels; Level++)
{
    FrameTicks[Level] = 0;
    VBO_SeedVector[Level] = 0;
    VBO_ModelMatrix[Level] = 0;

    //. Bind VAO for Object's Level of Detail
    glBindVertexArray(Meshes->GetMesh(Level)->GetVAO());

    if (!LogErrorGL(std::cout, "glGenBuffers"))
        return false;

    //. Generate Buffers for Object's SeedVector
    glGenBuffers(1, &VBO_SeedVector[Level]);

    if (!LogErrorGL(std::cout, "glGenBuffers"))
        return false;

    //. Enable Vertex Attribute Arrays
    glEnableVertexAttribArray(2);

    if (!LogErrorGL(std::cout, "glEnableVertexAttribArray"))
        return false;

    //. Bind Buffer to Setup Instance Array
    glBindBuffer(GL_ARRAY_BUFFER, VBO_SeedVector[Level]);

    if (!LogErrorGL(std::cout, "glBindBuffer"))
        return false;

    //. Generate Instance Array for Object's SeedVector
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Vector4f), (void*)0);

    if (!LogErrorGL(std::cout, "glVertexAttribPointer"))
        return false;

    //. Apply Attribute Divisors
    glVertexAttribDivisor(2, 1);

    if (!LogErrorGL(std::cout, "glVertexAttribDivisor"))
        return false;

    //. Unbind Buffer
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //.
    //.
    //.

    //. Generate Buffers for Object's ModelMatrix
    glGenBuffers(1, &VBO_ModelMatrix[Level]);

    if (!LogErrorGL(std::cout, "glGenBuffers"))
        return false;

    //. Enable Vertex Attribute Arrays
    glEnableVertexAttribArray(3);
    glEnableVertexAttribArray(4);
    glEnableVertexAttribArray(5);
    glEnableVertexAttribArray(6);

    if (!LogErrorGL(std::cout, "glEnableVertexAttribArray"))
        return false;

    //. Bind Buffer to Setup Instance Arrays
    glBindBuffer(GL_ARRAY_BUFFER, VBO_ModelMatrix[Level]);

    if (!LogErrorGL(std::cout, "glBindBuffer"))
        return false;

    //. Generate Instance Array for Object's ModelMatrix
    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(0 * sizeof(Vector4f)));
    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(1 * sizeof(Vector4f)));
    glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(2 * sizeof(Vector4f)));
    glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4f), (void*)(3 * sizeof(Vector4f)));

    if (!LogErrorGL(std::cout, "glVertexAttribPointer"))
        return false;

    glVertexAttribDivisor(3, 1);
    glVertexAttribDivisor(4, 1);
    glVertexAttribDivisor(5, 1);
    glVertexAttribDivisor(6, 1);

    if (!LogErrorGL(std::cout, "glVertexAttribDivisor"))
        return false;

    //. Unbind Buffer
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //. Bind Default VAO ~ move to outside For Loop
    glBindVertexArray(0);

    if (!LogErrorGL(std::cout, "glBindVertexArray"))
        return false;

    ObjectSeeds.push_back(std::vector<Vector4f>());
    ObjectModels.push_back(std::vector<Matrix4f>());
}

当我尝试绑定VAO以加载更新数据时,所有工作都没有抛出任何GL错误,但我在InstanceObject :: Update()部分得到GL_INVALID_OPERATION:

    //. Load Instance Arrays into VAOs
for (unsigned int Level = 0; Level < Levels; Level++)
{
    glBindVertexArray(Meshes->GetMesh(Level)->GetVAO()); //. GL_INVALID OPERATION

    if (!LogErrorGL(std::cout, "glBindVertexArray"))
        return;

    //glGenBuffers(1, &VBO_SeedVector[Level]);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_SeedVector[Level]);

    if (!LogErrorGL(std::cout, "glBindBuffer"))
        return;

    glBufferData(GL_ARRAY_BUFFER, ObjectSeeds[Level].size() * sizeof(Vector4f), &ObjectSeeds[Level], GL_STATIC_DRAW);

    if (!LogErrorGL(std::cout, "glBufferData"))
        return;

    //glGenBuffers(1, &VBO_ModelMatrix[Level]);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_ModelMatrix[Level]);

    if (!LogErrorGL(std::cout, "glBindBuffer"))
        return;

    glBufferData(GL_ARRAY_BUFFER, ObjectModels[Level].size() * sizeof(Matrix4f), &ObjectModels[Level], GL_STATIC_DRAW);

    if (!LogErrorGL(std::cout, "glBufferData"))
        return;

1 个答案:

答案 0 :(得分:0)

<html> <head> <title>HHH</title> </head> <body> <h1 id="text" onmousedown="MouseDown()" onmouseup="Mouseup()">BBB </h1> <script> function MouseDown() { document.getElementById("text").innerHTML="CCC" ; } function Mouseup() { document.getElementById("text").innerHTML="AAA" ; } </script> </body> </html>中,您实际上绑定您正在创建的任何VBO。

GL'a属性数组指针始终包含对缓冲区对象名称的引用,以及到此缓冲区的字节偏移量(以及其他内容,如数据格式和步幅等)。 InstanceObject::Init()会将当前绑定的 glVertexAttribPointer的名称存储在属性指针中。