OpenGL学习24——实例化渲染

2021-07-29  本文已影响0人  蓬篙人

实例化(Instancing)渲染

for (unsigned int i = 0; i < amount_of_models_to_darw; i++)
{
    DoSomePreparations();   // bind VAO, bind Textures, set uniform etc.
    glDrawArrays(GL_TRIANGLES, 0, amount_of_vertices);
}
float quadVertices[] = {
    // position     // colors
    -0.05f,  0.05f, 1.0f, 0.0f, 0.0f,
     0.05f, -0.05f, 0.0f, 1.0f, 0.0f,
    -0.05f, -0.05f, 0.0f, 0.0f, 1.0f,

    -0.05f,  0.05f, 1.0f, 0.0f, 0.0f,
     0.05f, -0.05f, 0.0f, 1.0f, 0.0f,
     0.05f,  0.05f, 0.0f, 1.0f, 1.0f
}
#version 330 core
out vec4 FragColor;

in vec3 fColor;

void main()
{
    FragColor = vec4(fColor, 1.0);
}
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec3 aColor;

out vec3 fColor;

uniform vec2 offsets[100];

void main()
{
    vec2 offset = offsets[gl_InstanceID];
    gl_Position = vec4(aPos + offset, 0.0, 1.0);
    fColor = aColor;
}
glm::vec2 translations[100];
int index = 0;
float offset = 0.1f;
for (int y = -10; y < 10; y +=2)
{
    for (int x = -10; x < 10; x+=2)
    {
        glm::vec2 translation;
        translation.x = (float)x / 10.0f + offset;
        translation.y = (float)y / 10.0f + offset;
        translations[index++] = translation;
    }
}
shader.use();
for (unsigned int i = 0; i < 100; i++)
{
    shader.setVec2(("offsets[" + std::to_string(i) + "]"), translations[i]);
}

1. 实例数组

#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aOffset;

out vec3 fColor;

void main()
{
    gl_Position = vec4(aPos + aOffset, 0.0, 1.0);
    fColor = aColor;
}
unsigned int instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 100, &translations[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(objectVAO);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 第二个参数
// 0: 顶点着色器每次迭代都更新顶点属性内容
// 1: 开始渲染一个新的实例时更新顶点着色器的内容
// 2: 没渲染两个实例进行更新
glVertexAttribDivisor(2, 1);
glBindVertexArray(0);
void main()
{
    vec2 pos = aPos * (gl_InstanceID / 100.0);
    gl_Position = vec4(pos + aOffset, 0.0, 1.0);
    fColor = aColor;
}

2. 小行星带

unsigned int amount = 1000;
glm::mat4* modelMatrices;
modelMatrices = new glm::mat4[amount];
srand(glfwGetTime());   // 初始化随机种子
float radius = 50.0;
float offset = 2.5f;
for (unsigned int i = 0; i < amount; i++)
{
    glm::mat4 model = glm::mat4(1.0f);
    // 1. 平移:放置到半径为[-offset, offset]的圆圈
    float angle = (float)i / (float)amount * 360.0f;
    float displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;

    float x = sin(angle) * radius + displacement;
    displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;
    float y = displacement * 0.4f;   // 行星域高度保持小于x/z
    displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;
    float z = cos(angle) * radius + displacement;
    model = glm::translate(model, glm::vec3(x, y, z));

    // 2. 缩放:在0.05和0.25f之间缩放
    float scale = (rand() % 20) / 100.0f + 0.05;
    model = glm::scale(model, glm::vec3(scale));

    // 3. 旋转:绕随机旋转轴旋转
    float rotAngle = (rand() % 360);
    model = glm::rotate(model, rotAngle, glm::vec3(0.4f, 0.6f, 0.8f));

    modelMatrices[i] = model;
}
objectShader.use();
glm::mat4 view = camera.GetViewMatrix();
// 将投影远平面拉远
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 1000.0f);
objectShader.setMat4("view", view);
objectShader.setMat4("projection", projection);
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -3.0f, 0.0f));
model = glm::scale(model, glm::vec3(4.0));
objectShader.setMat4("model", model);
planetModel.Draw(objectShader);
for (unsigned int i = 0; i < amount; i++)
{
    objectShader.setMat4("model", modelMatrices[i]);
    rockModel.Draw(objectShader);
}
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in mat4 instanceMatrix;

out vec2 TexCoords;

uniform mat4 view;
uniform mat4 projection;

void main()
{
    TexCoords = aTexCoords;    
    gl_Position = projection * view * instanceMatrix * vec4(aPos, 1.0);
}
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);

// 注意这里模型类的meshs原先是private,需要修改为public
for (unsigned int i = 0; i < rockModel.meshes.size(); i++)
{
    unsigned int VAO = rockModel.meshes[i].VAO;
    glBindVertexArray(VAO);
    // vertex attributes
    std::size_t v4s = sizeof(glm::vec4);
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 4 * v4s, (void*)0);
    glEnableVertexAttribArray(4);
    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * v4s, (void*)(1 * v4s));
    glEnableVertexAttribArray(5);
    glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * v4s, (void*)(2 * v4s));
    glEnableVertexAttribArray(6);
    glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * v4s, (void*)(3 * v4s));

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

    glBindVertexArray(0);
}
instanceShader.use();
instanceShader.setMat4("view", view);
instanceShader.setMat4("projection", projection);
for (unsigned int i = 0; i < rockModel.meshes.size(); i++)
{
    glBindVertexArray(rockModel.meshes[i].VAO);
    glDrawElementsInstanced(GL_TRIANGLES, rockModel.meshes[i].indices.size(),
        GL_UNSIGNED_INT, 0, amount);
    glBindVertexArray(0);
}
上一篇下一篇

猜你喜欢

热点阅读