|
|
|
|
|
|
// for easier experimentation. |
|
|
|
Shader "RenderLoop/LowEnd" |
|
|
|
{ |
|
|
|
// Properties is just a copy of Standard.shader. Our example shader does not use all of them, |
|
|
|
// Properties is just a copy of Standard (Specular Setup).shader. Our example shader does not use all of them, |
|
|
|
|
|
|
|
|
|
|
|
_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" {} |
|
|
|
_GlossMapScale("Smoothness Factor", Range(0.0, 1.0)) = 1.0 |
|
|
|
[Enum(Specular Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 |
|
|
|
|
|
|
|
_SpecColor("Specular", Color) = (0.2,0.2,0.2) |
|
|
|
_SpecGlossMap("Specular", 2D) = "white" {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Blending state |
|
|
|
[HideInInspector] _Mode("__mode", Float) = 0.0 |
|
|
|
[HideInInspector] _SrcBlend("__src", Float) = 1.0 |
|
|
|
[HideInInspector] _DstBlend("__dst", Float) = 0.0 |
|
|
|
|
|
|
// 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" |
|
|
|
//UsePass "Standard/ShadowCaster" |
|
|
|
//UsePass "Standard (Specular setup)/FORWARD" |
|
|
|
//UsePass "Standard (Specular setup)/FORWARD_DELTA" |
|
|
|
Name "SINGLE_PASS_FORWARD" |
|
|
|
Tags { "LightMode" = "LowEndForwardBase" } |
|
|
|
|
|
|
|
// Use same blending / depth states as Standard shader |
|
|
|
|
|
|
#pragma target 2.0 |
|
|
|
#pragma vertex vert |
|
|
|
#pragma fragment frag |
|
|
|
#pragma shader_feature _METALLICGLOSSMAP |
|
|
|
#pragma shader_feature _SPECGLOSSMAP |
|
|
|
#pragma shader_feature LIGHTMAP_ON |
|
|
|
|
|
|
|
#pragma only_renderers d3d9 d3d11 d3d11_9x glcore gles gles3 |
|
|
|
|
|
|
|
#include "UnityCG.cginc" |
|
|
|
#include "UnityStandardBRDF.cginc" |
|
|
|
|
|
|
half4 spotDir; |
|
|
|
}; |
|
|
|
|
|
|
|
// 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; |
|
|
|
} |
|
|
|
|
|
|
|
inline int ComputeCascadeIndex(half eyeZ) |
|
|
|
{ |
|
|
|
// PSSMDistance is set to infinity for non active cascades. This way the comparison for unavailable cascades will always be zero. |
|
|
|
|
|
|
float distanceSqr = max(dot(posToLight, posToLight), 0.001); |
|
|
|
float lightAtten = 1.0 / (1.0 + distanceSqr * lightInput.atten.z); |
|
|
|
|
|
|
|
float3 lightDir = normalize(posToLight); |
|
|
|
float3 lightDir = posToLight * rsqrt(distanceSqr); |
|
|
|
float SdotL = saturate(dot(lightInput.spotDir.xyz, lightDir)); |
|
|
|
lightAtten *= saturate((SdotL - lightInput.atten.x) / lightInput.atten.y); |
|
|
|
|
|
|
|
|
|
|
shadowCoord.z = saturate(shadowCoord.z); |
|
|
|
|
|
|
|
// TODO: Apply proper bias considering NdotL |
|
|
|
half bias = 0.001; |
|
|
|
half bias = 0.0005; |
|
|
|
half shadowDepth = tex2D(g_tShadowBuffer, shadowCoord.xy).r; |
|
|
|
half shadowAttenuation = 1.0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct v2f |
|
|
|
{ |
|
|
|
float2 uv0 : TEXCOORD0; |
|
|
|
float2 uv1 : TEXCOORD1; |
|
|
|
float4 posWS : TEXCOORD2; // xyz: posWorld, w: eyeZ |
|
|
|
half4 normalWS : TEXCOORD3; // xyz: normal, w: fresnel term |
|
|
|
half3 tangentWS : TEXCOORD4; |
|
|
|
half3 binormalWS : TEXCOORD5; |
|
|
|
half4 viewDir : TEXCOORD6; // xyz: viewDir, w: grazingTerm; |
|
|
|
UNITY_FOG_COORDS_PACKED(7, half4) // x: fogCoord, yzw: vertexColor |
|
|
|
float4 uv01 : TEXCOORD0; // uv01.xy: uv0, uv01.zw: uv1 |
|
|
|
float4 posWS : TEXCOORD1; // xyz: posWorld, w: eyeZ |
|
|
|
half4 normalWS : TEXCOORD2;// xyz: normal, w: fresnel term |
|
|
|
half3 tangentWS : TEXCOORD3; |
|
|
|
half3 binormalWS : TEXCOORD4; |
|
|
|
half4 viewDir : TEXCOORD5; // xyz: viewDir, w: grazingTerm; |
|
|
|
UNITY_FOG_COORDS_PACKED(6, half4) // x: fogCoord, yzw: vertexColor |
|
|
|
float4 hpos : SV_POSITION; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex); |
|
|
|
o.uv1 = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw; |
|
|
|
UNITY_INITIALIZE_OUTPUT(v2f, o); |
|
|
|
|
|
|
|
o.uv01.xy = TRANSFORM_TEX(v.texcoord, _MainTex); |
|
|
|
o.uv01.zw = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw; |
|
|
|
|
|
|
|
o.posWS.xyz = mul(unity_ObjectToWorld, v.vertex).xyz; |
|
|
|
o.posWS.w = -UnityObjectToViewPos(v.vertex).z; |
|
|
|
|
|
|
|
|
|
|
half sign = v.tangent.w * unity_WorldTransformParams.w; |
|
|
|
o.tangentWS = UnityObjectToWorldDir(v.tangent); |
|
|
|
o.binormalWS = cross(o.normalWS.xyz, o.tangentWS) * v.tangent.w; |
|
|
|
#else |
|
|
|
o.tangentWS = half3(1, 0, 0); |
|
|
|
o.binormalWS = half3(0, 1, 0); |
|
|
|
#endif |
|
|
|
|
|
|
|
half3 diffuseAndSpecularColor = half3(1.0, 1.0, 1.0); |
|
|
|
|
|
|
o.fogCoord.yzw += EvaluateOneLight(lightInput, diffuseAndSpecularColor, diffuseAndSpecularColor, o.normalWS, o.posWS.xyz, o.viewDir.xyz); |
|
|
|
} |
|
|
|
|
|
|
|
o.fogCoord.x = 1.0; |
|
|
|
UNITY_TRANSFER_FOG(o, o.hpos); |
|
|
|
return o; |
|
|
|
} |
|
|
|
|
|
|
#if _NORMALMAP |
|
|
|
half3 normalmap = UnpackNormal(tex2D(_BumpMap, i.uv0)); |
|
|
|
half3 normalmap = UnpackNormal(tex2D(_BumpMap, i.uv01.xy)); |
|
|
|
|
|
|
|
// TODO: This will generate unoptimized code from the glsl compiler. Store the transpose matrix and compute dot manually |
|
|
|
half3x3 tangentToWorld = half3x3(i.tangentWS, i.binormalWS, i.normalWS.xyx); |
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
half4 diffuseAlbedo = tex2D(_MainTex, i.uv0); |
|
|
|
half2 metalSmooth; |
|
|
|
#ifdef _METALLICGLOSSMAP |
|
|
|
metalSmooth = tex2D(_MetallicGlossMap, i.uv0).ra; |
|
|
|
#else |
|
|
|
metalSmooth.r = _Metallic; |
|
|
|
metalSmooth.g = _Glossiness; |
|
|
|
#endif |
|
|
|
half occlusion = Occlusion(i.uv0.xy); |
|
|
|
half3 emission = Emission(i.uv0.xy); |
|
|
|
half4 diffuseAlbedo = tex2D(_MainTex, i.uv01.xy); |
|
|
|
half3 diffuse = diffuseAlbedo.rgb * _Color.rgb; |
|
|
|
half alpha = diffuseAlbedo.a * _Color.a; |
|
|
|
half3 specular; |
|
|
|
half oneMinuReflectivity; |
|
|
|
half3 diffuse = DiffuseAndSpecularFromMetallic(diffuseAlbedo.rgb, metalSmooth.x, specular, oneMinuReflectivity); |
|
|
|
half4 specGloss = SpecularGloss(i.uv01.xy); |
|
|
|
half3 specular = specGloss.rgb; |
|
|
|
half smoothness = specGloss.a; |
|
|
|
half oneMinusReflectivity; |
|
|
|
diffuse = EnergyConservationBetweenDiffuseAndSpecular(diffuse, specular, /*out*/ oneMinusReflectivity); |
|
|
|
|
|
|
|
giIndirect.diffuse = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1)) * occlusion; |
|
|
|
#ifdef LIGHTMAP_ON |
|
|
|
giIndirect.diffuse = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv01.zw)); |
|
|
|
#else |
|
|
|
giIndirect.diffuse = half3(0, 0, 0); |
|
|
|
#endif |
|
|
|
giIndirect.specular = half3(0, 0, 0); |
|
|
|
half3 indirectColor = BRDF3_Indirect(diffuse, specular, giIndirect, i.posWS.w, i.normalWS.w); |
|
|
|
|
|
|
|
|
|
|
#if DEBUG_CASCADES |
|
|
|
return half4(EvaluateMainLight(mainLight, diffuse, specular, normal, i.posWS, viewDir), 1.0); |
|
|
|
#endif |
|
|
|
|
|
|
|
directColor += EvaluateMainLight(mainLight, diffuse, specular, normal, i.posWS, viewDir); |
|
|
|
|
|
|
|
// Compute direct contribution from additional lights. |
|
|
|
|
|
|
directColor += EvaluateOneLight(additionalLight, diffuse, specular, normal, posWorld, viewDir); |
|
|
|
} |
|
|
|
|
|
|
|
half3 color = directColor + indirectColor + emission; |
|
|
|
half3 color = directColor + indirectColor + _EmissionColor; |
|
|
|
} |
|
|
|
}; |
|
|
|
Name "SHADOW_CASTER" |
|
|
|
Tags { "Lightmode" = "ShadowCaster" } |
|
|
|
|
|
|
|
ZWrite On ZTest LEqual Cull Front |
|
|
|
|
|
|
ENDCG |
|
|
|
} |
|
|
|
} |
|
|
|
Fallback "RenderLoop/Error" |
|
|
|
CustomEditor "StandardShaderGUI" |
|
|
|
} |