您的位置:首页 > 其它

Shader 学习笔记 20151102

2015-11-02 10:13 204 查看

Segment 0 回顾

surf和litmodel传进去的参数

1, surf 的参数主要有两个,一个是结构体作为input, 里面主要包含了fragment着色器所需要的材质信息(材质本身以及材质坐标,材质坐标的方式很奇异,是直接把uv加材质前面的方式—uv_Texture);另外一个就是inout SurfaceOutput s,SurfaceOutput的类型是Unity自己定义的,其中包含了每一个点的空间位置信息和颜色信息(具体可以去Unity的Lighting.cginc里面看,Unity Shaders and Effects Cookbook page18)

2, litmodel传进去的参数是有指定方式的,一共有三种(Unity shader manual里面有),其基本的意思就是处理材质点s,入射光,camera视点这三个东西(还有一个是attenuation参数,作为衰减用的)。因此litmodel带的参数也就是 SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, half atten。

此处还存在一个问题就是诸如lightDir,viewDir,atten这些东西都是从哪里来的。只能理解为从Unity的场景Object带进来的(其中atten有可能是定义在Lighting.cgin里面,但是我没看)。

litmodel里面的_LightColor0是怎么传进去的?从哪里定义的?

是定义在Lighting.cginc里面,表示光源颜色,有一种说法说_LightColor0是反射光颜色,我觉得太离谱。

albedo和rgb之间的关系 以及 col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2) 是什么鬼?为何颜色能相乘?!

albedo按照单词翻译叫做反射率,而在shader里面它一般是由材质的rgb颜色赋值的。然后我就晕了,为何反射率是材质的颜色值?这不是害人么? 其实,细想一下,还是很有道理的,例如一个蓝色的材质(0,0,1)在白色光(1,1,1)照射下,请问是什么颜色(0*1, 0*1, 1*1)?必然是蓝色(0,0,1)。再深思一步,一个物体是绿色的是什么意思?白色物体在黄灯下面为何是黄色的? 我们所说物体具有某种颜色一般默认它是在白光下面的颜色,所以我们说香蕉是黄色的时候暗含着香蕉是在白光照射下的香蕉,如果用蓝光射蕉肯定又有不同。这样看来,白色物体在不同灯光下反映出不同颜色的现象暗含着一个深刻的事实,它就是物体在白光下的颜色就是它的反射率(Albedo)

明白了物体颜色就是反射率这个事实之后,就很好理解s.Albedo这个rgb乘以_LightColor0.rgb是啥意思了,有一种说法管这个叫做color modulation(色彩调制,高大上的很,参见http://www.zhihu.com/question/24026277

另外还有一个很有趣的概念是镜面反射,那个就是色彩相加了,此处不展开。

difLight * atten又是什么鬼?先说atten,它实质上是材质对环境光的反射系数(0 < atten < 1)(具体参见GPU 编程与CG 语言之阳春白雪下里巴人.pdf page98)。difLight是根据Lambert反射模型搞出来的(当方向光照射到朗伯反射体上时,漫反射光的光强与入射光的方向和入射点表面法向夹角的余弦成正比,这称之为 Lambert 定律)

Segment 1 阅读

看了Creating a ramp texture to control diffuse shading in cook book

看了Creating a faked BRDF using a 2D ramp texture in cook book

Segment 2 理解

BRDF名词解释,bidirectional reflectance distribution function。意思也很通俗,就是在光源渲染的时候,既考虑光源和物体法线之间的夹角,又考虑视点和物体法线之间的夹角,然后用这两个夹角做文章。

一般的玩法是用这两个夹角的余弦值做uv坐标,然后去2Dtexture里面取色。

具体请看下图,他就是用了 光源-法线夹角余弦视点-法线夹角余弦 去定位坐标。



以下是核心的code

//计算光源法线点乘,也就是它们之间的夹角余弦
float difLight = dot (s.Normal, lightDir);
//计算视点法线点乘,也就是它们之间的夹角余弦
float rimLight = dot(s.Normal, viewDir);
//给光源法线点乘搞了一个hLambert效果(就是让非光照面也有明暗变化细节,
//但是在这里其实是给difLight搞一个归一化,因为difLight范围是负1到正1)
float hLambert = difLight * 0.5 + 0.5;
//关键的来了,用这两个余弦值去找2Dtexure上面的像素颜色。
float3 ramp = tex2D(_RampTex, float2(hLambert,rimLight)).rgb;


好吧,这玩意从算法上看是很通俗,那么直观上的理解到底是啥?这种方法用能干些啥呢?

先回答这个直观上理解是什么东西,直观上看可以理解为我们渲染的这个物体,越靠近光源的部分其颜色就越显蓝色,越远离光源的部分其颜色就越红。同时,请注意同时,眼睛看这个物体时,这个物体中心亮,轮廓暗(中心亮、轮廓暗这个其实是特别针对这个球来说的,由rimLight的算法可以看出来,物体上法线和视线平行的点就亮,垂直的就暗),为啥会有红、蓝、明、暗这区别呢?就是BRDF这个材质图决定的,现在把材质图放大放在下面。(图中的两个轴我还未体悟清楚)



rimLight 或者叫做有视点参数参与的玩法究竟怎么玩才好玩! ( cook book page 27 )

1, A bubble type transparency

2, The start of a rim light effect

3, Shield effects

4, Toon outline effect

也就是说,因为你有了视点控制,那么基本上根据轮廓然后做各种处理都可以搞了,我自己觉得最NB的就是超级街霸4里面人物的水墨勾边,真心吊。



今天写code时候出了个很严重的问题,由是想到有没有一种灵活debug的方法。目前。。。还没看到。。。

//此处出了个大问题,ramp 被我声明成float 而 不是float3,得到非常难查的结果
float3 ramp = tex2D(_RampTex, float2(hLambert,rimLight)).rgb;


编辑器的使用,自带的MonoDevelop简直反人类,既没关键词连想,又没提示。是不是用VS来代替呢?不知道,但是(http://www.jianshu.com/p/7b9498e58659)

里面的东西看起来很美,就是不知道是不是能实时save之后更新Unity scene
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shader color