public void Add(Decal decal, GameObject limitTo) { switch (decal.RenderMode) { case Decal.DecalRenderMode.Deferred: AddDeferred(decal); break; case Decal.DecalRenderMode.Unlit: AddUnlit(decal); break; default: break; } }
protected void AddUnlit(Decal decal) { if (!_unlitDecals.ContainsKey(decal.RenderOrder)) { _unlitDecals.Add(decal.RenderOrder, new Dictionary <Material, HashSet <Decal> >()); } var dict = _unlitDecals[decal.RenderOrder]; if (!dict.ContainsKey(decal.Material)) { dict.Add(decal.Material, new HashSet <Decal>() { decal }); } else { dict[decal.Material].Add(decal); } }
private void DrawUnlitDecals(Camera cam) { if (_unlitDecals.Count == 0) { return; } // Render third pass: unlit decals _bufferUnlit.SetRenderTarget(BuiltinRenderTextureType.CameraTarget); // Traverse over decal render order values var allRenderOrderEnum = _unlitDecals.GetEnumerator(); while (allRenderOrderEnum.MoveNext()) { var allDecalEnum = allRenderOrderEnum.Current.Value.GetEnumerator(); while (allDecalEnum.MoveNext()) { Material material = allDecalEnum.Current.Key; HashSet <Decal> decals = allDecalEnum.Current.Value; int n = 0; var decalListEnum = decals.GetEnumerator(); while (decalListEnum.MoveNext()) { Decal decal = decalListEnum.Current; if (decal != null) { #if UNITY_5_5_OR_NEWER if (UseInstancing) { _matrices[n] = decal.transform.localToWorldMatrix; _fadeValues[n] = decal.Fade; _limitToValues[n] = decal.LimitTo ? decal.LimitTo.GetInstanceID() : float.NaN; ++n; if (n == 1023) { _instancedBlock.Clear(); _instancedBlock.SetFloatArray("_MaskMultiplier", _fadeValues); _instancedBlock.SetFloatArray("_LimitTo", _limitToValues); _bufferUnlit.DrawMeshInstanced(_cubeMesh, 0, material, 0, _matrices, n, _instancedBlock); n = 0; } } else #endif { _instancedBlock.Clear(); _instancedBlock.SetFloat("_MaskMultiplier", decal.Fade); _instancedBlock.SetFloat("_LimitTo", decal.LimitTo ? decal.LimitTo.GetInstanceID() : float.NaN); _bufferUnlit.DrawMesh(_cubeMesh, decal.transform.localToWorldMatrix, material, 0, 0, _instancedBlock); } } } #if UNITY_5_5_OR_NEWER if (UseInstancing && n > 0) { _instancedBlock.Clear(); _instancedBlock.SetFloatArray("_MaskMultiplier", _fadeValues); _instancedBlock.SetFloatArray("_LimitTo", _limitToValues); _bufferUnlit.DrawMeshInstanced(_cubeMesh, 0, material, 0, _matrices, n, _instancedBlock); } #endif } } }
private void DrawDeferredDecals_NormSpecSmooth(Camera cam) { if (_deferredDecals.Count == 0) { return; } var copy1id = Shader.PropertyToID("_CameraGBufferTexture1Copy"); _bufferDeferred.GetTemporaryRT(copy1id, -1, -1, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); var copy2id = Shader.PropertyToID("_CameraGBufferTexture2Copy"); _bufferDeferred.GetTemporaryRT(copy2id, -1, -1, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); // Traverse over decal render order values var allRenderOrderEnum = _deferredDecals.GetEnumerator(); while (allRenderOrderEnum.MoveNext()) { // Render second pass: specular / smoothness and normals var allDecalEnum = allRenderOrderEnum.Current.Value.GetEnumerator(); while (allDecalEnum.MoveNext()) { Material material = allDecalEnum.Current.Key; HashSet <Decal> decals = allDecalEnum.Current.Value; int n = 0; var decalListEnum = decals.GetEnumerator(); while (decalListEnum.MoveNext()) { Decal decal = decalListEnum.Current; if (decal != null && decal.DrawNormalAndGloss) { if (decal.HighQualityBlending) { // Create of copy of GBuffer1 (specular / smoothness) and GBuffer 2 (normal) _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer1, copy1id); _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer2, copy2id); _bufferDeferred.SetRenderTarget(_normalRenderTarget, BuiltinRenderTextureType.CameraTarget); _instancedBlock.Clear(); _instancedBlock.SetFloat("_MaskMultiplier", decal.Fade); _instancedBlock.SetFloat("_LimitTo", decal.LimitTo ? decal.LimitTo.GetInstanceID() : float.NaN); _bufferDeferred.DrawMesh(_cubeMesh, decal.transform.localToWorldMatrix, material, 0, 1, _instancedBlock); } else { #if UNITY_5_5_OR_NEWER if (UseInstancing) { // Instanced drawing _matrices[n] = decal.transform.localToWorldMatrix; _fadeValues[n] = decal.Fade; _limitToValues[n] = decal.LimitTo ? decal.LimitTo.GetInstanceID() : float.NaN; ++n; if (n == 1023) { // Create of copy of GBuffer1 (specular / smoothness) and GBuffer 2 (normal) _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer1, copy1id); _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer2, copy2id); _bufferDeferred.SetRenderTarget(_normalRenderTarget, BuiltinRenderTextureType.CameraTarget); _instancedBlock.Clear(); _instancedBlock.SetFloatArray("_MaskMultiplier", _fadeValues); _instancedBlock.SetFloatArray("_LimitTo", _limitToValues); _bufferDeferred.DrawMeshInstanced(_cubeMesh, 0, material, 1, _matrices, n, _instancedBlock); n = 0; } } else #endif { if (n == 0) { // Create of copy of GBuffer1 (specular / smoothness) and GBuffer 2 (normal) _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer1, copy1id); _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer2, copy2id); } _bufferDeferred.SetRenderTarget(_normalRenderTarget, BuiltinRenderTextureType.CameraTarget); _instancedBlock.Clear(); _instancedBlock.SetFloat("_MaskMultiplier", decal.Fade); _instancedBlock.SetFloat("_LimitTo", decal.LimitTo ? decal.LimitTo.GetInstanceID() : float.NaN); _bufferDeferred.DrawMesh(_cubeMesh, decal.transform.localToWorldMatrix, material, 0, 1, _instancedBlock); ++n; } } } } #if UNITY_5_5_OR_NEWER if (UseInstancing && n > 0) { // Create of copy of GBuffer1 (specular / smoothness) and GBuffer 2 (normal) _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer1, copy1id); _bufferDeferred.Blit(BuiltinRenderTextureType.GBuffer2, copy2id); _bufferDeferred.SetRenderTarget(_normalRenderTarget, BuiltinRenderTextureType.CameraTarget); _instancedBlock.Clear(); _instancedBlock.SetFloatArray("_MaskMultiplier", _fadeValues); _instancedBlock.SetFloatArray("_LimitTo", _limitToValues); _bufferDeferred.DrawMeshInstanced(_cubeMesh, 0, material, 1, _matrices, n, _instancedBlock); } #endif } } }
private void DrawDeferredDecals_Albedo(Camera cam) { if (_deferredDecals.Count == 0) { return; } // Render first pass: albedo _bufferDeferred.SetRenderTarget(_albedoRenderTarget, BuiltinRenderTextureType.CameraTarget); // Traverse over decal render order values var allRenderOrderEnum = _deferredDecals.GetEnumerator(); while (allRenderOrderEnum.MoveNext()) { var allMaterialEnum = allRenderOrderEnum.Current.Value.GetEnumerator(); while (allMaterialEnum.MoveNext()) { Material material = allMaterialEnum.Current.Key; HashSet <Decal> decals = allMaterialEnum.Current.Value; int decalCount = decals.Count; int n = 0; var decalListEnum = decals.GetEnumerator(); while (decalListEnum.MoveNext()) { Decal decal = decalListEnum.Current; if (decal != null && decal.DrawAlbedo) { #if UNITY_5_5_OR_NEWER if (UseInstancing && !decal.UseLightProbes) { _matrices[n] = decal.transform.localToWorldMatrix; _fadeValues[n] = decal.Fade; _limitToValues[n] = decal.LimitTo ? decal.LimitTo.GetInstanceID() : float.NaN; ++n; if (n == 1023) { _instancedBlock.Clear(); _instancedBlock.SetFloatArray("_MaskMultiplier", _fadeValues); _instancedBlock.SetFloatArray("_LimitTo", _limitToValues); SetLightProbeOnBlock(RenderSettings.ambientProbe, _instancedBlock); _bufferDeferred.DrawMeshInstanced(_cubeMesh, 0, material, 0, _matrices, n, _instancedBlock); n = 0; } } else #endif { // Fall back to non-instanced rendering _directBlock.Clear(); _directBlock.SetFloat("_MaskMultiplier", decal.Fade); _directBlock.SetFloat("_LimitTo", decal.LimitTo ? decal.LimitTo.GetInstanceID() : float.NaN); // Interpolate a light probe for this probe, if requested if (decal.UseLightProbes) { SphericalHarmonicsL2 probe; // TODO: GC allocs due to GetComponent? LightProbes.GetInterpolatedProbe(decal.transform.position, decal.GetComponent <MeshRenderer>(), out probe); SetLightProbeOnBlock(probe, _directBlock); } _bufferDeferred.DrawMesh(_cubeMesh, decal.transform.localToWorldMatrix, material, 0, 0, _directBlock); } } } #if UNITY_5_5_OR_NEWER if (UseInstancing && n > 0) { _instancedBlock.Clear(); _instancedBlock.SetFloatArray("_MaskMultiplier", _fadeValues); _instancedBlock.SetFloatArray("_LimitTo", _limitToValues); SetLightProbeOnBlock(RenderSettings.ambientProbe, _instancedBlock); _bufferDeferred.DrawMeshInstanced(_cubeMesh, 0, material, 0, _matrices, n, _instancedBlock); } #endif } } }