ImageVerifierCode 换一换
格式:DOC , 页数:12 ,大小:289KB ,
资源ID:8051493      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/8051493.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(建立高动态范围(HDR)渲染器.doc)为本站上传会员【s4****5z】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

建立高动态范围(HDR)渲染器.doc

1、建立高动态范围(HDR)渲染器 HDR简介       这篇教程讲解了如何实现一个HDR渲染系统。HDR(High Dynamic Range,高动态范围)是一种图像后处理技术,是一种表达超过了显示器所能表现的亮度范围的图像映射技术。高动态范围技术能够很好地再现现实生活中丰富的亮度级别,产生逼真的效果。HDR已成为目前游戏应用不可或缺的一部分。通常,显示器能够显示R、G、B分量在[0,255]之间的像素值。而256个不同的亮度级别显然不能表示自然界中光线的亮度情况。比如,太阳的亮度可能是一个白炽灯亮度的几千倍,是一个被白炽灯照亮的桌面的亮度的几十万倍,这远远超出了显示器的亮度表示能力

2、如何在有限的亮度范围内显示如此宽广的亮度范围,正式HDR技术所要解决的问题。     将一个宽广的亮度范围映射到纸张或屏幕能表示的亮度范围类似于照相机的曝光功能。人眼也有类似的功能。通过照相机的光圈,可以控制进入感光器的光线数量,感光器得到的明暗程度经过一定的处理,就可以得到令人信服的照片。照相机是一个典型的从高动态范围映射到低动态范围的例子。如果我们能够在一定程度上模拟照相机的工作原理,就可以在屏幕上显示高动态范围的图像。对于人眼或镜头,过亮的光线射入时会产生光晕效果,这一点也可以通过一些方法模拟。动态曝光控制和光晕效果结合起来,就构成了一个经典的高动态范围渲染器。 一个运行中的H

3、DR渲染器,背景墙由于过亮而产生了光晕 这组图像演示了动态曝光技术,图为从黑暗的隧道走向明亮的房间的一个过程,可以看到动态光线适应的过程:房间从全白色过渡到正常曝光颜色     下面将结合OpenGL详细地介绍HDR的实现过程。其他图形API在方法上是一致的,只是具体的实现细节略有差异。   HDR技术原理       我们已经知道,HDR渲染包含两个步骤,一是曝光控制,即将高动态范围的图像映射到一个固定的低范围中,既屏幕能够显示的(0,1)的范围内。二是对于特别亮的部分实现光晕的效果。其中曝光控制是HDR渲染的核心环节,光晕效果对表现高亮的像素起了重要的作用。这里先分别介

4、绍两个步骤的原理和方法,再介绍如何实现一个完整的HDR渲染器。     在所有步骤开始之前,你必须已经通过某种方法得到了一个高动态范围的图像。高动态范围的图像每一个像素都由浮点型的R,G,B分量表示,这样每个分量都可以任意大。对于渲染器而言,这意味着一个浮点纹理。那么,如何将一个场景渲染到一个高动态范围的浮点纹理中呢?你可以为场景中的每个表面创建一张浮点格式的光照贴图,这张光照贴图的每个象素代表了表面上相应位置的光强。然后使用OpenGL的FBO(帧缓冲对象)将绑定了浮点光照贴图的场景渲染到一个同屏幕大小一致的浮点纹理中。关于FBO和浮点纹理的使用请参考《OpenGL中的浮点纹理和帧缓冲对象

5、》 。     好的,先来看看所谓得、的曝光控制。这个步骤在HDR渲染中被称为Tone Mapping。翻译成中文即“调和映射”。Tone Mapping有很多具体的方法,每个方法都是一个从高动态范围到低范围的一个映射,我们把这些方法统称为 Tone Mapping Operator(TMO),可见,TMO的好坏直接决定了图像的最终质量。例如,     是一个简单的TMO,其中Lfinal是映射后的像素亮度值,L是映射前的像素亮度值,alpha是图像中的最小亮度值,beta是图像中的最大亮度值。     又如:  -- (1)       也是一个简单的TMO。这两个TMO

