查看: 1395|回复: 1
打印 上一主题 下一主题

[Shaders] 初探Surface Shader背后的机制(2)

[复制链接]

711

主题

10

听众

5805

积分

高级设计师

Rank: 6Rank: 6

纳金币
2954
精华
3

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2015-1-28 22:13:47 |只看该作者 |倒序浏览
LIGHTMAP_OFF

// lightmaps:
#ifndef LIGHTMAP_OFF
// 计算LightMap,这部分不懂
#ifndef DIRLIGHTMAP_OFF
// directional lightmaps
fixed4 lmtex = tex2D(unity_Lightmap, IN.lmap.xy);
fixed4 lmIndTex = tex2D(unity_LightmapInd, IN.lmap.xy);
half3 lm = LightingLambert_DirLightmap(o, lmtex, lmIndTex, 0).rgb;
#else // !DIRLIGHTMAP_OFF
// single lightmap
fixed4 lmtex = tex2D(unity_Lightmap, IN.lmap.xy);
fixed3 lm = DecodeLightmap (lmtex);
#endif // !DIRLIGHTMAP_OFF

// combine lightmaps with realtime shadows
#ifdef SHADOWS_SCREEN
#if (defined(SHADER_API_GLES) || defined(SHADER_API_GLES3)) && defined(SHADER_API_MOBILE)
c.rgb += o.Albedo * min(lm, atten*2);
#else
c.rgb += o.Albedo * max(min(lm,(atten*2)*lmtex.rgb), lm*atten);
#endif
#else // SHADOWS_SCREEN
c.rgb += o.Albedo * lm;
#endif // SHADOWS_SCREEN

// 给Alpha通道赋值
c.a = o.Alpha;
#endif // LIGHTMAP_OFF

// 调用自定义的final函数,
// 对像素值进行最后的更改
final (surfIN, o, c);
return c;
}

ENDCG

}

// —- end of surface shader generated code

#LINE 57

}
FallBack “Diffuse”
}

其中比较重要的部分我都写了注释。




一些问题

回到我们一开始的那个问题:为什么我的场景里没有灯光,但物体不是全黑的呢?这一切都是Fragment Shader中一些颜色叠加计算的结果。


我们仔细观察Fragment Shader中计算颜色的部分。前面说过,它使用LightingXXX对颜色值进行初始化,但后面还进行了一系列颜色叠加计算。其中,在没有使用LightMap的情况下,Unity还计算了vertex lights对颜色的影响,也就是下面这句话:
#ifdef LIGHTMAP_OFF
// 如果没有开启LightMap,
// 向像素叠加vertex light的光照颜色
c.rgb += o.Albedo * IN.vlight;
#endif // LIGHTMAP_OFF
而IN.vlight是在Vertex Shader中计算的:
//如果没有开启LightMap,
//vertex lights就是球面调和函数的结果
//球面调和函数ShadeSH9在UnityCG.cginc里定义
float3 shlight = ShadeSH9 (float4(worldN,1.0));
o.vlight = shlight;
我们可以去查看ShadeSH9函数的实现:
// normal should be normalized, w=1.0
half3 ShadeSH9 (half4 normal)
{
half3 x1, x2, x3;

// Linear + constant polynomial terms
x1.r = dot(unity_SHAr,normal);
x1.g = dot(unity_SHAg,normal);
x1.b = dot(unity_SHAb,normal);

// 4 of the quadratic polynomials
half4 vB = normal.xyzz * normal.yzzx;
x2.r = dot(unity_SHBr,vB);
x2.g = dot(unity_SHBg,vB);
x2.b = dot(unity_SHBb,vB);

// Final quadratic polynomial
float vC = normal.x*normal.x – normal.y*normal.y;
x3 = unity_SHC.rgb * vC;
return x1 + x2 + x3;
}
它是一个球面调和函数,但unity_SHAr这些变量具体是什么我还不清楚。。。如果有人知道麻烦告诉我一下,不胜感激~但是,这些变量是和Unity使用了一个全局环境光(你可以在Edit->RenderSettings->Ambient Light中调整)有关。如果把这个环境光也调成黑色,那么场景就真的全黑了。


呼呼呼,关于这些光源计算的部分就是一开始所说的那些让写shader变得很复杂的原因之一!如果你真的去看那些在UnityCG.cginc、AutoLight.cginc等文件里的关于指令的定义,可以发现Unity是根据定义的光照类型来处理不同的光照的。这部分还没有搞明白,后面会继续探究一下的!


转载: 游戏开发网
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

115

主题

3

听众

5676

积分

高级设计师

Rank: 6Rank: 6

纳金币
7268
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2015-1-28 23:33:10 |只看该作者
Thanks for sharing this one !
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-5-9 01:15 , Processed in 0.078878 second(s), 27 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部