写出unity urp 次表面散射 shader
时间: 2023-06-23 12:49:32 浏览: 145
以下是一个基本的Unity URP次表面散射(SSS)着色器示例:
```
Shader "Custom/URP SSS" {
Properties {
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_NormalMap ("Normal Map", 2D) = "bump" {}
_SubsurfaceColor ("Subsurface Color", Color) = (1,1,1,1)
_SubsurfaceRadius ("Subsurface Radius", Range(0.0,1.0)) = 0.25
_ThicknessMap ("Thickness Map", 2D) = "white" {}
_SpecularColor ("Specular Color", Color) = (0.5,0.5,0.5,1)
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags {"RenderType"="Opaque"}
LOD 100
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
float4 tangent : TANGENT;
};
struct v2f {
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
float3 worldTangent : TEXCOORD3;
float3 worldBitangent : TEXCOORD4;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
sampler2D _MainTex;
sampler2D _NormalMap;
sampler2D _ThicknessMap;
float4 _MainTex_ST;
float4 _ThicknessMap_ST;
float _SubsurfaceRadius;
float4 _SubsurfaceColor;
float4 _SpecularColor;
float _Glossiness;
float _Metallic;
float3 CalculateTangent(float3 n, float3 p, float2 uv, float3 dpdu) {
float3 dpdv = cross(n, dpdu);
float3 t = normalize(dpdv - uv.y * dpdu);
return t;
}
float3 CalculateBitangent(float3 n, float3 p, float2 uv, float3 dpdu) {
float3 dpdv = cross(n, dpdu);
float3 b = normalize(cross(n, dpdv));
return b;
}
float3 CalculateSubsurface(float3 worldPos, float3 worldNormal, float3 worldTangent, float3 worldBitangent) {
// Calculate tangent space vectors
float3x3 TBN = float3x3(worldTangent, worldBitangent, worldNormal);
// Calculate thickness
float thickness = tex2D(_ThicknessMap, TRANSFORM_TEX(worldPos, _ThicknessMap)).r;
// Calculate subsurface scattering
float3 subsurface = _SubsurfaceColor.rgb * thickness * _SubsurfaceRadius;
// Transform subsurface scattering to world space
subsurface = mul(TBN, subsurface);
return subsurface;
}
float4 LightingURP(SurfaceOutputStandard s, float3 lightDir, float3 worldPos, float atten) {
// Calculate subsurface scattering
float3 subsurface = CalculateSubsurface(worldPos, s.Normal, s.Tangent, s.Bitangent);
// Calculate diffuse lighting
float diff = max(0.0, dot(s.Normal, lightDir));
float3 diffuse = (s.Albedo * _LightColor0.rgb * diff);
// Calculate specular lighting
float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
float3 halfDir = normalize(lightDir + viewDir);
float spec = pow(max(0.0, dot(s.Normal, halfDir)), s.Smoothness);
float3 specular = _SpecularColor.rgb * _LightColor0.rgb * spec;
// Combine lighting
float3 finalColor = ((diffuse + specular) * atten) + subsurface;
return float4(finalColor, s.Alpha);
}
v2f vert (appdata v) {
v2f o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldTangent = UnityObjectToWorldDir(UnityObjectToWorldDir(v.tangent.xyz, UNITY_MATRIX_IT_MV), UNITY_MATRIX_IT_MV);
o.worldBitangent = cross(o.worldNormal, o.worldTangent) * v.tangent.w;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_SETUP_INSTANCE_ID(v);
return o;
}
fixed4 frag (v2f i) : SV_Target {
SurfaceOutputStandard s = SurfaceOutputStandard();
s.Albedo = tex2D(_MainTex, i.uv).rgb;
s.Normal = UnpackNormal(tex2D(_NormalMap, i.uv));
s.Smoothness = _Glossiness;
s.Metallic = _Metallic;
float3 worldPos = i.worldPos;
float3 worldNormal = normalize(i.worldNormal);
float3 worldTangent = normalize(i.worldTangent);
float3 worldBitangent = normalize(i.worldBitangent);
float4 finalColor = LightingURP(s, normalize(_WorldSpaceLightPos0.xyz), worldPos, _LightColor0.a);
return finalColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
```
这个着色器包含了一个基本的表面纹理、法线贴图、次表面散射颜色和半径、厚度贴图、高光颜色、光滑度和金属度选项。在顶点着色器中,我们还计算了Tangent和Bitangent向量,并传递给片段着色器以计算次表面散射。在片段着色器中,我们计算了次表面散射、漫反射和高光光照,并将它们合并以产生最终颜色。请注意,此着色器是基于URP版本的标准表面着色器,并使用UnityCG.cginc文件中定义的LightingURP函数来计算光照。