// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE #pragma anki technique ForwardLegacy vert pixel #include #pragma anki struct AnKiLocalConstants #pragma anki member Vec3 m_diffColor 1.0 1.0 1.0 #pragma anki member F32 m_roughness 0.9 #pragma anki member F32 m_metallic 0.0 #pragma anki member Vec3 m_initialEmission 0.0 0.0 0.0 #pragma anki member Vec3 m_finalEmission 0.0 0.0 0.0 #pragma anki struct_end struct VertIn { U32 m_svVertexId : SV_VERTEXID; U32 m_svInstanceId : SV_INSTANCEID; }; struct VertOut { ANKI_RELAXED_PRECISION nointerpolation F32 m_lifeFactor : LIFE_FACTOR; nointerpolation U32 m_constantsOffset : CONSTANTS_OFFSET; Vec2 m_uv : TEXCOORD; Vec4 m_svPosition : SV_POSITION; }; #if ANKI_VERTEX_SHADER VertOut main(VertIn input) { VertOut output; const GpuScenePerDraw instance = getGpuScenePerDraw(); const GpuSceneParticleEmitter2 particles = SBUFF(g_particleEmitters2, instance.m_particleEmitterIndex); const GpuSceneMeshLod meshLod = SBUFF(g_meshLods, instance.m_meshLodIndex); const Vec3 localPos = g_unifiedGeom_R16G16B16A16_Unorm[meshLod.m_vertexOffsets[(U32)VertexStreamId::kPosition] + input.m_svVertexId] * meshLod.m_positionScale + meshLod.m_positionTranslation; U32 offset = particles.m_aliveParticleIndicesOffset + input.m_svInstanceId * sizeof(U32); const U32 particleId = BAB_LOAD(g_gpuScene, U32, offset); output.m_uv = g_unifiedGeom_R32G32_Sfloat[meshLod.m_vertexOffsets[(U32)VertexStreamId::kUv] + input.m_svVertexId]; // Compute pos { offset = particles.m_particleStateSteamOffsets[(U32)ParticleProperty::kPosition] + particleId * sizeof(Vec3); const Vec3 particlePos = BAB_LOAD(g_gpuScene, Vec3, offset); offset = particles.m_particleStateSteamOffsets[(U32)ParticleProperty::kVelocity] + particleId * sizeof(Vec3); const Vec3 velocity = BAB_LOAD(g_gpuScene, Vec3, offset); offset = particles.m_particleStateSteamOffsets[(U32)ParticleProperty::kScale] + particleId * sizeof(Vec3); const Vec3 particleScale = BAB_LOAD(g_gpuScene, Vec3, offset); const Vec3 xAxis = normalize(-velocity); const Vec3 zAxis = normalize(g_globalConstants.m_cameraTransform.getColumn(2)); const Vec3 yAxis = normalize(cross(zAxis, xAxis)); Mat3 rot; rot.setColumns(xAxis, yAxis, zAxis); Vec3 worldPos = localPos; worldPos *= particleScale; worldPos = mul(rot, worldPos); worldPos += particlePos; output.m_svPosition = mul(g_globalConstants.m_viewProjectionMatrix, Vec4(worldPos, 1.0)); } // Life factor offset = particles.m_particleStateSteamOffsets[(U32)ParticleProperty::kLifeFactor] + particleId * sizeof(F32); output.m_lifeFactor = BAB_LOAD(g_gpuScene, F32, offset); output.m_lifeFactor = saturate(output.m_lifeFactor); output.m_constantsOffset = instance.m_constantsOffset; return output; } #endif // ANKI_VERTEX_SHADER #if ANKI_PIXEL_SHADER # include PixelOut main(VertOut input) { PixelOut output; const AnKiLocalConstants localConstants = loadAnKiLocalConstants(g_gpuScene, input.m_constantsOffset); const Vec2 ndc = uvToNdc(input.m_uv); F32 alpha = min(1.0, length(ndc)); alpha = 1.0 - alpha; alpha = pow(alpha, 2.0); alpha *= 1.0 - input.m_lifeFactor; F32 emissionFactor = input.m_lifeFactor; // emissionFactor = sqrt(emissionFactor); emissionFactor *= 1.0 - alpha; const Vec3 emission = lerp(localConstants.m_initialEmission, localConstants.m_finalEmission, emissionFactor); particleAlpha(Vec4(emission, alpha), 1.0, 0.0, output); return output; } #endif // ANKI_PIXEL_SHADER