友情提示:继续本节之前,需要保存此前的代码,本节为了试验,会对代码做一些修改,但后续的修改需要我们把代码返回之前的进度。

OpenGL内置支持Instancing,有专门的函数来处理这件事情。

为了方便,我们先使用最简单的三角形来学习

先修改sendDataToOpenGL()函数:

 void MyGlWindow::sendDataToOpenGL()
{
GLfloat tri[] = {
-1.0f,+0.0f,
-1.0f,+1.0f,
-0.9f,+0.0f
}; GLuint vertexBufferID;
glGenBuffers(, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(tri), tri, GL_STATIC_DRAW);
glEnableVertexAttribArray();
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , ); GLushort indices[] = { ,, };
GLuint indexArrayBufferID;
glGenBuffers(, &indexArrayBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexArrayBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
numIndices = ;
}

相应的修改vertexshader

 #version                            

 in layout(location=) vec2 position;   

 out vec3 passingColor;

 void main()
{ gl_Position = vec4(position.xy,,);
passingColor= vec3(,,);
}

以及paintGL()函数:

 void MyGlWindow::paintGL()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glViewport(, , width(), height()); glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, );
}

进行了上述修改之后,会在画布左上角绘制一个简单的红色三角形。

假如我们现在需要达到这样的目的:复制这个三角形多次,每次都横向偏移一定的量。

为了使用OpenGL提供的Instancing 方法,避免每次都调用glDrawElements,我们可以提供一个数组,作为偏移信息数组。

在sendDataToOpenGL()函数中定义一个GLfloat数组,把它绑定到GL_ARRAY_BUFFER上,开启一个新的通道,把数据传输进去。

最后在paintGL中使用glDrawElementsInstanced函数来绘制多个实例。

具体代码如下:

 void MyGlWindow::sendDataToOpenGL()
{
GLfloat tri[] = {
-1.0f,+0.0f,
-1.0f,+1.0f,
-0.9f,+0.0f
}; GLuint vertexBufferID;
glGenBuffers(, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(tri), tri, GL_STATIC_DRAW);
glEnableVertexAttribArray();
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , ); GLfloat offsets[] = {0.0f, 0.5f, 1.0f, 1.2f, 1.6f};
GLuint offsetsBufferID;
glGenBuffers(, &offsetsBufferID);
glBindBuffer(GL_ARRAY_BUFFER, offsetsBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(offsets), offsets, GL_STATIC_DRAW);
glEnableVertexAttribArray();
glVertexAttribPointer(, , GL_FLOAT, GL_FALSE, , );
glVertexAttribDivisor(, ); GLushort indices[] = { ,, };
GLuint indexArrayBufferID;
glGenBuffers(, &indexArrayBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexArrayBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
numIndices = ;
}

16-23行是新增内容。

16行定义了一个GLfloat数组,有5个元素。

17-20行我们已经很熟悉,不再解释了

21行开启了通道1

22行设定了通道1的数据格式,第一个参数表示通道1,第二个参数表示每1个数据作为一个单元

23行glVertexAttribDivsior是个新函数,它是配合实例化绘制的。没有它的情况下,tri数组每2个元素结合offsets数组的1个元素,也就是说offsets数组每个元素只用一次。有了这个函数之后,offsets数组的每个元素都要做一次循环,和tri数组的每组元素结合一次,形成5个批次。

修改VertexShader:

 #version                            

 in layout(location=) vec2 position;
in layout(location=) float offset; out vec3 passingColor; void main()
{ gl_Position = vec4(position.x + offset, + position.y,,);
passingColor= vec3(,,);
}

增加了第4行,对应sendDataToOpenGL的新增通道1.

第11行中,我们把position的x坐标进行了offset的偏移。

最后修改paintGL()函数:

 void MyGlWindow::paintGL()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glViewport(, , width(), height());
glDrawElementsInstanced(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, , );
}

第5行使用glDrawElementsInstanced函数代替glDrawElements函数,进行了批量绘制。

第五个参数表示绘制五个实例。

最后效果:

3D Computer Grapihcs Using OpenGL - 15 Draw Element Instanced的更多相关文章

  1. 3D Computer Grapihcs Using OpenGL - 16 使用DrawElementsInstanced绘制立方体

    我们使用15节学到的知识来绘制14节的立方体. 在第14节我们使用了两次glDrawElements实现了OpenGL实例化,发现这样仍然不太方便,如果需要绘制成千上万的立方体,就需要手写成千上万次的 ...

  2. 3D Computer Grapihcs Using OpenGL - 09 Enable Depth Test

    启用Depth Test OpenGL是个3D绘图API,也就是说不只有xy坐标轴,还有第三个坐标轴z,z轴的方向是垂直于屏幕,指向屏幕内. 靠近人眼的方向是负方向,标准化设备坐标的最小值是-1, 最 ...

  3. 3D Computer Grapihcs Using OpenGL - 06 Vertex and Fragment Shaders

    从这里就接触到了可编程图形渲染管线. 下面介绍使用Vertex Shader (顶点着色器)和 Fragment Shader(像素着色器)的方法. 我们的目标是使用这两个着色器给三角形填充绿色. 添 ...

  4. 3D Computer Grapihcs Using OpenGL - 03 OpenGL Buffer Data

    本节绘制一个三角形,并讲解Buffer Object-缓冲对象 OpenGL的窗口坐标 屏幕中心为坐标原点,横向朝右为x正方向,纵向朝上为y正方向,最大值最小值分别为1,-1. Buffer Obje ...

  5. 3D Computer Grapihcs Using OpenGL - 19 Vertex Array Object(顶点数组对象)

    大部分OpenGL教程都会在一开始就讲解VAO,但是该教程的作者认为这是很不合理的,因为要理解它的作用需要建立在我们此前学过的知识基础上.因此直到教程已经进行了一大半,作者才引入VAO这个概念.在我看 ...

  6. 3D Computer Grapihcs Using OpenGL - 14 OpenGL Instancing

    如果我们需要绘制两个(或者多个)一样的立方体(或者物体),只是位置.缩放.旋转不一样,那么我们可以不需要多次将这个物体的顶点信息.颜色信息等发送到显卡,而是发送一次,绘制多次,仅仅是每次绘制之前应用不 ...

  7. 3D Computer Grapihcs Using OpenGL - 11 Model View Projection Matrices

    本节我们将绘制一个3维物体,立方体. 如果要渲染3D物体,我们需要了解MVP(Model View Projection),它表示三个转换矩阵.实际上这个名字不够明确,更加确切的释义如下: Model ...

  8. 3D Computer Grapihcs Using OpenGL - 10 Color Buffer

    本节我们将尝试利用三角形制作一个“走马灯”效果. 一个三角形如图示方式,从左向右依次移动. 先看一下代码: MyGlWindow.cpp #include <gl\glew.h> #inc ...

  9. 3D Computer Grapihcs Using OpenGL - 07 Passing Data from Vertex to Fragment Shader

    上节的最后我们实现了两个绿色的三角形,而绿色是直接在Fragment Shader中指定的. 这节我们将为这两个三角形进行更加自由的着色——五个顶点各自使用不同的颜色. 要实现这个目的,我们分两步进行 ...

随机推荐

  1. [转帖]虚拟内存探究 -- 第四篇:malloc, heap & the program break

    虚拟内存探究 -- 第四篇:malloc, heap & the program break http://blog.coderhuo.tech/2017/10/19/Virtual_Memo ...

  2. Springboot与springcloud

    1.什么是Spring Boot? 它简化了搭建Spring项目,自动配置Spring,简化maven配置,自带tomcat无需部署war包,创建独立的spring引用程序main方法运行: 2.Sp ...

  3. 什么是SQL注入以及mybatis中#{}为什么能防止SQL注入而${}为什么不能防止SQL注入

    1.什么是SQL注入 答:SQL注入是通过把SQL命令插入到web表单提交或通过页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL指令. 注入攻击的本质是把用户输入的数据当做代码执行. 举例如: ...

  4. SpringMVC上传文件总结

    如果是maven项目 需要在pom.xml文件里面引入下面两个jar包 <dependency> <groupId>commons-fileupload</groupId ...

  5. 数位dp(二进制01问题)

    http://poj.org/problem?id=3252 题意:给你一个区间,求区间有多少个满足条件的数.条件是:把该数转为二进制后,如果0的数量大于等于1的数量,则为满足条件的数量. 题解:数位 ...

  6. springBoot2.0使用@ImportResource引入spring配置文件.xml

    1. 编写spring配置文件.xml 这里是bean.xml <?xml version="1.0" encoding="UTF-8"?> < ...

  7. C#获取主机信息

    获取主机信息 最近需要做一个配合集控系统收集各个终端设备的一些信息,大致需要收集终端设备的硬件信息,CPU.内存以及硬盘使用率等信息.网上查看了一番,使用WMI来获取这些信息是最方便的.实现代码如下: ...

  8. Jquery复习(八)之遍历

    jQuery 遍历 - 祖先 parent() parents() parentsUntil() jQuery parent() 方法 parent() 方法返回被选元素的直接父元素. 该方法只会向上 ...

  9. ubuntu 安装mysql5.7

    一.Windows mysql5.6 解压版 安装 关于widnows平台上的安装教程,可参考百度经验: 链接:https://jingyan.baidu.com/article/f3ad7d0ffc ...

  10. 用python 获取照片的Exif 信息(获取拍摄设备,时间,地点等信息)

    第一步:先安装 pip install exifread 第二部:上代码 import exifread import requests class PhotoExifInfo(): def __in ...