从零到搞定:URP Lit彩色箱子材质的开发碎碎念

开场白

做一款咖啡主题的休闲游戏时,我被一个问题难住了:怎么让3D物体既色彩鲜艳又不失立体感?Unity的URP标准Lit材质虽然牛,但总觉得有点"用力过猛",暗部黑得像锅底,颜色也容易被光照"洗"得没那么鲜艳。折腾了一圈后,我搞了个自定义的彩色箱子材质,简单粗暴又好用。这篇博客就聊聊我是怎么从头到尾搞定这个Shader的心路历程,顺便吐槽下踩过的坑。

问题在哪儿?

标准材质的"坑"用URP的Lit材质时,我发现几个让人头大的问题:

  1. 颜色不够鲜:光照一打,颜色就没那么饱和,感觉像被"漂白"了。
  2. 暗部太黑:阴影直接变成黑漆漆一块,色彩细节全没了。
  3. 参数太烦:Metallic、Smoothness这些参数,美术看了直摇头,调起来像解谜。

游戏到底想要啥?我们这款休闲游戏的美术需求很简单:

  • 颜色得鲜艳,像咖啡店的杯子那样抓眼球。
  • 暗部不能是纯黑,得保留点色彩,比如咖啡杯暗处带点暖棕色。
  • 参数得直观,美术能一秒上手,不用翻文档。
  • 立体感不能丢,光影得有点层次。

摸索的过程

先搞懂光照咋算的要搞Shader,先得弄明白URP的光照逻辑。核心就是这个公式:

ini 复制代码
float NdotL = dot(normalWS, mainLight.direction);
float lightIntensity = saturate(NdotL);

翻译成人话:物体表面法线和光源方向的夹角决定光亮不亮。夹角小,亮;夹角大,暗。简单粗暴,但也给了我灵感:暗的地方能不能不黑,而是用自定义颜色?找到救命的参数瞎折腾了几天,我发现两个神器:

  • _ShadowColor:暗部的颜色,可以随便定,比如紫色、蓝色啥的。
  • _ShadowStrength:控制暗部颜色有多"重",调这个就能决定阴影是"淡淡的"还是"浓浓的"。

有了这俩,我感觉离目标不远了!色彩混合的"魔法公式"核心突破是这个混合逻辑:

ini 复制代码
float shadowIntensity = 1 - lightIntensity;
half3 finalColor = lerp(baseColor, _ShadowColor.rgb, shadowIntensity * _ShadowStrength);

啥意思呢?shadowIntensity是暗部强度,0是亮处,1是最暗。lerp就是在基础颜色和暗部颜色间"滑来滑去",_ShadowStrength决定滑得多狠。这公式让我第一次看到暗部不是黑的,激动得差点拍桌子!

一步步搞定

  1. 定义材质参数先把材质属性写好,尽量让美术一看就懂:
scss 复制代码
Properties
{
    _BaseColor("基础颜色", Color) = (1,1,1,1)
    _BaseMap("基础贴图", 2D) = "white" {}
    _ShadowColor("暗部颜色", Color) = (0.3,0.3,0.5,1)
    _ShadowStrength("暗部强度", Range(0,1)) = 0.5
    _Darkness("整体暗度", Range(0,1)) = 0
    _Smoothness("高光强度", Range(0,1)) = 0.5
}

我把_Metallic改名叫_Darkness,意思是"整体暗度",美术一听就知道干啥用的,省得解释半天。

  1. 顶点着色器顶点着色器没啥花头,标准流程,传点数据给片段着色器:
ini 复制代码
Varyings vert(Attributes input)
{
    Varyings output;
    output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
    output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
    output.normalWS = TransformObjectToWorldNormal(input.normalOS);
    output.positionWS = TransformObjectToWorld(input.positionOS.xyz);
    return output;
}
  1. 光照计算片段着色器开始干正事,先算光照:
ini 复制代码
Light mainLight = GetMainLight();
float NdotL = dot(input.normalWS, mainLight.direction);
float lightIntensity = saturate(NdotL);
float shadowIntensity = 1 - lightIntensity;

shadowIntensity就是暗部强度的"灵魂",接下来全靠它。

  1. 色彩混合这部分是核心,稍微搞复杂点:
ini 复制代码
half3 finalColor = lerp(baseColor, _ShadowColor.rgb, shadowIntensity * _ShadowStrength);
finalColor = lerp(finalColor * lightIntensity, _ShadowColor.rgb, shadowIntensity * _ShadowStrength);

第一行:把基础颜色和暗部颜色混起来。第二行:再根据光照强度调一下,保证暗部有颜色而不是黑乎乎的。两次lerp看着简单,调的时候可没少翻车。

  1. 整体明暗控制用_Darkness来控制整体亮度,简单粗暴:
ini 复制代码
finalColor *= (1 - _Darkness);

美术说想暗点?调高_Darkness就行,傻瓜式操作。

  1. 加点高光为了让物体更有立体感,我加了高光:
ini 复制代码
float3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
float3 halfDir = normalize(mainLight.direction + viewDirWS);
float NdotH = dot(input.normalWS, halfDir);
float specular = pow(saturate(NdotH), _Smoothness * 100 + 1);
specular *= _Smoothness;
finalColor += mainLight.color * specular * (1 - _Darkness);

高光让物体看起来更有"质感",而且跟_Darkness联动,保证整体风格统一。

调参的血泪史

挑暗部颜色试了一堆颜色后,我总结了点经验:

  • 蓝色系((0.3,0.3,0.5,1)):冷色调,适合清爽的物体。
  • 紫色系((0.4,0.2,0.6,1)):有点神秘,适合装饰品。
  • 橙色系((0.6,0.4,0.2,1)):暖色调,咖啡杯用这个超有感觉。

暗部强度咋调?_ShadowStrength得看风格:

  • 0.3-0.5:轻快风格,暗部像蒙了层纱。
  • 0.5-0.7:中规中矩,色彩和光影平衡。
  • 0.7-0.9:高对比,适合想突出光影的场景。

调的时候美术老跟我battle,说"太暗了""太淡了",调到最后我都觉得自己是调色大师了。实际效果咋样?在游戏里,这材质的表现真没让我失望:

  • 咖啡杯:橙色暗部,暖洋洋的,像刚泡好的咖啡。
  • 装饰物:蓝色暗部,清新感拉满,场景瞬间活了。
  • 背景:调高_ShadowStrength,层次感强了不少,场景不再"平"。

总结和碎碎念

搞完这个Shader,我有几点感悟:

  1. 简单点好:PBR很牛,但有时候简单点更对味。
  2. 参数得友好:技术再牛,美术用着不爽等于白干。
  3. 色彩有魔法:暗部颜色选对了,能让玩家心情都不一样。

这过程其实挺折腾,中间改代码改到半夜,调参数调到怀疑人生。但看到最后效果,觉得值了!这彩色箱子材质虽然不是啥高科技,但完美解决了我们游戏的需求,算是个小骄傲吧。

本文章权益归属火腾(www.firedance.cn),转载请注明来源于火腾(www.firedance.cn)。

相关推荐
谷宇.1 小时前
【Unity3D实例-功能-拔枪】角色拔枪(三)IK的使用-紧握武器
游戏·unity·c#·unity3d·游戏开发·游戏编程·steam
evamango3 小时前
《Unity Shader入门精要》十、高级纹理
unity3d
半夜微笑狗2 天前
数据持久化-PlayerPrefs
unity3d
Thomas游戏开发3 天前
博毅创为 Unity_0基础就业班
前端框架·unity3d·游戏开发
谷宇.4 天前
【Unity3D实例-功能-拔枪】角色拔枪(二)分割上身和下身
游戏·unity·c#·游戏程序·unity3d·游戏开发·游戏编程
谷宇.7 天前
【Unity3D实例-功能-移动】角色行走和奔跑的相互切换
游戏·unity·c#·unity3d·游戏开发·游戏编程
谷宇.17 天前
【Unity3D实例-功能-镜头】第三人称视觉
游戏·unity·unity3d·游戏开发·游戏编程·steam
Thomas游戏开发21 天前
Unity Root Motion 开发详解
前端框架·unity3d·游戏开发
evamango24 天前
《Unity Shader入门精要》七、基础纹理
unity3d