OpenGL学习日记-2015.3.13——多实例渲染
是一种很有效的。有用少量api调用来渲染大量几何体的方法。OpenGL提供多种机制,同意着色器对不同渲染实例赋予不同的顶点属性。
几个简单的多实例渲染命令:
多实例渲染顶点属性控制:
而该属性的属性数组大小将为(instance/divisor),instance为之前设置的渲染实例数(primCount),如果在多实例渲染中改变实例的颜色,设divisor为2。instance为100。颜色数组至少为100/2
= 50组rgba数据,才干保证每一个实例都有自己的颜色值,不然将是黑漆漆的。
最后假设divisor设置为0,将代表是非实例化,渲染的结果是,全部实例都是黑漆漆的,可能这个黑漆漆的结果也不是必定的,我猜想的是这时候着色器的输入变量vec4 color为默认的(0.0,0.0。0.0,1.0)并没有设置它的值,所以是黑色的。
顶点着色器分析:
片元着色器分析:
应用程序代码:
- #include "instancing_1.h"
- #include "vutils.h"
- #include "vmath.h"
- #include "vbm_ch3_intancing1.h"
- namespace instancing1
- {
- float shade_aspect = 800 / 600;
- GLuint color_buffer;
- GLuint model_matrix_buffer;
- GLuint render_prog;
- GLuint model_matrix_loc;
- GLuint view_matrix_loc;
- GLuint projection_matrix_loc;
- VBObject object;
- #define INSTANCE_COUNT 100
- GLenum gl_err = 0;
- static const GLubyte* errorStr = NULL;
- };
- using namespace instancing1;
- void instancing1Init()
- {
- int n;
- //创建着色器程序
- render_prog = glCreateProgram();
- //着色器字符串
- static const char render_vs[] =
- "#version 410\n"
- "\n"
- "// 'position' and 'normal' are regular vertex attributes\n"
- "layout (location = 0) in vec4 position;\n"
- "layout (location = 1) in vec3 normal;\n"
- "\n"
- "// Color is a per-instance attribute\n"
- "layout (location = 2) in vec4 color;\n"
- "\n"
- "// model_matrix will be used as a per-instance transformation\n"
- "// matrix. Note that a mat4 consumes 4 consecutive locations, so\n"
- "// this will actually sit in locations, 3, 4, 5, and 6.\n"
- "layout (location = 3) in mat4 model_matrix;\n"
- "\n"
- "// The view matrix and the projection matrix are constant across a draw\n"
- "uniform mat4 view_matrix;\n"
- "uniform mat4 projection_matrix;\n"
- "\n"
- "// The output of the vertex shader (matched to the fragment shader)\n"
- "out VERTEX\n"
- "{\n"
- " vec3 normal;\n"
- " vec4 color;\n"
- "} vertex;\n"
- "\n"
- "// Ok, go!\n"
- "void main(void)\n"
- "{\n"
- " // Construct a model-view matrix from the uniform view matrix\n"
- " // and the per-instance model matrix.\n"
- " mat4 model_view_matrix = view_matrix * model_matrix;\n"
- "\n"
- " // Transform position by the model-view matrix, then by the\n"
- " // projection matrix.\n"
- " gl_Position = projection_matrix * (model_view_matrix * position);\n"
- " // Transform the normal by the upper-left-3x3-submatrix of the\n"
- " // model-view matrix\n"
- " vertex.normal = mat3(model_view_matrix) * normal;\n"
- " // Pass the per-instance color through to the fragment shader.\n"
- " vertex.color = color;\n"
- "}\n";
- static const char render_fs[] =
- "#version 410\n"
- "\n"
- "layout (location = 0) out vec4 color;\n"
- "\n"
- "in VERTEX\n"
- "{\n"
- " vec3 normal;\n"
- " vec4 color;\n"
- "} vertex;\n"
- "\n"
- "void main(void)\n"
- "{\n"
- " color = vertex.color * (0.1 + abs(vertex.normal.z)) + vec4(0.8, 0.9, 0.7, 1.0) * pow(abs(vertex.normal.z), 40.0);\n"
- "}\n";
- //shader创建,编译,装载
- vglAttachShaderSource( render_prog, GL_VERTEX_SHADER, render_vs );
- vglAttachShaderSource( render_prog, GL_FRAGMENT_SHADER, render_fs );
- //连接着色器成为可用程序
- glLinkProgram(render_prog);
- //激活着色器
- glUseProgram(render_prog);
- //获取视图矩阵位置
- view_matrix_loc = glGetUniformLocation(render_prog, "view_matrix");
- //获取投影矩阵位置
- projection_matrix_loc = glGetUniformLocation(render_prog, "projection_matrix");
- //载入vbm模型文件
- //@pram 1路径、2顶点location 3法线location、4纹理location(颜色)
- object.LoadFromVBM("../8edlib/media/armadillo_low.vbm", 0, 1, 2);
- //绑定顶点数组
- object.BindVertexArray();
- //获取顶点着色器in变量location
- int position_loc = glGetAttribLocation( render_prog, "position" );
- int normal_loc = glGetAttribLocation( render_prog, "normal" );
- int color_loc = glGetAttribLocation( render_prog, "color" );
- int matrix_loc = glGetAttribLocation( render_prog, "model_matrix");
- //每一个实例的颜色数组
- vmath::vec4 colors[INSTANCE_COUNT];
- for (n = 0; n < INSTANCE_COUNT; n++ )
- {
- float a = float(n) / 4.0f;
- float b = float(n) / 5.0f;
- float c = float(n) / 6.0f;
- colors[n][0] = 0.5f + 0.25f * (sinf(a + 1.0f) + 1.0f );
- colors[n][1] = 0.5f + 0.25f * (sinf(b + 2.0f) + 1.0f );
- colors[n][2] = 0.5f + 0.25f * (sinf(c + 3.0f) + 1.0f );
- colors[n][3] = 1.0f;
- }
- //缓存对象
- glGenBuffers(1, &color_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, color_buffer);//3个工作。
- glBufferData( GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW );//动态改变用于绘制的数据
- glVertexAttribPointer( color_loc, 4, GL_FLOAT, GL_FALSE, 0, NULL );
- glEnableVertexAttribArray( color_loc );
- //!!!启用顶点属性多实例属性,每一个实例读取一次颜色值
- glVertexAttribDivisor( color_loc, 1);
- //模型矩阵数据
- glGenBuffers(1, &model_matrix_buffer );
- glBindBuffer( GL_ARRAY_BUFFER, model_matrix_buffer );
- //NULL保留内存
- glBufferData( GL_ARRAY_BUFFER, INSTANCE_COUNT * sizeof(vmath::mat4), NULL, GL_DYNAMIC_DRAW );
- for (int i = 0; i < 4; i++ )
- {
- glVertexAttribPointer(matrix_loc + i, 4, GL_FLOAT, GL_FALSE, sizeof(vmath::mat4), (void *)(sizeof(vmath::vec4)* i));
- glEnableVertexAttribArray( matrix_loc + i );
- glVertexAttribDivisor( matrix_loc + i, 1 );
- }
- //解除vao绑定,至于为什么要这句呢,我的理解是:这是个好习惯。用完之后吧OpenGL还原默认状态。
- glBindVertexArray(0);
- }
- static inline int min( int a, int b )
- {
- return a < b ? a : b;
- }
- void instancing1Display()
- {
- float t = float(GetTickCount() & 0x3FFF) / float(0x3FFF);
- int n;
- //清屏
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- //
- glEnable( GL_CULL_FACE );
- glEnable( GL_DEPTH_TEST );
- glDepthFunc( GL_LEQUAL );
- //绑定vbo,改动数据
- glBindBuffer( GL_ARRAY_BUFFER, model_matrix_buffer );
- //获取当前vbo的OpenGL指针
- vmath::mat4* matrices = (vmath::mat4*)glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
- for (n = 0; n < INSTANCE_COUNT; n++ )
- {
- float a = 50.0f * float(n) / 4.0f;
- float b = 50.0f * float(n) / 5.0f;
- float c = 50.0f * float(n) / 6.0f;
- matrices[n] = vmath::rotate(a + t * 360.0f, 1.0f, 0.0f, 0.0f) *
- vmath::rotate(a + t * 360.0f, 0.0f, 1.0f, 0.0f) *
- vmath::rotate(a + t * 360.0f, 0.0f, 0.0f, 1.0f) *
- vmath::translate(10.0f + a, 40.0f + b, 50.0f + c);//平移,再旋转
- }
- //数据操作完成,解除映射!必须
- glUnmapBuffer( GL_ARRAY_BUFFER );
- //确认激活须要的着色器程序
- glUseProgram( render_prog );
- //生成视图矩阵和投影矩阵
- vmath::mat4 view_matrix(vmath::translate(0.0f, 0.0f, -1500.0f) * vmath::rotate(t * 360.0f * 2.0f, 0.0f, 1.0f, 0.0f));
- vmath::mat4 projection_matrix(vmath::frustum(-1.0f, 1.0f, -shade_aspect, shade_aspect, 1.0f, 5000.0f));
- //设置视图矩阵和投影矩阵
- glUniformMatrix4fv( view_matrix_loc, 1, GL_FALSE, view_matrix );//这次你就没写错參数,能不能不坑爹,之前我都以为自己智商出问题了。
- glUniformMatrix4fv( projection_matrix_loc, 1, GL_FALSE, projection_matrix );
- //渲染多个实例
- object.Render( 0, INSTANCE_COUNT ); //能不能不坑爹。
- 。后面的vbm竟然不兼容前面的vbm.....
- GLenum error = glGetError();//
- const GLubyte* errorStr = gluErrorString(error);
- //这个几个意思。。
- 。lookat仅仅是生成了一个矩阵而已。。。
- //vmath::lookat( vmath::vec3(0.0f, 0.0f, 0.0f), vmath::vec3(1.0f, 0.0f, 0.0f), vmath::vec3(0.0f, 1.0f, 0.0f) ); //摄像机?????????/
- }
- void instancing1Update(float)
- {
- }
还有一个多实例渲染实例,纹理打包,着色器内置变量gl_InstanceID使用:
实例计数器gl_InstanceID:
该变量被声明为一个整数,初始为0,每一个实例被渲染之后,他会加1.他总是存在于顶点着色器中,即使当前没有启用多实例特性,此时他的值保持0.gl_InstanceID能够作为uniform数组的索引使用,也能够作为纹理查找的參数,或者作为某个分析函数的输入,等等。
新实例分析:
在这里用到了纹理缓存对象,对于我又是一个未使用过的特性,在接受新东西的时候总不会认为乏味。
OpenGL学习日记-2015.3.13——多实例渲染的更多相关文章
- OpenGL学习之路(三)
1 引子 这些天公司一次次的软件发布节点忙的博主不可开交,另外还有其它的一些事也占用了很多时间.现在坐在电脑前,在很安静的环境下,与大家分享自己的OpenGL学习笔记和理解心得,感到格外舒服.这让我回 ...
- Linux学习日记-使用EF6 Code First(四)
一.在linux上使用EF 开发环境 VS2013+mono 3.10.0 +EF 6.1.0 先检测一下EF是不是6的 如果不是 请参阅 Linux学习日记-EF6的安装升级(三) 由于我的数据库 ...
- python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例
python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...
- OpenGL学习进程(12)第九课:矩阵乘法实现3D变换
本节是OpenGL学习的第九个课时,下面将详细介绍OpenGL的多种3D变换和如何操作矩阵堆栈. (1)3D变换: OpenGL中绘制3D世界的空间变换包括:模型变换.视图变换.投影变换和视口 ...
- OpenGL学习进程(11)第八课:颜色绘制的详解
本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿. (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...
- OpenGL学习笔记:拾取与选择
转自:OpenGL学习笔记:拾取与选择 在开发OpenGL程序时,一个重要的问题就是互动,假设一个场景里面有很多元素,当用鼠标点击不同元素时,期待作出不同的反应,那么在OpenGL里面,是怎么知道我当 ...
- OpenGL学习之路(一)
1 引子 虽然是计算机科班出身,但从小对几何方面的东西就不太感冒,空间想象能力也较差,所以从本科到研究生,基本没接触过<计算机图形学>.为什么说基本没学过呢?因为好奇(尤其是惊叹于三维游戏 ...
- OpenGL学习之路(四)
1 引子 上次读书笔记主要是学习了应用三维坐标变换矩阵对二维的图形进行变换,并附带介绍了GLSL语言的编译.链接相关的知识,之后介绍了GLSL中变量的修饰符,着重介绍了uniform修饰符,来向着色器 ...
- android学习日记05--Activity间的跳转Intent实现
Activity间的跳转 Android中的Activity就是Android应用与用户的接口,所以了解Activity间的跳转还是必要的.在 Android 中,不同的 Activity 实例可能运 ...
随机推荐
- hotmail邮箱pop3server设置方法
hotmail邮箱 的POP3/SMTP功能仅仅向Hotmail Plus的用户开放,普通用户想要使用这一功能的话,得进行一些特别的设置.如今这一功能总算面向全部的用户开放了,虽然微软官方还没宣布这一 ...
- sha1加密java代码
sha1 加密 java代码 public static String getSha1(String str){ if(str==null||str.length()==0){ return null ...
- U14Linux的帐号与用户组
1.在/etc/group和/etc/gshadow中查找mousegroup: grep mousegroup /etc/group /etc/gshadow (grep的使用) 2.其实Linux ...
- jQuery Fancybox插件说明
这里有jquery影像回放路径插件称为Fancybox,项目主页地址:http://fancybox.net/ Fancybox的特点例如以下: 1.能够支持图片.html文本.flash动画.ifr ...
- 在html中禁用自己主动完毕
输入框输入内容时总是显示历史输入历史记录,现禁用的方法是加入一个属性: <input type="text name="txt_xm" autocomplete=& ...
- LeetCode: Unique Binary Search Trees [095]
[题目] Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For ...
- Unable to start MySQL service. Another MySQL daemon is already running with the same UNIX socket
Unable to start MySQL service. Another MySQL daemon is already running with the same UNIX socket 特征 ...
- SQL SERVER IN参数化处理
方法一. CREATE TABLE [dbo].[Users] ( Id INTEGER IDENTITY(1, 1) PRIMARY KEY , Name NVARCHAR(50) NOT NULL ...
- registerWithTouchDispatcher()函数的使用
registerWithTouchDispatcher()函数的使用 registerWithTouchDispatcher()函数主要用于注册Touch事件. 当我们使用this->setTo ...
- 基于VLC的视频播放器
原文:基于VLC的视频播放器 最近在研究视频播放的功能,之前是使用VideoView.在网上看了一下,感觉不是很好,支持的格式比较少,现在网络视频的格式各种各样,感觉用VideoView播放起来局限性 ...