Minecraft(我的世界)中文论坛

 找回密码
 注册(register)

!header_login!

只需一步,立刻登录

查看: 3698|回复: 48

[教程] [20w22a]不会有人看的深度缓冲着色器分析&用途 (6.10更新!)

  [复制链接]
ChapterII 当前离线
积分
2358
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-7-9
查看详细资料
 楼主| 发表于 2020-6-3 11:25:13 | 显示全部楼层 |阅读模式

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x
本帖最后由 ChapterII 于 2020-6-10 22:41 编辑

下文转载材质包已取得原作者授权

2020.6.10 18:30更新:景深、实例之吸血鬼
2020.6.7 14:25更新:深度缓冲访问方法,线性深度,Distance解析.


众所周知,20w22a加入了着色器对深度缓冲的访问支持。
“然而,这意味着什么呢?”



1.什么是深度缓冲
摘自LearnOpenGL-CN
深度缓冲是图形编程中的一个基础概念。渲染三维图形(这里以立方体举例)时
由于三角形绘制的先后顺序(计算机会把图形分解为三角形进行渲染)
仅仅按正常的顺序渲染一个立方体,会
image.png

这的确有点像是一个立方体,但又有种说不出的奇怪。立方体的某些本应被遮挡住的面被绘制在了这个立方体其他面之上。之所以这样是因为OpenGL是一个三角形一个三角形地来绘制你的立方体的,所以即便之前那里有东西它也会覆盖之前的像素。因为这个原因,有些三角形会被绘制在其它三角形上面,虽然它们本不应该是被覆盖的。

幸运的是,OpenGL存储深度信息在一个叫做Z缓冲(Z-buffer)的缓冲中,它允许OpenGL决定何时覆盖一个像素而何时不覆盖。通过使用Z缓冲,我们可以配置OpenGL来进行深度测试。

注:Z缓冲又称深度缓冲
当一个面的Z缓冲顺序在前,就不会渲染其后的面。
因此,引入了深度缓冲解决了物体的绘制问题。

“但是,你说好的着色器呢?”


