Deferred shading技术简介

2024-09-08 07:58
文章标签 技术 简介 shading deferred

本文主要是介绍Deferred shading技术简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考文章:http://blog.sina.com.cn/s/blog_458f871201017i06.html


Deferred shading是这样一种技术:将光照/渲染计算推迟到第二步进行计算。我们这样做的目的是为了避免多次(超过1次)渲染同一个像素。

基本思想如下:

1、在第一步中,我们渲染场景,但是与通常情况下应用反射模型计算片断颜色不同的是,我们只是简单的将几何信息(位置坐标,法线向量,纹理坐标,反射系数等等)存储在中间缓冲区中,这样的缓冲区我们称之为g-buffer(g是几何geometry的缩写)。

2、在第二步,我们从g-buffer中读取信息,应用反射模型,计算出每个像素的最终颜色。


Deferred shading技术的应用使得我们避免了应用反射模型于最终不可见的片断上。例如,考虑这样的像素,它位于两个多边形重叠的区域。通常的片断着色器会读对每个多边形分别计算那个像素一次;然而,两次执行的结果最终只有一个成为该像素的最终颜色(这里基于的一个假设是:混合已被禁用)。这样,其中的一次计算就是无用的。有了Deferred shading技术,反射模型的计算会推迟到所有几何体被处理之后,那时候每个像素位置几何体的可见性也是已知的。这样,对于屏幕上的每个像素,反射模型的计算只会发生一次。


Deferred shading容易懂而且便于使用。它能够帮助实施很复杂的光照/反射模型。


二、结合例子来说明Deferred shading技术

下面的例子采用Deferred shading技术渲染了一个包含一个茶壶和一个圆环的场景。效果如下:


图一 场景渲染效果图

在这个例子中,我们将位置坐标、法线以及漫反射因子存储在g-buffer里。在第二步的时候,我们使用g-buffer里面的数据来进行漫反射光照模型的计算。

g-buffer包含3个纹理:分别用来存储位置坐标、法线以及漫反射因子。对应的采用了3个uniform变量:PositionTex、NormalTex、ColorTex。

他们均被关联到一个FBO上。关于FBO使用见:FBO。


下面是创建包含g-buffer的FBO的代码:

[cpp]  view plain copy
  1. GLuint depthBuf, posTex, normTex, colorTex;  
  2.   
  3.     // Create and bind the FBO   
  4.     glGenFramebuffers(1, &deferredFBO);  
  5.     glBindFramebuffer(GL_FRAMEBUFFER, deferredFBO);  
  6.   
  7.     // The depth buffer   
  8.     glGenRenderbuffers(1, &depthBuf);  
  9.     glBindRenderbuffer(GL_RENDERBUFFER, depthBuf);  
  10.     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);  
  11.   
  12.     // The position buffer   
  13.     glActiveTexture(GL_TEXTURE0);   // Use texture unit 0   
  14.     glGenTextures(1, &posTex);  
  15.     glBindTexture(GL_TEXTURE_2D, posTex);  
  16.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);  
  17.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
  18.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  
  19.   
  20.     // The normal buffer   
  21.     glActiveTexture(GL_TEXTURE1);  
  22.     glGenTextures(1, &normTex);  
  23.     glBindTexture(GL_TEXTURE_2D, normTex);  
  24.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);  
  25.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
  26.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  
  27.   
  28.     // The color buffer   
  29.     glActiveTexture(GL_TEXTURE2);  
  30.     glGenTextures(1, &colorTex);  
  31.     glBindTexture(GL_TEXTURE_2D, colorTex);  
  32.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);  
  33.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
  34.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  
  35.   
  36.     // Attach the images to the framebuffer   
  37.     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuf);  
  38.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, posTex, 0);  
  39.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normTex, 0);  
  40.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorTex, 0);  
  41.   
  42.     GLenum drawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,  
  43.                         GL_COLOR_ATTACHMENT2};  
  44.     glDrawBuffers(4, drawBuffers);  
  45.   
  46.     glBindFramebuffer(GL_FRAMEBUFFER, 0);  
[cpp]  view plain copy
  1. GLuint depthBuf, posTex, normTex, colorTex;  
  2.   
  3.     // Create and bind the FBO  
  4.     glGenFramebuffers(1, &deferredFBO);  
  5.     glBindFramebuffer(GL_FRAMEBUFFER, deferredFBO);  
  6.   
  7.     // The depth buffer  
  8.     glGenRenderbuffers(1, &depthBuf);  
  9.     glBindRenderbuffer(GL_RENDERBUFFER, depthBuf);  
  10.     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);  
  11.   
  12.     // The position buffer  
  13.     glActiveTexture(GL_TEXTURE0);   // Use texture unit 0  
  14.     glGenTextures(1, &posTex);  
  15.     glBindTexture(GL_TEXTURE_2D, posTex);  
  16.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);  
  17.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
  18.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  
  19.   
  20.     // The normal buffer  
  21.     glActiveTexture(GL_TEXTURE1);  
  22.     glGenTextures(1, &normTex);  
  23.     glBindTexture(GL_TEXTURE_2D, normTex);  
  24.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);  
  25.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
  26.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  
  27.   
  28.     // The color buffer  
  29.     glActiveTexture(GL_TEXTURE2);  
  30.     glGenTextures(1, &colorTex);  
  31.     glBindTexture(GL_TEXTURE_2D, colorTex);  
  32.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);  
  33.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
  34.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  
  35.   
  36.     // Attach the images to the framebuffer  
  37.     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuf);  
  38.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, posTex, 0);  
  39.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normTex, 0);  
  40.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorTex, 0);  
  41.   
  42.     GLenum drawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,  
  43.                         GL_COLOR_ATTACHMENT2};  
  44.     glDrawBuffers(4, drawBuffers);  
  45.   
  46.     glBindFramebuffer(GL_FRAMEBUFFER, 0);  
