| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> GAMES202作业1-实现过程详细步骤 -> 正文阅读 |
|
[游戏开发]GAMES202作业1-实现过程详细步骤 |
目录 均匀圆盘采样?Stride=20, NUM_SAMPLES=100 泊松圆盘采样?Stride=20, NUM_SAMPLES=100 EPS=1e-2,?NUM_SAMPLES=80, Stride=10 ?EPS=1e-3,?NUM_SAMPLES=80, Stride=10
查看初始模型首先打开查看一下初始模型:? 很好!可以打开!另外,我最开始是直接从VS Code右键选择index.html进入的页面,会出现打开界面但不显示模型的情况,只有一个202,F12也没有任何报错,然后多刷新几次又行了: 保险起见每次从终端进入就行。 Shadow Map要求1 CalcLightMVP()了解1-该方法如何参与到后续的环节需要补全这个函数以得到光源方向的lightMVP,这个CalcLightMVP()方法通过以下途径参与到后面的环节中:
在PhongMaterial中进行
在ShadowMaterial中进行
还需要知道的一点,传入的transform和scale是在engine中定义好的:
了解2-WebGL中glMatrix的使用要想实现MVP变换矩阵,现在我们就不用像101一样自己写出变换矩阵了,借助WebGL的API就行! 还记得我们再index.html中从lib中加入了文件gl-matrix-min:
这就是加入了js用于矩阵处理的库glMatrix,可以用它来实现MVP矩阵以创建camera和model、view、projection变换的操作。 我们需要了解都有哪些跟矩阵相关的API,这些操作相关的我会在代码中给一点点注释,这里推荐我了解glMatrix参考的博客: glMatrix — WebGL — Den's Website (dens.website) WebGL学习06-投影,视图和模型矩阵 - 掘金 (juejin.cn) 学习WebGL之变换矩阵 - 简书 (jianshu.com) 补充代码(截图)以上是了解CalcLightMVP()做的准备,下面是我分别对方法每一步实现做的注释:
useShadowMap()参数传入1 -> shadowMap
main()调用它时传入的参数为
其中?
这里出现了新的关键字sampler2D,这是WeblGL在处理图片纹理时会声明的一个变量,它跟vec、float一样也表示一种数据类型,它表示的是一种取样器变量,从对应的纹理图片中提取像素值。 关于这个type为什么是texture?这个type其实是模型绘制入口MeshRender.js中为了绑定材质中参数所创建的字符串,除了'texture'外还有:'3fv' '1f'等等。 参数传入2 -> shadowCoord
WebGL内置函数 -> texture2D实现ShadowMap第一步就需要查询纹理图片对应坐标上的深度值,而实现深度值查询首先要查血对应的颜色,WebGL就提供了这样一个glsl的内建函数来查询对应位置纹理的颜色RGBA值——texture2D。
关于WebGL其他的内置函数,我看了这篇文章总结了比较常用的,贴过来以供参考:WebGL内置函数 - 简书 (jianshu.com)? unpack()这个函数在框架分析那个博客就提到过,用来将RGBA值转换成在范围[0,1]的float值。 转化成NDC坐标main()中首先将像素坐标归一化了
也就是说,像素被缩放成了[-1,1]3(1指的只是一个unit,并非像素尺寸那个1),那么转换成[0,1]3的NDC坐标就先要进行一系列矫正: (-1,-1,-1) -> (0,0,0)? ?(1,1,1) -> (1,1,1)? (-1,1,0) -> (0,1,0) 带入就能知道需要先+1再/2
补充代码(截图)
?并在main()把以下被注释掉的useShadowMap和gl_FragColor放出来,以实现替换
硬阴影实现结果优化->自适应Shadow Bias可以发现上面实现出来的阴影是有问题的,由于自遮挡导致锯齿: 这个由于自遮挡产生锯齿的问题叫做阴影瑕疵(shadow acne),而shadow bias就是为了解决这个问题而提出的。 课上也提到,可以在进行深度判断时给个bias,在判断前先每个shading point深度往光照方向挪一挪,让由于自遮挡被判断处于阴影的点挪到有光照的地方,就能很大程度改善这一点。朝着光照方向挪动的距离即为bias,但是这个方法暂且是给每个shading point执行一个固定长度的bias。? 自适应Shadow Bias算法 - 知乎 (zhihu.com)这篇文章中给出了更加清晰地数学模型,并给出了bias为什么产生的,感兴趣的话可以去看看,这里就不赘述。 根据上面参考文章最后给出的公式: shadow bias 代码(截图)添加一个函数getBias()以计算bias,给了一个调整量ctrl。 根据效果调整大小,最终定在了1.4效果最佳,useShadowMap()也需要加上计算bias的步骤
优化自遮挡后的结果新问题->Peter Panning 阴影丢失可以发现优化了acne后,有了新问题,阴影会“悬浮” ?解决阴影丢失问题的对策是:采取基于物体斜度的bias,称为?slope scale based depth bias。这理就不再继续写代码了,具体步骤可参考:Unity基础6 Shadow Map 阴影实现 - RubbyZhang - 博客园 (cnblogs.com) PCF要求采样方法X2框架中给我们提供了两个采样方法,一个是泊松圆盘采样一个是均匀圆盘采样,二者都是根据
?定义的样本数量NUM_SAMPLES,这个过程会进行20次,得到的结果就是
Filtering关于卷积可以参考文章:CNN 基础知识 - 卷积 (Convolution) 填充 (Padding) 步长 (Stride)-老唐笔记 (oldtang.com) 课上老师也提到过,PCF其实是基于shadow map做AA(Anti-Aliasing,即反走样)。 在进行shading point的深度与shadowmap比较时,不只比较一个方向的值,而是与周围像素做卷积,在周围采样多个点的深度值,逐一比较之后求平均值,就能得到一个[0,1]的连续分布,可以表示不同明暗程度的阴影,不再是硬阴影那样非0即1对比强烈的感觉,阴影就变得柔和起来,也就实现了人工软阴影化。 注意,PCF是实现的并不是:
而是比较深度后再计算一个平均值。 filter size 卷积核大小?PCF就是在做卷积,把卷积核也叫做过滤器,也就是filter。
采样偏移值 -> 与步长Sride关系在卷积过程中,将每次卷积核滑动的行数/列数称为Stride(步长)。有时需要在卷积时通过设置的Stride来压缩一部分信息,成倍缩小尺寸。 对于作业1而言,由于PCF输入的坐标coords归一到了[0,1]的范围,那么给定采样点的偏移值poissonDiskSamples[i]也需要缩小一定范围以迎合coords坐标的尺寸,因此需要给定Stride以缩小尺寸。缩小比例当然是Stride/ShaodowMapSize,框架中ShadowMapSize=2048,Stride可以给定一个初始值1,根据效果进行调整。 代码实现(截图)
?
? PCF结果通过给NUM_SAMPLES和Stride赋值,调整阴影的效果,可以发现:
NUM_SAMPLES=20, Stride=10NUM_SAMPLES=100, Stride=10
Stride=2, NUM_SAMPLES=100Stride=20, NUM_SAMPLES=100
均匀圆盘采样?Stride=20, NUM_SAMPLES=100泊松圆盘采样?Stride=20, NUM_SAMPLES=100可以看到泊松圆盘确实比均匀圆盘效果要好一点,且均匀圆盘采样消耗也会更多。
在调整的过程中还发现,EPS的大小虽然对地板上的阴影没啥影响,但是对模型上阴影判断效果有很大的影响,其实原因其实跟shadowmap的一样,shadow acne。EPS初始值给的是0.001,浅看一下0.001和0.01的区别: EPS=1e-2,?NUM_SAMPLES=80, Stride=10?EPS=1e-3,?NUM_SAMPLES=80, Stride=10PCSS总算到了最后的PCSS环节了! 要求半影范围?? ?为半影范围,它其实就可以表示我们的阴影程度,?越大,我们的阴影越“软”,这一点也可以由相似三角形表示出来
由相似三角形就能得到 1 Blocker Search这一步其实就是在计算上面公式里的——Blocker depth。 首先给定基数BlockerNum和总的Block_depth。从当前的shading point连向方向光源light,方向上击中一点P,取点P周围的一个区域(利用到了泊松圆盘采样),判断区域里的点是否在阴影里,如果在则:BlockerNum++、Block_depth+=cur_depth;如果不在,则不纳入计算。 可以发现这个判断过程跟前面的shadowmap和PCF都是一样的,但是目的不同,这里是在求blocker的深度! 实现代码(截图)2 Penumbra estimation利用上面的公式计算 3 PCF这里其实就是又进行了一次PCF,不过与PCF不同的是!这里考虑了阴影接受面与光源距离(dReceiver)对阴影软硬的影响,?这也是我们第二步计算得到半影范围的用途,使得到的阴影达到距离光源近的更硬,距离光源远的更软的效果,也更接近现实。 实现代码(截图)最后在main()里给PCSS去掉注释即可。 PCSS结果到这里作业1内容就做完了 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/17 3:12:23- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |