Opengl学习程序之多实例
来源:互联网 发布:mysql 5.1.73.tar.gz 编辑:程序博客网 时间:2024/05/08 16:17
示例一:
triangles.vert
#version 410 core//位置和法线都是规则的顶点属性layout(location = 0) in vec4 position;layout(location = 1) in vec3 normal;//颜色是一个逐实例的属性layout(location = 2) in vec4 color;//model_matrix是一个逐实例的变换矩阵。注意一个mat4会占据4个连续位置//因此它实际上占据了3,4,5,6四个索引位。layout(location = 3) in mat4 model_matrix;
triangles.frag
#version 410 corein vec4 vs_fs_color;layout(location = 0)out vec4 color;void main(void){ color = vs_fs_color;}
实现程序
#include "stdafx.h"#include<iostream>using namespace std;#include "vgl.h"#include "LoadShaders.h"#include "vmath.h"void init(void){ ShaderInfo shaders[] = { { GL_VERTEX_SHADER, "triangles.vert" }, { GL_FRAGMENT_SHADER, "triangles.frag" }, { GL_NONE,NULL} }; GLuint prog = LoadShaders(shaders); //获取顶点属性在prog当中的位置,prog就是我们准备用于渲染的着色器程序对象。 //注意,这一步并不是必须的,因为我们已经在顶点着色器中设置了所有属性的位置。 //这里的代码可以编写的更简单一些,只需要直接给出程序中已经设置的属性位置即可。 int position_loc = glGetAttribLocation(prog, "position"); int normal_loc = glGetAttribLocation(prog, "normal"); int color_loc = glGetAttribLocation(prog, "color"); int matrix_loc = glGetAttribLocation(prog, "model_matrix"); //配置正规的顶点属性数组--顶点和法线。 glBindBuffer(GL_ARRAY_BUFFER, position_buffer); glVertexAttribPointer(position_loc, 4, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(position_loc); glBindBuffer(GL_ARRAY_BUFFER, normal_buffer); glVertexAttribPointer(normal_loc, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(normal_loc); //设置颜色的数组,我们希望几何体的每个实例都有一个不同的颜色,因此 //直接将颜色值置入缓存对象中,然后设置一个实例化的顶点属性。 glBindBuffer(GL_ARRAY_BUFFER, color_buffer); glVertexAttribPointer(color_loc, 4, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(color_loc); //这里的设置很重要。。。。设置颜色数组的更新频率为1,那么Opengl会给每个实例 //设置一个新的颜色值,而不是每个顶点的设置。 glVertexAttribDivisor(color_loc, 1); //与之类似,我们给模型矩阵也做了同样的设置。注意输入到顶点着色器的矩阵 //会占据N个连续的输入位置,其中N表示矩阵的列数。因此。。。我们等于设置了4个顶点属性 glBindBuffer(GL_ARRAY_BUFFER, model_matrix_buffer); //循环遍历矩阵的每一列 for (int i = 0; i < 4; i++) { //设置顶点属性 glVertexAttribPointer(matrix_loc + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4)*i)); //启用顶点属性 glEnableVertexAttribArray(matrix_loc + i); //实现多实例化 //void glVertexAttribDivisor(GLuint index,GLuint divisor) //设置多实例渲染时,位于index位置的顶点着色器中顶点属性是如何分配值到每个实例的。divisor的值如果是0的话, //那么该属性的多实例特性将被禁用,而其他的值则表示顶点着色器,每divisor个实例都会分配一个新的属性值 glVertexAttribDivisor(matrix_loc + i, 1); }}
示例二:
triangles.vert
uniform mat4 view_matrix;uniform mat4 projection_matrix;//顶点着色器的输出(对应于片元着色器的输入)out VERTEX{ vec3 normal; vec4 color;}vertex;//现在开始void main(void){ //根据uniform的观察矩阵和逐实例的模型矩阵构建完整的模型-视点矩阵 mat4 model_view_matrix = view_matrix*model_matirx; //首先用模型-视点矩阵变换位置,然后是投影矩阵 gl_Position = projection_matrix*(model_view_matrix*position); //使用模型-视点矩阵的左上3x3子矩阵变换法线 vertex.normal = mat3(model_view_matrix)*normal; //将逐实例的颜色值直接传入片元着色器}
实现程序
#include "stdafx.h"#include<iostream>using namespace std;#include "vgl.h"#include "LoadShaders.h"#include "vmath.h"void init(void){ ShaderInfo shaders[] = { { GL_VERTEX_SHADER, "triangles.vert" }, { GL_FRAGMENT_SHADER, "triangles.frag" }, { GL_NONE,NULL} }; GLuint prog = LoadShaders(shaders); //映射缓存 //void* glMapBuffer(GLenum target,GLenum access) //将当前绑定到target的缓存对象的整个数据区域映射到客户端的地址空间中。之后可以根据给定的access策略,通过返回的指针 //对数据进行直接读或者写的操作。如果OpenGL无法将缓存对象的数据映射出来,那么glMapBuffer()将产生一个错误并且返回NULL. //发生这种情况的原因可能是与系统相关的,比如可用的虚拟内存过低等。 mat4 *matrices = (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] = rotation(a + t * 360.0f, 1.0f, 0.0f, 0.0f) * rotation(b + t * 360.0f, 0.0f, 1.0f, 0.0f)* rotation(c + t * 360.0f, 0.0f, 0.0f, 1.0f)* translation(10.0f + a, 40.0f + b, 50.0f + c); } //完成后解除映射 //GLboolean glUnmapBuffer(GLenum target) //解除glMapBuffer()创建的映射。如果对象数据的内容在映射过程中没有发生损坏,那么glUnmapBuffer()将返回GL_TRUE. //发生损坏的原因通常与系统相关,例如屏幕模式发生变化,这会影响内存的可用性。这种情况下,函数的返回值为GL_FALSE, //并且对应的数据内容是不可预测的。应用程序必须考虑到这种几率较低的情形,并且及时对数据进行重新初始化。 glUnmapBuffer(GL_ARRAY_BUFFER); //启用多实例的程序 glUseProgram(prog); //设置观察矩阵和投影矩阵 mat4 view_matrix(translation(0.0f, 0.0f, -1500.0f)* rotation(t * 360.0f * 2.0f, 0.0f, 1.0f, 0.0f)); mat4 projection_matrix(frustum(-1.0f, 1.0f, -aspect, aspect, 1.0f, 5000.0f)); glUniformMatrix4fv(view_matrix_loc, 1, GL_FALSE, view_matrix); glUniformMatrix4fv(projection_matrix_loc, 1, GL_FALSE, projection_matrix); //渲染INSTANCE_COUNT个模型 //void glDrawArraysInstanced(GLenum mode,GLint first,GLsizei count,GLsizei primCount) //通过mode,first和count所构成的几何体图元集(相当于glDrawArrays()函数所需的独立参数),绘制它的primCount个实例 //对于每个实例,内置变量gl_InstanceID都会依次递增,新的数值会被传递到顶点着色器,以区分不同实例的顶点属性。 glDrawArraysInstanced(GL_TRIANGLES, 0, object_size, INSTANCE_COUNT);}
示例三:
triangles.vert
//矩阵和投影矩阵在绘制过程中都是常数uniform mat4 view_matrix;uniform mat4 projection_matrix;//设置TBO来保存逐实例的颜色数据和模型矩阵数据uniform samplerBuffer color_tbo;uniform samplerBuffer model_matrix_tbo;//顶点着色器的输出(对应于片元着色器的输入)out VERTEX{ vec3 normal; vec4 color;}vertex;//现在开始void main(void){ //使用gl_InstanceID从颜色值的TBO当中获取数据 vec4 color = texelFetch(color_tbo,gl_InstanceID); //模型矩阵的生成更为复杂一些,因为我们不能直接在TBO中存储mat4数据 //我们需要将每个矩阵都保存为四个vec4的变量,然后在着色器中重新装配 //为矩阵的形式。首先,获取矩阵的四列数据(注意,矩阵在内存中的存储 //采用了列主序的方式) vec4 col1 = texelFetch(model_matrix_tbo,gl_InstanceID * 4); vec4 col2 = texelFetch(model_matrix_tbo,gl_InstanceID * 4 + 1); vec4 col3 = texelFetch(model_matrix_tbo,gl_InstanceID * 4 + 2); vec4 col4 = texelFetch(model_matrix_tbo,gl_InstanceID * 4 + 3); //现在将四列装配为一个矩阵 mat4 model_matrix = mat4(col1,col2,col3,col4); //根据uniform观察矩阵和逐实例的模型矩阵构建完整的模型-视点矩阵 mat4 model_view_matrix = view_matrix * model_matrix; //首先用模型-视点矩阵变换位置,然后是投影矩阵 gl_position = projection_matrix * (model_view_matrix * position); //使用模型-视点矩阵的左上3x3子矩阵变换法线 vertex.normal = mat3(model_view_matrix) * normal; //将逐实例的颜色值直接传入片元着色器}
实现程序:
#include "stdafx.h"#include<iostream>using namespace std;#include "vgl.h"#include "LoadShaders.h"#include "vmath.h"void init(void){ ShaderInfo shaders[] = { { GL_VERTEX_SHADER, "triangles.vert" }, { GL_FRAGMENT_SHADER, "triangles.frag" }, { GL_NONE, NULL } }; GLuint prog = LoadShaders(shaders); //获取顶点属性在prog当中的位置,prog就是准备用于渲染的着色器程序 //对象。注意,这一步并不是必需的,因为我们已经在顶点着色器中设置了所 //有属性的位置。这里的代码可以编写的更简单一些,只需要直接给出程序中 //已经设置的属性位置即可 int position_loc = glGetAttribLocation(prog, "position"); int normal_loc = glGetAttribLocation(prog, "normal"); //配置正规的顶点属性数组--顶点和法线 glBindBuffer(GL_ARRAY_BUFFER, position_buffer); glVertexAttribPointer(position_loc, 4, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(position_loc); glBindBuffer(GL_ARRAY_BUFFER, normal_buffer); glVertexAttribPointer(normal_loc, 3, GL_FLOAT, GL_FALSE, 0, NULL); glEnableVertexAttribArray(normal_loc); //现在设置多实例颜色和模型矩阵的TBO //首先创建TBO来存储颜色值,绑定一个缓存然后初始化数据格式。缓存必须 //在之前已经创建,并且大小可以包含一个vec4的逐实例数据 glGenTextures(1, &color_tbo); glBindTexture(GL_TEXTURE_BUFFER, color_tbo); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, color_buffer); //再次使用TBO来存储模型矩阵值。这个缓存对象(model_matrix_buffer)必须 //在之前已经创建,并且大小可以包含一个mat4的逐实例数据 glGenTextures(1, &model_matrix_tbo); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_BUFFER, model_matrix_tbo); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, model_matrix_buffer);}
0 0
- Opengl学习程序之多实例
- Python学习之多进程实例
- OpenGL实例程序
- OpenGL程序:实例练习
- java基础学习之多态实例
- opengl程序学习
- OpenGL学习 : 简单的线段OpenGL程序
- ADA程序实例(面向对象特性之多态)
- OpenGL红宝石实例程序2-14
- Opengl学习程序之三角形
- Opengl学习程序之uniform
- Opengl学习程序之纹理
- OpenGL学习笔记与水面波纹实例
- java之多线程实例
- Delphi之多线程实例
- Delphi之多线程实例
- Java之多线程实例
- OpenGL编程学习之《一个简单的OpenGL程序》
- QString 字符编码
- React Native 填坑指南
- Java程序员面试失败的5大原因
- ansible 批量停止iptables
- CAP->BASE
- Opengl学习程序之多实例
- POJ 3007(字符串hash)
- DP(大容量背包的一种做法)—— POJ 1786
- 对于思维导图打印该如何设置页面
- 3. StringBuffer 线程安全的可变字符序列
- structs2配置及应用
- myeclipse10 破解版run.bat闪退
- Windows 各种计时函数总结
- 首次安装Qt后,创建项目时出现“No valid kits found” 的解决办法