注意:三个纹理分别使用函数glFramebufferTexture2D()关联到FBO的颜色关联点0、1、2上面。接着调用函数glDrawBuffers把它们和片断着色器的输出变量联系起来。

函数glDrawBuffer指示了FBO成员和片断着色器输出变量之间的联系。FBO中的第i个成员对应片断着色器中的索引为i的输出变量。这样,片断着色器(下面列出了完整代码)中相对应的输出变量分别是PosiutionData,NormalData和ColorData。


顶点着色器实现了一个很简单的功能:将位置坐标和法线转化到eye sapce中,然后传递到片断着色器中。而纹理坐标则没有发生变化。


片断着色器如下:

[cpp]  view plain copy
  1. #version 400   
  2.   
  3. struct LightInfo {  
  4.   vec4 Position;  // Light position in eye coords.   
  5.   vec3 Intensity; // A,D,S intensity   
  6. };  
  7. uniform LightInfo Light;  
  8.   
  9. struct MaterialInfo {  
  10.   vec3 Kd;            // Diffuse reflectivity   
  11. };  
  12. uniform MaterialInfo Material;  
  13.   
  14. subroutine void RenderPassType();  
  15. subroutine uniform RenderPassType RenderPass;  
  16.   
  17. uniform sampler2D PositionTex, NormalTex, ColorTex;  
  18.   
  19. in vec3 Position;  
  20. in vec3 Normal;  
  21. in vec2 TexCoord;  
  22.   
  23. layout (location = 0) out vec4 FragColor;  
  24. layout (location = 1) out vec3 PositionData;  
  25. layout (location = 2) out vec3 NormalData;  
  26. layout (location = 3) out vec3 ColorData;  
  27.   
  28. vec3 diffuseModel( vec3 pos, vec3 norm, vec3 diff )  
  29. {  
  30.     vec3 s = normalize(vec3(Light.Position) - pos);  
  31.     float sDotN = max( dot(s,norm), 0.0 );  
  32.     vec3 diffuse = Light.Intensity * diff * sDotN;  
  33.   
  34.     return diffuse;  
  35. }  
  36.   
  37. subroutine (RenderPassType)  
  38. void pass1()  
  39. {  
  40.     // Store position, normal, and diffuse color in textures   
  41.     PositionData = Position;  
  42.     NormalData = Normal;  
  43.     ColorData = Material.Kd;  
  44. }  
  45.   
  46. subroutine(RenderPassType)  
  47. void pass2()  
  48. {  
  49.     // Retrieve position and normal information from textures   
  50.     vec3 pos = vec3( texture( PositionTex, TexCoord ) );  
  51.     vec3 norm = vec3( texture( NormalTex, TexCoord ) );  
  52.     vec3 diffColor = vec3( texture(ColorTex, TexCoord) );  
  53.   
  54.     FragColor = vec4( diffuseModel(pos,norm,diffColor), 1.0 );  
  55. }  
  56.   
  57. void main() {  
  58.     // This will call either pass1 or pass2   
  59.     RenderPass();  
  60. }  
[cpp]  view plain copy
  1. #version 400  
  2.   
  3. struct LightInfo {  
  4.   vec4 Position;  // Light position in eye coords.  
  5.   vec3 Intensity; // A,D,S intensity  
  6. };  
  7. uniform LightInfo Light;  
  8.   
  9. struct MaterialInfo {  
  10.   vec3 Kd;            // Diffuse reflectivity  
  11. };  
  12. uniform MaterialInfo Material;  
  13.   
  14. subroutine void RenderPassType();  
  15. subroutine uniform RenderPassType RenderPass;  
  16.   
  17. uniform sampler2D PositionTex, NormalTex, ColorTex;  
  18.   
  19. in vec3 Position;  
  20. in vec3 Normal;  
  21. in vec2 TexCoord;  
  22.   
  23. layout (location = 0) out vec4 FragColor;  
  24. layout (location = 1) out vec3 PositionData;  
  25. layout (location = 2) out vec3 NormalData;  
  26. layout (location = 3) out vec3 ColorData;  
  27.   
  28. vec3 diffuseModel( vec3 pos, vec3 norm, vec3 diff )  
  29. {  
  30.     vec3 s = normalize(vec3(Light.Position) - pos);  
  31.     float sDotN = max( dot(s,norm), 0.0 );  
  32.     vec3 diffuse = Light.Intensity * diff * sDotN;  
  33.   
  34.     return diffuse;  
  35. }  
  36.   
  37. subroutine (RenderPassType)  
  38. void pass1()  
  39. {  
  40.     // Store position, normal, and diffuse color in textures  
  41.     PositionData = Position;  
  42.     NormalData = Normal;  
  43.     ColorData = Material.Kd;  
  44. }  
  45.   
  46. subroutine(RenderPassType)  
  47. void pass2()  
  48. {  
  49.     // Retrieve position and normal information from textures  
  50.     vec3 pos = vec3( texture( PositionTex, TexCoord ) );  
  51.     vec3 norm = vec3( texture( NormalTex, TexCoord ) );  
  52.     vec3 diffColor = vec3( texture(ColorTex, TexCoord) );  
  53.   
  54.     FragColor = vec4( diffuseModel(pos,norm,diffColor), 1.0 );  
  55. }  
  56.   
  57. void main() {  
  58.     // This will call either pass1 or pass2  
  59.     RenderPass();  
  60. }  

片断着色器则包含了关于光源、材料的一些信息,都是uniform变量,以用于光照计算。

片断着色器里面使用了subroutine技术,实现了两个函数pass1和pass2,分别包含了第一步和第二步的操作。我们在OpenGL应用程序中通过设置uniform变量的值可以选择使用相应的功能。


在OpenGL应用程序里面,

实施第一步的步骤如下:

1、绑定FBO;

2、情况颜色以及深度缓冲区,选择pass1 subroutine函数,启用深度测试;

3、渲染场景。


实施第二步的步骤是:

1、去除FBO绑定(将其绑定到0),目的是能够渲染场景到默认缓冲区,而不是FBO里面,它就能显示到屏幕上;

2、清除颜色缓冲去对象。禁用深度测试;

3、选择pass2 subroutine函数,渲染一个充满屏幕的四边形,带有纹理坐标,每个方向的纹理坐标的范围都是从0到1.计算光照模型,得出最后的片断颜色。


三、如何选择使用Deferred shading技术

在图形学领域,关于Deferred shading技术的优点和缺陷备受争议。这种技术并不适用所有的场合,它取决于你的应用程序的需求。因此在觉得是否采用这个技术之前一定要权衡它带来的优点和缺陷。

Deferred shading技术带来一个很重要的缺点就是不能使用基于硬件实现的多重采样抗锯齿功能。因为渲染过程发生在第二步,所以我们在第二步需要多个样本。但是,在第二步我们只有每一个像素的一个样本。

另外一个缺点就是不能使用混合技术。


参考资料:

《GPU Gems 2》的第9章

《GPU Gems 3》的第19章

这篇关于Deferred shading技术简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147558

相关文章

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

金融业开源技术 术语

金融业开源技术  术语 1  范围 本文件界定了金融业开源技术的常用术语。 本文件适用于金融业中涉及开源技术的相关标准及规范性文件制定和信息沟通等活动。

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

业务协同平台--简介

一、使用场景         1.多个系统统一在业务协同平台定义协同策略,由业务协同平台代替人工完成一系列的单据录入         2.同时业务协同平台将执行任务推送给pda、pad等执行终端,通知各人员、设备进行作业执行         3.作业过程中,可设置完成时间预警、作业节点通知,时刻了解作业进程         4.做完再给你做过程分析,给出优化建议         就问你这一套下

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

系统架构设计师: 信息安全技术

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 系统架构设计师: 信息安全技术前言信息安全的基本要素:信息安全的范围:安全措施的目标:访问控制技术要素:访问控制包括:等保

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

前端技术(七)——less 教程

一、less简介 1. less是什么? less是一种动态样式语言,属于css预处理器的范畴,它扩展了CSS语言,增加了变量、Mixin、函数等特性,使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 ,也可以借助Node.js在服务端运行。 less的中文官网:https://lesscss.cn/ 2. less编译工具 koala 官网 http://koala-app.

【Tools】AutoML简介

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 AutoML(自动机器学习)是一种使用机器学习技术来自动化机器学习任务的方法。在大模型中的AutoML是指在大型数据集上使用自动化机器学习技术进行模型训练和优化。

Spring的设计⽬标——《Spring技术内幕》

读《Spring技术内幕》第二版,计文柯著。 如果我们要简要地描述Spring的设计⽬标,可以这么说,Spring为开发者提供的是⼀个⼀站式的轻量级应⽤开发框架(平台)。 作为平台,Spring抽象了我们在 许多应⽤开发中遇到的共性问题;同时,作为⼀个轻量级的应⽤开发框架,Spring和传统的J2EE开发相⽐,有其⾃⾝的特点。 通过这些⾃⾝的特点,Spring充分体现了它的设计理念:在