目录
前言
minecraft作为一款知名的沙盒游戏,影响了一代人 ,我从初中开始玩minecraft,一直玩到带学 。
minecraft本身的画质并不好,但是打了shadermod之后,可以达到炸裂般的高画质。shadermod又称光影mod,他需要配合光影包(即一系列的代码)来实现渲染的效果。渲染的效果取决于代码。
小时候,由于家里电脑配置并不好,无法流畅地运行光影mod,于是我开始想办法做“优化”,比如尝试删掉光影包里面的一些代码,或者减少其for循环的次数等等 。作为初中生,我无法理解其代码工作原理,当时很好奇,人生中第一次接触的编程语言就是GLSL。
变量,if,循环,在我眼里都很新奇,我尝试改变一个颜色变量的值,于是屏幕变成了对应的颜色,我发现虽然我不会写,但是我能够基于别人写的光影包,做出修改,我敲下第一段代码,来将太阳的颜色做出调整… 我发现自己对编程有点兴趣 这可能也为我之后选择计算机专业埋下了伏笔 。
基于别人的光影包来修改虽然很方便,但是我还是希望能自己动手编写一个属于自己的光影包。因为当时上初中不会编程 ,课业繁忙(其实就是自己太菜),一直没能实现这个愿望。到了带学,我逐渐忘记了这个愿望。直到我的hxd AbysStartdust 在他的Linux上搭建了一个mc服务器,我才重新玩回mc,想起来自己曾经有这么个愿望,正好下学期有图形学的课 遂学glsl。
我参考的资料
因为shadermod(光影mod)的参考资料非常少,学习起来非常困难,下面整理一些我经常看的资料:
- szszss大神的博客,强烈推荐 看他(她?)的博客,非常详细,教科书般的讲解,简直就是shadermod的中文手册+例程代码,对我的帮助非常大,感谢szszss大神!
- continue团队的教程,全英文生肉,无字幕,当时看的时候可费劲了。。。 这是他的油管空间 ,有热心hxd把它搬到b站上面来了,这是b站链接
- shadermod的wiki,全英文,不过比较简陋,只有一些变量最基本的介绍。。。
- wshxbqq的GitHub,是学习笔记,对GLSL有比较全面的介绍
其中对我帮助最大的要数老越共 szszss大神的博客,真的太强了!
坐标系与坐标变换
在GLSL中,或者说在opengl中,坐标系都是非常重要的东西。有了坐标系,就能够在扁平化的片段着色器中,确定像素的位置,这使得我们可以完成一些复杂的渲染,比如阴影。下面来介绍opengl中常用的坐标系
世界坐标系
世界坐标系即绝对坐标系,一个顶点在世界坐标系中的位置,不会随着视角或者相机的位置改变而改变。事实上,在任何情况下,一个顶点的世界坐标被确定,那么将永远不会发生变化。
模型坐标系
模型坐标系是当前顶点相对于模型而言的坐标系。模型发生旋转,模型坐标系轴随之转动。这个坐标系我们在编写着色器的时候不关心,因为总是要通过各种变换把它变换到其他坐标系。
眼坐标系
眼坐标系又名相机坐标系,视角坐标系。眼坐标系以摄像机视点中心为原点。和模型坐标系类似,顶点在眼坐标系中的坐标,随着相机(视角)的较度改变而改变。
值得注意的是,眼坐标系中的坐标是不包含投影变换的。比如下图中,红蓝方块位于眼坐标系x轴的相同位置:
裁剪坐标系
裁剪坐标系通过投影而得到。投影的具体方法,就是根据摄像机的 镜头视场 ,将场景裁剪摄像机 能够看到 的部分,然后 投影 到摄像机 镜头 上
值得注意的是,投影变换只是获得场景中相机的可视部分,并未做透视除法,只是裁剪掉了不可视的部分,因此名叫裁剪坐标系。
NDC坐标
NDC坐标又名归一化的设备坐标。裁剪坐标系下的坐标通过 透视除法 得到NDC坐标系下的坐标。
裁剪坐标通过 透视除法 得到NDC坐标。透视除法 其实就是裁剪坐标系下的坐标的xyz分量,除以自己的w分量。
透视除法,使得近处的坐标值大,远处的坐标值小。如图,红蓝方块具有不同的x轴坐标:
除此之外,NDC坐标的xyz都是[-1, 1]
这个区间中的。
屏幕坐标系
屏幕坐标系中,屏幕左下角为(0, 0)而右上角为(1, 1)。
屏幕坐标由NDC坐标经过视口变换而得到,其实就是缩放(乘0.5再加0.5)
值得注意的是,因为由NDC坐标转换而来,屏幕坐标系同样包含了投影变换。比如如图的红蓝方块在屏幕坐标系中x轴位置就不相同:
MVP与坐标变换
MVP变换又称:模型-视图-投影
变换。在着色器中:
- 顶点的坐标一开始位于模型坐标系,通过
模型(M -- Model)
变换,变换到世界坐标系下 - 再通过
视图(V -- View)
变换,变换到眼坐标系下 - 然后通过
投影(P -- Projection)
变换,变换到裁剪坐标系 - 随后通过
透视除法
变换到NDC坐标系 - 最后做一个
视口变换
变换到屏幕坐标系
下面的流程图给出了顶点变换的全部流程: