OPenGL 您所在的位置:网站首页 opengl绘制多个物体 OPenGL

OPenGL

2024-05-27 15:59| 来源: 网络整理| 查看: 265

简述

多实例渲染是一种连续执行多次相同的渲染命令的方法,并且每个渲染命令所产生的结果都会有轻微的差异。这是一种使用少量API来渲染大量几何体的有效方法。

当一个模型需要创建多个实例时,一般地可以在程序中循环调用glDrawArrays()函数完成多次绘制,这样,顶点着色器对每次输入的顶点运行一次,就会从内存中重复提取一次的数据,绘制多次相当于多次运行OPenGL整个管线。给GPU造成了潜在的处理负担。如果使用实例化方式创建,则只会多次运行几何着色器及以后的渲染管线,而不会运行全部的管线,效率会显著提升。当然,两种方法也可以同时使用。

常见的多实例绘制函数

glDrawArraysInstanced(),  glDrawElementsInstanced(), glDrawElementsInstancedBaseVertex()。

voidglDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primCount)

功  能:多实例绘制函数

返回值:void

参数:前三个参数是绘制几何体图元集的参数(与glDrawArrays()中的参数完全相同

primCount参数表示绘制实例的个数)

这个函数是glDrawArrays()的多实例版,这两个函数的参数完全是等价的,只是多了一个primCount参数,用于设置实例化的个数。其他绘制函数也有对应的实例化版本,函数glDrawElements()对应glDrawElementsInstanced(),函数glDrawElementsBaseVertex()对应glDrawElementsInstancedBaseVertex(),它们函数参数相同,只是实例化版的都会多一个参数设置实例化个数。

对于每个实例,在GLSL中的内置变量gl_InstanceID都会递增一次,新的数值会传递到顶点着色器中,以区分不同实例的顶点属性。

 

实例化实现思路

单纯实例化的实现非常简单,只需要调用上面实例化版本的绘制函数,并设置实例化个数就可以实现。但这样绘制的实例几乎是一摸一样的,包括位置颜色等属性,没有任何实际意义。

因此需要给每个实例都设置自己的属性,比如为每个实例设置不同的位置。

 

顶点着色器

1.这里的用uniform变量从程序中向实例传递数据,如果需要实例化100个,那么就在顶点着色其中声明一个数组来存储。

uniform vec2 offsets[100];

2.在原来的位置上进行偏移,根据GLSL中的内置变量gl_InstanceID索引每个实例的属性

gl_Position = vec4(aPos + offset[gl_InstanceID], 0, 1.0);

3.顶点着色器应该是这样的,其他着色器不变。

#version 330 core

layout (location = 0) in vec2 aPos;

layout (location = 1) in vec3 aColor;

 

out vec3 fColor;

uniform vec2 offsets[100];

 

void main()

{

   fColor = aColor;

   gl_Position = vec4(aPos + offsets[gl_InstanceID], 0, 1.0);

};

应用程序

在应用程序中要做的就是准备着色器中要的数据,并传递到着色器中,每个实例需要和数据一一对应。再调用多实例绘制函数就可以完成了。

1.准备数据

要实例化100个就需要准备100分数据,也是一个数组。

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;

}

}

2.传递数据

准备好数据后需要传到着色器中,应用程序设置uniform数据要有名称索引,所以需要拼接字符串和着色器中的变量意义对应。

for (unsigned int i = 0; i < 100; i++)

{

std::stringstream ss;

std::string index;

ss



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有