OpenGL3.3_C++_Windows(24)

渲染平行光阴影

阴影作用:

  • 有了阴影的渲染,更容易地区分出物体之间的位置关系,
  • 如何判断片段是否在阴影中?

普通思路:

  • 以光的位置为视角进行渲染,我们绘制一条从光源出发的射线,测试更新射线经过的所有片段,与当前min最近片段比较,如果更远,就在阴影中

弊端:

  • 射线上的成千上万个点进行遍历是个极端消耗性能,所以换种思路,利用深度缓冲

深度缓冲:

  • 深度缓冲大小符合窗口的宽高,当运行深度测试时,每个像素的深度值和已经存储在这个像素的深度值(深度缓冲)进行比较,根据深度测试函数,决定片段是否丢弃

深度/阴影/shadow Mapping贴图

  • 从光源的透视图 来渲染场景,并把深度值的结果储存到纹理中,深度值因为会不断测试更新,最后的结果,就是最近的片段的深度值,通过纹理坐标,可以对它进行采样,获取深度值

T变换

  • 来自光源的视图投影矩阵,可以将任何三维位置(从世界坐标)转变到光源的可见坐标空间

如何利用深度贴图判断片段是否在阴影中?

  • 首先T变换 到光源的坐标空间里,使用生成的深度贴图计算片段是否在阴影之中,z深度 如果 > 片段的深度缓冲的深度值,则在阴影中

运算:

创建新的帧缓冲

  • 因为要对深度值采样,所以应存储在纹理附件(非渲染缓冲对象附件),应用的纹理格式为GL_DEPTH_COMPONENT,
  • 注意:不包含颜色缓冲的帧缓冲对象是不完整的,所以我们需要显式告诉OpenGL我们不适用任何颜色数据进行渲染。glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE);

平行光源空间的T变换矩阵

  • LookAt()计算光(位置+看的方向)的view矩阵(实质,将物体坐标变换到相机坐标的视角下),

  • 如果使用一个所有光线都平行的定向光,使用正交投影矩阵,否则点光源和聚光灯,使用透视投影矩阵(因为投影矩阵实质,是决定可见的范围,以及范围的形状,光空间的范围,即光线的散射组成的范围,被光覆盖的范围)

渲染到深度贴图

  • 启用帧缓冲,渲染场景,使用的新glsl中,将每个顶点变换到光空间,从而深度值保存到了深度纹理附件中,fragment什么都不用做,我们只需要深度缓冲(默认更新),也可以手动设置gl_FragDepth = gl_FragCoord.z;

//深度缓冲视觉化

  • 这次渲染quad,并应用深度纹理附件作为quad 的纹理。
  • 但是注意:正交不受深度值影响,透视投影矩阵,当深度缓冲视觉化经常会得到一个几乎全白的结果,深度变成了非线性的深度值,只有距离很近,颜色亮度才会骤降。
  • 解决方案就是变为线性深度值。

深度缓冲视觉化

渲染阴影:Fragment glsl

  • 将要产生阴影的物体,在vs中将世界空间顶点位置转换为光空间,传入fs,计算出一个shadow值,当fragment在阴影中时是1.0,在阴影外是0.0
  • 将(1 - shadow )* 其他冯氏颜色分量(由于当shadow = 1的时候(在阴影),结果颜色为0),由于阴影不会是全黑的,把ambient分量从乘法中剔除。
  • 这样保证,当片断位于阴影,结果为ambient * 其他冯氏颜色分量,当非阴影 = ((ambient + 1 * 其他冯氏颜色分量

计算阴影():

  • 光空间的片段位置(被判断的像素)和第一个渲染阶段得到的深度贴图(取深度值)
    • 光空间片段位置转换为裁切空间的标准化设备坐标。
    • 当运行到gl_Position时,OpenGL自动进行一个透视除法,x、y、z元素除以向量的w元素来实现,我们必须自己做透视除法
    • 因为来自深度贴图的深度在0到1的范围,我们再次将NDC坐标变换为0到1的范围
    • 从深度贴图,采样片段坐标,对应的深度值,如果片段的z高于采样的深度值,则表明片段在阴影中,返回1,否则返回0
相关推荐
啦啦啦啦啦zzzz2 小时前
设计模式:原型模式
c++·设计模式·原型模式
小保CPP2 小时前
OpenCV C++基于CNN模型的场景文本检测(OCR)
c++·人工智能·opencv·计算机视觉·cnn·ocr·光学字符识别
郝学胜-神的一滴2 小时前
Qt 高级编程 037:QSS按钮样式封神指南
开发语言·c++·qt·软件工程·用户界面
霍霍的袁3 小时前
【C++】string类 从 入门使用 到 底层深浅拷贝模拟实现
开发语言·c++·visual studio
noipp4 小时前
推荐题目:洛谷 P3726 [AHOI2017/HNOI2017] 抛硬币
c语言·数据结构·c++·算法·编程·洛谷·luogu
c238564 小时前
C/C++每日一练14
c语言·c++·算法
影视飓风TIM4 小时前
C++ STL 完整入门笔记[8]:deque 底层原理深度剖析
开发语言·c++·笔记
zmzb01034 小时前
C++课后习题训练记录Day176
开发语言·c++
qz5zwangzihan15 小时前
题解:Atcoder Beginner Contest abc469 F - GCD Maximum Spanning Tree
c++·图论·kruskal·并查集·atcoder·abc469·abc469_f
王维同学5 小时前
跨位数进程的映像、命令行与环境块读取
c++·windows·安全