位置: 编程技术 - 正文

OpenGL学习笔记-2015.3.24——transform feedback缓存&粒子系统示例分析(opengl教程48讲)

编辑:rootadmin

推荐整理分享OpenGL学习笔记-2015.3.24——transform feedback缓存&粒子系统示例分析(opengl教程48讲),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:opengl learning,opengl教程48讲,opengl使用教程,opengl learn,opengl learn,opengl learn,opengl learn,opengl基础教程,内容如对您有帮助,希望把文章链接给更多的朋友!

OpenGL学习笔记-2015.3.24——transform feedback缓存&粒子系统示例分析(opengl教程48讲)

transform feedback是OpenGL中比较酷炫的特性之一,他让客户端应用程序可以获取到渲染流水线上的顶点数据。基于这一特性实现了基于z-pass场景决策渲染技术,当然在此并没有去了解何为z-pass场景决策渲染技术,总之是一个可以有效减少渲染数据的输送。这里只是通过一个简单的例子系统,去了解transform feedback对象的使用方法。

正文: 1、transform feedback: transform feedback是OpenGL渲染管线中,顶点处理阶段结束之后,图元装配和光栅化之前的一个步骤。transform feedback可以重新捕获即将装配为图元(点,线段,三角形)的顶点,然后你将他们的部分或者全部属性传递到缓存对象。每个顶点在传递到图元装配阶段时(之前),将所有需要捕获的属性数据记录到一个或者多个缓存对象当中(至于捕获那些数据,都是在我们控制之下的),程序可以通过缓存回读这些数据,或者将他们用于后续的渲染操作。 tansform feedback所有状态通过一个transform feedback对象管理,这个状态包括所有用于记录顶点数据的缓存对象,用于标识缓存对象的计数器(名称glGen*系列函数返回),以及用于标识transform feedback当前是否启用的状态量。transform对象的创建绑定过程和一般的OpenGL对象相&#;: a. void glGenTransformFeedbacks( GLsizei n, GLuint* ids ) 为transform feedback对象生成n个名称,并且将生成的名称记录到数组ids中。0是保留名称,openGL默认tranform feedback,函数将永远不会返回0. b. void glBindTransformFeedback( GLenum target, GLuint id ) 将一个id(glGen*返回的名称)绑定到指定的target(必须是GL_TRANSFORM_FEEDBACK)所指定的环境中。他做了三个工作:1、如果第一次绑定这个名称,将创建一个tranform feedback对象,使用默认状态&#;对他进行初始化,并设为当前transform feedback;2、否则单纯的帮该transform feedback激活为当前;3、如果id为0,则相当于重新回到默认的transform feedback对象上(解除所有&#;钱绑定的transform feedback对象) c. GLboolean glIsTransformFeedback( GLenum id )判断id是否为一个transform feedback对象。 d.当绑定了一个transform feedback对象之后,所有可能会影响到transform feedback状态的命令都会作用于这个对象。不过并不需要为了使用transform feedback相关功能而去特别定义一个transform feedback对象想,因为系统会内置一个默认的transform feedback对象(名称为id = 0) e. void glDeleteTransformFeedbacks( GLsizei n, const GLuint* ids )删除n个transform feedback对象。在本次transform feedback结束之后才回去删除 2.transform feedback缓存 transform feedback主要用来管理将顶点捕捉到缓存对象的相关状态。这个状态中包含当前连接到的transform feedback缓存绑定点的缓存对象。可以同时给transform feedback绑定多个缓存,也可以绑定缓存对象的多个子块,甚至可以将同一个缓存对象不用子块绑定到不同的transform feedback缓存绑定点上。绑定接口: void glBindBufferBase( GLenum target, GLuint index, GLuint buffer ) 其中target自然必须为GL_TRANSFORM_FEEDBACK_BUFFER,而index必须为当前绑定的transform feedback对象的缓存绑定点索引,绑定点最大数与设备实现有关可以通关GL_MAX_TRANSFORM_FEEDBACK_BUFFERS的&#;来查询。所有的OpenGL设备实现都可以至少支持个绑定点。也可以将一个缓存对象的一部分绑定到某个transform feedback绑定点:void glBindBufferRange( GLenum GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size ) offset 和size单位都为字节,定义了buffer缓存的范围。需要特别注意的是亮点:1、保证一个缓存绑定到多个transform feedback绑定点时他们使用的区域不能重叠。2.、glBindBufferBase()和glBindBufferRange()都不会主动去创建缓存对象(这与glBindBuffer不同),而创建缓存对象的工作还是由glBindBuffer()来承担,数据操作还是由glBufferData(),glBufferSubData(),glGetBufferSubData()来完成。(关于缓存绑定点的解释:在这里可能会问缓存绑定点指的是什么?其实就是一个点,也可以理解为一个名称,他有着最大限制,至少为,是着色器访问缓存对象的一个桥梁(快速便捷的),略微搜了下,有个一个叫UBO(uniform Block Object)的应用,看了多少会对绑定点有所了解,遗憾的是并没有找到,transform feedback的关于这个桥梁保证准确找到数据的呢?现在也并不能很好的理解之,mark下一个地址: 讲述了transform feedback的高级应用) 初始化过程示例: //缓存名称 GLuint buffer; glGenBuffers( 1, &buffer ) //绑定到TRANSFORM_FEEDBACK创建缓存对象。 glBindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, buffer ) //glBufferData初始化数据,参数为NULL,申请空间保留使用 glBufferData( GL_TRANFORM_FEEDBACK_BUFFER, *, NULL, GL_DYNAMIC_COPY ) //绑定到缓存绑定点,一般用于index = 1,一般用于index = 0 glBindBufferRange( GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, * ) glBindBufferRange( GL_TRANSFORM_FEEDBACK_BUFFER, 1, buffer, *, * ) 3、transform feedback的变量配置transform feedback所绑定的缓存是一个transform feedback对象关联在一起,顶点(或者几何)着色器的输出要记录在那些缓存当中,这些配置信息是保存在当前程序对象当中。openGL提供了相应的接口让我们配置那些变量应该被记录。 void glTransformFeedbackVaryings( GLuint program, GLsizei count, const GLchar** varyings, GLenum bufferMode ) 参数varyings指定了一个变量数组,也就是那些需要被feedback的变量。program是对应的着色器程序,count表示varyings中字符串的数量,bufferMode指定了捕获变量的模式:a、分离模式(GL_SEPARATE_ATTRIBS):每个变量将会被记录到单独的缓存对象中;b、交叉模式(GL_INTERLEAVED_ATTRIBS):那么所有的变量是一个接着一个记录到绑定到当前transform feedback对象的第一个绑定点的缓存对象里! openGL还提供了一些内置变量来帮助 我们更灵活的控制捕获的数据在缓存中的对齐方式:gl_SkipComponents1、gl_SkipComponents2、gl_SkipComponents3、gl_SkipComponents4、gl_NextBuffer。对于gl_SkipComponents*,OpenGL会留出指定数量的空隙(1,2,3,4)。当捕获模式为交叉模式这些才可以使用这些gl_SkipComponents*内置变量;而对于gl_NextBuffer,OpenGL会把变量传递到当前绑定点的下一个transform feedback缓存中,这样在GL_INTERLEAVED_ATTRIBS模式下也可以将变量保存在单独的缓存当中,如果捕获模式为GL_SEPARATE_ATTRIBS是遇到gl_NextBuffer,或者在GL_INTERLEAVED_ATTRIBS下连续遇到gl_NextBuffer(两个而上)那么将跳过当前绑定点,并在当前绑定的缓存中不会记录任何数据。在这里&#;乎可以回答之前括号里面关于绑定点的疑惑:首先每个绑定点对应于一个缓存或一部分缓存,他总是独立享有指定的缓存,不能与其他绑定点交叉。对于顶点着色器和几何着色器而言绑定点&#;乎可以理解为地址。在捕获数据是总是先从索引为当前transform feedback对象的第一个绑定点索引开始(索引&#;最小那个)输出数据,并根据glTransformFeedbackVaryings() varyings 参数指定的对齐方式存放在缓存当中。 4、transform feedback捕获启动与停止、 transform feedback 可以随时启动和停止,甚至暂停。一些控制transform启动停止的api: void glBeginTransformFeedback( GLenum primitiveMode ):开始并设置transform feedback将要记录的图元类型,primitiveMode必须是:GL_POINTS, GL_LINES、GL_TRIANGLES三个之一。在之后的绘制命令中团员类型需要与之相符,或则几何着色器中输出类型需要与之相符。、 void glPuaseTransformFeedback():暂停transform feedback对变量的记录,但transform feedback还是处于启动状态。如果transform feedback没有启动则OpenGL产生错误。 void glResumeTransformFeedback():重新开启一个之前通过glPuaseTransformFeedback()暂停的feedback过程,如果transform feedback没有启动,或者没有被处于活动状态,则产生OpenGL错误。 void glEndTransformFeedback()结束transform feedback过程。 5、基于transform feedback的粒子系统分析 程序分为两个处理过程,创建了2个着色器分别管理这两个过程。第一个负责渲染模型对象,第二个负责渲染粒子和实现粒子与模型对象的碰撞检测。在碰撞检测过程中用到的模型顶点数据就是将是通过transform feedback获取,而由于需要记录粒子的位置速度信息需要保留给当前渲染使用,单一缓冲无法对新数据进行记录,所以采用了双缓冲区,同样使用transform feedback来记录本次粒子渲染结果,给下一帧使用。 粒子系统渲染顶点着色器分析:#version uniform mat4 model_matrix; uniform mat4 projection_matrix; uniform int triangle_count;//模型的,在绘制更新粒子前赋&#;三角形数量 //输入 layout (location = 0) in vec4 position; layout (location = 1) in vec3 velocity; //输出 out vec4 position_out; out vec3 velocity_out;//在transform feedback记录的数据,使用纹理查找tbo获取三角形平面 uniform samplerBuffer geometry_tbo; uniform float time_step = 0.;//更新时间步长//线段与三角形平面相交测试 bool intersect(vec3 origin, vec3 direction, vec3 v0, vec3 v1, vec3 v2, out vec3 point) { vec3 u, v, n; vec3 w0, w; float r, a, b; u = (v1 - v0); v = (v2 - v0); n = cross(u, v); if (length(n) < 0.1) return false; w0 = origin - v0; a = -dot(n, w0); b = dot(n, direction); if (abs(b) < 0.1) return false; r = a / b; if (r < 0.0 || r > 1.0) return false; point = origin &#; r * direction; float uu, uv, vv, wu, wv, D; uu = dot(u, u); uv = dot(u, v); vv = dot(v, v); w = point - v0; wu = dot(w, u); wv = dot(w, v); D = uv * uv - uu * vv; float s, t; s = (uv * wv - vv * wu) / D; if (s < 0.0 || s > 1.0) return false; t = (uv * wu - uu * wv) / D; if (t < 0.0 || (s &#; t) > 1.0) return false; return true; } //碰撞后反射向量计算 vec3 reflect_vector(vec3 v, vec3 n) { return v - 2.0 * dot(v, n) * n; } void main(void) { vec3 accelleration = vec3(0.0, -0.3, 0.0); vec3 new_velocity = velocity &#; accelleration * time_step; vec4 new_position = position &#; vec4(new_velocity * time_step, 0.0);//计算粒子新的速度和位置 vec3 v0, v1, v2; vec3 point; int i; for (i = 0; i < triangle_count; i&#;&#;) { //利用纹理查找tbo获取模型的三角形平面。做相交测试,如果相交在交点处计算反弹之后的新速度向量和位置 v0 = texelFetch(geometry_tbo, i * 3).xyz v1 = texelFetch(geometry_tbo, i * 3 &#; 1).xyz; v2 = texelFetch(geometry_tbo, i * 3 &#; 2).xyz; if (intersect(position.xyz, position.xyz - new_position.xyz, v0, v1, v2, point)) { vec3 n = normalize(cross(v1 - v0, v2 - v0)); new_position = vec4(point &#; reflect_vector(new_position.xyz - point, n), 1.0); new_velocity = 0.8 * reflect_vector(new_velocity, n); } } //超出一定范围,回归。 if (new_position.y < -.0) { new_position = vec4(-new_position.x * 0.3, position.y &#; .0, 0.0, 1.0); new_velocity *= vec3(0.2, 0.1, -0.3); } velocity_out = new_velocity * 0.;//几乎无衰减的速度 position_out = new_position; gl_Position = projection_matrix * (model_matrix * position); }粒子系统片元着色器:非常简单,只是设置了粒子的颜色为白色。#version layout (location = 0) out vec4 color; void main(void) { color = vec4(1.0); }模型渲染的顶点着色器和片元着色器和之前的例子没什么区别。可以再代码里面看到。或者在之前的文章中看到相关详细注释5.粒子实例运行截图粒子从模型头顶落下粒子撞击模型时被弹开Then End~~~(牢骚:愈发无聊的生活,愈发没有激情的工作,青春只是在流逝,没有痕迹)被遗忘的代码(.3.)

