手搓融球版星之卡比(下)

使用SDF制作融球角色

Posted by Pavel on December 19, 2024

【附工程分享】如何在Unity中用融球绘制卡比(下)

上篇中介绍了绘制融球角色的核心函数,通过光线步进和SDF函数我们获得了融球的隐式表面并且计算出了法线和深度,此篇中我们将开始制作材质和表情。

1. 光照模型实现

【附工程分享】如何在Unity中用融球绘制卡比(下)

                        //===============Lighting====================
                        //直接光镜面反射
                        float4 highlight = 1;
                        highlight.rgb = step(_HighLightPow*0.1+0.9, dot(N, halfDir) * dot(N, halfDir)) * lCol; 
                        highlight.a = step(_HighLightPow*0.1+0.9, dot(N, halfDir) * dot(N, halfDir));
                        #if defined(_ISHIGHLIGHT_OFF)
                        highlight = 0;
                        #endif
                        
                        //环境光镜面反射
                        float2 MatCapuv = cross(normalize(TransformWorldToView(pos)),TransformWorldToView(N));
                        MatCapuv = float2(MatCapuv.x,MatCapuv.y*-1)*0.5+0.5;
                        float EnvFresnelRate = Fresnel(N,rayDir,_EnvSpecBios,_EnvSpecInt,_EnvSpecPower);
                        float3 EnvSpec = SAMPLE_TEXTURE2D(_CubeMap, smp, MatCapuv) * _EnvSpecInt * EnvFresnelRate;

                        //漫反射
                        float3 hLambert = (dot(N, L)*0.5+0.5)*baseColor+_EnvColor;
                        
                        #if defined(_ISENVSPEC_OFF)
                        EnvSpec = 0;
                        #endif
                        
                        float3 finalColor = EnvSpec+highlight+hLambert;

2. 表情贴图采样

2.1 UV

采样一张格子图的结果。 【附工程分享】如何在Unity中用融球绘制卡比(下)-1

                        //表情由模型空间坐标xy值采样贴图实现
                        float3 modelPos = TransformWorldToObject(pos);
                        float2 posUV = modelPos.xy * _TestTex_ST.xy + _TestTex_ST.zw;
                        

由于没有真实的uv空间我们可以拿已有的数据组成uv,如模型空间下的顶点的x,y值,缺点是中间会有拉伸,尽量避免将贴图内容覆盖到这块区域。

2.2 眼睛

【附工程分享】如何在Unity中用融球绘制卡比(下)-2

对UV的x,y值进行偏移,这里的实现逻辑跟帧动画的制作类似,都是走格子。 【附工程分享】如何在Unity中用融球绘制卡比(下)-3 上图是UV走格子时行数与列数和自变量x的关系。

                        //眼睛
                        float eyeMask = step(_EmotionRange, 1 - distance(posUV, 0));
                        float2 baseEeysUV = ((modelPos.xy * 0.5) + 0.5) * _EyesTex_ST.xy + _EyesTex_ST.zw;
                        leftEyeUV = baseEeysUV * 0.5 + float2(0.4, 0.45);
                        leftEyeUV.x += frac(_EyesType.x / 2);
                        leftEyeUV.y += floor(_EyesType.x / 2) / 4;

                        rightEyeUV = (float2(1 - baseEeysUV.x, baseEeysUV.y)) * 0.5 + float2(0.4, 0.45);
                        rightEyeUV.x += frac(_EyesType.y / 2);
                        rightEyeUV.y += floor(_EyesType.y / 2) / 4;

                        float4 lefEyeColor = SAMPLE_TEXTURE2D(_EyesTex, smp, leftEyeUV.xy);
                        float4 rightEyeColor = SAMPLE_TEXTURE2D(_EyesTex, smp, rightEyeUV.xy);
                        
                        lefEyeColor.rgb = lerp(0, 1, lefEyeColor.b) + lerp(0, _EyesColor1, lefEyeColor.r) + lerp(
                            0, _EyesColor2, lefEyeColor.g);
                        rightEyeColor.rgb = lerp(0, 1, rightEyeColor.b) + lerp(0, _EyesColor1, rightEyeColor.r) + lerp(
                            0, _EyesColor2, rightEyeColor.g);
                        
                        float4 eyesColor = (rightEyeColor + lefEyeColor) * eyeMask;

这是一张PS绘制的眼睛贴图,rgb三个通道分别控制了眼睛的不同部分方便调整颜色。 【附工程分享】如何在Unity中用融球绘制卡比(下)-4 克苏鲁卡比

【附工程分享】如何在Unity中用融球绘制卡比(下)-5 遮罩形状

值得注意的是为了之渲染一对眼睛,我在这里以uv原点为中心取一个圆形遮罩,去掉范围之外的眼睛。

2.3 嘴巴

                        //嘴巴
                        float mouthMask = step(_EmotionRange + 0.01, 1 - distance(float2(posUV.x, posUV.y + 0.04), 0));
                        float2 baseMouthUV = ((modelPos.xy * 0.5) + 0.5) * _MouthTex_ST.xy + _MouthTex_ST.zw;
                        mouthUV.x = baseMouthUV.x + frac(_MouthType / 2);
                        mouthUV.y = baseMouthUV.y + floor(_MouthType / 2) / 2;
                        float4 mouthColor = SAMPLE_TEXTURE2D(_MouthTex, smp, mouthUV) ;

与眼睛采样类似的采样嘴巴贴图,并给出嘴巴范围遮罩。

3.Decal阴影实现

这里的Decal阴影采用Unity自带的Decal工具实现。 【附工程分享】如何在Unity中用融球绘制卡比(下)-6|188【附工程分享】如何在Unity中用融球绘制卡比(下)-7|188