| 187 | } |
| 188 | |
| 189 | void DrawEmitterCPU(RenderContextBatch& renderContextBatch, ParticleBuffer* buffer, DrawCall& drawCall, DrawPass drawModes, StaticFlags staticFlags, const BoundingSphere& bounds, uint32 renderModulesIndices, int8 sortOrder) |
| 190 | { |
| 191 | // Skip if CPU buffer is empty |
| 192 | if (buffer->CPU.Count == 0) |
| 193 | return; |
| 194 | const auto context = GPUDevice::Instance->GetMainContext(); |
| 195 | auto emitter = buffer->Emitter; |
| 196 | |
| 197 | // Check if need to perform any particles sorting |
| 198 | if (EmitterUseSorting(renderContextBatch, buffer, drawModes, bounds) && (buffer->CPU.Count != 0 || buffer->GPU.SortedIndices)) |
| 199 | { |
| 200 | // Prepare sorting data |
| 201 | if (!buffer->GPU.SortedIndices) |
| 202 | buffer->AllocateSortBuffer(); |
| 203 | |
| 204 | // Execute all sorting modules |
| 205 | for (int32 moduleIndex = 0; moduleIndex < emitter->Graph.SortModules.Count(); moduleIndex++) |
| 206 | { |
| 207 | auto module = emitter->Graph.SortModules[moduleIndex]; |
| 208 | const int32 sortedIndicesOffset = module->SortedIndicesOffset; |
| 209 | const auto sortMode = static_cast<ParticleSortMode>(module->Values[2].AsInt); |
| 210 | const int32 stride = buffer->Stride; |
| 211 | const int32 listSize = buffer->CPU.Count; |
| 212 | const int32 indicesByteSize = listSize * buffer->GPU.SortedIndices->GetStride(); |
| 213 | RenderListAlloc sortingAllocs[4]; |
| 214 | auto* renderList = renderContextBatch.GetMainContext().List; |
| 215 | uint32* sortingKeys[2] = { sortingAllocs[0].Init<uint32>(renderList, listSize), sortingAllocs[1].Init<uint32>(renderList, listSize) }; |
| 216 | void* sortingIndices[2] = { sortingAllocs[2].Init(renderList, indicesByteSize, GPU_SHADER_DATA_ALIGNMENT), sortingAllocs[3].Init(renderList, indicesByteSize, GPU_SHADER_DATA_ALIGNMENT) }; |
| 217 | uint32* sortedKeys = sortingKeys[0]; |
| 218 | const uint32 sortKeyXor = sortMode != ParticleSortMode::CustomAscending ? MAX_uint32 : 0; |
| 219 | switch (sortMode) |
| 220 | { |
| 221 | case ParticleSortMode::ViewDepth: |
| 222 | { |
| 223 | const int32 positionOffset = emitter->Graph.GetPositionAttributeOffset(); |
| 224 | if (positionOffset == -1) |
| 225 | break; |
| 226 | const Matrix viewProjection = renderContextBatch.GetMainContext().View.ViewProjection(); |
| 227 | const byte* positionPtr = buffer->CPU.Buffer.Get() + positionOffset; |
| 228 | if (emitter->SimulationSpace == ParticlesSimulationSpace::Local) |
| 229 | { |
| 230 | for (int32 i = 0; i < buffer->CPU.Count; i++) |
| 231 | { |
| 232 | // TODO: use SIMD |
| 233 | sortedKeys[i] = RenderTools::ComputeDistanceSortKey(Matrix::TransformPosition(viewProjection, Matrix::TransformPosition(drawCall.World, *(const Float3*)positionPtr)).W) ^ sortKeyXor; |
| 234 | positionPtr += stride; |
| 235 | } |
| 236 | } |
| 237 | else |
| 238 | { |
| 239 | for (int32 i = 0; i < buffer->CPU.Count; i++) |
| 240 | { |
| 241 | sortedKeys[i] = RenderTools::ComputeDistanceSortKey(Matrix::TransformPosition(viewProjection, *(const Float3*)positionPtr).W) ^ sortKeyXor; |
| 242 | positionPtr += stride; |
| 243 | } |
| 244 | } |
| 245 | break; |
| 246 | } |
no test coverage detected