public void DestroyDecalEntity(DecalEntity decalEntity) { if (!m_DecalEntityIndexer.IsValid(decalEntity)) { return; } var decalItem = m_DecalEntityIndexer.GetItem(decalEntity); m_DecalEntityIndexer.DestroyDecalEntity(decalEntity); int chunkIndex = decalItem.chunkIndex; int arrayIndex = decalItem.arrayIndex; DecalEntityChunk entityChunk = entityChunks[chunkIndex]; DecalCachedChunk cachedChunk = cachedChunks[chunkIndex]; DecalCulledChunk culledChunk = culledChunks[chunkIndex]; DecalDrawCallChunk drawCallChunk = drawCallChunks[chunkIndex]; int lastArrayIndex = entityChunk.count - 1; if (arrayIndex != lastArrayIndex) { m_DecalEntityIndexer.UpdateIndex(entityChunk.decalEntities[lastArrayIndex], arrayIndex); } entityChunk.RemoveAtSwapBack(arrayIndex); cachedChunk.RemoveAtSwapBack(arrayIndex); culledChunk.RemoveAtSwapBack(arrayIndex); drawCallChunk.RemoveAtSwapBack(arrayIndex); }
private void Execute(DecalEntityChunk entityChunk, DecalCachedChunk cachedChunk, int count) { if (count == 0) { return; } cachedChunk.currentJobHandle.Complete(); // Make sure draw order is up to date var material = entityChunk.material; if (material.HasProperty("_DrawOrder")) { cachedChunk.drawOrder = material.GetInt("_DrawOrder"); } // Shader can change any time in editor, so we have to update passes each time #if !UNITY_EDITOR if (!cachedChunk.isCreated) #endif { int passIndexDBuffer = material.FindPass(DecalShaderPassNames.DBufferProjector); cachedChunk.passIndexDBuffer = passIndexDBuffer; int passIndexEmissive = material.FindPass(DecalShaderPassNames.DecalProjectorForwardEmissive); cachedChunk.passIndexEmissive = passIndexEmissive; int passIndexScreenSpace = material.FindPass(DecalShaderPassNames.DecalScreenSpaceProjector); cachedChunk.passIndexScreenSpace = passIndexScreenSpace; int passIndexGBuffer = material.FindPass(DecalShaderPassNames.DecalGBufferProjector); cachedChunk.passIndexGBuffer = passIndexGBuffer; cachedChunk.isCreated = true; } using (new ProfilingScope(null, m_SamplerJob)) { UpdateTransformsJob updateTransformJob = new UpdateTransformsJob() { positions = cachedChunk.positions, rotations = cachedChunk.rotation, scales = cachedChunk.scales, dirty = cachedChunk.dirty, scaleModes = cachedChunk.scaleModes, sizeOffsets = cachedChunk.sizeOffsets, decalToWorlds = cachedChunk.decalToWorlds, normalToWorlds = cachedChunk.normalToWorlds, boundingSpheres = cachedChunk.boundingSpheres, minDistance = 0.0001f, }; var handle = updateTransformJob.Schedule(entityChunk.transformAccessArray); cachedChunk.currentJobHandle = handle; } }
public DecalEntity CreateDecalEntity(DecalProjector decalProjector) { var material = decalProjector.material; if (material == null) { material = errorMaterial; } using (new ProfilingScope(null, m_AddDecalSampler)) { int chunkIndex = CreateChunkIndex(material); int entityIndex = entityChunks[chunkIndex].count; DecalEntity entity = m_DecalEntityIndexer.CreateDecalEntity(entityIndex, chunkIndex); DecalEntityChunk entityChunk = entityChunks[chunkIndex]; DecalCachedChunk cachedChunk = cachedChunks[chunkIndex]; DecalCulledChunk culledChunk = culledChunks[chunkIndex]; DecalDrawCallChunk drawCallChunk = drawCallChunks[chunkIndex]; // Make sure we have space to add new entity if (entityChunks[chunkIndex].capacity == entityChunks[chunkIndex].count) { using (new ProfilingScope(null, m_ResizeChunks)) { int newCapacity = entityChunks[chunkIndex].capacity + entityChunks[chunkIndex].capacity; newCapacity = math.max(8, newCapacity); entityChunk.SetCapacity(newCapacity); cachedChunk.SetCapacity(newCapacity); culledChunk.SetCapacity(newCapacity); drawCallChunk.SetCapacity(newCapacity); } } entityChunk.Push(); cachedChunk.Push(); culledChunk.Push(); drawCallChunk.Push(); entityChunk.decalProjectors[entityIndex] = decalProjector; entityChunk.decalEntities[entityIndex] = entity; entityChunk.transformAccessArray.Add(decalProjector.transform); UpdateDecalEntityData(entity, decalProjector); return(entity); } }
public void UpdateDecalEntityData(DecalEntity decalEntity, DecalProjector decalProjector) { var decalItem = m_DecalEntityIndexer.GetItem(decalEntity); int chunkIndex = decalItem.chunkIndex; int arrayIndex = decalItem.arrayIndex; DecalCachedChunk cachedChunk = cachedChunks[chunkIndex]; cachedChunk.sizeOffsets[arrayIndex] = Matrix4x4.Translate(decalProjector.decalOffset) * Matrix4x4.Scale(decalProjector.decalSize); float drawDistance = decalProjector.drawDistance; float fadeScale = decalProjector.fadeScale; float startAngleFade = decalProjector.startAngleFade; float endAngleFade = decalProjector.endAngleFade; Vector4 uvScaleBias = decalProjector.uvScaleBias; int layerMask = decalProjector.gameObject.layer; ulong sceneLayerMask = decalProjector.gameObject.sceneCullingMask; float fadeFactor = decalProjector.fadeFactor; cachedChunk.drawDistances[arrayIndex] = new Vector2(drawDistance, fadeScale); // In the shader to remap from cosine -1 to 1 to new range 0..1 (with 0 - 0 degree and 1 - 180 degree) // we do 1.0 - (dot() * 0.5 + 0.5) => 0.5 * (1 - dot()) // we actually square that to get smoother result => x = (0.5 - 0.5 * dot())^2 // Do a remap in the shader. 1.0 - saturate((x - start) / (end - start)) // After simplification => saturate(a + b * dot() * (dot() - 2.0)) // a = 1.0 - (0.25 - start) / (end - start), y = - 0.25 / (end - start) if (startAngleFade == 180.0f) // angle fade is disabled { cachedChunk.angleFades[arrayIndex] = new Vector2(0.0f, 0.0f); } else { float angleStart = startAngleFade / 180.0f; float angleEnd = endAngleFade / 180.0f; var range = Mathf.Max(0.0001f, angleEnd - angleStart); cachedChunk.angleFades[arrayIndex] = new Vector2(1.0f - (0.25f - angleStart) / range, -0.25f / range); } cachedChunk.uvScaleBias[arrayIndex] = uvScaleBias; cachedChunk.layerMasks[arrayIndex] = layerMask; cachedChunk.sceneLayerMasks[arrayIndex] = sceneLayerMask; cachedChunk.fadeFactors[arrayIndex] = fadeFactor; cachedChunk.scaleModes[arrayIndex] = decalProjector.scaleMode; cachedChunk.positions[arrayIndex] = decalProjector.transform.position; cachedChunk.rotation[arrayIndex] = decalProjector.transform.rotation; cachedChunk.scales[arrayIndex] = decalProjector.transform.lossyScale; cachedChunk.dirty[arrayIndex] = true; }
public void Execute(DecalCachedChunk cachedChunk, DecalCulledChunk culledChunk, int count) { cachedChunk.currentJobHandle.Complete(); CullingGroup cullingGroup = culledChunk.cullingGroups; cullingGroup.targetCamera = m_Camera; cullingGroup.SetDistanceReferencePoint(m_Camera.transform.position); cullingGroup.SetBoundingDistances(m_BoundingDistance); cachedChunk.boundingSpheres.CopyTo(cachedChunk.boundingSphereArray); cullingGroup.SetBoundingSpheres(cachedChunk.boundingSphereArray); cullingGroup.SetBoundingSphereCount(count); culledChunk.cameraPosition = m_Camera.transform.position; culledChunk.cullingMask = m_Camera.cullingMask; #if UNITY_EDITOR culledChunk.sceneCullingMask = GetSceneCullingMaskFromCamera(m_Camera); #endif }
private void Draw(CommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int passIndex) { var mesh = m_EntityManager.decalProjectorMesh; var material = GetMaterial(decalEntityChunk); decalCachedChunk.propertyBlock.SetVector("unity_LightData", new Vector4(1, 1, 1, 0)); // GetMainLight requires z component to be set int subCallCount = decalDrawCallChunk.subCallCount; for (int i = 0; i < subCallCount; ++i) { var subCall = decalDrawCallChunk.subCalls[i]; for (int j = subCall.start; j < subCall.end; ++j) { decalCachedChunk.propertyBlock.SetMatrix("_NormalToWorld", decalDrawCallChunk.normalToDecals[j]); cmd.DrawMesh(mesh, decalDrawCallChunk.decalToWorlds[j], material, 0, passIndex, decalCachedChunk.propertyBlock); } } }
protected override int GetPassIndex(DecalCachedChunk decalCachedChunk) { switch (m_Technique) { case DecalTechnique.DBuffer: return(((decalCachedChunk.passIndexDBuffer == -1) && (decalCachedChunk.passIndexEmissive == -1)) ? 0 : -1); case DecalTechnique.ScreenSpace: return(decalCachedChunk.passIndexScreenSpace == -1 ? 0 : -1); case DecalTechnique.GBuffer: return(decalCachedChunk.passIndexGBuffer == -1 ? 0 : -1); case DecalTechnique.Invalid: return(0); default: return(0); } }
private void Execute(CommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int count) { decalCachedChunk.currentJobHandle.Complete(); decalDrawCallChunk.currentJobHandle.Complete(); Material material = GetMaterial(decalEntityChunk); int passIndex = GetPassIndex(decalCachedChunk); if (count == 0 || passIndex == -1 || material == null) { return; } if (SystemInfo.supportsInstancing && material.enableInstancing) { DrawInstanced(cmd, decalEntityChunk, decalCachedChunk, decalDrawCallChunk, passIndex); } else { Draw(cmd, decalEntityChunk, decalCachedChunk, decalDrawCallChunk, passIndex); } }
protected override int GetPassIndex(DecalCachedChunk decalCachedChunk) => decalCachedChunk.passIndexGBuffer;
protected override int GetPassIndex(DecalCachedChunk decalCachedChunk) => decalCachedChunk.passIndexEmissive;
private void DrawInstanced(CommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int passIndex) { var mesh = m_EntityManager.decalProjectorMesh; var material = GetMaterial(decalEntityChunk); decalCachedChunk.propertyBlock.SetVector("unity_LightData", new Vector4(1, 1, 1, 0)); // GetMainLight requires z component to be set int subCallCount = decalDrawCallChunk.subCallCount; for (int i = 0; i < subCallCount; ++i) { var subCall = decalDrawCallChunk.subCalls[i]; var decalToWorldSlice = decalDrawCallChunk.decalToWorlds.Reinterpret <Matrix4x4>(); NativeArray <Matrix4x4> .Copy(decalToWorldSlice, subCall.start, m_WorldToDecals, 0, subCall.count); var normalToWorldSlice = decalDrawCallChunk.normalToDecals.Reinterpret <Matrix4x4>(); NativeArray <Matrix4x4> .Copy(normalToWorldSlice, subCall.start, m_NormalToDecals, 0, subCall.count); decalCachedChunk.propertyBlock.SetMatrixArray("_NormalToWorld", m_NormalToDecals); cmd.DrawMeshInstanced(mesh, 0, material, passIndex, m_WorldToDecals, subCall.end - subCall.start, decalCachedChunk.propertyBlock); } }
protected abstract int GetPassIndex(DecalCachedChunk decalCachedChunk);
protected override int GetPassIndex(DecalCachedChunk decalCachedChunk) => decalCachedChunk.passIndexScreenSpace;