6、都可以将高动态的像素值映射到(0,1)上。然而,这些TMO的效果并不令人满意。人的眼睛往往能适应场景中的光的强度,在一个黑暗的屋子里,你仍然能看见其中的东西,分辨物体的亮度和颜色,当你从屋子中突然走向明亮的室外时,会有刺眼的感觉,但很快眼睛优惠适应新的环境,从而能够看清更亮的场景。为了模拟人眼的这种特性,我们需要计算当前要渲染的高动态范围图像的平均亮度,然后根据平均亮度确定一个曝光参数,然后使用这个曝光参数将图像正确地映射到屏幕能现实的颜色区域内。这里介绍DirectX 9.0 SDK中所介绍的方法。假设Lumave(稍后介绍)为计算得到的原始图像平均亮度,那么对于原始图像中的任一像素点Lum

7、x,y),有下面的映射关系:     其中,Lscaled为映射后的值,alpha为一个常数,alpha的大小决定了映射后场景的整体明暗程度,可以根据需要适当调整,这个值在以后的实现中称为Key值。经过这样的映射后,Lscaled并不一定处在(0,1)的范围中,我们再结合(1)式,使最终的像素值处在(0,1)上:       这样就完成了最终的映射。 现在讨论如何计算原始图像的平均亮度。平均亮度的计算由下面的公式给出:     上式中,δ是一个较小的常数,用于防止求对数的计算结果趋于负无穷的情况。如δ可取0.0001。这个式子的意义是,对于原始图像每个像素,计算出该像素

8、的亮度值Lum(x,y),然后求出该亮度值的自然对数。接着对所有像素亮度值的对数求平均值,再求平均值的自然指数值。至于为什么这样算出的值能够合理地表示图像的平均亮度,这里就不再详细说明了,有兴趣可以参看相关论文[1]。     那么,对于一个像素P(r,g,b),如何计算像素的亮度Lum呢?其计算公式为:    这些RGB分量的权重是根据人眼对不同光的敏感程度得到的。以上是Tone Mapping的基本理论。可能你还未能完全理解某些细节,但没有关系,在后面的具体实现过程中,将会讲解具体的实现方法。     现在再看一下光晕效果是如何实现的。所谓光晕效果,就是抽出场景中色彩比较亮

9、的部分,然后加以模糊,使这些较量的像素扩散到周边像素中,再把模糊后的图像叠加在Tone Mapping之后的图像上。其过程如下图所示。 Tone Mapping之后的图像 取出原始图像中较亮的部分,并缩小其尺寸 进行模糊 将模糊后的图像拉伸叠加到Tone Mapping之后的图像上   实现过程       本文仅详细介绍如何对渲染得到的高动态范围浮点纹理进行高动态范围后处理的过程,不关注场景的渲染过程。我们把渲染器的工作分为以下几个函数:     BeginRendering(); 这个函数在一切场景绘制操作被调用之前执行。它负责准备FBO对象,初

10、始化一个渲染到浮点纹理的渲染环境。     EndRendering(); 这个函数在场景绘制操作结束后执行,它负责处理FBO中已得到的高动态范围数据,并映射到低范围中,并将最终结果显示在屏幕上。     PostProcess(); 这个函数被EndRendering()调用,它负责HDR处理的全过程。     MeasureLuminance();这个函数用于计算图像的平均亮度值。     此外,我们假定有一个CGPUImage类,它创建并维护一个浮点格式的纹理。CImageBlurFilter负责模糊一个图像。CImageScaleCopy负责把一个浮点纹理中的数据缩小尺

11、寸后复制到另一个纹理中去。     下面看一下HDR处理的大致流程: 1.初始化操作。创建一个和屏幕同样大小的浮点纹理texColor,创建FBO对象stdfbo,创建一个为屏幕1/4大小的浮点纹理texBloom,创建一个32*32大小的浮点纹理imgLumSample。此操作在应用程序初始化阶段执行一次。 2.渲染前操作。将texColor绑定到stdfbo对象中,并应用stdfbo对象。 3.渲染场景。像往常一样渲染场景,只不过场景中的贴图、光照可以为浮点数,并且会向缓冲区(texColor)中写入浮点型的数据。 4.渲染后操作。 (1)将texBloom绑定到stdfb