OpenGL画点、直线、虚线和多边形 //从这里开始进行所有的绘制intDrawGLScene(GLvoid)glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除屏幕和深度缓存glLoadIdentity();//重置当前的模型观察矩阵glColor3f(

解决使用第三方扫描二维码后返回界面出现的OpenGL error 0x 在使用Zxing第三方sdk扫描二维码扫描之后,返回游戏后台一直报OpenGLerror0x:.........然后界面显示图片完全变形或者显示不全之类的绘制问题。原来后

Tips(1)glewExperimental glewExperimental=true;//Neededforcoreprofile如不书写上一句,openGL程序运行会崩溃!

标签: opengl教程48讲

本文链接地址:https://www.jiuchutong.com/biancheng/369611.html 转载请保留说明!

上一篇:opengl 绘制简单的带纹理贴图的立方体(opengl绘制简单矩形代码)

下一篇:OpenGL画点、直线、虚线和多边形(opengl 画线)

  • 平均税额怎么算
  • 本年利润和利润分配未分配利润的区别
  • 企业的主要经营哲学理念
  • 财务报表的资产负债表怎么填
  • 销售过程中客户买的是什么
  • 企业退回企业所得税分录
  • 未及时扣除的分数怎么算
  • 专票红冲后还需重新开票吗
  • 银行漏记账会造成什么后果
  • 税收优惠退回的税金怎么入账
  • 企业采购材料没有发票是要交企业所得税吗
  • 辅助生产交互分配后的实际费用应在进行分配
  • 注销公司房产税从哪年从哪年开始交
  • 装卸费收取的税收筹划是怎样的?
  • 自来水企业应该交什么税
  • 增值税适用范围和税率
  • 向境外企业购买国内企业股权
  • 特种设备培训费计入什么会计科目
  • 已预缴税款金额可以不申请退税吗
  • 企业利润表中营业收入在资产负债表中有勾千盾关系吗
  • 房地产公司未售房产出租账务处理
  • 公司组织的团建受伤算工伤吗
  • windows4月更新
  • 员工因违反公司规章制度被辞退有补偿吗
  • 个体工商户投资金额填多少
  • 圣海伦斯山国家火山纪念区
  • 土地增值税清算收入如何确定
  • vue父组件调用子组件的方法报错
  • 免税怎么开
  • 一般纳税人企业所得税税率多少
  • 图片转base64格式返回给前端,前端如何展示?
  • 出租包装物和出售包装物有什么区别
  • python基本功
  • php判断useragent
  • 有限公司股权转让的规定最新
  • 摄像头标定方法
  • node.js deno
  • 独立的分公司可以注册吗
  • 购买员工宿舍用品报销
  • 用python写
  • 股东分红放到哪个会计科目
  • 年度一次性奖励扣税
  • 租集体土地建厂合法吗
  • 差额征税可以开专票抵扣吗
  • 货到票未到的会计分录怎么做
  • datatable怎么用
  • 个体户查账征收个人所得税税率
  • 车辆保险费用查询
  • 存款利息收入应计入收入总额吗
  • 公司购买股东的东西
  • 库存商品过期了还能用吗
  • 内部往来科目设置在哪类下
  • 建筑行业挂靠代扣税款如何入账?
  • 诉讼财产保全保函
  • 转售水电费收入确认
  • 小企业会计准则和一般企业会计准则的区别
  • 独立核算和非独立核算哪个好
  • 实缴资本在公司能查到吗
  • 报销需要发票吗?
  • 材料的运费计入哪个科目
  • 公司折旧怎么算
  • win8.1应用
  • xp系统多了explorer进程
  • 微软surface pro 3按键驱动
  • winxp怎么做系统
  • 进程lsass.exe
  • windows10 uac关闭
  • win10系统需不需要装杀毒软件
  • dos 批处理
  • cocos2dx解密
  • windows定时计划
  • unity shaders and effects cookbook
  • linux用c语言实现命令功能
  • dw中css规则定义中文
  • unity 3d教程
  • Http TCP 协议
  • 生成0-100的随机数,直到生成88为止,停止循环
  • python3使用PyMysql连接mysql数据库实例
  • unity3d功能介绍
  • 个人的房产出租征收什么税
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设