2.如何访问深度缓冲?
  1. "auxtargets": [
  2.                 {
  3.                     "name": "DiffuseDepthSampler",
  4.                     "id": "minecraft:main:depth"
  5.                 },
复制代码
在post Json文件里需要访问深度缓冲的操作的auxtargets加入如上内容.
同理,在着色器的Json里
  1. "samplers": [
  2.         { "name": "DiffuseSampler" },
  3.         { "name": "DiffuseDepthSampler" },
复制代码
最后,在片段着色器里
  1. uniform sampler2D DiffuseSampler;
  2. uniform sampler2D DiffuseDepthSampler;
复制代码
这样,就可以通过DiffuseDepthSampler访问深度缓冲了,
  1. texture2D(DiffuseDepthSampler,vec2(0.5,0.5));
复制代码



3.Onnowhere的深度缓冲着色器
https://github.com/onnowhere/depth_shaders/
Onnowhere一共发布了4个资源包
分析:
Depth Shader Test(Distance) (咕)
Depth Shader Test(Fog)(√)
                           (DoF) (注Depth of Field)(咕)
                           (Stripe)(咕)
从最简单的Fog说起
fog1.png
这是在下界使用Fog资源包的截图。
片段着色器很简短:depth_test.fsh
  1. <blockquote>#version 110
复制代码

DiffuseDepthSampler即是深度缓冲(采样器)。
  1. texture2D(DiffuseDepthSampler, texCoord)
复制代码
获取了texCoord处片段的深度。
1.0减去vec4会使每项被1.0减去,因此最终效果为对该处深度取反。
*500.0是一个系数,可以根据个人需求调整。
最后再取反,达到图中的效果。
实际上,该着色器做的只是将它的颜色进行了缩放操作,
  1. gl_FragColor = texture2D(DiffuseDepthSampler, texCoord);
复制代码

可以直接使深度缓冲可视化,好奇的读者可以自己尝试。




Depth Shader Test(Distance)资源包
该资源包的效果有点过于目眩神迷dizzy,请自行尝试
会以摄像机为中心,每隔1方块距离的点进行着色,类似同心圆。

  1. #version 110

  2. uniform sampler2D DiffuseSampler;
  3. uniform sampler2D DiffuseDepthSampler;

  4. uniform vec2 ScreenSize;
  5. uniform float _FOV;

  6. varying vec2 texCoord;

  7. float near = 0.1;
  8. float far  = 1000.0;

  9. float LinearizeDepth(float depth)
  10. {
  11.     float z = depth * 2.0 - 1.0;
  12.     return (near * far) / (far + near - z * (far - near));   
  13. }

  14. void main() {
  15.     float depth = LinearizeDepth(texture2D(DiffuseDepthSampler, texCoord).r);
  16.     float distance = length(vec3(1., (2.*texCoord - 1.) * vec2(ScreenSize.x/ScreenSize.y,1.) * tan(radians(_FOV / 2.))) * depth);
  17.     if (mod(distance, 1.0) <= 0.05) {
  18.         gl_FragColor = vec4(1.0,0.0,0.0,0.1);
  19.     } else {
  20.         gl_FragColor = vec4(texture2D(DiffuseSampler, texCoord).rgb, 1.0);
  21.     }
  22. }
复制代码

uniform _FOV是视野(Field of View),即角视场.
因为深度缓冲里每个像素的颜色(vec4)的r、g、b均为同一个值(深度),
因此取texture2D(DiffuseDepthSampler, texCoord).r就是该片段深度。以下内容可能难以理解,但是是看懂其它三个资源包的基础内容。如果看不懂公式没关系,只要记住蓝底字内容即可。
Onnowhere定义了函数float LinearizeDepth(float depth) ,Linearize意味"用线表示",GLSL里一般解释为“线性深度”这里需要解释一下,
要想有正确的投影性质,需要使用一个非线性的深度方程,它是与 1/z 成正比的。
它做的就是在z值很小的时候提供非常高的精度,而在z值很远的时候提供更少的精度。
花时间想想这个:我们真的需要对1000单位远的深度值和只有1单位远的充满细节的物体使用相同的精度吗?
线性方程并不会考虑这一点。屏幕空间中的深度值是非线性的,即它在z值很小的时候有很高的精度,而z值很大的时候有较低的精度。
片段的深度值会随着距离迅速增加,所以几乎所有的顶点的深度值都是接近于1.0的。

(引用文字节选自LearnOpenGL-CN:深度测试
简单来说,为了效率,深度值不是线性的,即不是随距离增大而匀速增大的。
image.png

OpenGL非线性的深度方程计算如上,
为了实现距离的均匀,我们需要将非线性的化为线性深度。
然而,我们也可以让片段非线性的深度值变换为线性的。要实现这个,我们需要仅仅反转深度值的投影变换。这也就意味着我们需要首先将深度值从[0, 1]范围重新变换到[-1, 1]范围的标准化设备坐标(裁剪空间)。接下来我们需要像投影矩阵那样反转这个非线性方程(方程2),并将这个反转的方程应用到最终的深度值上。最终的结果就是一个线性的深度值了。听起来是可行的,对吧?

首先我们将深度值变换为NDC,不是非常困难:

float z = depth * 2.0 - 1.0;
接下来使用获取到的z值,应用逆变换来获取线性的深度值:

float linearDepth = (2.0 * near * far) / (far + near - z * (far - near));
这个方程是用投影矩阵推导得出的,它使用了方程2来非线性化深度值,返回一个near与far之间的深度值。这篇注重数学的文章为感兴趣的读者详细解释了投影矩阵,它也展示了这些方程是怎么来的。

总而言之,要转化"不均匀的"深度为"均匀的",好比向上大下小的杯子里匀速倒水,水面上涨的速度不与倒水速度成正比。
而实现该目的的,是LinearizeDepth函数。
image.png
上为LinearizeDepth函数。
该函数实现了线性深度转化为非线性的逆过程。
main()中的内容较为简单,是判断该片段与玩家的距离是否为整数(有0.05的浮动范围),如果是则gl_FragColor = vec4(1.0,0.0,0.0,0.1);



(Stripe)
和Distance基本上同理,
看懂了线性深度这个应该很好理解吧疯狂暗示
所以,那么是不是可以偷个懒的呀?
“那么,你什么时候填坑呢?”
(无响应)


(DoF)DoF,Depth of Field.
DoF看着很陌生,"场地深度?"
实际上,它就是我们常说的景深.
稍微涉及过一点相机方面知识的玩家,都知道当拍摄远处的一个独立的景物时,近处的环境会变模糊。
在拍摄截图时,景深会非常有用:
file_1591783508000.jpg

看起来,是不是山峰被突出了?
远处的和近处的都被模糊了,达到了突出所拍摄目标的效果。
实际上,作者只是在某个范围内正常显示,在范围外模糊的简单原理。
作为思考题因为作者懒,请自己阅读片段着色器代码(逃)

4.除了这些特效,深度缓冲还可以用来做些什么?——实战

As many as you can come up with.
比如,阴影的实现,是在光源的角度根据深度缓冲生成一张“深度纹理”,
然后转回摄像机视角,根据深度纹理绘制出阴影。
上述技术是最为常见的阴影实现方法,阴影贴图。

至于真正有点意义的……
吸血鬼小游戏应该都听说过吧,Hypixel的VampireZ:
玩家使用了失明效果,但自定义化程度较低。
如果用深度缓冲……一定不错!
  1. #version 110

  2. uniform sampler2D DiffuseSampler;
  3. uniform sampler2D DiffuseDepthSampler;

  4. uniform vec2 ScreenSize;
  5. uniform float _FOV;

  6. varying vec2 texCoord;

  7. float near = 0.1;
  8. float far  = 1000.0;
  9.   
  10. float LinearizeDepth(float depth)
  11. {
  12.     float z = depth * 2.0 - 1.0;
  13.     return (near * far) / (far + near - z * (far - near));   
  14. }

  15. void main() {
  16.     float depth = LinearizeDepth(texture2D(DiffuseDepthSampler, texCoord).r);
  17.     if(depth < 10.0) gl_FragColor=texture2D(DiffuseSampler,texCoord);
  18.     else gl_FragColor=vec4(0.0,0.0,0.0,1.0);
  19. }
复制代码
代码很简单,只要看懂了线性深度即可;
2020-06-10_18.18.14.png

但是,总感觉边界有点……锐利?
  1. ++ else if(depth < 13.0) gl_FragColor=texture2D(DiffuseSampler,texCoord) * (1.0-(depth-10.0)/3.0);
复制代码

2020-06-10_18.29.24.png

效果如何?
那还不加分去!

“所以,某个蓝蓝的东西呢?”
下载页面位于https://github.com/onnowhere/depth_shaders/
未提供某在线云文件存储服务的转载

“然后,要不要加分呢?”
金粒可以不给,人气还不给点吗~不给的话人家再也不这么努力写帖子了




















评分

参与人数 21人气 +41 金粒 +320 贡献 +4 收起 理由
Yong_Hu_Ming + 2 MCBBS有你更精彩~
沉默的秋水 + 1 + 10 有用
Argon_gas + 2 ohhhhhhhh
落天望月 + 1 + 15 MCBBS有你更精彩~
空辰KC + 2 + 20 神乎其技!6的飞起!
crystal_水晶 + 1 + 10 MCBBS有你更精彩~
BlackCB. + 2 + 5 MCBBS有你更精彩~
chyx + 3 MCBBS有你更精彩~
Chelover_C60 + 2 + 40 是着色器!
纪华裕 + 2 MCBBS有你更精彩~
ItIsEnderman + 4 + 50 + 1 MCBBS有你更精彩~
六月奈 + 4 + 50 + 2 精华
Jokey_钥匙 + 2 MCBBS有你更精彩~
玄素 + 3 + 1 MCBBS有你更精彩~
kongbaiyo + 2 + 50 好!
ETW_Derp + 1 + 10 神乎其技!6的飞起!
👴是hlnb + 1 看不懂,是原版有光影了吗?
。—。 + 1 神乎其技!6的飞起!
1041159637 + 1 + 20 神乎其技!6的飞起!
晴路卡 + 40 额 自从1.7.10之后

查看全部评分

尾丸青猫 当前离线
积分
2034
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2017-6-18
查看详细资料
发表于 2020-6-3 11:29:48 | 显示全部楼层
有趣的着色器越来越多,等我这个地图做完很想试试。国内现在有什么用了着色器的地图可以玩吗?
回复

使用道具 举报

ChapterII 当前离线
积分
2358
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-7-9
查看详细资料
 楼主| 发表于 2020-6-3 11:31:40 | 显示全部楼层
[SL]John_Stapp 发表于 2020-6-3 11:29
有趣的着色器越来越多,等我这个地图做完很想试试。国内现在有什么用了着色器的地图可以玩吗? ...

好……像……没……有……吧(小声)
但是很多dalao在做了
回复

使用道具 举报

Kanonymous 当前离线
积分
17692
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2011-5-22
查看详细资料
发表于 2020-6-3 11:48:34 | 显示全部楼层
2020-06-03_11.47.54.png

Distance 的效果

确实 Dizzy
回复

使用道具 举报

晴路卡 当前离线
积分
6541
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2015-3-15
查看详细资料
发表于 2020-6-3 13:50:55 | 显示全部楼层
只能想到用来做些奇怪的东西...
file_1591163126000.jpg
回复

使用道具 举报

ChapterII 当前离线
积分
2358
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-7-9
查看详细资料
 楼主| 发表于 2020-6-3 14:28:07 | 显示全部楼层
本帖最后由 ChapterII 于 2021-8-20 10:29 编辑
晴路卡 发表于 2020-6-3 13:50
只能想到用来做些奇怪的东西...

希望会有更多奇奇怪怪好玩的地图吧
回复

使用道具 举报

小冰糖a 当前离线
积分
12112
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-2-24
查看详细资料
发表于 2020-6-3 15:09:27 | 显示全部楼层
着色器目前国内做的不多吧
(至少mcbbs还没专门开个板块做这个)
回复

使用道具 举报

ChapterII 当前离线
积分
2358
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-7-9
查看详细资料
 楼主| 发表于 2020-6-3 15:35:17 | 显示全部楼层
深拥v 发表于 2020-6-3 15:09
着色器目前国内做的不多吧
(至少mcbbs还没专门开个板块做这个)

还好,这个应该算是资源包的一部分
地图作者和原版模组也都有用的
所以不算单独的版块,最多放在材质版?
回复

使用道具 举报

⭐✔️ 当前离线
积分
28273
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2013-1-5
查看详细资料
发表于 2020-6-7 11:06:32 | 显示全部楼层
你能不能用[code]标签,黑背景怪费眼的

评分

参与人数 1人气 +1 金粒 +20 收起 理由
ChapterII + 1 + 20 遵命

查看全部评分

回复

使用道具 举报

Оil 当前离线
积分
26947
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2012-2-19
查看详细资料
发表于 2020-6-14 10:56:54 | 显示全部楼层
>>这个公式的非官方表述让我看得血压升高……= =
回复

使用道具 举报

年检费就 当前离线
积分
34
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-2-8
查看详细资料
发表于 2020-6-14 20:21:11 | 显示全部楼层
这个真棒           
回复

使用道具 举报

👴是hlnb 当前离线
积分
2349
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-1-7
查看详细资料
发表于 2020-6-14 22:48:28 来自手机 | 显示全部楼层
以后就有香草光影了?
回复

使用道具 举报

ChapterII 当前离线
积分
2358
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-7-9
查看详细资料
 楼主| 发表于 2020-6-15 08:45:31 来自手机 | 显示全部楼层
👴是hlnb 发表于 2020-6-14 22:48
以后就有香草光影了?

SBMJ对着色器的限制使得不能获取光源的位置,也不能获取当前的材质反射贴图之类的,所以离光影还有很远的路要走
回复

使用道具 举报

炽炽灼华 当前离线
积分
319
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2019-10-5
查看详细资料
发表于 2020-6-15 09:06:22 | 显示全部楼层
是在下输了
回复

使用道具 举报

1172429976 当前离线
积分
244
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2013-10-5
查看详细资料
发表于 2020-6-16 00:57:40 | 显示全部楼层
支持~~~~~~~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册(register)

本版积分规则

Archiver|小黑屋|Mcbbs.net ( 京ICP备15023768号-1 ) | 京公网安备 11010502037624号 | 手机版

GMT+8, 2021-9-21 20:14 , Processed in 0.073445 second(s), Total 39, Slave 32 queries, Release: Build.2021.09.13 2028, Gzip On, Redis On.

"Minecraft"以及"我的世界"为Mojang Synergies AB的商标 本站与Mojang以及微软公司没有从属关系

© 2010-2020 我的世界中文论坛 版权所有 本站原创图文内容版权属于原创作者,未经许可不得转载

快速回复 返回顶部 返回列表