12、o对象,然后以texColor为纹理,渲染一个为屏幕1/4大小的矩形,这样texBloom便成为texColor的1/4大小的副本。 (2)把texBloom绑定到stdfbo对象,然后以imgLumSample为纹理,渲染一个32*32大小的正方形,并使用一个shader对每个象素取对数。这样imgLumSample成为texColor的更小尺寸的取了对数后副本。 (3)把imgLumSample的数据回读到系统内存,然后计算出平均亮度。(如果你觉得回读是一个很慢的操作,也可以在GPU上继续执行下采样操作,直到纹理大小缩小到1*1,那么这个像素的值取值数就代表了平均亮度。而经过我的试验,

13、这样做的效率会比回读更加低下。) (4)步骤(3)执行后,imgLumSample中的数据就没有作用了,但接下来可以把texBloom下采样到imgLumSample中,在下采样的过程中只选取高亮度的像素。再对imgLumSample进行模糊,这样imgLumSample就成为了texBloom的更小尺寸高亮度部分的副本。 (5)对imgLumSample运用高斯模糊。这一步也是通过shader实现的。 (6)禁用FBO对象,接下来对屏幕输出最后渲染结果。绑定Tone Mapping Shader,在Shader中根据计算出来的平均亮度值对texColor进行Tone Mapping,T

14、one Mapping之后的结果和imgLumSample叠加后输出到屏幕上。     另外,人眼对光线变化有一个适应过程,为了模拟这个过程,我们可以维护另一个浮点类型的变量LumAdapt,存储当前人眼已经适应的亮度值。在每一帧计算出当前帧的平均亮度LumAve后,让LumAdapt慢慢向LumAve逼进。使用下面的代码完成这一点:     lumAdapt += (lum - lumAdapt) * ( 1 - pow( 0.98f, 30 * dTime ) );     其中,lum是当前场景的平均亮度,dTime是自从上一帧到现在所经过的时间。     接下来,我们仔细研究一

15、下后处理的具体代码。 浏览器不支持嵌入式框架,或被配置为不显示嵌入式框架。     下面给出上面代码涉及到的Shader程序。Shader程序的组成如下: 程序对象 Vertex Shader Fragment Shader 作用 progBloom Common.vs Bloom.fs 提取场景中的高亮部分 progDownSample8 Common.vs DownSample8.fs 将输入图像下采样到1/8大小 progTone Common.vs Tone.fs Tone Mapping并负责整合Bloom map产生最终结果输出到屏幕上 pro

16、gLogSample Common.vs LogSample.fs 对输入图像进行下采样,并取对数值 progBlurX Common.vs BlurX.fs 在X方向上对图像进行高斯模糊 progBlurY Common.vs BlurY.fs 在Y方向上对图像进行高斯模糊 progScaleCopy Common.vs ScaleCopy.fs 下采样原图像到1/4大小     所有shader程序共用同一个Vertex Shader,这个Vertex Shader非常简单,就是传递顶点位置和纹理坐标到后面的管线。因为所有的操作都是在Fragment Sha

17、der里面完成的。 Common.vs: void main() {      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;      gl_TexCoord[0] = gl_MultiTexCoord0; } 1/4无损下采样 //ScaleCopy.fs 用于下采样图象到1/4大小 #version 110 #extension GL_ARB_draw_buffers : enable uniform sampler2D texSrc; uniform int imgW,imgH; void m

18、ain() {     float dx = 1.0/float(imgW);     float dy = 1.0/float(imgH);     vec4 color = texture2D(texSrc,gl_TexCoord[0].xy);     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx,0.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*2.0,0.0));     color += texture2D(texSrc,gl_TexC

19、oord[0].xy+vec2(dx*3.0,0.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,dy));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx,dy));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*2.0,dy));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*3.0,dy));    

20、color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,dy*2.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx,dy*2.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*2.0,dy*2.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*3.0,dy*2.0));     color += texture2D(te

21、xSrc,gl_TexCoord[0].xy+vec2(0.0,dy*3.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx,dy*3.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*2.0,dy*3.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*3.0,dy*3.0));     color /= 16.0;     gl_FragData[0] = color

22、 } 1/8有损下采样 //DownSample8.htm 下采样到1/8大小,可能丢失细节。 #version 110 #extension GL_ARB_draw_buffers : enable uniform sampler2D texSrc; uniform int imgH,imgW; void main() {     float dx = 1.0/float(imgW);     float dy = 1.0/float(imgH);     vec4 color = texture2D(texSrc,gl_TexCoord[0].xy);

23、    color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*2.0,0.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*4.0,0.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*6.0,0.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,dy*2.0));     color += texture2D(tex

24、Src,gl_TexCoord[0].xy+vec2(dx*2.0,dy*2.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*4.0,dy*2.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*6.0,dy*2.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,dy*4.0));     color += texture2D(texSrc,gl_TexCoord[0

25、].xy+vec2(dx*2.0,dy*4.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*4.0,dy*4.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*6.0,dy*4.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,dy*6.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*2.0,

26、dy*6.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*4.0,dy*6.0));     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(dx*6.0,dy*6.0));     color /= 16.0;     gl_FragData[0] = color; } 对数采样: //LogSample.fs 用于对原始图像进行采样,并对计算采样后像素的亮度,然后再对亮度取对数后输出。 #version 120 #extension GL_ARB

27、draw_buffers : enable uniform sampler2D texSrc; void main() {     vec4 lumfact = vec4(0.27,0.67,0.06,0.0);     vec4 color = texture2D(texSrc,gl_TexCoord[0].xy);     float lum = log(dot(color , lumfact) + 0.0001);     gl_FragData[0] = vec4(lum,lum,lum,1.0); } 高斯模糊: //高斯模糊在X轴和Y轴上各做一次

28、共需要两个pass // 在X轴上的高斯模糊 #version 110 #extension GL_ARB_draw_buffers : enable uniform sampler2D texSrc; uniform int imgW; void main() {     float d = 1.0/float(imgW);     vec4 color = vec4(0.0,0.0,0.0,0.0);     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(-5.0*d,0.0)) * 0.1;     co

29、lor += texture2D(texSrc,gl_TexCoord[0].xy+vec2(-4.0*d,0.0)) * 0.22;     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(-3.0*d,0.0)) * 0.358;     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(-2.0*d,0.0)) * 0.523;     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2(-1.0*d,0.0)) * 0.843;    

30、 color += texture2D(texSrc,gl_TexCoord[0].xy ) * 1.0;     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2( 1.0*d,0.0)) * 0.843;     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2( 2.0*d,0.0)) * 0.523;     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2( 3.0*d,0.0)) * 0.358;     color += text

31、ure2D(texSrc,gl_TexCoord[0].xy+vec2( 4.0*d,0.0)) * 0.22;     color += texture2D(texSrc,gl_TexCoord[0].xy+vec2( 5.0*d,0.0)) * 0.1;     color /= 5.0;     gl_FragData[0] = color; } //在Y轴上的高斯模糊。原理相同 #version 110 #extension GL_ARB_draw_buffers : enable uniform sampler2D texSrc; uniform int im

32、gH; void main() { float d = 1.0/float(imgH); vec4 color = vec4(0.0,0.0,0.0,0.0); color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,-5.0*d)) * 0.1; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,-4.0*d)) * 0.22; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.

33、0,-3.0*d)) * 0.358; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,-2.0*d)) * 0.563; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0,-1.0*d)) * 0.873; color +=     texture2D(texSrc,gl_TexCoord[0].xy      ) * 1.0; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0, 1

34、0*d)) * 0.873; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0, 2.0*d)) * 0.563; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0, 3.0*d)) * 0.358; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2(0.0, 4.0*d)) * 0.22; color +=     texture2D(texSrc,gl_TexCoord[0].xy+vec2

35、0.0, 5.0*d)) * 0.1; color /= 5.0; gl_FragData[0] = color; }   产生Bloom map(即抽出高亮部分) //Bloom.fs 产生Bloom贴图 #version 110 #extension GL_ARB_draw_buffers : enable uniform sampler2D texColor; uniform float AveLum; uniform int imgH,imgW; void main() { float dx = 1.0/float(imgW); floa

36、t dy = 1.0/float(imgH); //对texColor进行采样 vec4 color = texture2D(texColor,gl_TexCoord[0].xy); color += texture2D(texColor,gl_TexCoord[0].xy+vec2(dx*3.0,0.0)); color += texture2D(texColor,gl_TexCoord[0].xy+vec2(0.0,dy)); color += texture2D(texColor,gl_TexCoord[0].xy+vec2(dx*3.0,dy)); co

