public void SetupBounds(Decal decal) { if (decal == null) { return; } decal.SetupBounds(); }
public void AddOrUpdateDecal(Decal d) { RemoveDecal(d); if (d.DecalMaterial == null) { return; } if (m_Decals.Count == 0) { m_Decals.Add(d); } else { for (int i = 0; i <= m_Decals.Count; i++) { if (i == m_Decals.Count) { m_Decals.Add(d); break; } if (m_Decals[i].SortingOrder > d.SortingOrder) { m_Decals.Insert(i, d); break; } } } /*for (int i = 0; i < m_Decals.Count; i++) * { * Debug.LogWarning(m_Decals[i].name + " " + m_Decals[i].SortingOrder); * }*/ }
private void OnEnable() { decal = target as Decal; }
public void RemoveDecal(Decal d) { m_Decals.Remove(d); }
public void Render(Camera camera) { var cam = camera; if (!cam) { return; } // before lighting buffer CommandBuffer bufferBeforeLighting = null; if (m_Cameras.ContainsKey(cam)) { bufferBeforeLighting = m_Cameras[cam]; if (LockRebuild) { return; } bufferBeforeLighting.Clear(); } else { bufferBeforeLighting = new CommandBuffer(); bufferBeforeLighting.name = "Deferred decals"; m_Cameras[cam] = bufferBeforeLighting; // set this command buffer to be executed just before deferred lighting pass // in the camera var buffers = cam.GetCommandBuffers(CameraEvent.BeforeReflections); for (int i = 0; i < buffers.Length; i++) { if (buffers[i].name.Equals("Deferred decals")) { cam.RemoveCommandBuffer(CameraEvent.BeforeReflections, buffers[i]); } } cam.AddCommandBuffer(CameraEvent.BeforeReflections, bufferBeforeLighting); } if (UseExclusionMask) { if (!m_ExclusionMasks.TryGetValue(cam, out exclusionMaskRenderTarget)) { exclusionMaskRenderTarget = new RenderTexture(cam.pixelWidth, cam.pixelHeight, 16, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear); exclusionMaskRenderTarget.filterMode = FilterMode.Point; exclusionMaskRenderTarget.Create(); exclusionMaskRenderTarget.name = "Exclusion Mask for camera " + cam.name; m_ExclusionMasks.Add(cam, exclusionMaskRenderTarget); } if (exclusionMaskRenderTarget != null && (cam.pixelWidth != exclusionMaskRenderTarget.width || cam.pixelHeight != exclusionMaskRenderTarget.height)) { m_ExclusionMasks.Remove(cam); DestroyImmediate(exclusionMaskRenderTarget, true); exclusionMaskRenderTarget = new RenderTexture(cam.pixelWidth, cam.pixelHeight, 16, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear); exclusionMaskRenderTarget.filterMode = FilterMode.Point; exclusionMaskRenderTarget.Create(); exclusionMaskRenderTarget.name = "Exclusion Mask for camera " + cam.name; m_ExclusionMasks.Add(cam, exclusionMaskRenderTarget); } exclusionCamera.CopyFrom(cam); exclusionCamera.depth = cam.depth - 0.01f; exclusionCamera.transform.position = cam.transform.position; exclusionCamera.transform.rotation = cam.transform.rotation; exclusionCamera.cullingMask = ExclusionMask; exclusionCamera.targetTexture = exclusionMaskRenderTarget; exclusionCamera.renderingPath = RenderingPath.Forward; exclusionCamera.clearFlags = CameraClearFlags.Color; exclusionCamera.backgroundColor = Color.clear; exclusionCamera.RenderWithShader(depthShader, "RenderType"); bufferBeforeLighting.EnableShaderKeyword("EXCLUSIONMASK"); bufferBeforeLighting.SetGlobalTexture("_ExclusionMask", exclusionMaskRenderTarget); } else { bufferBeforeLighting.DisableShaderKeyword("EXCLUSIONMASK"); } bool isSceneViewCamera = cam.cameraType == CameraType.SceneView; CommandBuffer selectionBuffer = null; if (m_CamerasSceneview.ContainsKey(cam)) { selectionBuffer = m_CamerasSceneview[cam]; selectionBuffer.Clear(); } else { if (isSceneViewCamera) { selectionBuffer = new CommandBuffer(); selectionBuffer.name = "Deferred decals selection"; m_CamerasSceneview[cam] = selectionBuffer; // set this command buffer to be executed just before deferred lighting pass // in the camera var buffers = cam.GetCommandBuffers(CameraEvent.AfterLighting); for (int i = 0; i < buffers.Length; i++) { if (buffers[i].name.Equals("Deferred decals selection")) { cam.RemoveCommandBuffer(CameraEvent.AfterLighting, buffers[i]); } } cam.AddCommandBuffer(CameraEvent.AfterLighting, selectionBuffer); } } // frustum culling cameraPlanes = GeometryUtility.CalculateFrustumPlanes(camera); currentDecalsVisibility.Clear(); var system = DeferredDecalsManager.instance; // cache visibility for each decal if (FrustumCulling) { foreach (var decal in system.m_Decals) { if (decal == null) { continue; } SetupBounds(decal); bool isDecalVisible = IsBoundsVisible(cameraPlanes, decal.Bounds); currentDecalsVisibility.Add(decal, isDecalVisible); } } else { foreach (var decal in system.m_Decals) { if (decal == null) { continue; } currentDecalsVisibility.Add(decal, true); } } BuiltinRenderTextureType emissionTexture = cam.allowHDR ? BuiltinRenderTextureType.CameraTarget : BuiltinRenderTextureType.GBuffer3; // copy g-buffer normals into a temporary RT var normalsID = Shader.PropertyToID("_NormalsCopy"); bufferBeforeLighting.GetTemporaryRT(normalsID, -1, -1, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); bufferBeforeLighting.Blit(BuiltinRenderTextureType.GBuffer2, normalsID); // copy g-buffer specrough into a temporary RT var specularID = Shader.PropertyToID("_SpecularTarget"); bufferBeforeLighting.GetTemporaryRT(specularID, -1, -1, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); bufferBeforeLighting.Blit(BuiltinRenderTextureType.GBuffer1, specularID); // copy g-buffer specrough into a temporary RT var smoothnessID = Shader.PropertyToID("_SmoothnessTarget"); bufferBeforeLighting.GetTemporaryRT(smoothnessID, -1, -1, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); bufferBeforeLighting.Blit(BuiltinRenderTextureType.GBuffer1, smoothnessID, specularSmoothnessBlitterMaterial, 0); // copy g-buffer camera target into a temporary RT var emissionID = Shader.PropertyToID("_CameraTargetCopy"); bufferBeforeLighting.GetTemporaryRT(emissionID, -1, -1, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32); bufferBeforeLighting.Blit(emissionTexture, emissionID); instancedBlock.Clear(); var sortedDecalsBySortingOrder = system.m_Decals; decalsGrouped.Clear(); DecalsGroup groupKey; Vector3 camPos = cam.transform.position; float currentDistanceToCamera; float fadeFactor; foreach (var decal in sortedDecalsBySortingOrder) { if (!currentDecalsVisibility[decal]) { continue; } if (DistanceCulling) { currentDistanceToCamera = Vector3.Distance(camPos, decal.transform.position); if (currentDistanceToCamera >= StartFadeDistance + FadeLength) { continue; } fadeFactor = Mathf.InverseLerp(StartFadeDistance, StartFadeDistance + FadeLength, currentDistanceToCamera); decal.DistanceFade = 1 - fadeFactor; } else { decal.DistanceFade = 1f; } groupKey.Material = decal.DecalMaterial; groupKey.SortingOrder = decal.SortingOrder; groupKey.Instancing = decal.DecalMaterial.enableInstancing; List <Decal> decalsByMaterials; if (!decalsGrouped.TryGetValue(groupKey, out decalsByMaterials)) { decalsByMaterials = new List <Decal>(); decalsGrouped.Add(groupKey, decalsByMaterials); } decalsByMaterials.Add(decal); } RenderTargetIdentifier[] mrtDifNormSpecRough = { BuiltinRenderTextureType.GBuffer0, BuiltinRenderTextureType.GBuffer2, emissionTexture }; bufferBeforeLighting.SetRenderTarget(mrtDifNormSpecRough, BuiltinRenderTextureType.CameraTarget); Color tint; Vector4 uv; Vector4 uvOne = new Vector4(1, 1, 0, 0); foreach (var decalGroup in decalsGrouped) { var decalsList = decalGroup.Value; if (decalGroup.Key.Instancing) { bufferBeforeLighting.SetGlobalColor("_NotInstancedColor", Color.white); bufferBeforeLighting.SetGlobalVector("_NotInstancedUV", uvOne); int batchCount = 1 + Mathf.FloorToInt(decalsList.Count / 1024); for (int i = 0; i < batchCount; i++) { int drawCount = Mathf.Min(1023, decalsList.Count); for (int j = 0; j < drawCount; j++) { tintArray[j] = decalsList[j].InstancedColor; tintArray[j].w *= decalsList[j].Fade * decalsList[j].DistanceFade; uvArray[j] = decalsList[j].UV; matrices[j] = decalsList[j].transform.localToWorldMatrix; } if (drawCount > 0) { instancedBlock.SetVectorArray("_Tint", tintArray); instancedBlock.SetVectorArray("_UV", uvArray); bufferBeforeLighting.DrawMeshInstanced(CubeMesh, 0, decalGroup.Key.Material, 0, matrices, drawCount, instancedBlock); } } } else { foreach (var decal in decalsList) { tint = decal.InstancedColor; tint.a *= decal.Fade * decal.DistanceFade; bufferBeforeLighting.SetGlobalColor("_NotInstancedColor", tint); uv = decal.UV; bufferBeforeLighting.SetGlobalVector("_NotInstancedUV", uv); bufferBeforeLighting.DrawMesh(CubeMesh, decal.transform.localToWorldMatrix, decal.DecalMaterial, 0, 0); } } } mrtDifNormSpecRough = new RenderTargetIdentifier[] { specularID, smoothnessID }; bufferBeforeLighting.SetRenderTarget(mrtDifNormSpecRough, BuiltinRenderTextureType.CameraTarget); foreach (var decalGroup in decalsGrouped) { var decalsList = decalGroup.Value; if (decalGroup.Key.Instancing) { bufferBeforeLighting.SetGlobalColor("_NotInstancedColor", Color.white); bufferBeforeLighting.SetGlobalVector("_NotInstancedUV", uvOne); int batchCount = 1 + Mathf.FloorToInt(decalsList.Count / 1024); for (int i = 0; i < batchCount; i++) { int drawCount = Mathf.Min(1023, decalsList.Count); for (int j = 0; j < drawCount; j++) { tintArray[j] = decalsList[j].InstancedColor; tintArray[j].w *= decalsList[j].Fade; uvArray[j] = decalsList[j].UV; matrices[j] = decalsList[j].transform.localToWorldMatrix; } if (drawCount > 0) { instancedBlock.SetVectorArray("_Tint", tintArray); instancedBlock.SetVectorArray("_UV", uvArray); bufferBeforeLighting.DrawMeshInstanced(CubeMesh, 0, decalGroup.Key.Material, 2, matrices, drawCount, instancedBlock); } } } else { foreach (var decal in decalsList) { tint = decal.InstancedColor; tint.a *= decal.Fade; bufferBeforeLighting.SetGlobalColor("_NotInstancedColor", tint); uv = decal.UV; bufferBeforeLighting.SetGlobalVector("_NotInstancedUV", uv); bufferBeforeLighting.DrawMesh(CubeMesh, decal.transform.localToWorldMatrix, decal.DecalMaterial, 0, 2); } } } bufferBeforeLighting.SetGlobalTexture("_Alpha", smoothnessID); bufferBeforeLighting.Blit(specularID, BuiltinRenderTextureType.GBuffer1, specularSmoothnessBlitterMaterial, 1); if (TerrainDecals == TerrainDecalsType.MultiTerrain) { foreach (var d in system.m_Decals) { d.DecalMaterial.EnableKeyword("MULTI_TERRAIN_DECAL"); } } else { foreach (var d in system.m_Decals) { d.DecalMaterial.DisableKeyword("MULTI_TERRAIN_DECAL"); } } if (Terrain.activeTerrains == null || Terrain.activeTerrains.Length == 0) { foreach (var d in system.m_Decals) { d.DecalMaterial.EnableKeyword("NO_TERRAIN"); } } else { foreach (var d in system.m_Decals) { d.DecalMaterial.DisableKeyword("NO_TERRAIN"); } } if (TerrainDecals != TerrainDecalsType.None) { if (TerrainDecals == TerrainDecalsType.OneTerrain) { Terrain terrain = Terrain.activeTerrain; terrain.drawHeightmap = true; Shader.SetGlobalMatrix("_World2Terrain", terrain.transform.worldToLocalMatrix); Shader.SetGlobalTexture("_TerrainHeightMap", terrain.terrainData.heightmapTexture); Shader.SetGlobalVector("_TerrainSize", terrain.terrainData.size); } else if (TerrainDecals == TerrainDecalsType.MultiTerrain) { Terrain[] terrains = Terrain.activeTerrains; if (copyHeightmapsBuffer == null) { CopyHeightmaps(); } terrainsDataBuffer.SetData(terrainsData); SetupToShaders(); } } #if UNITY_EDITOR if (isSceneViewCamera) { float deltaTime = (float)(UnityEditor.EditorApplication.timeSinceStartup - lastRenderTime); lastRenderTime = UnityEditor.EditorApplication.timeSinceStartup; decalsToRemove.Clear(); foreach (var decalTime in lastSelectedDecals) { decalTime.Value.Value += deltaTime; if (decalTime.Value.Value >= selectionDuration) { decalsToRemove.Add(decalTime.Key); } } foreach (var decal in decalsToRemove) { lastSelectedDecals.Remove(decal); } var selectedObjects = UnityEditor.Selection.objects; if (selectedObjects != null) { selectionBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget, BuiltinRenderTextureType.CameraTarget); foreach (var o in selectedObjects) { GameObject go = o as GameObject; if (go != null) { Decal decal = go.GetComponent <Decal>(); if (decal != null) { FloatValue time; if (lastSelectedDecals.TryGetValue(decal, out time)) { tint = decal.InstancedColor; tint.a *= decal.Fade; selectionBuffer.SetGlobalColor("_NotInstancedColor", tint); uv = decal.UV; selectionBuffer.SetGlobalVector("_NotInstancedUV", uv); selectionBuffer.SetGlobalFloat("SelectionTime", selectionFadeCurve.Evaluate(time.Value / selectionDuration)); selectionBuffer.DrawMesh(CubeMesh, decal.transform.localToWorldMatrix, decal.DecalMaterial, 0, 1); // selection pass - 1 } } } } } } #endif // release temporary RT bufferBeforeLighting.ReleaseTemporaryRT(normalsID); bufferBeforeLighting.ReleaseTemporaryRT(specularID); if (selectionBuffer != null) { selectionBuffer.ReleaseTemporaryRT(normalsID); } }