您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

273 行
8.8 KiB

// Shader targeted for LowEnd mobile devices. Single Pass Forward Rendering. Shader Model 2
//
// The parameters and inspector of the shader are the same as Standard shader,
// for easier experimentation.
Shader "RenderLoop/LowEnd"
{
// 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"
Pass
{
Tags { "LightMode" = "LowEndForwardBase" }
// Use same blending / depth states as Standard shader
Blend[_SrcBlend][_DstBlend]
ZWrite[_ZWrite]
CGPROGRAM
#pragma enable_d3d11_debug_symbols
#pragma target 2.0
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature _METALLICGLOSSMAP
#include "UnityCG.cginc"
#include "UnityStandardBRDF.cginc"
#include "UnityStandardUtils.cginc"
#define DEBUG_CASCADES 0
#define MAX_SHADOW_CASCADES 4
#define MAX_LIGHTS 8
// 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[MAX_LIGHTS];
float4 globalLightPos[MAX_LIGHTS];
float4 globalLightSpotDir[MAX_LIGHTS];
float4 globalLightAtten[MAX_LIGHTS];
int4 globalLightCount; // x: pixelLightCount, y = totalLightCount (pixel + vert)
// Global ambient/SH probe, similar to unity_SH* built-in variables.
float4 globalSH[7];
sampler2D _MainTex; float4 _MainTex_ST;
sampler2D _MetallicGlossMap;
sampler2D g_tShadowBuffer;
float _Metallic;
float _Glossiness;
float4x4 _WorldToShadow[MAX_SHADOW_CASCADES];
float _PSSMDistances[MAX_SHADOW_CASCADES - 1];
struct LightInput
{
half4 pos;
half4 color;
half4 atten;
half4 spotDir;
};
inline half3 EvaluateOneLight(LightInput lightInput, half3 diffuseColor, half3 specularColor, float3 normal, float3 posWorld, half3 viewDir)
{
float3 posToLight = lightInput.pos.xyz;
posToLight -= posWorld * lightInput.pos.w;
float distanceSqr = max(dot(posToLight, posToLight), 0.001);
float lightAtten = 1.0 / (1.0 + distanceSqr * lightInput.atten.z);
float3 lightDir = normalize(posToLight);
float SdotL = saturate(dot(lightInput.spotDir.xyz, lightDir));
lightAtten *= saturate((SdotL - lightInput.atten.x) / lightInput.atten.y);
float cutoff = step(distanceSqr, lightInput.atten.w);
lightAtten *= cutoff;
float NdotL = saturate(dot(normal, lightDir));
half3 halfVec = normalize(lightDir + viewDir);
half NdotH = saturate(dot(normal, halfVec));
half3 lightColor = lightInput.color.rgb * lightAtten;
half3 diffuse = diffuseColor * lightColor * NdotL;
half3 specular = specularColor * lightColor * pow(NdotH, 128.0f) * _Glossiness;
return diffuse + specular;
}
inline half3 EvaluateOneLightAndShadow(LightInput lightInput, half3 diffuseColor, half3 specularColor, float3 normal, float3 posWorld, half3 viewDir, half3 shadowCoord)
{
// TODO: Apply proper bias considering NdotL
half bias = 0.001;
half shadowDepth = tex2D(g_tShadowBuffer, shadowCoord.xy).r;
half shadowAttenuation = 1.0;
#if defined(UNITY_REVERSED_Z)
shadowAttenuation = step(shadowDepth - bias, shadowCoord.z);
#else
shadowAttenuation = step(shadowCoord.z - bias, shadowDepth);
#endif
half3 color = EvaluateOneLight(lightInput, diffuseColor, specularColor, normal, posWorld, viewDir);
return color * shadowAttenuation;
}
inline int ComputeCascadeIndex(float eyeZ)
{
for (int index = 0; index < MAX_SHADOW_CASCADES - 1; ++index)
{
if (eyeZ < _PSSMDistances[index])
return index;
}
return MAX_SHADOW_CASCADES - 2;
}
struct VertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float3 texcoord : TEXCOORD0;
};
// Vertex shader
struct v2f
{
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 color : TEXCOORD3;
float3 shadowCoord : TEXCOORD4;
float4 hpos : SV_POSITION;
};
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);
half eyePosZ = mul(UNITY_MATRIX_V, float4(o.positionWS, 1.0)).z;
half3 diffuseAndSpecularColor = half3(1.0, 1.0, 1.0);
half3 viewDir = normalize(_WorldSpaceCameraPos - o.positionWS);
int cascadeIndex = ComputeCascadeIndex(eyePosZ);
o.shadowCoord = mul(_WorldToShadow[3], float4(o.positionWS, 1.0));
for (int lightIndex = globalLightCount.x; lightIndex < globalLightCount.y; ++lightIndex)
{
LightInput lightInput;
lightInput.pos = globalLightPos[lightIndex];
lightInput.color = globalLightColor[lightIndex];
lightInput.atten = globalLightAtten[lightIndex];
lightInput.spotDir = globalLightSpotDir[lightIndex];
o.color += EvaluateOneLight(lightInput, diffuseAndSpecularColor, diffuseAndSpecularColor, o.normalWS, o.positionWS, viewDir);
}
#if DEBUG_CASCADES
half4 cascadeColors[MAX_SHADOW_CASCADES] = { half4(0.5, 0, 0, 1) , half4(0, 0.5, 0, 1) , half4(0, 0.0, 0.5, 1) , half4(0.5, 0, 0.5, 1) };
o.color = cascadeColors[cascadeIndex];
#endif
return o;
}
half4 frag(v2f i) : SV_Target
{
i.normalWS = normalize(i.normalWS);
half3 viewDir = normalize(_WorldSpaceCameraPos - i.positionWS);
half4 diffuseAlbedo = tex2D(_MainTex, i.uv);
half2 metalSmooth;
#ifdef _METALLICGLOSSMAP
metalSmooth = tex2D(_MetallicGlossMap, i.uv).ra;
#else
metalSmooth.r = _Metallic;
metalSmooth.g = _Glossiness;
#endif
half3 specColor;
half oneMinuReflectivity;
half3 diffuse = DiffuseAndSpecularFromMetallic(diffuseAlbedo.rgb, metalSmooth.x, specColor, oneMinuReflectivity);
half3 color = i.color * diffuseAlbedo.rgb;
#if !DEBUG_CASCADES
for (int lightIndex = 0; lightIndex < globalLightCount.x; ++lightIndex)
{
LightInput lightInput;
lightInput.pos = globalLightPos[lightIndex];
lightInput.color = globalLightColor[lightIndex];
lightInput.atten = globalLightAtten[lightIndex];
lightInput.spotDir = globalLightSpotDir[lightIndex];
if (lightIndex == 0)
color += EvaluateOneLightAndShadow(lightInput, diffuse, specColor, i.normalWS, i.positionWS, viewDir, i.shadowCoord);
else
color += EvaluateOneLight(lightInput, diffuse, specColor, i.normalWS, i.positionWS, viewDir);
}
#endif
return half4(color, diffuseAlbedo.a);
}
ENDCG
}
Pass
{
Tags { "Lightmode" = "ShadowCaster" }
ZWrite On ZTest LEqual
CGPROGRAM
#pragma enable_d3d11_debug_symbols
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 vert(float4 position : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(position);
}
half4 frag() : SV_TARGET
{
return 0;
}
ENDCG
}
}
CustomEditor "StandardShaderGUI"
}