Unity Shader 双通道光线混合

  用Unity的着色器写了一个卡通渲染的效果,一共渲染了两个光源,发现有点问题。效果怎么样先放一边,光照的关系是错的。用Blend One One把两个pass的结果混合起来,发现看上去像是把阴影给合在一起了。

  项目用的是Unity的Standard Assets Example Project。后来查了一下。本来以为场景里是一个点光一个平行光,结果发现是两个平行光,角度是这样的。这张图片的角度是从人物正面看过去的。

  结果找到问题了,toon ramp的纹理做反了。原来是酱婶儿的,

其实应该是酱婶儿的。

    这里面还有个背景必须得说,第一个通道用的是伪BRDF,为了要个边缘光照的效果。纹理是2D的,酱婶儿的;

 

第二个通道用的是普通的纹理映射,按光源和法线角度铺上去。

  所以问题出现了,现在效果对了,但是两个纹理是反着的

  这事儿不应该啊。

  又翻了翻代码,发现两个通道里光线和法线夹角的计算方式不太一样。

  一个是酱婶儿的(第一个通道,LightMode=ForwardBase),

    float diff = max(0,dot(N, normalize(i.lightDir)));

一个是酱婶儿的(第二个通道,LightMode=ForwardAdd),

    float diff = dot(N, normalize(i.lightDir));

N是法线,i.lightDir就是光线方向。dot是对两个向量求点积,两个向量都是单位向量,所以求出来的是余弦值

  也就是说,第二个通道把模型背光部分的余弦值也保留了,在着色器里面就当成正面一块处理了。

  所以把第二个通道的diff也按第一个通道处理了。第二个通道处理的也是平行光,所以顶点着色器里面光线角度要用ObjSpaceLightDir()来计算,再把材质换回来,这个结果就对了。

 

  所以现在光照关系是对的了,

 

 

但是混合还是有问题。

 

  目前的混合模式是Blend One One,即将已有的图像缓存加上当前通道产生的图像。按说如果是在现实当中这样的混合模式不会有问题。但由于目前的光照模型与显示不尽相同:目前这个着色器标准阴影不是用黑色表示的,这就会导致两个光源都没有照射到的部分,在通道叠加之后反而变亮了,并不符合实际的光照效果。

  根据http://www.ceeger.com/Components/SL-Blend.html对Unity混合模式的介绍,这里提到了BlendOp

  BlendOp共有五个模式,Add,Max,Min,Sub,RevSub。每个Pass缺省BlendOp为Add,即处理过的源图像+处理过的本通道图像。这里使用Max模式,即Max(处理过的源图像,处理过的本通道图像),效果如图。

 

  这次光照关系对了,但是模型的纹理颜色不对了。原本是在第一个通道内渲染了纹理,纹理颜色深于阴影色,于是被第二个通道的阴影覆盖了。

  我的解决方法是,在每一个通道都渲染材质。虽然会觉得浪费,但是想想也符合物理规律。

 

  其实现在还有一些问题,光源颜色相同的话可以使用BlendOp Max,但是如果是不同颜色的光,就不能简单地只取出里面最亮的一个值了。但是也不能两个通道的结果都加起来再除以二,这等于求了个平均值,结果还是错的。如果有人知道怎么写,还请不吝赐教。

 

  这篇是测试课的作业,老师要求发出来。可能写的不太清楚,如果有幸有人看到而且感兴趣但是看不懂,请联系我。

 

posted on 2016-05-03 14:12  thair  阅读(1631)  评论(0编辑  收藏  举报

导航