您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
186 行
6.2 KiB
186 行
6.2 KiB
// Example shader for a scriptable render loop that calculates multiple lights
|
|
// in a single forward-rendered shading pass.
|
|
// The parameters and inspector of the shader are the same as Standard shader,
|
|
// for easier experimentation.
|
|
Shader "RenderLoop/Basic/Standard"
|
|
{
|
|
// Properties is just a copy of Standard.shader. Our example shader does not use all of them,
|
|
// but the inspector UI expects all these to exist.
|
|
Properties
|
|
{
|
|
_Color("Color", Color) = (1,1,1,1)
|
|
_MainTex("Albedo", 2D) = "white" {}
|
|
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
|
|
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
|
|
_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
|
|
[Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
|
|
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
|
|
_MetallicGlossMap("Metallic", 2D) = "white" {}
|
|
[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
|
|
[ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
|
|
_BumpScale("Scale", Float) = 1.0
|
|
_BumpMap("Normal Map", 2D) = "bump" {}
|
|
_Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
|
|
_ParallaxMap ("Height Map", 2D) = "black" {}
|
|
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
|
|
_OcclusionMap("Occlusion", 2D) = "white" {}
|
|
_EmissionColor("Color", Color) = (0,0,0)
|
|
_EmissionMap("Emission", 2D) = "white" {}
|
|
_DetailMask("Detail Mask", 2D) = "white" {}
|
|
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
|
|
_DetailNormalMapScale("Scale", Float) = 1.0
|
|
_DetailNormalMap("Normal Map", 2D) = "bump" {}
|
|
[Enum(UV0,0,UV1,1)] _UVSec("UV Set for secondary textures", Float) = 0
|
|
[HideInInspector] _Mode("__mode", Float) = 0.0
|
|
[HideInInspector] _SrcBlend("__src", Float) = 1.0
|
|
[HideInInspector] _DstBlend("__dst", Float) = 0.0
|
|
[HideInInspector] _ZWrite("__zw", Float) = 1.0
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Tags { "RenderType" = "Opaque" "PerformanceChecks" = "False" }
|
|
LOD 300
|
|
|
|
// Include forward (base + additive) pass from regular Standard shader.
|
|
// They are not used by the scriptable render loop; only here so that
|
|
// if we turn off our example loop, then regular forward rendering kicks in
|
|
// and objects look just like with a Standard shader.
|
|
UsePass "Standard/FORWARD"
|
|
UsePass "Standard/FORWARD_DELTA"
|
|
|
|
|
|
// Multiple lights at once pass, for our example Basic render loop.
|
|
Pass
|
|
{
|
|
Tags { "LightMode" = "BasicPass" }
|
|
|
|
// Use same blending / depth states as Standard shader
|
|
Blend[_SrcBlend][_DstBlend]
|
|
ZWrite[_ZWrite]
|
|
|
|
CGPROGRAM
|
|
|
|
#pragma target 3.0
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#include "UnityCG.cginc"
|
|
|
|
// Global lighting data (setup from C# code once per frame).
|
|
CBUFFER_START(GlobalLightData)
|
|
// The variables are very similar to built-in unity_LightColor, unity_LightPosition,
|
|
// unity_LightAtten, unity_SpotDirection as used by the VertexLit shaders, except here
|
|
// we use world space positions instead of view space.
|
|
half4 globalLightColor[8];
|
|
float4 globalLightPos[8];
|
|
float4 globalLightSpotDir[8];
|
|
float4 globalLightAtten[8];
|
|
int4 globalLightCount;
|
|
// Global ambient/SH probe, similar to unity_SH* built-in variables.
|
|
float4 globalSH[7];
|
|
CBUFFER_END
|
|
|
|
|
|
struct v2f
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
float3 positionWS : TEXCOORD1;
|
|
float3 normalWS : TEXCOORD2;
|
|
float4 hpos : SV_POSITION;
|
|
};
|
|
|
|
float4 _MainTex_ST;
|
|
|
|
v2f vert(appdata_base v)
|
|
{
|
|
v2f o;
|
|
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
|
|
o.hpos = UnityObjectToClipPos(v.vertex);
|
|
o.positionWS = mul(unity_ObjectToWorld, v.vertex).xyz;
|
|
o.normalWS = UnityObjectToWorldNormal(v.normal);
|
|
return o;
|
|
}
|
|
|
|
// Compute illumination from one light, given attenuation
|
|
half3 ComputeLighting(int idx, half3 dirToLight, half3 normalWS, half4 diffuseAlbedo, float atten)
|
|
{
|
|
half NdotL = max(dot(normalWS, dirToLight), 0.0);
|
|
// diffuse
|
|
half3 color = NdotL * diffuseAlbedo.rgb * globalLightColor[idx].rgb;
|
|
return color * atten;
|
|
}
|
|
|
|
|
|
// Compute attenuation & illumination from one light
|
|
half3 ComputeOneLight(int idx, float3 positionWS, half3 normalWS, half4 diffuseAlbedo)
|
|
{
|
|
float3 dirToLight = globalLightPos[idx].xyz;
|
|
dirToLight -= positionWS * globalLightPos[idx].w;
|
|
// distance attenuation
|
|
float att = 1.0;
|
|
float distSqr = dot(dirToLight, dirToLight);
|
|
att /= (1.0 + globalLightAtten[idx].z * distSqr);
|
|
if (globalLightPos[idx].w != 0 && distSqr > globalLightAtten[idx].w) att = 0.0; // set to 0 if outside of range
|
|
distSqr = max(distSqr, 0.000001); // don't produce NaNs if some vertex position overlaps with the light
|
|
dirToLight *= rsqrt(distSqr);
|
|
// spot angle attenuation
|
|
float rho = max(dot(dirToLight, globalLightSpotDir[idx].xyz), 0.0);
|
|
float spotAtt = (rho - globalLightAtten[idx].x) * globalLightAtten[idx].y;
|
|
att *= saturate(spotAtt);
|
|
|
|
return min(ComputeLighting(idx, dirToLight, normalWS, diffuseAlbedo, att), 1.0);
|
|
}
|
|
|
|
|
|
// Evaluate 2nd order spherical harmonics, given normalized world space direction.
|
|
// Similar to ShadeSH9 in UnityCG.cginc
|
|
half3 EvaluateSH(half3 n)
|
|
{
|
|
half3 res;
|
|
half4 normal = half4(n, 1);
|
|
|
|
// Linear (L1) + constant (L0) polynomial terms
|
|
res.r = dot(globalSH[0], normal);
|
|
res.g = dot(globalSH[1], normal);
|
|
res.b = dot(globalSH[2], normal);
|
|
|
|
// 4 of the quadratic (L2) polynomials
|
|
half4 vB = normal.xyzz * normal.yzzx;
|
|
res.r += dot(globalSH[3], vB);
|
|
res.g += dot(globalSH[4], vB);
|
|
res.b += dot(globalSH[5], vB);
|
|
|
|
// Final (5th) quadratic (L2) polynomial
|
|
half vC = normal.x*normal.x - normal.y*normal.y;
|
|
res += globalSH[6].rgb * vC;
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
sampler2D _MainTex;
|
|
|
|
|
|
// Main pixel shader
|
|
half4 frag(v2f i) : SV_Target
|
|
{
|
|
half4 diffuseAlbedo = tex2D(_MainTex, i.uv);
|
|
|
|
// Ambient lighting
|
|
half4 color = half4(0,0,0, diffuseAlbedo.a);
|
|
color.rgb += EvaluateSH(i.normalWS) * diffuseAlbedo.rgb;
|
|
|
|
// Add illumination from all lights
|
|
for (int il = 0; il < globalLightCount.x; ++il)
|
|
{
|
|
color.rgb += ComputeOneLight(il, i.positionWS, i.normalWS, diffuseAlbedo);
|
|
}
|
|
return color;
|
|
}
|
|
|
|
ENDCG
|
|
}
|
|
}
|
|
|
|
CustomEditor "StandardShaderGUI"
|
|
}
|