如何为多个对象使用不同的变换实例绘制 [英] How to instance draw with different transformations for multiple objects

查看:75
本文介绍了如何为多个对象使用不同的变换实例绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 glDrawArraysInstanced()有点问题.

现在我正试图用棋子画一个棋盘.

Right now Im trying to draw a chess board with pieces.

我已经正确加载了所有模型.

I have all the models loaded in properly.

我尝试过仅使用实例绘图来绘制棋子,并且可以正常工作.我将发送带有转换vec3s的数组到统一着色器,并使用 gl_InstanceID

Ive tried drawing pawns only with instance drawing and it worked. I would send an array with transformation vec3s to shader through a uniform and move throught the array with gl_InstanceID

这可以通过for循环(每个模型的单独绘制调用)来完成:

That would be done with this for loop (individual draw call for each model):

for (auto& i : this->models) {
    i->draw(this->shaders[0], count);
}

最终导致:

glDrawArraysInstanced(GL_TRIANGLES, 0, vertices.size(), count);

顶点着色器所在的位置:

#version 460

layout(location = 0) in vec3 vertex_pos;
layout(location = 1) in vec2 vertex_texcoord;
layout(location = 2) in vec3 vertex_normal;

out vec3 vs_pos;
out vec2 vs_texcoord;
out vec3 vs_normal;
flat out int InstanceID;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

uniform vec3 offsets[16];

void main(void){
    vec3 offset = offsets[gl_InstanceID];  //saving transformation in the offset 

    InstanceID = gl_InstanceID; //unimportant

    vs_pos = vec4(modelMatrix * vec4(vertex_pos + offset, 1.f)).xyz; //using the offset

    vs_texcoord = vec2(vertex_texcoord.x,1.f-vertex_texcoord.y);

    vs_normal = mat3(transpose(inverse(modelMatrix))) * vertex_normal;

    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(vertex_pos + offset,1.f); //using the offset
}

现在我的问题是我不知道如何以这种方式绘制多个对象并更改其变换,因为 gl_InstanceID 在每次绘制调用时均从0开始,因此从开始(这只会在棋子的位置绘制下一块).

Now my problem is that I dont know how to draw multiple objects in this way and change their transformations since gl_InstanceID starts from 0 on each draw call and thus my array with transformations would be used again from the beggining (which would just draw next pieces on pawns positions).

任何帮助将不胜感激.

推荐答案

您有两个问题.或者说,您有一个问题,但是自然的解决方案会为您造成第二个问题.

You've got two problems. Or rather, you have one problem, but the natural solution will create a second problem for you.

您的问题的自然解决方案是使用基础实例渲染功能之一,例如 glDrawElementsInstancedBaseInstance .这些使您可以为实例化的渲染调用指定起始实例.

The natural solution to your problem is to use one of the base-instance rendering functions, like glDrawElementsInstancedBaseInstance. These allow you to specify a starting instance for your instanced rendering calls.

这将引发第二个问题: gl_InstanceID 不尊重基本实例.它将始终在[0,instancecount)范围内.只有实例数组尊重基本实例.因此,您必须使用实例数组渲染,而不是使用统一的方法来提供每个实例的数据.这意味着将每个实例的数据存储在一个缓冲区对象中(无论如何,您都应该这样做),并通过VS输入(通过VAO指定特定实例的实例访问)来访问它.

This will precipitate a second problem: gl_InstanceID does not respect the base instance. It will always be on the range [0, instancecount). Only instance arrays respect the base instance. So instead of using a uniform to provide your per-instance data, you must use instance array rendering. This means storing the per-instance data in a buffer object (which you should have done anyway) and accessing it via a VS input whose VAO specifies that the particular attribute is instanced.

这还具有不将实例数限制为统一限制的优点.

This also has the advantage of not restricting your instance count to uniform limitations.

OpenGL 4.6/ARB_shader_draw_parameters允许访问 gl_BaseInstance 顶点着色器输入,该输入提供了draw命令指定的 baseinstance 值.因此,如果您不想/不能使用实例数组(例如,每个实例的数据量对于属性限制而言太大),则必须依靠该扩展/4.6功能.最新的桌面GL驱动程序提供了此功能,因此,如果您的硬件是全新的,则应该可以使用它.

OpenGL 4.6/ARB_shader_draw_parameters allows access to the gl_BaseInstance vertex shader input, which provides the baseinstance value specified by the draw command. So if you don't want to/can't use instanced arrays (for example, the amount of per-instance data is too big for the attribute limitations), you will have to rely on that extension/4.6 functionality. Recent desktop GL drivers offer this functionality, so if your hardware is decently new, you should be able to use it.

这篇关于如何为多个对象使用不同的变换实例绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