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
原创粉丝点击