37、lor += texture2D(texColor,gl_TexCoord[0].xy+vec2(0.0,dy*2.0)); color += texture2D(texColor,gl_TexCoord[0].xy+vec2(dx*3.0,dy*2.0)); color += texture2D(texColor,gl_TexCoord[0].xy+vec2(0.0,dy*3.0)); color += texture2D(texColor,gl_TexCoord[0].xy+vec2(dx*3.0,dy*3.0)); color /= 8.0; //计算该像素在To

38、ne Mapping之后的亮度值,如果依然很大,则该像素将产生光晕 vec4 cout = vec4(0.0,0.0,0.0,0.0); float lum = color.x * 0.3 + color.y *0.59 + color.z * 0.11; vec4 p = color*(lum/AveLum); p /= vec4(vec4(1.0,1.0,1.0,0.0)+p); float luml = (p.x+p.y+p.z)/3.0; if (luml > 0.8) { cout = p; } gl_FragData[0] = cout;

39、 } Tone Mapping 和输出 //Tone.fs uniform sampler2D texSrc; uniform sampler2D texBloom; uniform float AveLum; uniform float Key; const vec4 lumfact = vec4(0.27,0.67,0.06,0.0); void main() {     vec4 color = texture2D(texSrc,gl_TexCoord[0].xy);     float lum = dot(color , lumfact);     c

40、olor *= Key *lum/AveLum;     color /= vec4(vec4(1.0,1.0,1.0,0.0)+color);     gl_FragColor = clamp(color + texture2D(texBloom,gl_TexCoord[0].xy)*1.3, 0.0,1.0); }   补充:修改后的算法详细流程    在写完本文后,我发现原有算法有些不足之处,在texColor下采样到texLumSample的过程中损失过大,导致光晕的形状不能得到很好的重现,且当高亮区域较小时会导致光晕完全消失,同时光晕还有抖动现象。近来也有一些朋友对算法的

41、部分细节不太理解,这里我将把算法流程详细地说清楚。     初始化操作。创建以下浮点纹理(GL_RGBA16F_ARB):texColor(屏幕大小),img64(大小为64*64),img16(大小为16*16,后面的名称依此类推),img4,img1,imgHalf(屏幕1/2大小),imgQuarter(屏幕1/4大小),imgEighth(屏幕1/8大小)。     渲染操作。将场景渲染到texColor。     HDR后处理操作: 1.每隔几帧(如10帧)执行以下操作 (1)将texColor下采样到imgQuater。 (2)绑定LogSample.fs着色器(上文介

42、绍),然后把imgQuater渲染到img64,这样img64存储imgQuater的对数亮度值 (3)把img64下采样到img16,再把img16下采样到img4,再把img4采样到img1,此时img1即场景的对数平均亮度值 (4)把img1的像素值读回主内存,对读回的数据执行exp()操作后得到场景的平均亮度,并计算曝光适应后的已适应亮度lumAdapted(这一步会导致速度下降,但通过改进算法完全可以直接在GPU上完成曝光适应过程,这样就可以省去回读操作) 2.绑定Bloom.fs着色器,抽出texColor中的高亮部分,并下采样到imgHalf中。 3.把imgHalf下采

43、样到imgQuater,再把imgQuater下采样到imgEighth。 4.对imgEighth进行高斯模糊(依次使用BlurX.fs,BlurY.fs着色器)。 5.绑定Tone.fs着色器,对texColor进行Tone Mapping,映射之后的值和imgEighth(也即Bloom Map)的相应的值相加后输出到屏幕帧缓冲。 整个过程就是这样,如果还有不明白的地方,欢迎和我交流。(推荐使用留言板,这样可以更好地同他人共享) 参考文献   [1] Reinhard, Erik, Mike Stark, Peter Shirley, and James Ferwerda. "Photographic Tone Reproduction for Digital Images" . ACM Transactions on Graphics (TOG), Proceedings of the 29th Annual Conference on Computer Graphics and Interactive Techniques (SIGGRAPH), pp. 267-276. New York, NY: ACM Press, 2002. [2] "HDR Lighting sample" in DirectX 9.0c SDK

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服