1+ using UnityEngine ;
2+ using System . Collections ;
3+ using UnityEngine . Rendering ;
4+ using System . Collections . Generic ;
5+ using System ;
6+
7+ using UnityEditor ;
8+
9+ namespace UnityEngine . ScriptableRenderLoop
10+ {
11+ public class ForwardRenderLoop : ScriptableRenderLoop
12+ {
13+ [ MenuItem ( "Renderloop/CreateForwardRenderLoop" ) ]
14+ static void CreateForwardRenderLoop ( )
15+ {
16+ var instance = ScriptableObject . CreateInstance < ForwardRenderLoop > ( ) ;
17+ AssetDatabase . CreateAsset ( instance , "Assets/forwardrenderloop.asset" ) ;
18+ }
19+
20+ [ SerializeField ]
21+ ShadowSettings m_ShadowSettings = ShadowSettings . Default ;
22+ ShadowRenderPass m_ShadowPass ;
23+
24+
25+ const int MAX_LIGHTS = 10 ;
26+ const int MAX_SHADOWMAP_PER_LIGHTS = 6 ;
27+ const int MAX_DIRECTIONAL_SPLIT = 4 ;
28+ // Directional lights become spotlights at a far distance. This is the distance we pull back to set the spotlight origin.
29+ const float DIRECTIONAL_LIGHT_PULLBACK_DISTANCE = 10000.0f ;
30+
31+ [ NonSerialized ] private int m_nWarnedTooManyLights = 0 ;
32+
33+
34+ void OnEnable ( )
35+ {
36+ Rebuild ( ) ;
37+ }
38+
39+ void OnValidate ( )
40+ {
41+ Rebuild ( ) ;
42+ }
43+
44+ void Rebuild ( )
45+ {
46+ m_ShadowPass = new ShadowRenderPass ( m_ShadowSettings ) ;
47+ }
48+
49+ //---------------------------------------------------------------------------------------------------------------------------------------------------
50+ void UpdateLightConstants ( ActiveLight [ ] activeLights , ref ShadowOutput shadow )
51+ {
52+ int nNumLightsIncludingTooMany = 0 ;
53+
54+ int g_nNumLights = 0 ;
55+
56+ Vector4 [ ] g_vLightColor = new Vector4 [ MAX_LIGHTS ] ;
57+ Vector4 [ ] g_vLightPosition_flInvRadius = new Vector4 [ MAX_LIGHTS ] ;
58+ Vector4 [ ] g_vLightDirection = new Vector4 [ MAX_LIGHTS ] ;
59+ Vector4 [ ] g_vLightShadowIndex_vLightParams = new Vector4 [ MAX_LIGHTS ] ;
60+ Vector4 [ ] g_vLightFalloffParams = new Vector4 [ MAX_LIGHTS ] ;
61+ Vector4 [ ] g_vSpotLightInnerOuterConeCosines = new Vector4 [ MAX_LIGHTS ] ;
62+ Matrix4x4 [ ] g_matWorldToShadow = new Matrix4x4 [ MAX_LIGHTS * MAX_SHADOWMAP_PER_LIGHTS ] ;
63+ Vector4 [ ] g_vDirShadowSplitSpheres = new Vector4 [ MAX_DIRECTIONAL_SPLIT ] ;
64+
65+ for ( int nLight = 0 ; nLight < activeLights . Length ; nLight ++ )
66+ {
67+
68+ nNumLightsIncludingTooMany ++ ;
69+ if ( nNumLightsIncludingTooMany > MAX_LIGHTS )
70+ continue ;
71+
72+ ActiveLight light = activeLights [ nLight ] ;
73+ LightType lightType = light . lightType ;
74+ Vector3 position = light . light . transform . position ;
75+ Vector3 lightDir = light . light . transform . forward . normalized ;
76+ AdditionalLightData additionalLightData = light . light . GetComponent < AdditionalLightData > ( ) ;
77+
78+ // Setup shadow data arrays
79+ bool hasShadows = shadow . GetShadowSliceCountLightIndex ( nLight ) != 0 ;
80+
81+ if ( lightType == LightType . Directional )
82+ {
83+ g_vLightColor [ g_nNumLights ] = light . finalColor ;
84+ g_vLightPosition_flInvRadius [ g_nNumLights ] = new Vector4 (
85+ position . x - ( lightDir . x * DIRECTIONAL_LIGHT_PULLBACK_DISTANCE ) ,
86+ position . y - ( lightDir . y * DIRECTIONAL_LIGHT_PULLBACK_DISTANCE ) ,
87+ position . z - ( lightDir . z * DIRECTIONAL_LIGHT_PULLBACK_DISTANCE ) ,
88+ - 1.0f ) ;
89+ g_vLightDirection [ g_nNumLights ] = new Vector4 ( lightDir . x , lightDir . y , lightDir . z ) ;
90+ g_vLightShadowIndex_vLightParams [ g_nNumLights ] = new Vector4 ( 0 , 0 , 1 , 1 ) ;
91+ g_vLightFalloffParams [ g_nNumLights ] = new Vector4 ( 0.0f , 0.0f , float . MaxValue , ( float ) lightType ) ;
92+ g_vSpotLightInnerOuterConeCosines [ g_nNumLights ] = new Vector4 ( 0.0f , - 1.0f , 1.0f ) ;
93+
94+ if ( hasShadows )
95+ {
96+ for ( int s = 0 ; s < MAX_DIRECTIONAL_SPLIT ; ++ s )
97+ {
98+ g_vDirShadowSplitSpheres [ s ] = shadow . directionalShadowSplitSphereSqr [ s ] ;
99+ }
100+ }
101+ }
102+ else if ( lightType == LightType . Point )
103+ {
104+ g_vLightColor [ g_nNumLights ] = light . finalColor ;
105+
106+ g_vLightPosition_flInvRadius [ g_nNumLights ] = new Vector4 ( position . x , position . y , position . z , 1.0f / light . range ) ;
107+ g_vLightDirection [ g_nNumLights ] = new Vector4 ( 0.0f , 0.0f , 0.0f ) ;
108+ g_vLightShadowIndex_vLightParams [ g_nNumLights ] = new Vector4 ( 0 , 0 , 1 , 1 ) ;
109+ g_vLightFalloffParams [ g_nNumLights ] = new Vector4 ( 1.0f , 0.0f , light . range * light . range , ( float ) lightType ) ;
110+ g_vSpotLightInnerOuterConeCosines [ g_nNumLights ] = new Vector4 ( 0.0f , - 1.0f , 1.0f ) ;
111+ }
112+ else if ( lightType == LightType . Spot )
113+ {
114+ g_vLightColor [ g_nNumLights ] = light . finalColor ;
115+ g_vLightPosition_flInvRadius [ g_nNumLights ] = new Vector4 ( position . x , position . y , position . z , 1.0f / light . range ) ;
116+ g_vLightDirection [ g_nNumLights ] = new Vector4 ( lightDir . x , lightDir . y , lightDir . z ) ;
117+ g_vLightShadowIndex_vLightParams [ g_nNumLights ] = new Vector4 ( 0 , 0 , 1 , 1 ) ;
118+ g_vLightFalloffParams [ g_nNumLights ] = new Vector4 ( 1.0f , 0.0f , light . range * light . range , ( float ) lightType ) ;
119+
120+ float flInnerConePercent = AdditionalLightData . GetInnerSpotPercent01 ( additionalLightData ) ;
121+ float spotAngle = light . light . spotAngle ;
122+ float flPhiDot = Mathf . Clamp ( Mathf . Cos ( spotAngle * 0.5f * Mathf . Deg2Rad ) , 0.0f , 1.0f ) ; // outer cone
123+ float flThetaDot = Mathf . Clamp ( Mathf . Cos ( spotAngle * 0.5f * flInnerConePercent * Mathf . Deg2Rad ) , 0.0f , 1.0f ) ; // inner cone
124+ g_vSpotLightInnerOuterConeCosines [ g_nNumLights ] = new Vector4 ( flThetaDot , flPhiDot , 1.0f / Mathf . Max ( 0.01f , flThetaDot - flPhiDot ) ) ;
125+
126+ }
127+
128+ if ( hasShadows )
129+ {
130+ // Enable shadows
131+ g_vLightShadowIndex_vLightParams [ g_nNumLights ] . x = 1 ;
132+ for ( int s = 0 ; s < shadow . GetShadowSliceCountLightIndex ( nLight ) ; ++ s )
133+ {
134+ int shadowSliceIndex = shadow . GetShadowSliceIndex ( nLight , s ) ;
135+ g_matWorldToShadow [ g_nNumLights * MAX_SHADOWMAP_PER_LIGHTS + s ] = shadow . shadowSlices [ shadowSliceIndex ] . shadowTransform . transpose ;
136+ }
137+ }
138+
139+ g_nNumLights ++ ;
140+ }
141+
142+ // Warn if too many lights found
143+ if ( nNumLightsIncludingTooMany > MAX_LIGHTS )
144+ {
145+ if ( nNumLightsIncludingTooMany > m_nWarnedTooManyLights )
146+ {
147+ Debug . LogError ( "ERROR! Found " + nNumLightsIncludingTooMany + " runtime lights! Valve renderer supports up to " + MAX_LIGHTS +
148+ " active runtime lights at a time!\n Disabling " + ( nNumLightsIncludingTooMany - MAX_LIGHTS ) + " runtime light" +
149+ ( ( nNumLightsIncludingTooMany - MAX_LIGHTS ) > 1 ? "s" : "" ) + "!\n " ) ;
150+ }
151+ m_nWarnedTooManyLights = nNumLightsIncludingTooMany ;
152+ }
153+ else
154+ {
155+ if ( m_nWarnedTooManyLights > 0 )
156+ {
157+ m_nWarnedTooManyLights = 0 ;
158+ Debug . Log ( "SUCCESS! Found " + nNumLightsIncludingTooMany + " runtime lights which is within the supported number of lights, " + MAX_LIGHTS + ".\n \n " ) ;
159+ }
160+ }
161+
162+ // Send constants to shaders
163+ Shader . SetGlobalInt ( "g_nNumLights" , g_nNumLights ) ;
164+
165+ // New method for Unity 5.4 to set arrays of constants
166+ Shader . SetGlobalVectorArray ( "g_vLightPosition_flInvRadius" , g_vLightPosition_flInvRadius ) ;
167+ Shader . SetGlobalVectorArray ( "g_vLightColor" , g_vLightColor ) ;
168+ Shader . SetGlobalVectorArray ( "g_vLightDirection" , g_vLightDirection ) ;
169+ Shader . SetGlobalVectorArray ( "g_vLightShadowIndex_vLightParams" , g_vLightShadowIndex_vLightParams ) ;
170+ Shader . SetGlobalVectorArray ( "g_vLightFalloffParams" , g_vLightFalloffParams ) ;
171+ Shader . SetGlobalVectorArray ( "g_vSpotLightInnerOuterConeCosines" , g_vSpotLightInnerOuterConeCosines ) ;
172+ Shader . SetGlobalMatrixArray ( "g_matWorldToShadow" , g_matWorldToShadow ) ;
173+ Shader . SetGlobalVectorArray ( "g_vDirShadowSplitSpheres" , g_vDirShadowSplitSpheres ) ;
174+
175+ // Time
176+ #if ( UNITY_EDITOR )
177+ {
178+ Shader . SetGlobalFloat ( "g_flTime" , Time . realtimeSinceStartup ) ;
179+ //Debug.Log( "Time " + Time.realtimeSinceStartup );
180+ }
181+ #else
182+ {
183+ Shader . SetGlobalFloat ( "g_flTime" , Time . timeSinceLevelLoad ) ;
184+ //Debug.Log( "Time " + Time.timeSinceLevelLoad );
185+ }
186+ #endif
187+
188+ // PCF 3x3 Shadows
189+ float flTexelEpsilonX = 1.0f / m_ShadowSettings . shadowAtlasWidth ;
190+ float flTexelEpsilonY = 1.0f / m_ShadowSettings . shadowAtlasHeight ;
191+ Vector4 g_vShadow3x3PCFTerms0 = new Vector4 ( 20.0f / 267.0f , 33.0f / 267.0f , 55.0f / 267.0f , 0.0f ) ;
192+ Vector4 g_vShadow3x3PCFTerms1 = new Vector4 ( flTexelEpsilonX , flTexelEpsilonY , - flTexelEpsilonX , - flTexelEpsilonY ) ;
193+ Vector4 g_vShadow3x3PCFTerms2 = new Vector4 ( flTexelEpsilonX , flTexelEpsilonY , 0.0f , 0.0f ) ;
194+ Vector4 g_vShadow3x3PCFTerms3 = new Vector4 ( - flTexelEpsilonX , - flTexelEpsilonY , 0.0f , 0.0f ) ;
195+
196+ Shader . SetGlobalVector ( "g_vShadow3x3PCFTerms0" , g_vShadow3x3PCFTerms0 ) ;
197+ Shader . SetGlobalVector ( "g_vShadow3x3PCFTerms1" , g_vShadow3x3PCFTerms1 ) ;
198+ Shader . SetGlobalVector ( "g_vShadow3x3PCFTerms2" , g_vShadow3x3PCFTerms2 ) ;
199+ Shader . SetGlobalVector ( "g_vShadow3x3PCFTerms3" , g_vShadow3x3PCFTerms3 ) ;
200+ }
201+
202+ public override void Render ( Camera [ ] cameras , RenderLoop renderLoop )
203+ {
204+ foreach ( var camera in cameras )
205+ {
206+ CullResults cullResults ;
207+ CullingParameters cullingParams ;
208+ if ( ! CullResults . GetCullingParameters ( camera , out cullingParams ) )
209+ continue ;
210+
211+ m_ShadowPass . UpdateCullingParameters ( ref cullingParams ) ;
212+
213+ cullResults = CullResults . Cull ( ref cullingParams , renderLoop ) ;
214+
215+ ShadowOutput shadows ;
216+ m_ShadowPass . Render ( renderLoop , cullResults , out shadows ) ;
217+
218+ renderLoop . SetupCameraProperties ( camera ) ;
219+
220+ UpdateLightConstants ( cullResults . culledLights , ref shadows ) ;
221+
222+ DrawRendererSettings settings = new DrawRendererSettings ( cullResults , camera , new ShaderPassName ( "ForwardBase" ) ) ;
223+ settings . rendererConfiguration = RendererConfiguration . ConfigureOneLightProbePerRenderer | RendererConfiguration . ConfigureReflectionProbesProbePerRenderer ;
224+ settings . sorting . sortOptions = SortOptions . SortByMaterialThenMesh ;
225+
226+ renderLoop . DrawRenderers ( ref settings ) ;
227+ renderLoop . Submit ( ) ;
228+ }
229+
230+ // Post effects
231+ }
232+ }
233+ }
0 commit comments