diff --git a/Assets/shaders/Billboard/Default/Billboard.azsl b/Assets/shaders/Billboard/Default/Billboard.azsl index 4c2ccb8..7c26b70 100644 --- a/Assets/shaders/Billboard/Default/Billboard.azsl +++ b/Assets/shaders/Billboard/Default/Billboard.azsl @@ -5,12 +5,16 @@ #include #include -#include + +#include "../../Common/PopcornOptions.azsli" +#include + +#include "../../Common/MaterialSrg.azsli" // Billboarding shader: #include "../../Common/ComputeBillboardVertex.azsli" // Material: -#include "../../Common/MaterialSrg.azsli" +#include "../../Common/RendererFeatures.azsli" option bool o_hasDiffuse; option bool o_hasEmissive; @@ -24,11 +28,13 @@ struct VertexInput struct VertexOutput { float4 m_position : SV_Position; - float2 m_texCoords0 : UV0; - float2 m_texCoords1 : UV1; + float2 m_texCoord0 : UV0; + float2 m_texCoord1 : UV1; float m_texFrameLerp : UV2; float4 m_diffuseColor : COLOR0; - float3 m_emissiveColor : COLOR1; + float4 m_emissiveColor : COLOR1; + float m_alphaCursor : UV3; + float4 m_clipPosition : UV4; }; VertexOutput BillboardVS(VertexInput input) @@ -45,13 +51,21 @@ VertexOutput BillboardVS(VertexInput input) ComputeBillboardVertex(particleIdx, input.m_uv, vtxWorldPos, vtxUV0, vtxUV1, vtxTexFrameLerp); output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(vtxWorldPos, 1.0f)); - output.m_texCoords0 = vtxUV0; + output.m_clipPosition = output.m_position; + output.m_texCoord0 = vtxUV0; + // Atlas animation blending: + output.m_texCoord1 = float2(0, 0); + output.m_texFrameLerp = 0; if (HasOneRendererFlags(Has_AnimBlend)) { + output.m_texCoord1 = vtxUV1; output.m_texFrameLerp = vtxTexFrameLerp; - output.m_texCoords1 = vtxUV1; } + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleIdx]; // Get additional fields: if (o_hasDiffuse) @@ -60,8 +74,9 @@ VertexOutput BillboardVS(VertexInput input) } if (o_hasEmissive) { - output.m_emissiveColor = RendererSrg::m_emissiveColors[particleIdx]; + output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); } + return output; } @@ -73,33 +88,36 @@ struct PixelOutput PixelOutput BillboardFS(VertexOutput input) { PixelOutput output; - + float4 diffuseColor = float4(0, 0, 0, 0); float4 emissiveColor = float4(0, 0, 0, 0); if (o_hasDiffuse) { - float4 texColor = MaterialSrg::m_diffuseMap.Sample(MaterialSrg::m_sampler, input.m_texCoords0); - if (HasOneRendererFlags(Has_AnimBlend_Linear)) - { - float4 texColor1 = MaterialSrg::m_diffuseMap.Sample(MaterialSrg::m_sampler, input.m_texCoords1); - texColor = lerp(texColor, texColor1, input.m_texFrameLerp); - } - diffuseColor = texColor; + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); } + if (o_hasEmissive) { - float4 texColor = MaterialSrg::m_emissiveMap.Sample(MaterialSrg::m_sampler, input.m_texCoords0); - if (HasOneRendererFlags(Has_AnimBlend_Linear)) - { - float4 texColor1 = MaterialSrg::m_emissiveMap.Sample(MaterialSrg::m_sampler, input.m_texCoords1); - texColor = lerp(texColor, texColor1, input.m_texFrameLerp); - } - emissiveColor = texColor; - emissiveColor.rgb *= input.m_emissiveColor; + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; } output.m_color = float4(diffuseColor.rgb * diffuseColor.a + emissiveColor.rgb * emissiveColor.a, diffuseColor.a); return output; -} \ No newline at end of file +} + diff --git a/Assets/shaders/Billboard/Default/BillboardLit.azsl b/Assets/shaders/Billboard/Default/BillboardLit.azsl new file mode 100644 index 0000000..61248f7 --- /dev/null +++ b/Assets/shaders/Billboard/Default/BillboardLit.azsl @@ -0,0 +1,167 @@ +//---------------------------------------------------------------------------- +// Copyright Persistant Studios, SARL. All Rights Reserved. +// https://www.popcornfx.com/terms-and-conditions/ +//---------------------------------------------------------------------------- + +#include +#include + +#define PK_LIT_SHADER + +#include "../../Common/MaterialSrg.azsli" +#include "../../Common/LightingHelper.azsli" + +// Billboarding shader: +#include "../../Common/ComputeBillboardVertex.azsli" +// Material: +#include "../../Common/RendererFeatures.azsli" + +option bool o_hasDiffuse = false; +option bool o_hasEmissive = true; + +struct VertexInput +{ + float2 m_uv : POSITION; + uint m_instanceID : SV_InstanceID; +}; + +struct VSOutput +{ + precise float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + + float2 m_texCoord0 : UV1; + float2 m_texCoord1 : UV2; + float m_texFrameLerp : UV3; + float4 m_diffuseColor : COLOR0; + float4 m_emissiveColor : COLOR1; + float m_alphaCursor : UV4; + float4 m_clipPosition : UV5; +}; + +VSOutput BillboardVS(VertexInput input) +{ + VSOutput output; + uint particleIdx = RendererSrg::m_indices[GetParticleId_Sliced(input.m_instanceID)]; + + // Billboarding outputs: + float3 vtxWorldPos; + float3 vtxNormal; + float4 vtxTangent; + float2 vtxUV0; + float2 vtxUV1; + float vtxTexFrameLerp; + + ComputeBillboardVertex(particleIdx, input.m_uv, vtxWorldPos, vtxNormal, vtxTangent, vtxUV0, vtxUV1, vtxTexFrameLerp); + + // TBN: + float3 vtxBitangent = cross(vtxNormal, vtxTangent.xyz) * vtxTangent.w; + + output.m_normal = vtxNormal; + output.m_tangent = vtxTangent.xyz; + output.m_bitangent = vtxBitangent; + output.m_worldPosition = vtxWorldPos; + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(vtxWorldPos, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = vtxUV0; + + // Atlas animation blending: + if (HasOneRendererFlags(Has_AnimBlend)) + { + output.m_texCoord1 = vtxUV1; + output.m_texFrameLerp = vtxTexFrameLerp; + } + else + { + output.m_texCoord1 = float2(0, 0); + output.m_texFrameLerp = 0; + } + + if (HasOneRendererFlags(Has_Emissive)) + output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleIdx]; + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleIdx]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + } + + return output; +} + +ForwardPassOutput BillboardFS(VSOutput input, bool isFrontFace : SV_IsFrontFace) +{ + float2 texCoord0 = input.m_texCoord0; + float2 texCoord1 = input.m_texCoord1; + + // Motion vectors: + GetMotionVectorsUV(texCoord0, texCoord1, input.m_texFrameLerp); + + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + float3 vertexNormal = normalize(isFrontFace ? input.m_normal : -input.m_normal); + float3 normal = vertexNormal; + const float3 tangent = normalize(input.m_tangent); + const float3 bitangent = normalize(input.m_bitangent); + + // Normal map: + if (HasOneRendererFlags(Has_NormalMap)) + { + float2 texNormal = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_texCoord0).xy; + if (HasOneRendererFlags(Has_AnimBlend)) + { + // Lerping between normal maps is not the correct way to handle that + // We should use ReorientTangentSpaceNormal instead + float2 texNormal1 = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_texCoord1).xy; + texNormal = lerp(texNormal, texNormal1, input.m_texFrameLerp); + } + normal = GetWorldSpaceNormal(texNormal, normal, tangent, bitangent); + } + + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + // Compute lighting: + return ComputeParticleLighting( input.m_worldPosition, + input.m_position, + vertexNormal, + normal, + tangent, + bitangent, + diffuseColor, + emissiveColor.rgb * emissiveColor.a); +} diff --git a/Assets/shaders/Billboard/Default/BillboardLit.shader b/Assets/shaders/Billboard/Default/BillboardLit.shader new file mode 100644 index 0000000..8ffc12e --- /dev/null +++ b/Assets/shaders/Billboard/Default/BillboardLit.shader @@ -0,0 +1,55 @@ +{ + "Source" : "BillboardLit.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + }, + "Stencil" : + { + "Enable" : true, + "ReadMask" : "0x00", + "WriteMask" : "0xFF", + "FrontFace" : + { + "Func" : "Always", + "DepthFailOp" : "Keep", + "FailOp" : "Keep", + "PassOp" : "Replace" + } + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "BillboardVS", + "type": "Vertex" + }, + { + "name": "BillboardFS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Billboard/Default/BillboardLit.shadervariantlist b/Assets/shaders/Billboard/Default/BillboardLit.shadervariantlist new file mode 100644 index 0000000..09dad5b --- /dev/null +++ b/Assets/shaders/Billboard/Default/BillboardLit.shadervariantlist @@ -0,0 +1,149 @@ +{ + "Shader": "shaders/Billboard/Default/BillboardLit.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 2, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 3, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 4, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 5, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 6, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 7, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 8, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 9, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 10, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 11, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 12, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 13, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + }, + { + "StableId": 14, + "Options": { + "o_hasAtlas": "false", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + }, + { + "StableId": 15, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "false", + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + }, + { + "StableId": 16, + "Options": { + "o_hasAtlas": "true", + "o_hasBillboardCapsules": "true", + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Billboard/Legacy/BillboardLit_Legacy.azsl b/Assets/shaders/Billboard/Legacy/BillboardLit_Legacy.azsl index bcb19a7..72abb77 100644 --- a/Assets/shaders/Billboard/Legacy/BillboardLit_Legacy.azsl +++ b/Assets/shaders/Billboard/Legacy/BillboardLit_Legacy.azsl @@ -83,7 +83,7 @@ VSOutput BillboardVS(VertexInput input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleIdx); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) diff --git a/Assets/shaders/Billboard/Legacy/Billboard_Legacy.azsl b/Assets/shaders/Billboard/Legacy/Billboard_Legacy.azsl index c8bf8fb..934757a 100644 --- a/Assets/shaders/Billboard/Legacy/Billboard_Legacy.azsl +++ b/Assets/shaders/Billboard/Legacy/Billboard_Legacy.azsl @@ -66,7 +66,7 @@ VertexOutput BillboardVS(VertexInput input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleIdx); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) diff --git a/Assets/shaders/Common/RendererSrg.azsli b/Assets/shaders/Common/RendererSrg.azsli index d6daf81..c13f612 100644 --- a/Assets/shaders/Common/RendererSrg.azsli +++ b/Assets/shaders/Common/RendererSrg.azsli @@ -37,9 +37,17 @@ bool HasOneRendererFlags(uint rendererFlags) return (RendererSrg::m_rendererFlags & rendererFlags) != 0; } -float3 GetEmissiveParticleColor(uint particleID) +float3 GetEmissiveParticleColorLegacy(uint particleID) { return float3( RendererSrg::m_emissiveColors[particleID * 3 + 0], RendererSrg::m_emissiveColors[particleID * 3 + 1], RendererSrg::m_emissiveColors[particleID * 3 + 2]); } + +float4 GetEmissiveParticleColor(uint particleID) +{ + return float4( RendererSrg::m_emissiveColors[particleID * 4 + 0], + RendererSrg::m_emissiveColors[particleID * 4 + 1], + RendererSrg::m_emissiveColors[particleID * 4 + 2], + RendererSrg::m_emissiveColors[particleID * 4 + 3]); +} diff --git a/Assets/shaders/Mesh/Default/Mesh.azsl b/Assets/shaders/Mesh/Default/Mesh.azsl new file mode 100644 index 0000000..42fe096 --- /dev/null +++ b/Assets/shaders/Mesh/Default/Mesh.azsl @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------------- +// Copyright Persistant Studios, SARL. All Rights Reserved. +// https://www.popcornfx.com/terms-and-conditions/ +//---------------------------------------------------------------------------- + +#include +#include + +#include "../../Common/PopcornOptions.azsli" +#include + +#include "../../Common/MaterialSrg.azsli" +// Renderer: +#include "../../Common/MeshSrg.azsli" +// Material: +#include "../../Common/RendererFeatures.azsli" + +option bool o_hasDiffuse; +option bool o_hasEmissive; + +struct VertexInput +{ + float3 m_position : POSITION; + float2 m_texCoord0 : UV0; + + uint m_vertexID : SV_VertexID; + uint m_instanceID : SV_InstanceID; +}; + +struct VertexOutput +{ + float4 m_position : SV_Position; + float2 m_texCoord0 : UV0; + float4 m_diffuseColor : COLOR0; + float4 m_emissiveColor : COLOR1; + float m_alphaCursor : UV1; +}; + +VertexOutput MeshVS(VertexInput input) +{ + VertexOutput output; + uint particleIdx = input.m_instanceID; + + float4x4 mat = transpose(RendererSrg::m_matrices[particleIdx]); + + float4 pos = mul(mat, float4(input.m_position.xyz, 1)); + + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, pos); + + output.m_texCoord0 = input.m_texCoord0; + + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleIdx]; + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleIdx]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + } + + return output; +} + +struct PixelOutput +{ + float4 m_color : SV_Target0; +}; + +PixelOutput MeshFS(VertexOutput input) +{ + PixelOutput output; + + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + output.m_color = float4(diffuseColor.rgb * diffuseColor.a + emissiveColor.rgb * emissiveColor.a, diffuseColor.a); + return output; +} \ No newline at end of file diff --git a/Assets/shaders/Mesh/Default/Mesh.shader b/Assets/shaders/Mesh/Default/Mesh.shader new file mode 100644 index 0000000..dd98a24 --- /dev/null +++ b/Assets/shaders/Mesh/Default/Mesh.shader @@ -0,0 +1,42 @@ +{ + "Source" : "Mesh.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MeshVS", + "type": "Vertex" + }, + { + "name": "MeshFS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Mesh/Default/Mesh.shadervariantlist b/Assets/shaders/Mesh/Default/Mesh.shadervariantlist new file mode 100644 index 0000000..256354f --- /dev/null +++ b/Assets/shaders/Mesh/Default/Mesh.shadervariantlist @@ -0,0 +1,17 @@ +{ + "Shader" : "Mesh.shader", + "Variants" : [ + { + "StableId": 1, "Options": { "o_hasDiffuse": "false", "o_hasEmissive": "false" } + }, + { + "StableId": 2, "Options": { "o_hasDiffuse": "true", "o_hasEmissive": "false" } + }, + { + "StableId": 3, "Options": { "o_hasDiffuse": "true", "o_hasEmissive": "true" } + }, + { + "StableId": 4, "Options": { "o_hasDiffuse": "false", "o_hasEmissive": "true" } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Mesh/Default/MeshLit.azsl b/Assets/shaders/Mesh/Default/MeshLit.azsl new file mode 100644 index 0000000..5bae5d6 --- /dev/null +++ b/Assets/shaders/Mesh/Default/MeshLit.azsl @@ -0,0 +1,137 @@ +//---------------------------------------------------------------------------- +// Copyright Persistant Studios, SARL. All Rights Reserved. +// https://www.popcornfx.com/terms-and-conditions/ +//---------------------------------------------------------------------------- + +#include +#include + +#define PK_LIT_SHADER + +#include "../../Common/MaterialSrg.azsli" +#include "../../Common/LightingHelper.azsli" + +// Renderer: +#include "../../Common/MeshSrg.azsli" +// Material: +#include "../../Common/RendererFeatures.azsli" + +option bool o_hasDiffuse; +option bool o_hasEmissive; + +struct VertexInput +{ + float3 m_position : POSITION; + float2 m_texCoord0 : UV0; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + + uint m_vertexID : SV_VertexID; + uint m_instanceID : SV_InstanceID; +}; + +struct VertexOutput +{ + float4 m_position : SV_Position; + float3 m_normal : NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + + float4 m_diffuseColor : COLOR0; + float4 m_emissiveColor : COLOR1; + + float3 m_worldPosition : UV0; + + float2 m_texCoord0 : UV1; + float m_alphaCursor : UV2; + float4 m_clipPosition : UV3; +}; + +VertexOutput MeshVS(VertexInput input) +{ + VertexOutput output; + uint particleIdx = input.m_instanceID; + + float4x4 mat = transpose(RendererSrg::m_matrices[particleIdx]); + + float4 vtxWorldPos = mul(mat, float4(input.m_position.xyz, 1)); + float3 vtxNormal = mul(mat, input.m_normal.xyz); + + // TBN: + float3 vtxTangent = mul(mat, input.m_tangent.xyz); + float3 vtxBitangent = mul(mat, cross(input.m_normal, input.m_tangent.xyz) * -input.m_tangent.w); + + output.m_normal = vtxNormal.xyz; + output.m_tangent = vtxTangent.xyz; + output.m_bitangent = vtxBitangent.xyz; + output.m_worldPosition = vtxWorldPos.xyz; + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(vtxWorldPos.xyz, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = input.m_texCoord0; + + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleIdx]; + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleIdx]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + } + + return output; +} + +ForwardPassOutput MeshFS(VertexOutput input, bool isFrontFace : SV_IsFrontFace) +{ + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + float3 vertexNormal = normalize(isFrontFace ? input.m_normal : -input.m_normal); + float3 normal = vertexNormal; + const float3 tangent = normalize(input.m_tangent); + const float3 bitangent = normalize(input.m_bitangent); + + // Normal map: + if (HasOneRendererFlags(Has_NormalMap)) + { + float2 texNormal = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_texCoord0).xy; + normal = GetWorldSpaceNormal(texNormal, normal, tangent, bitangent); + } + + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + // Compute lighting: + return ComputeParticleLighting( input.m_worldPosition, + input.m_position, + vertexNormal, + normal, + tangent, + bitangent, + diffuseColor, + emissiveColor.rgb * emissiveColor.a); +} diff --git a/Assets/shaders/Mesh/Default/MeshLit.shader b/Assets/shaders/Mesh/Default/MeshLit.shader new file mode 100644 index 0000000..9e4b462 --- /dev/null +++ b/Assets/shaders/Mesh/Default/MeshLit.shader @@ -0,0 +1,62 @@ +{ + "Source" : "MeshLit.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + }, + "Stencil" : + { + "Enable" : true, + "ReadMask" : "0x00", + "WriteMask" : "0xFF", + "FrontFace" : + { + "Func" : "Always", + "DepthFailOp" : "Keep", + "FailOp" : "Keep", + "PassOp" : "Replace" + }, + "BackFace" : + { + "Func" : "Always", + "DepthFailOp" : "Keep", + "FailOp" : "Keep", + "PassOp" : "Replace" + } + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MeshVS", + "type": "Vertex" + }, + { + "name": "MeshFS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "forward" +} diff --git a/Assets/shaders/Mesh/Default/MeshLit.shadervariantlist b/Assets/shaders/Mesh/Default/MeshLit.shadervariantlist new file mode 100644 index 0000000..dab64a6 --- /dev/null +++ b/Assets/shaders/Mesh/Default/MeshLit.shadervariantlist @@ -0,0 +1,17 @@ +{ + "Shader" : "MeshLit.shader", + "Variants" : [ + { + "StableId": 1, "Options": { "o_hasDiffuse": "false", "o_hasEmissive": "false" } + }, + { + "StableId": 2, "Options": { "o_hasDiffuse": "true", "o_hasEmissive": "false" } + }, + { + "StableId": 3, "Options": { "o_hasDiffuse": "true", "o_hasEmissive": "true" } + }, + { + "StableId": 4, "Options": { "o_hasDiffuse": "false", "o_hasEmissive": "true" } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Mesh/Legacy/MeshLit_Legacy.azsl b/Assets/shaders/Mesh/Legacy/MeshLit_Legacy.azsl index e760ab3..5c43b5b 100644 --- a/Assets/shaders/Mesh/Legacy/MeshLit_Legacy.azsl +++ b/Assets/shaders/Mesh/Legacy/MeshLit_Legacy.azsl @@ -76,7 +76,7 @@ VertexOutput MeshVS(VertexInput input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleIdx); if (HasOneRendererFlags(Has_AlphaRemap)) output.m_alphaCursor = RendererSrg::m_alphaCursors[particleIdx]; return output; diff --git a/Assets/shaders/Mesh/Legacy/Mesh_Legacy.azsl b/Assets/shaders/Mesh/Legacy/Mesh_Legacy.azsl index ba6411f..004fd47 100644 --- a/Assets/shaders/Mesh/Legacy/Mesh_Legacy.azsl +++ b/Assets/shaders/Mesh/Legacy/Mesh_Legacy.azsl @@ -56,7 +56,7 @@ VertexOutput MeshVS(VertexInput input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleIdx); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleIdx); if (HasOneRendererFlags(Has_AlphaRemap)) output.m_alphaCursor = RendererSrg::m_alphaCursors[particleIdx]; return output; diff --git a/Assets/shaders/Ribbon/Default/Ribbon.azsl b/Assets/shaders/Ribbon/Default/Ribbon.azsl new file mode 100644 index 0000000..0925f27 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/Ribbon.azsl @@ -0,0 +1,294 @@ +//---------------------------------------------------------------------------- +// Copyright Persistant Studios, SARL. All Rights Reserved. +// https://www.popcornfx.com/terms-and-conditions/ +//---------------------------------------------------------------------------- + +#include +#include + +#include "../../Common/PopcornOptions.azsli" +#include + +#include "../../Common/MaterialSrg.azsli" +#include "../../Common/RibbonSrg.azsli" + +#include "../../Common/RendererFeatures.azsli" + +option bool o_hasDiffuse = false; +option bool o_hasEmissive = true; + +struct VertexInput +{ + float4 m_position : POSITION; + float2 m_texCoord0 : UV0; + + uint m_vertexID : SV_VertexID; +}; + +struct VertexInputAtlasBlend +{ + float4 m_position : POSITION; + float2 m_texCoord0 : UV0; + float2 m_texCoord1 : UV1; + float m_texFrameLerp : UV2; + + uint m_vertexID : SV_VertexID; +}; + +struct VertexInputCorrectDeformation +{ + float4 m_position : POSITION; + float2 m_texCoord0 : UV0; + float4 m_UVRemap : UV1; + float2 m_UVFactors : UV2; + + uint m_vertexID : SV_VertexID; +}; + +struct VertexOutput +{ + float4 m_position : SV_Position; + float2 m_texCoord0 : UV0; + float4 m_diffuseColor : UV1; + float4 m_emissiveColor : UV2; + float m_alphaCursor : UV3; + float4 m_clipPosition : UV4; +}; + +struct VertexOutputAtlasBlend +{ + float4 m_position : SV_Position; + float2 m_texCoord0 : UV0; + float2 m_texCoord1 : UV1; + float m_texFrameLerp : UV2; + float4 m_diffuseColor : UV3; + float4 m_emissiveColor : UV4; + float m_alphaCursor : UV5; + float4 m_clipPosition : UV6; +}; + +struct VertexOutputCorrectDeformation +{ + float4 m_position : SV_Position; + float2 m_texCoord0 : UV0; + float4 m_UVRemap : UV1; + float4 m_UVFactors : UV2; + float4 m_diffuseColor : UV3; + float4 m_emissiveColor : UV4; + float m_alphaCursor : UV5; + float4 m_clipPosition : UV6; +}; + +VertexOutput RibbonVS(VertexInput input) +{ + VertexOutput output; + + // Billboarding outputs: + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(input.m_position.xyz, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = input.m_texCoord0; + + uint particleID = GetParticleIdx(input.m_vertexID); + + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleID]; + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleID]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleID); + } + + return output; +} + +VertexOutputAtlasBlend RibbonVS_AtlasBlend(VertexInputAtlasBlend input) +{ + VertexOutputAtlasBlend output; + + // Billboarding outputs: + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(input.m_position.xyz, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = input.m_texCoord0; + output.m_texCoord1 = input.m_texCoord1; + output.m_texFrameLerp = frac(input.m_texFrameLerp); + + uint particleID = GetParticleIdx(input.m_vertexID); + + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleID]; + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleID]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleID); + } + + return output; +} + +VertexOutputCorrectDeformation RibbonVS_CorrectDeformation(VertexInputCorrectDeformation input) +{ + VertexOutputCorrectDeformation output; + + // Billboarding outputs: + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(input.m_position.xyz, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = input.m_texCoord0; + output.m_UVRemap = input.m_UVRemap; + output.m_UVFactors = GetCorrectDeformationUVFactors(input.m_UVFactors, input.m_vertexID); + + uint particleID = GetParticleIdx(input.m_vertexID); + + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleID]; + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleID]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleID); + } + + return output; +} + +struct PixelOutput +{ + float4 m_color : SV_Target0; +}; + +PixelOutput RibbonFS(VertexOutput input) +{ + PixelOutput output; + + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + // Soft particles: + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + output.m_color = float4(diffuseColor.rgb * diffuseColor.a + emissiveColor.rgb * emissiveColor.a, diffuseColor.a); + return output; +} + +PixelOutput RibbonFS_AtlasBlend(VertexOutputAtlasBlend input) +{ + PixelOutput output; + + float2 texCoord0 = input.m_texCoord0; + float2 texCoord1 = input.m_texCoord1; + + GetMotionVectorsUV(texCoord0, texCoord1, input.m_texFrameLerp); + + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(texCoord0, texCoord1, input.m_texFrameLerp); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(texCoord0, texCoord1, input.m_texFrameLerp); + emissiveColor *= input.m_emissiveColor; + } + + // Soft particles: + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + output.m_color = float4(diffuseColor.rgb * diffuseColor.a + emissiveColor.rgb * emissiveColor.a, diffuseColor.a); + return output; +} + +PixelOutput RibbonFS_CorrectDeformation(VertexOutputCorrectDeformation input) +{ + PixelOutput output; + + float2 texCoord = GetCorrectDeformationUV(input.m_texCoord0, input.m_UVFactors, input.m_UVRemap); + + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(texCoord); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(texCoord); + emissiveColor *= input.m_emissiveColor; + } + + // Soft particles: + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + output.m_color = float4(diffuseColor.rgb * diffuseColor.a + emissiveColor.rgb * emissiveColor.a, diffuseColor.a); + return output; +} diff --git a/Assets/shaders/Ribbon/Default/Ribbon.shader b/Assets/shaders/Ribbon/Default/Ribbon.shader new file mode 100644 index 0000000..d25e8f3 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/Ribbon.shader @@ -0,0 +1,42 @@ +{ + "Source" : "Ribbon.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "RibbonVS", + "type": "Vertex" + }, + { + "name": "RibbonFS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Ribbon/Default/Ribbon.shadervariantlist b/Assets/shaders/Ribbon/Default/Ribbon.shadervariantlist new file mode 100644 index 0000000..6831229 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/Ribbon.shadervariantlist @@ -0,0 +1,33 @@ +{ + "Shader": "shaders/Ribbon/Default/Ribbon.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 2, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 3, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 4, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Ribbon/Default/RibbonAtlasBlend.shader b/Assets/shaders/Ribbon/Default/RibbonAtlasBlend.shader new file mode 100644 index 0000000..5f0c326 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonAtlasBlend.shader @@ -0,0 +1,42 @@ +{ + "Source" : "Ribbon.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "RibbonVS_AtlasBlend", + "type": "Vertex" + }, + { + "name": "RibbonFS_AtlasBlend", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Ribbon/Default/RibbonAtlasBlend.shadervariantlist b/Assets/shaders/Ribbon/Default/RibbonAtlasBlend.shadervariantlist new file mode 100644 index 0000000..2b84309 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonAtlasBlend.shadervariantlist @@ -0,0 +1,33 @@ +{ + "Shader": "shaders/Ribbon/Default/RibbonAtlasBlend.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 2, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 3, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 4, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Ribbon/Default/RibbonCorrectDeformation.shader b/Assets/shaders/Ribbon/Default/RibbonCorrectDeformation.shader new file mode 100644 index 0000000..0625ba5 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonCorrectDeformation.shader @@ -0,0 +1,42 @@ +{ + "Source" : "Ribbon.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "RibbonVS_CorrectDeformation", + "type": "Vertex" + }, + { + "name": "RibbonFS_CorrectDeformation", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Ribbon/Default/RibbonCorrectDeformation.shadervariantlist b/Assets/shaders/Ribbon/Default/RibbonCorrectDeformation.shadervariantlist new file mode 100644 index 0000000..6b7f807 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonCorrectDeformation.shadervariantlist @@ -0,0 +1,33 @@ +{ + "Shader": "shaders/Ribbon/Default/RibbonCorrectDeformation.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 2, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 3, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 4, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Ribbon/Default/RibbonLit.azsl b/Assets/shaders/Ribbon/Default/RibbonLit.azsl new file mode 100644 index 0000000..73e298d --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonLit.azsl @@ -0,0 +1,386 @@ +//---------------------------------------------------------------------------- +// Copyright Persistant Studios, SARL. All Rights Reserved. +// https://www.popcornfx.com/terms-and-conditions/ +//---------------------------------------------------------------------------- + +#include +#include +#include "../../Common/MaterialSrg.azsli" +#include "../../Common/RibbonSrg.azsli" + +#include "../../Common/LightingHelper.azsli" +#include "../../Common/RendererFeatures.azsli" + +option bool o_hasDiffuse = false; +option bool o_hasEmissive = true; + +struct VertexInput +{ + float4 m_position : POSITION; + float2 m_texCoord0 : UV0; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + + uint m_vertexID : SV_VertexID; +}; + +struct VertexInputAtlasBlend +{ + float4 m_position : POSITION; + float2 m_texCoord0 : UV0; + float2 m_texCoord1 : UV1; + float m_texFrameLerp : UV2; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + + uint m_vertexID : SV_VertexID; +}; + +struct VertexInputCorrectDeformation +{ + float4 m_position : POSITION; + float2 m_texCoord0 : UV0; + float4 m_UVRemap : UV1; + float2 m_UVFactors : UV2; + float3 m_normal : NORMAL; + float4 m_tangent : TANGENT; + + uint m_vertexID : SV_VertexID; +}; + +struct VertexOutput +{ + linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + + float2 m_texCoord0 : UV1; + float4 m_diffuseColor : COLOR0; + float4 m_emissiveColor : COLOR1; + float m_alphaCursor : UV2; + float4 m_clipPosition : UV3; +}; + +struct VertexOutputAtlasBlend +{ + linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + + float2 m_texCoord0 : UV1; + float2 m_texCoord1 : UV2; + float m_texFrameLerp : UV3; + float4 m_diffuseColor : COLOR0; + float4 m_emissiveColor : COLOR1; + float m_alphaCursor : UV4; + float4 m_clipPosition : UV5; +}; + +struct VertexOutputCorrectDeformation +{ + linear centroid float4 m_position : SV_Position; + float3 m_normal: NORMAL; + float3 m_tangent : TANGENT; + float3 m_bitangent : BITANGENT; + float3 m_worldPosition : UV0; + + float2 m_texCoord0 : UV1; + float4 m_UVRemap : UV2; + float4 m_UVFactors : UV3; + float4 m_diffuseColor : COLOR0; + float4 m_emissiveColor : COLOR1; + float m_alphaCursor : UV4; + float4 m_clipPosition : UV5; +}; + +VertexOutput RibbonVS(VertexInput input) +{ + VertexOutput output; + + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(input.m_position.xyz, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = input.m_texCoord0; + + uint particleID = GetParticleIdx(input.m_vertexID); + + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleID]; + + // Lighting: + output.m_normal = input.m_normal; + output.m_tangent = input.m_tangent.xyz; + output.m_bitangent = cross(input.m_tangent.xyz, input.m_normal) * input.m_tangent.w; + output.m_worldPosition = input.m_position.xyz; + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleID]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleID); + } + + return output; +} + +VertexOutputAtlasBlend RibbonVS_AtlasBlend(VertexInputAtlasBlend input) +{ + VertexOutputAtlasBlend output; + + // Billboarding outputs: + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(input.m_position.xyz, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = input.m_texCoord0; + output.m_texCoord1 = input.m_texCoord1; + output.m_texFrameLerp = frac(input.m_texFrameLerp); + + uint particleID = GetParticleIdx(input.m_vertexID); + + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleID]; + + // Lighting: + output.m_normal = input.m_normal; + output.m_tangent = input.m_tangent.xyz; + output.m_bitangent = cross(input.m_normal, input.m_tangent.xyz) * input.m_tangent.w; + output.m_worldPosition = input.m_position.xyz; + + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleID]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleID); + } + + return output; +} + +VertexOutputCorrectDeformation RibbonVS_CorrectDeformation(VertexInputCorrectDeformation input) +{ + VertexOutputCorrectDeformation output; + + // Billboarding outputs: + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(input.m_position.xyz, 1.0f)); + output.m_clipPosition = output.m_position; + output.m_texCoord0 = input.m_texCoord0; + output.m_UVRemap = input.m_UVRemap; + output.m_UVFactors = GetCorrectDeformationUVFactors(input.m_UVFactors, input.m_vertexID); + + uint particleID = GetParticleIdx(input.m_vertexID); + + // Alpha remap: + output.m_alphaCursor = 0; + if (HasOneRendererFlags(Has_AlphaRemap)) + output.m_alphaCursor = RendererSrg::m_alphaCursors[particleID]; + + // Lighting: + output.m_normal = input.m_normal; + output.m_tangent = input.m_tangent.xyz; + output.m_bitangent = cross(input.m_normal, input.m_tangent.xyz) * input.m_tangent.w; + output.m_worldPosition = input.m_position.xyz; + + + // Get additional fields: + if (o_hasDiffuse) + { + output.m_diffuseColor = RendererSrg::m_diffuseColors[particleID]; + } + if (o_hasEmissive) + { + output.m_emissiveColor = GetEmissiveParticleColor(particleID); + } + + return output; +} + +struct PixelOutput +{ + float4 m_color : SV_Target0; +}; + +ForwardPassOutput RibbonFS(VertexOutput input, bool isFrontFace : SV_IsFrontFace) +{ + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + // Normal map: + float3 vertexNormal = normalize(isFrontFace ? input.m_normal : -input.m_normal); + float3 normal = vertexNormal; + const float3 tangent = normalize(input.m_tangent); + const float3 bitangent = normalize(input.m_bitangent); + if (HasOneRendererFlags(Has_NormalMap)) + { + float2 texNormal = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_texCoord0).xy; + normal = GetWorldSpaceNormal(texNormal, normal, tangent, bitangent); + } + + // Soft particles: + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + // Compute lighting: + return ComputeParticleLighting( input.m_worldPosition, + input.m_position, + vertexNormal, + normal, + tangent, + bitangent, + diffuseColor, + emissiveColor.rgb * emissiveColor.a); +} + +ForwardPassOutput RibbonFS_AtlasBlend(VertexOutputAtlasBlend input, bool isFrontFace : SV_IsFrontFace) +{ + float2 texCoord0 = input.m_texCoord0; + float2 texCoord1 = input.m_texCoord1; + + GetMotionVectorsUV(texCoord0, texCoord1, input.m_texFrameLerp); + + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + // Normal map: + float3 vertexNormal = normalize(isFrontFace ? input.m_normal : -input.m_normal); + float3 normal = vertexNormal; + const float3 tangent = normalize(input.m_tangent); + const float3 bitangent = normalize(input.m_bitangent); + if (HasOneRendererFlags(Has_NormalMap)) + { + float2 texNormal = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_texCoord0).xy; + if (HasOneRendererFlags(Has_AnimBlend)) + { + // Lerping between normal maps is not the correct way to handle that + // We should use ReorientTangentSpaceNormal instead + float2 texNormal1 = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_texCoord1).xy; + texNormal = lerp(texNormal, texNormal1, input.m_texFrameLerp); + } + normal = GetWorldSpaceNormal(texNormal, normal, tangent, bitangent); + } + + // Soft particles: + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + // Compute lighting: + return ComputeParticleLighting( input.m_worldPosition, + input.m_position, + vertexNormal, + normal, + tangent, + bitangent, + diffuseColor, + emissiveColor.rgb * emissiveColor.a); +} + +ForwardPassOutput RibbonFS_CorrectDeformation(VertexOutputCorrectDeformation input, bool isFrontFace : SV_IsFrontFace) +{ + float2 texCoord = GetCorrectDeformationUV(input.m_texCoord0, input.m_UVFactors, input.m_UVRemap); + + float4 diffuseColor = float4(0, 0, 0, 0); + float4 emissiveColor = float4(0, 0, 0, 0); + + if (o_hasDiffuse) + { + diffuseColor = GetDiffuseColor(input.m_texCoord0); + if (HasOneRendererFlags(Has_AlphaRemap)) + diffuseColor = ApplyAlphaRemap(diffuseColor, input.m_alphaCursor); + diffuseColor *= input.m_diffuseColor; + diffuseColor.a = clamp(diffuseColor.a, 0, 1); + + ApplyOpaqueMasked(diffuseColor.a); + } + + if (o_hasEmissive) + { + emissiveColor = GetEmissiveColor(input.m_texCoord0); + emissiveColor *= input.m_emissiveColor; + } + + // Normal map: + float3 vertexNormal = normalize(isFrontFace ? input.m_normal : -input.m_normal); + float3 normal = vertexNormal; + const float3 tangent = normalize(input.m_tangent); + const float3 bitangent = normalize(input.m_bitangent); + if (HasOneRendererFlags(Has_NormalMap)) + { + float2 texNormal = MaterialSrg::m_normalMap.Sample(MaterialSrg::m_sampler, input.m_texCoord0).xy; + normal = GetWorldSpaceNormal(texNormal, normal, tangent, bitangent); + } + + // Soft particles: + if (HasOneRendererFlags(Has_Soft)) + { + float3 clipPos = input.m_clipPosition.xyz / input.m_clipPosition.w; + float fade = GetSoftParticleFade(clipPos); + diffuseColor *= fade; + emissiveColor *= fade; + } + + // Compute lighting: + return ComputeParticleLighting( input.m_worldPosition, + input.m_position, + vertexNormal, + normal, + tangent, + bitangent, + diffuseColor, + emissiveColor.rgb * emissiveColor.a); +} diff --git a/Assets/shaders/Ribbon/Default/RibbonLit.shader b/Assets/shaders/Ribbon/Default/RibbonLit.shader new file mode 100644 index 0000000..3b5dcee --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonLit.shader @@ -0,0 +1,42 @@ +{ + "Source" : "RibbonLit.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "RibbonVS", + "type": "Vertex" + }, + { + "name": "RibbonFS", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Ribbon/Default/RibbonLit.shadervariantlist b/Assets/shaders/Ribbon/Default/RibbonLit.shadervariantlist new file mode 100644 index 0000000..06d6f01 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonLit.shadervariantlist @@ -0,0 +1,33 @@ +{ + "Shader": "shaders/Ribbon/Default/RibbonLit.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 2, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 3, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 4, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Ribbon/Default/RibbonLitAtlasBlend.shader b/Assets/shaders/Ribbon/Default/RibbonLitAtlasBlend.shader new file mode 100644 index 0000000..65028d8 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonLitAtlasBlend.shader @@ -0,0 +1,42 @@ +{ + "Source" : "RibbonLit.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "RibbonVS_AtlasBlend", + "type": "Vertex" + }, + { + "name": "RibbonFS_AtlasBlend", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Ribbon/Default/RibbonLitAtlasBlend.shadervariantlist b/Assets/shaders/Ribbon/Default/RibbonLitAtlasBlend.shadervariantlist new file mode 100644 index 0000000..42e98ff --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonLitAtlasBlend.shadervariantlist @@ -0,0 +1,33 @@ +{ + "Shader": "shaders/Ribbon/Default/RibbonLitAtlasBlend.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 2, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 3, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 4, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Ribbon/Default/RibbonLitCorrectDeformation.shader b/Assets/shaders/Ribbon/Default/RibbonLitCorrectDeformation.shader new file mode 100644 index 0000000..71df782 --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonLitCorrectDeformation.shader @@ -0,0 +1,42 @@ +{ + "Source" : "RibbonLit.azsl", + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : true, + "CompareFunc" : "GreaterEqual" + } + }, + + "RasterState" : + { + "CullMode" : "None" + }, + + "GlobalTargetBlendState" : + { + "Enable" : true, + "BlendSource" : "One", + "BlendDest" : "AlphaSourceInverse", + "BlendAlphaOp" : "Add" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "RibbonVS_CorrectDeformation", + "type": "Vertex" + }, + { + "name": "RibbonFS_CorrectDeformation", + "type": "Fragment" + } + ] + }, + + "DrawList" : "transparent" +} diff --git a/Assets/shaders/Ribbon/Default/RibbonLitCorrectDeformation.shadervariantlist b/Assets/shaders/Ribbon/Default/RibbonLitCorrectDeformation.shadervariantlist new file mode 100644 index 0000000..8f4ae3b --- /dev/null +++ b/Assets/shaders/Ribbon/Default/RibbonLitCorrectDeformation.shadervariantlist @@ -0,0 +1,33 @@ +{ + "Shader": "shaders/Ribbon/Default/RibbonLitCorrectDeformation.shader", + "Variants": [ + { + "StableId": 1, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "false" + } + }, + { + "StableId": 2, + "Options": { + "o_hasDiffuse": "false", + "o_hasEmissive": "true" + } + }, + { + "StableId": 3, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "false" + } + }, + { + "StableId": 4, + "Options": { + "o_hasDiffuse": "true", + "o_hasEmissive": "true" + } + } + ] +} \ No newline at end of file diff --git a/Assets/shaders/Ribbon/Legacy/RibbonLit_Legacy.azsl b/Assets/shaders/Ribbon/Legacy/RibbonLit_Legacy.azsl index a09f482..06bd371 100644 --- a/Assets/shaders/Ribbon/Legacy/RibbonLit_Legacy.azsl +++ b/Assets/shaders/Ribbon/Legacy/RibbonLit_Legacy.azsl @@ -111,7 +111,7 @@ VertexOutput RibbonVS(VertexInput input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleID); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleID); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) @@ -146,7 +146,7 @@ VertexOutputAtlasBlend RibbonVS_AtlasBlend(VertexInputAtlasBlend input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleID); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleID); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) @@ -181,7 +181,7 @@ VertexOutputCorrectDeformation RibbonVS_CorrectDeformation(VertexInputCorrectDef // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleID); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleID); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) diff --git a/Assets/shaders/Ribbon/Legacy/Ribbon_Legacy.azsl b/Assets/shaders/Ribbon/Legacy/Ribbon_Legacy.azsl index 1afa873..f57e388 100644 --- a/Assets/shaders/Ribbon/Legacy/Ribbon_Legacy.azsl +++ b/Assets/shaders/Ribbon/Legacy/Ribbon_Legacy.azsl @@ -94,7 +94,7 @@ VertexOutput RibbonVS(VertexInput input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleID); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleID); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) @@ -122,7 +122,7 @@ VertexOutputAtlasBlend RibbonVS_AtlasBlend(VertexInputAtlasBlend input) // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleID); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleID); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) @@ -150,7 +150,7 @@ VertexOutputCorrectDeformation RibbonVS_CorrectDeformation(VertexInputCorrectDef // Emissive particle color: output.m_emissiveColor = float3(0, 0, 0); if (HasOneRendererFlags(Has_Emissive)) - output.m_emissiveColor = GetEmissiveParticleColor(particleID); + output.m_emissiveColor = GetEmissiveParticleColorLegacy(particleID); // Alpha remap: output.m_alphaCursor = 0; if (HasOneRendererFlags(Has_AlphaRemap)) diff --git a/Code/CMakeLists.txt b/Code/CMakeLists.txt index adfa4ff..b988d84 100644 --- a/Code/CMakeLists.txt +++ b/Code/CMakeLists.txt @@ -3,7 +3,7 @@ # https://www.popcornfx.com/terms-and-conditions/ #---------------------------------------------------------------------------- -set(POPCORNFX_VERSION 2.20.1) +set(POPCORNFX_VERSION 2.20.2) set(POPCORNFX_LICENSE O3DE) o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} "${gem_restricted_path}" "${gem_path}" "${gem_name}") diff --git a/Code/Platform/Linux/PAL_linux.cmake b/Code/Platform/Linux/PAL_linux.cmake index 68b3daf..9cac285 100644 --- a/Code/Platform/Linux/PAL_linux.cmake +++ b/Code/Platform/Linux/PAL_linux.cmake @@ -6,12 +6,12 @@ set(LY_PACKAGE_SERVER_URLS ${LY_PACKAGE_SERVER_URLS} "https://downloads.popcornfx.com/o3de-packages") if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") set(package_name PopcornFX-${POPCORNFX_VERSION}-${POPCORNFX_LICENSE}-linux) - set(pk_package_hash 37caeb9bd6fa8b89820dfd3f27fb91207834b169c3ed6942f9fb9c0b65683838) - set(pk_package_id UsqgOwkkPIotbGLE) + set(pk_package_hash f154096ceee3268e5b6894d8bab56b9a335cf32cfbca5def50ecea9031c41658) + set(pk_package_id 1QdGMQ1JWwhurfqD) elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") set(package_name PopcornFX-${POPCORNFX_VERSION}-${POPCORNFX_LICENSE}-linux-aarch64) - set(pk_package_hash 37caeb9bd6fa8b89820dfd3f27fb91207834b169c3ed6942f9fb9c0b65683838_ARM64) - set(pk_package_id UsqgOwkkPIotbGLE_ARM64) + set(pk_package_hash f154096ceee3268e5b6894d8bab56b9a335cf32cfbca5def50ecea9031c41658_ARM64) + set(pk_package_id 1QdGMQ1JWwhurfqD_ARM64) else() message(FATAL_ERROR "Unsupported linux architecture ${CMAKE_SYSTEM_PROCESSOR}") endif() diff --git a/Code/Platform/Mac/PAL_mac.cmake b/Code/Platform/Mac/PAL_mac.cmake index 9c0812e..140dec4 100644 --- a/Code/Platform/Mac/PAL_mac.cmake +++ b/Code/Platform/Mac/PAL_mac.cmake @@ -5,8 +5,8 @@ set(LY_PACKAGE_SERVER_URLS ${LY_PACKAGE_SERVER_URLS} "https://downloads.popcornfx.com/o3de-packages") set(package_name PopcornFX-${POPCORNFX_VERSION}-${POPCORNFX_LICENSE}-mac) -set(pk_package_hash 269f82977c7bc3cf5c113627ecd8c26b2a1548f72e2b27734a84f531cafa082e) -set(pk_package_id or2If26Gt6FboQ5x) +set(pk_package_hash a7598f23cceae600cfcfa8a68bdf5b7dc41d01a60c355228ad8d60da20e1f528) +set(pk_package_id y5KQOjPw7QBbBG5T) ly_associate_package(PACKAGE_NAME ${package_name} TARGETS PopcornFX PACKAGE_HASH ${pk_package_hash}) pk_download_package_ifn(${package_name} ${pk_package_id}) diff --git a/Code/Platform/Windows/PAL_windows.cmake b/Code/Platform/Windows/PAL_windows.cmake index 35cd238..158b7a3 100644 --- a/Code/Platform/Windows/PAL_windows.cmake +++ b/Code/Platform/Windows/PAL_windows.cmake @@ -5,8 +5,8 @@ set(LY_PACKAGE_SERVER_URLS ${LY_PACKAGE_SERVER_URLS} "https://downloads.popcornfx.com/o3de-packages") set(package_name PopcornFX-${POPCORNFX_VERSION}-${POPCORNFX_LICENSE}-windows) -set(pk_package_hash 3a9c25da7fe7c58f7cbfb278c63e9806faba5f5cbbd8e25337235e4de1c3ddad) -set(pk_package_id bzoBrc2Rvgs8eSMs) +set(pk_package_hash 2e1d99d52adba4002e90d798e456613281ccb55e039869059decdb2e3e6b24b2) +set(pk_package_id oX1jNyQLOcVw3ViZ) ly_associate_package(PACKAGE_NAME ${package_name} TARGETS PopcornFX PACKAGE_HASH ${pk_package_hash}) pk_download_package_ifn(${package_name} ${pk_package_id}) diff --git a/Code/Source/Integration/Managers/RenderManager.h b/Code/Source/Integration/Managers/RenderManager.h index 64d2fe7..8098747 100644 --- a/Code/Source/Integration/Managers/RenderManager.h +++ b/Code/Source/Integration/Managers/RenderManager.h @@ -36,7 +36,7 @@ class CRenderManager const CAtomFrameCollector &GetFrameCollector() const { return m_FrameCollector; } - const SAtomRenderContext &GetRenderContext() const { return m_RenderContext; } + SAtomRenderContext &GetRenderContext() { return m_RenderContext; } void UnregisterEffectMaterials(const PParticleEffect &effect); private: diff --git a/Code/Source/Integration/Preloader/PopcornFXRendererLoader.cpp b/Code/Source/Integration/Preloader/PopcornFXRendererLoader.cpp index 61edc5d..fce421d 100644 --- a/Code/Source/Integration/Preloader/PopcornFXRendererLoader.cpp +++ b/Code/Source/Integration/Preloader/PopcornFXRendererLoader.cpp @@ -430,17 +430,42 @@ void PopcornFXRendererLoader::_OnAssetReady(AZ::Data::Asset const AZ::RPI::ModelLod::Mesh &mesh = modelLod->GetMeshes()[meshIndex]; geometryCache->m_PerGeometryViews[meshIndex].m_Bounds = ToPk(modelAsset->GetLodAssets()[0]->GetMeshes()[meshIndex].GetAabb()); - AZ::RPI::ModelLod::StreamBufferViewList streamBufferViews; +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + geometryCache->m_PerGeometryViews[meshIndex].m_IndexBuffer = mesh.GetIndexBufferView(); + geometryCache->m_PerGeometryViews[meshIndex].m_IndexCount = mesh.GetDrawArguments().m_indexed.m_indexCount; + + AZ::RHI::StreamBufferIndices streamIndices; [[maybe_unused]] bool result = modelLod->GetStreamsForMesh( inputStreamLayout, - streamBufferViews, + streamIndices, null, shaderInputContract, meshIndex); AZ_Assert(result, "Failed to retrieve mesh stream buffer views"); - //uint32_t positionBufferByteCount = streamBufferViews[0].GetBuffer()->GetDescriptor().m_byteCount; + geometryCache->m_PerGeometryViews[meshIndex].m_PositionBuffer = mesh.GetStreamBufferView(streamIndices.GetIndex(0)); + geometryCache->m_PerGeometryViews[meshIndex].m_NormalBuffer = mesh.GetStreamBufferView(streamIndices.GetIndex(1)); - //uint32_t normalBufferByteCount = streamBufferViews[1].GetBuffer()->GetDescriptor().m_byteCount; + const AZ::RHI::StreamBufferView &tangentBufferView = mesh.GetStreamBufferView(streamIndices.GetIndex(2)); + const AZ::RHI::StreamBufferView &bitangentBufferView = mesh.GetStreamBufferView(streamIndices.GetIndex(3)); + const AZ::RHI::StreamBufferView &uvBufferView = mesh.GetStreamBufferView(streamIndices.GetIndex(4)); + + if (tangentBufferView.GetBuffer()->GetDescriptor().m_byteCount > 0) + geometryCache->m_PerGeometryViews[meshIndex].m_TangentBuffer = tangentBufferView; + if (bitangentBufferView.GetBuffer()->GetDescriptor().m_byteCount > 0) + geometryCache->m_PerGeometryViews[meshIndex].m_BitangentBuffer = bitangentBufferView; + if (uvBufferView.GetBuffer()->GetDescriptor().m_byteCount > 0) + geometryCache->m_PerGeometryViews[meshIndex].m_UVBuffer = uvBufferView; +#else + geometryCache->m_PerGeometryViews[meshIndex].m_IndexCount = mesh.m_drawArguments.m_indexed.m_indexCount; + geometryCache->m_PerGeometryViews[meshIndex].m_IndexBuffer = mesh.m_indexBufferView; + + AZ::RPI::ModelLod::StreamBufferViewList streamBufferViews; + [[maybe_unused]] bool result = modelLod->GetStreamsForMesh( inputStreamLayout, + streamBufferViews, + null, + shaderInputContract, + meshIndex); + AZ_Assert(result, "Failed to retrieve mesh stream buffer views"); AZ::u64 tangentBufferByteCount = streamBufferViews[2].GetBuffer()->GetDescriptor().m_byteCount; @@ -448,8 +473,6 @@ void PopcornFXRendererLoader::_OnAssetReady(AZ::Data::Asset AZ::u64 uvBufferByteCount = streamBufferViews[4].GetBuffer()->GetDescriptor().m_byteCount; - geometryCache->m_PerGeometryViews[meshIndex].m_IndexCount = mesh.m_drawArguments.m_indexed.m_indexCount; - geometryCache->m_PerGeometryViews[meshIndex].m_PositionBuffer = streamBufferViews[0]; geometryCache->m_PerGeometryViews[meshIndex].m_NormalBuffer = streamBufferViews[1]; @@ -462,8 +485,7 @@ void PopcornFXRendererLoader::_OnAssetReady(AZ::Data::Asset if (uvBufferByteCount > 0) geometryCache->m_PerGeometryViews[meshIndex].m_UVBuffer = streamBufferViews[4]; - - geometryCache->m_PerGeometryViews[meshIndex].m_IndexBuffer = mesh.m_indexBufferView; +#endif } if (!PK_VERIFY(m_ModifiedCaches.PushBack(geometryCache).Valid())) return; @@ -585,9 +607,7 @@ AZ::RHI::ConstPtr PopcornFXRendererLoader::_CreatePipeli else if (IsRibbonShader(usedShader)) { AZ::RHI::InputStreamLayoutBuilder layoutBuilder; - if (usedShader == EPopcornFXShader::RibbonLegacy_Shader || - usedShader == EPopcornFXShader::RibbonLitLegacy_Shader || - usedShader == EPopcornFXShader::RibbonDistortion_Shader) + if (IsRibbonShaderDefault(usedShader)) { layoutBuilder.AddBuffer()->Channel("POSITION", AZ::RHI::Format::R32G32B32A32_FLOAT); if (assetType == AssetType_MaterialShader) @@ -595,8 +615,7 @@ AZ::RHI::ConstPtr PopcornFXRendererLoader::_CreatePipeli layoutBuilder.AddBuffer()->Channel("UV0", AZ::RHI::Format::R32G32_FLOAT); // texCoord 0 } } - else if (usedShader == EPopcornFXShader::RibbonAtlasBlendLegacy_Shader || - usedShader == EPopcornFXShader::RibbonLitAtlasBlendLegacy_Shader) + else if (IsRibbonShaderAtlasBlend(usedShader)) { layoutBuilder.AddBuffer()->Channel("POSITION", AZ::RHI::Format::R32G32B32A32_FLOAT); if (assetType == AssetType_MaterialShader) @@ -606,8 +625,7 @@ AZ::RHI::ConstPtr PopcornFXRendererLoader::_CreatePipeli layoutBuilder.AddBuffer()->Channel("UV2", AZ::RHI::Format::R32_FLOAT); // texFrameLerp } } - else if (usedShader == EPopcornFXShader::RibbonCorrectDeformationLegacy_Shader || - usedShader == EPopcornFXShader::RibbonLitCorrectDeformationLegacy_Shader) + else if (IsRibbonShaderCorrectDeformation(usedShader)) { layoutBuilder.AddBuffer()->Channel("POSITION", AZ::RHI::Format::R32G32B32A32_FLOAT); if (assetType == AssetType_MaterialShader) diff --git a/Code/Source/Integration/Render/AtomIntegration/AtomFrameCollectorTypes.h b/Code/Source/Integration/Render/AtomIntegration/AtomFrameCollectorTypes.h index 72cd12d..86282e9 100644 --- a/Code/Source/Integration/Render/AtomIntegration/AtomFrameCollectorTypes.h +++ b/Code/Source/Integration/Render/AtomIntegration/AtomFrameCollectorTypes.h @@ -42,6 +42,10 @@ struct SAtomRenderContext : public SRenderContext bool m_CastShadows = false; s32 m_GlobalSortOverride = 0; u32 m_InstanceOffset = 0; // Slices +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + u32 m_InstanceCount = 0; + AZ::RHI::GeometryView m_GeometryView; +#endif CAABB m_BoundingBox; AZ::RHI::DrawIndexed m_DrawIndexed; diff --git a/Code/Source/Integration/Render/AtomIntegration/AtomPipelineCache.cpp b/Code/Source/Integration/Render/AtomIntegration/AtomPipelineCache.cpp index 5edff41..f34bb15 100644 --- a/Code/Source/Integration/Render/AtomIntegration/AtomPipelineCache.cpp +++ b/Code/Source/Integration/Render/AtomIntegration/AtomPipelineCache.cpp @@ -300,6 +300,12 @@ void CAtomPipelineCache::ConfigureDrawCall(SAtomRenderContext::SDrawCall &drawCa drawCall.m_TransparentDepthMinDrawList = m_TransparentDepthMinDrawList; drawCall.m_TransparentDepthMaxPipelineState = m_TransparentDepthMaxPipelineState; drawCall.m_TransparentDepthMaxDrawList = m_TransparentDepthMaxDrawList; + +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + drawCall.m_GeometryView.SetIndexBufferView(m_IndexBuffer); + for (u32 i = 0; i < drawCall.m_VertexInputs.Count(); ++i) + drawCall.m_GeometryView.AddStreamBufferView(drawCall.m_VertexInputs[i]); +#endif } //---------------------------------------------------------------------------- diff --git a/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.cpp b/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.cpp index a7e3f9b..eb23565 100644 --- a/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.cpp +++ b/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.cpp @@ -20,9 +20,16 @@ namespace PopcornFX { const char *kPopcornFXShaderPaths[] = { "shaders/Billboard/Default/Billboard.azshader", // Billboard_Shader + "shaders/Billboard/Default/BillboardLit.azshader", // BillboardLit_Shader "shaders/Billboard/Legacy/Billboard_Legacy.azshader", // BillboardLegacy_Shader "shaders/Billboard/Legacy/BillboardLit_Legacy.azshader", // BillboardLitLegacy_Shader "shaders/Billboard/Default/BillboardDistortion.azshader", // BillboardDistortion_Shader + "shaders/Ribbon/Default/Ribbon.azshader", // Ribbon_Shader + "shaders/Ribbon/Default/RibbonAtlasBlend.azshader", // RibbonAtlasBlend_Shader + "shaders/Ribbon/Default/RibbonCorrectDeformation.azshader", // RibbonCorrectDeformation_Shader + "shaders/Ribbon/Default/RibbonLit.azshader", // RibbonLit_Shader + "shaders/Ribbon/Default/RibbonLitAtlasBlend.azshader", // RibbonLitAtlasBlend_Shader + "shaders/Ribbon/Default/RibbonLitCorrectDeformation.azshader", // RibbonLitCorrectDeformation_Shader "shaders/Ribbon/Legacy/Ribbon_Legacy.azshader", // RibbonLegacy_Shader "shaders/Ribbon/Legacy/RibbonAtlasBlend_Legacy.azshader", // RibbonAtlasBlendLegacy_Shader "shaders/Ribbon/Legacy/RibbonCorrectDeformation_Legacy.azshader", // RibbonCorrectDeformationLegacy_Shader @@ -30,18 +37,25 @@ const char *kPopcornFXShaderPaths[] = "shaders/Ribbon/Legacy/RibbonLitAtlasBlend_Legacy.azshader", // RibbonLitAtlasBlendLegacy_Shader "shaders/Ribbon/Legacy/RibbonLitCorrectDeformation_Legacy.azshader", // RibbonLitCorrectDeformationLegacy_Shader "shaders/Ribbon/Default/RibbonDistortion.azshader", // RibbonDistortion_Shader - "shaders/Mesh/Legacy/Mesh_Legacy.azshader", // Mesh_Shader - "shaders/Mesh/Legacy/MeshLit_Legacy.azshader", // MeshLit_Shader + "shaders/Mesh/Default/Mesh.azshader", // Mesh_Shader + "shaders/Mesh/Default/MeshLit.azshader", // MeshLit_Shader + "shaders/Mesh/Legacy/Mesh_Legacy.azshader", // MeshLegacy_Shader + "shaders/Mesh/Legacy/MeshLit_Legacy.azshader", // MeshLitLegacy_Shader }; //---------------------------------------------------------------------------- bool IsLitShader(EPopcornFXShader shader) { - return shader == BillboardLitLegacy_Shader || + return shader == BillboardLit_Shader || + shader == BillboardLitLegacy_Shader || + shader == RibbonLit_Shader || + shader == RibbonLitAtlasBlend_Shader || + shader == RibbonLitCorrectDeformation_Shader || shader == RibbonLitLegacy_Shader || shader == RibbonLitAtlasBlendLegacy_Shader || shader == RibbonLitCorrectDeformationLegacy_Shader || + shader == MeshLit_Shader || shader == MeshLitLegacy_Shader; } @@ -52,6 +66,7 @@ bool IsBillboardShader(EPopcornFXShader shader) return shader == BillboardLitLegacy_Shader || shader == BillboardLegacy_Shader || shader == Billboard_Shader || + shader == BillboardLit_Shader || shader == BillboardDistortion_Shader; } @@ -59,7 +74,13 @@ bool IsBillboardShader(EPopcornFXShader shader) bool IsRibbonShader(EPopcornFXShader shader) { - return shader == RibbonLegacy_Shader || + return shader == Ribbon_Shader || + shader == RibbonAtlasBlend_Shader || + shader == RibbonCorrectDeformation_Shader || + shader == RibbonLit_Shader || + shader == RibbonLitAtlasBlend_Shader || + shader == RibbonLitCorrectDeformation_Shader || + shader == RibbonLegacy_Shader || shader == RibbonAtlasBlendLegacy_Shader || shader == RibbonCorrectDeformationLegacy_Shader || shader == RibbonLitLegacy_Shader || @@ -70,6 +91,37 @@ bool IsRibbonShader(EPopcornFXShader shader) //---------------------------------------------------------------------------- +bool IsRibbonShaderDefault(EPopcornFXShader shader) +{ + return shader == Ribbon_Shader || + shader == RibbonLit_Shader || + shader == RibbonLegacy_Shader || + shader == RibbonLitLegacy_Shader || + shader == RibbonDistortion_Shader; +} + +//---------------------------------------------------------------------------- + +bool IsRibbonShaderAtlasBlend(EPopcornFXShader shader) +{ + return shader == RibbonAtlasBlend_Shader || + shader == RibbonLitAtlasBlend_Shader || + shader == RibbonAtlasBlendLegacy_Shader || + shader == RibbonLitAtlasBlendLegacy_Shader; +} + +//---------------------------------------------------------------------------- + +bool IsRibbonShaderCorrectDeformation(EPopcornFXShader shader) +{ + return shader == RibbonCorrectDeformation_Shader || + shader == RibbonLitCorrectDeformation_Shader || + shader == RibbonCorrectDeformationLegacy_Shader || + shader == RibbonLitCorrectDeformationLegacy_Shader; +} + +//---------------------------------------------------------------------------- + bool IsLegacyShader(EPopcornFXShader shader) { return shader == BillboardLegacy_Shader || @@ -82,14 +134,17 @@ bool IsLegacyShader(EPopcornFXShader shader) shader == RibbonLitCorrectDeformationLegacy_Shader || shader == BillboardDistortion_Shader || shader == RibbonDistortion_Shader || - shader == MeshLegacy_Shader; + shader == MeshLegacy_Shader || + shader == MeshLitLegacy_Shader; } //---------------------------------------------------------------------------- bool IsMeshShader(EPopcornFXShader shader) { - return shader == MeshLegacy_Shader || + return shader == Mesh_Shader || + shader == MeshLit_Shader || + shader == MeshLegacy_Shader || shader == MeshLitLegacy_Shader; } //---------------------------------------------------------------------------- @@ -319,7 +374,8 @@ void SParticleMaterialBasicDesc::InitFromRenderer(const CRendererDataBase &rende const CString diffuseMap = decl.GetPropertyValue_Path(SID_Diffuse_DiffuseMap(), CString::EmptyString); if (!diffuseMap.Empty()) { - PK_ASSERT(renderer.m_Declaration.FindAdditionalFieldIndex(SID_Diffuse_Color()).Valid()); + PK_ASSERT( renderer.m_Declaration.FindAdditionalFieldIndex(SID_Diffuse_Color()).Valid() || + renderer.m_Declaration.FindAdditionalFieldIndex(SID_Diffuse_DiffuseColor()).Valid()); // With the new "Experimental" shaders, emissive, diffuse, distortion and tint are features you can disable // to handle that we set changesPipelineState to true: _AddRendererFlags(RendererFlags::Has_Diffuse, true, true); @@ -474,27 +530,31 @@ void SParticleMaterialBasicDesc::InitFromRenderer(const CRendererDataBase &rende if (decl.IsFeatureEnabled(SID_Transparent())) { - const ETransparentType transparentType = decl.GetPropertyValue_Enum(SID_Transparent_Type(), Additive); - - m_PipelineStateKey.m_BlendMode = BlendMode::Additive; - switch (transparentType) + const SRendererFeaturePropertyValue *prop = decl.FindProperty(SID_Transparent_Type()); + if (prop != null) { - case Additive: + const ETransparentType transparentType = decl.GetPropertyValue_Enum(SID_Transparent_Type(), Additive); + m_PipelineStateKey.m_BlendMode = BlendMode::Additive; - break; - case AdditiveNoAlpha: - m_PipelineStateKey.m_BlendMode = BlendMode::AdditiveNoAlpha; - break; - case AlphaBlend: - m_PipelineStateKey.m_BlendMode = BlendMode::AlphaBlend; - break; - case PremultipliedAlpha: - m_PipelineStateKey.m_BlendMode = BlendMode::PremultipliedAlpha; - break; - default: - PK_ASSERT_NOT_REACHED(); - break; - }; + switch (transparentType) + { + case Additive: + m_PipelineStateKey.m_BlendMode = BlendMode::Additive; + break; + case AdditiveNoAlpha: + m_PipelineStateKey.m_BlendMode = BlendMode::AdditiveNoAlpha; + break; + case AlphaBlend: + m_PipelineStateKey.m_BlendMode = BlendMode::AlphaBlend; + break; + case PremultipliedAlpha: + m_PipelineStateKey.m_BlendMode = BlendMode::PremultipliedAlpha; + break; + default: + PK_ASSERT_NOT_REACHED(); + break; + }; + } } else if (decl.IsFeatureEnabled(SID_Opaque())) { @@ -527,8 +587,42 @@ void SParticleMaterialBasicDesc::InitFromRenderer(const CRendererDataBase &rende } else if (m_PipelineStateKey.m_BlendMode == BlendMode::BlendMode_Count) // No explicit blend mode, can use new materials... { + m_PipelineStateKey.m_BlendMode = BlendMode::PremultipliedAlpha; if (renderer.m_RendererType == ERendererClass::Renderer_Billboard) - m_PipelineStateKey.m_UsedShader = EPopcornFXShader::Billboard_Shader; + { + if (HasOneRendererFlags(RendererFlags::Has_Lighting)) + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::BillboardLit_Shader; + else + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::Billboard_Shader; + } + else if (renderer.m_RendererType == ERendererClass::Renderer_Ribbon) + { + if (HasOneRendererFlags(RendererFlags::Has_Lighting)) + { + if (HasOneRendererFlags(RendererFlags::Has_CorrectDeformation)) + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::RibbonLitCorrectDeformation_Shader; + else if (HasOneRendererFlags(RendererFlags::Has_AnimBlend)) + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::RibbonLitAtlasBlend_Shader; + else + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::RibbonLit_Shader; + } + else + { + if (HasOneRendererFlags(RendererFlags::Has_CorrectDeformation)) + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::RibbonCorrectDeformation_Shader; + else if (HasOneRendererFlags(RendererFlags::Has_AnimBlend)) + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::RibbonAtlasBlend_Shader; + else + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::Ribbon_Shader; + } + } + else if (renderer.m_RendererType == ERendererClass::Renderer_Mesh) + { + if (HasOneRendererFlags(RendererFlags::Has_Lighting)) + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::MeshLit_Shader; + else + m_PipelineStateKey.m_UsedShader = EPopcornFXShader::Mesh_Shader; + } } else { diff --git a/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.h b/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.h index b0f3634..8ddbfb1 100644 --- a/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.h +++ b/Code/Source/Integration/Render/AtomIntegration/AtomRendererCache.h @@ -83,9 +83,16 @@ namespace BlendMode enum EPopcornFXShader { Billboard_Shader, + BillboardLit_Shader, BillboardLegacy_Shader, BillboardLitLegacy_Shader, BillboardDistortion_Shader, + Ribbon_Shader, + RibbonAtlasBlend_Shader, + RibbonCorrectDeformation_Shader, + RibbonLit_Shader, + RibbonLitAtlasBlend_Shader, + RibbonLitCorrectDeformation_Shader, RibbonLegacy_Shader, RibbonAtlasBlendLegacy_Shader, RibbonCorrectDeformationLegacy_Shader, @@ -93,6 +100,8 @@ enum EPopcornFXShader RibbonLitAtlasBlendLegacy_Shader, RibbonLitCorrectDeformationLegacy_Shader, RibbonDistortion_Shader, + Mesh_Shader, + MeshLit_Shader, MeshLegacy_Shader, MeshLitLegacy_Shader, __Shader_Count @@ -105,6 +114,9 @@ extern const char *kPopcornFXShaderPaths[__Shader_Count]; bool IsLitShader(EPopcornFXShader shader); bool IsBillboardShader(EPopcornFXShader shader); bool IsRibbonShader(EPopcornFXShader shader); +bool IsRibbonShaderDefault(EPopcornFXShader shader); +bool IsRibbonShaderAtlasBlend(EPopcornFXShader shader); +bool IsRibbonShaderCorrectDeformation(EPopcornFXShader shader); bool IsLegacyShader(EPopcornFXShader shader); bool IsMeshShader(EPopcornFXShader shader); const char *GetPopornFXUsedShaderPath(EPopcornFXShader shader); diff --git a/Code/Source/Integration/Render/AtomIntegration/BillboardBatchDrawer.cpp b/Code/Source/Integration/Render/AtomIntegration/BillboardBatchDrawer.cpp index dbb4670..a475496 100644 --- a/Code/Source/Integration/Render/AtomIntegration/BillboardBatchDrawer.cpp +++ b/Code/Source/Integration/Render/AtomIntegration/BillboardBatchDrawer.cpp @@ -462,6 +462,8 @@ bool CBillboardBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDes m_PipelineCaches[0].SetBillboardingSrgBuffer(BillboardSrg::ParticleAtlasID_ShaderRead, buff); } AZ::RHI::Ptr diffuseColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Diffuse_Color()); + if (diffuseColor == null) + diffuseColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Diffuse_DiffuseColor()); if (diffuseColor != null) { #if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 @@ -474,10 +476,13 @@ bool CBillboardBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDes AZ::RHI::Ptr emissiveColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Emissive_EmissiveColor()); if (emissiveColor != null) { + const bool isLegacyShader = IsLegacyShader(rendererCache->m_BasicDescription.m_PipelineStateKey.m_UsedShader); + const u32 elementCount = isLegacyShader ? particleCount * 3 : particleCount * 4; + #if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 - AZ::RHI::Ptr buff = emissiveColor->BuildBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, particleCount * 3, sizeof(float))); + AZ::RHI::Ptr buff = emissiveColor->BuildBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, elementCount, sizeof(float))); #else - AZ::RHI::Ptr buff = emissiveColor->GetBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, particleCount * 3, sizeof(float))); + AZ::RHI::Ptr buff = emissiveColor->GetBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, elementCount, sizeof(float))); #endif m_PipelineCaches[0].SetBillboardingSrgBuffer(BillboardSrg::ParticleEmissiveColor_ShaderRead, buff); } @@ -522,11 +527,16 @@ bool CBillboardBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDes dc.m_BoundingBox = toEmit.m_BBox; // Draw call description: +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + dc.m_GeometryView.SetDrawArguments(AZ::RHI::DrawIndexed(0, m_DrawInstanceIdxCount, 0)); + dc.m_InstanceCount = toEmit.m_TotalParticleCount; +#else dc.m_DrawIndexed.m_indexCount = m_DrawInstanceIdxCount; dc.m_DrawIndexed.m_indexOffset = 0; dc.m_DrawIndexed.m_instanceCount = toEmit.m_TotalParticleCount; // Sliced draw calls can draw < drawPass.m_TotalParticleCount dc.m_DrawIndexed.m_instanceOffset = 0; dc.m_DrawIndexed.m_vertexOffset = 0; +#endif // See CPopcornFXFeatureProcessor::BuildDrawPacket() dc.m_InstanceOffset = toEmit.m_IndexOffset; // Sliced draw calls can have a non-zero offset diff --git a/Code/Source/Integration/Render/AtomIntegration/MeshBatchDrawer.cpp b/Code/Source/Integration/Render/AtomIntegration/MeshBatchDrawer.cpp index bfe490c..eeef0fe 100644 --- a/Code/Source/Integration/Render/AtomIntegration/MeshBatchDrawer.cpp +++ b/Code/Source/Integration/Render/AtomIntegration/MeshBatchDrawer.cpp @@ -257,6 +257,8 @@ bool CMeshBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDesc &to // Non constant data: additionnal inputs AZ::RHI::Ptr diffuseColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Diffuse_Color()); + if (diffuseColor == null) + diffuseColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Diffuse_DiffuseColor()); if (diffuseColor != null) { #if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 @@ -269,10 +271,14 @@ bool CMeshBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDesc &to AZ::RHI::Ptr emissiveColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Emissive_EmissiveColor()); if (emissiveColor != null) { + const bool isLegacyShader = IsLegacyShader(rendererCache->m_BasicDescription.m_PipelineStateKey.m_UsedShader); + const u32 elementOffset = isLegacyShader ? particleOffset * 3 : particleOffset * 4; + const u32 elementCount = isLegacyShader ? particleCount * 3 : particleCount * 4; + #if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 - AZ::RHI::Ptr buff = emissiveColor->BuildBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(particleOffset * 3, meshParticleCount * 3, sizeof(float))); + AZ::RHI::Ptr buff = emissiveColor->BuildBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(elementOffset, elementCount, sizeof(float))); #else - AZ::RHI::Ptr buff = emissiveColor->GetBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(particleOffset * 3, meshParticleCount * 3, sizeof(float))); + AZ::RHI::Ptr buff = emissiveColor->GetBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(elementOffset, elementCount, sizeof(float))); #endif m_PipelineCaches[i].SetMeshSrgBuffer(MeshSrg::ParticleEmissiveColor_ShaderRead, buff); } @@ -293,11 +299,16 @@ bool CMeshBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDesc &to dc.m_BoundingBox = toEmit.m_BBox; // Draw call description: +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + dc.m_InstanceCount = meshParticleCount; + dc.m_GeometryView.SetDrawArguments(AZ::RHI::DrawIndexed(0, views.m_IndexCount, 0)); +#else dc.m_DrawIndexed.m_indexCount = views.m_IndexCount; dc.m_DrawIndexed.m_indexOffset = 0; dc.m_DrawIndexed.m_instanceCount = meshParticleCount; dc.m_DrawIndexed.m_instanceOffset = 0; dc.m_DrawIndexed.m_vertexOffset = 0; +#endif // Draw instance indices and tex-coords: if (!PK_VERIFY(m_RenderContext->m_DrawCalls.PushBack(dc).Valid())) diff --git a/Code/Source/Integration/Render/AtomIntegration/ParticleBuffers.cpp b/Code/Source/Integration/Render/AtomIntegration/ParticleBuffers.cpp index 3ebb798..423d1e5 100644 --- a/Code/Source/Integration/Render/AtomIntegration/ParticleBuffers.cpp +++ b/Code/Source/Integration/Render/AtomIntegration/ParticleBuffers.cpp @@ -117,8 +117,10 @@ namespace PopcornFX { : m_UseLargeIndices(true) , m_RenderContext(null) { + m_HandledAdditionalFields.PushBack(SHandledAdditionalFields(BasicRendererProperties::SID_Diffuse_DiffuseColor(), BaseType_Float4)); m_HandledAdditionalFields.PushBack(SHandledAdditionalFields(BasicRendererProperties::SID_Diffuse_Color(), BaseType_Float4)); m_HandledAdditionalFields.PushBack(SHandledAdditionalFields(BasicRendererProperties::SID_Emissive_EmissiveColor(), BaseType_Float3)); + m_HandledAdditionalFields.PushBack(SHandledAdditionalFields(BasicRendererProperties::SID_Emissive_EmissiveColor(), BaseType_Float4)); m_HandledAdditionalFields.PushBack(SHandledAdditionalFields(BasicRendererProperties::SID_Distortion_Color(), BaseType_Float4)); m_HandledAdditionalFields.PushBack(SHandledAdditionalFields(BasicRendererProperties::SID_AlphaRemap_Cursor(), BaseType_Float)); m_HandledAdditionalFields.PushBack(SHandledAdditionalFields(BasicRendererProperties::SID_Atlas_TextureID(), BaseType_Float)); diff --git a/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.cpp b/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.cpp index 9cfba7b..2523c02 100644 --- a/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.cpp +++ b/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.cpp @@ -66,7 +66,7 @@ void CPopcornFXFeatureProcessor::Simulate(const SimulatePacket &packet) void CPopcornFXFeatureProcessor::Render(const RenderPacket &packet) { - const SAtomRenderContext &drawCalls = m_RenderManager.GetRenderContext(); + SAtomRenderContext &drawCalls = m_RenderManager.GetRenderContext(); // Delete the DrawPackets that were used last frame m_drawPackets.clear(); @@ -74,7 +74,7 @@ void CPopcornFXFeatureProcessor::Render(const RenderPacket &packet) { PK_NAMEDSCOPEDPROFILE("Append draw calls"); - for (const SAtomRenderContext::SDrawCall &dc : drawCalls.m_DrawCalls) + for (SAtomRenderContext::SDrawCall &dc : drawCalls.m_DrawCalls) { const bool castShadows = dc.m_CastShadows; @@ -131,7 +131,7 @@ void CPopcornFXFeatureProcessor::AppendLightParticles() } } -CPopcornFXFeatureProcessor::DrawPacketPtr CPopcornFXFeatureProcessor::BuildDrawPacket(const SAtomRenderContext::SDrawCall &pkfxDrawCall, +CPopcornFXFeatureProcessor::DrawPacketPtr CPopcornFXFeatureProcessor::BuildDrawPacket(SAtomRenderContext::SDrawCall &pkfxDrawCall, const AZ::RHI::ShaderResourceGroup *viewSrg, AZ::RHI::DrawItemSortKey sortKey) { @@ -143,8 +143,13 @@ CPopcornFXFeatureProcessor::DrawPacketPtr CPopcornFXFeatureProcessor::BuildDrawP #endif dpBuilder.Begin(null); +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + dpBuilder.SetGeometryView(&pkfxDrawCall.m_GeometryView); + dpBuilder.SetDrawInstanceArguments(AZ::RHI::DrawInstanceArguments(pkfxDrawCall.m_InstanceCount, 0)); +#else dpBuilder.SetDrawArguments(pkfxDrawCall.m_DrawIndexed); dpBuilder.SetIndexBufferView(pkfxDrawCall.m_Indices); +#endif dpBuilder.AddShaderResourceGroup(pkfxDrawCall.m_RendererSrg->GetRHIShaderResourceGroup()); dpBuilder.AddShaderResourceGroup(pkfxDrawCall.m_MaterialSrg->GetRHIShaderResourceGroup()); @@ -153,8 +158,12 @@ CPopcornFXFeatureProcessor::DrawPacketPtr CPopcornFXFeatureProcessor::BuildDrawP AZ::RHI::DrawPacketBuilder::DrawRequest materialDr; materialDr.m_listTag = pkfxDrawCall.m_MaterialDrawList; materialDr.m_pipelineState = pkfxDrawCall.m_MaterialPipelineState.get(); +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + materialDr.m_streamIndices = pkfxDrawCall.m_GeometryView.GetFullStreamBufferIndices(); +#else materialDr.m_streamBufferViews = AZStd::span( pkfxDrawCall.m_VertexInputs.RawDataPointer(), pkfxDrawCall.m_VertexInputs.Count()); +#endif // TODO: set this depending on lit state. materialDr.m_stencilRef = (AZ::Render::StencilRefs::UseIBLSpecularPass | AZ::Render::StencilRefs::UseDiffuseGIPass); @@ -163,6 +172,18 @@ CPopcornFXFeatureProcessor::DrawPacketPtr CPopcornFXFeatureProcessor::BuildDrawP dpBuilder.AddDrawItem(materialDr); } +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + AZ::RHI::StreamBufferIndices depthVtxInput; + if (pkfxDrawCall.m_RendererType == Renderer_Billboard || + pkfxDrawCall.m_RendererType == Renderer_Mesh) + { + depthVtxInput = pkfxDrawCall.m_GeometryView.GetFullStreamBufferIndices(); + } + else + { + depthVtxInput.AddIndex(0); + } +#else AZStd::span depthVtxInput; if (pkfxDrawCall.m_RendererType == Renderer_Billboard || @@ -176,13 +197,18 @@ CPopcornFXFeatureProcessor::DrawPacketPtr CPopcornFXFeatureProcessor::BuildDrawP depthVtxInput = AZStd::span( pkfxDrawCall.m_VertexInputs.RawDataPointer(), 1); } +#endif if (pkfxDrawCall.m_OpaqueDepthPipelineState != null) { AZ::RHI::DrawPacketBuilder::DrawRequest opaqueDepthDr; opaqueDepthDr.m_listTag = pkfxDrawCall.m_OpaqueDepthDrawList; opaqueDepthDr.m_pipelineState = pkfxDrawCall.m_OpaqueDepthPipelineState.get(); +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + opaqueDepthDr.m_streamIndices = depthVtxInput; +#else opaqueDepthDr.m_streamBufferViews = depthVtxInput; +#endif opaqueDepthDr.m_sortKey = sortKey; dpBuilder.AddDrawItem(opaqueDepthDr); } @@ -192,14 +218,22 @@ CPopcornFXFeatureProcessor::DrawPacketPtr CPopcornFXFeatureProcessor::BuildDrawP AZ::RHI::DrawPacketBuilder::DrawRequest transparentDepthMinDr; transparentDepthMinDr.m_listTag = pkfxDrawCall.m_TransparentDepthMinDrawList; transparentDepthMinDr.m_pipelineState = pkfxDrawCall.m_TransparentDepthMinPipelineState.get(); +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + transparentDepthMinDr.m_streamIndices = depthVtxInput; +#else transparentDepthMinDr.m_streamBufferViews = depthVtxInput; +#endif transparentDepthMinDr.m_sortKey = sortKey; dpBuilder.AddDrawItem(transparentDepthMinDr); AZ::RHI::DrawPacketBuilder::DrawRequest transparentDepthMaxDr; transparentDepthMaxDr.m_listTag = pkfxDrawCall.m_TransparentDepthMaxDrawList; transparentDepthMaxDr.m_pipelineState = pkfxDrawCall.m_TransparentDepthMaxPipelineState.get(); +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + transparentDepthMaxDr.m_streamIndices = depthVtxInput; +#else transparentDepthMaxDr.m_streamBufferViews = depthVtxInput; +#endif transparentDepthMaxDr.m_sortKey = sortKey; dpBuilder.AddDrawItem(transparentDepthMaxDr); } diff --git a/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.h b/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.h index e91d7af..bf1bce6 100644 --- a/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.h +++ b/Code/Source/Integration/Render/AtomIntegration/PopcornFXFeatureProcessor.h @@ -62,7 +62,7 @@ class CPopcornFXFeatureProcessor : public CPopcornFXFeatureProcessorInterface using DrawPackets = AZStd::vector>; #endif - DrawPacketPtr BuildDrawPacket(const SAtomRenderContext::SDrawCall &pkfxDrawCall, + DrawPacketPtr BuildDrawPacket(SAtomRenderContext::SDrawCall &pkfxDrawCall, const AZ::RHI::ShaderResourceGroup *viewSrg, AZ::RHI::DrawItemSortKey sortKey); diff --git a/Code/Source/Integration/Render/AtomIntegration/RibbonBatchDrawer.cpp b/Code/Source/Integration/Render/AtomIntegration/RibbonBatchDrawer.cpp index 8da6844..a6eed9b 100644 --- a/Code/Source/Integration/Render/AtomIntegration/RibbonBatchDrawer.cpp +++ b/Code/Source/Integration/Render/AtomIntegration/RibbonBatchDrawer.cpp @@ -362,6 +362,8 @@ bool CRibbonBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDesc & // Additional field buffers: AZ::RHI::Ptr diffuseColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Diffuse_Color()); + if (diffuseColor == null) + diffuseColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Diffuse_DiffuseColor()); if (diffuseColor != null) { #if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 @@ -374,10 +376,13 @@ bool CRibbonBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDesc & AZ::RHI::Ptr emissiveColor = GetCurBuffers().FindAdditionalFieldBuffer(BasicRendererProperties::SID_Emissive_EmissiveColor()); if (emissiveColor != null) { + const bool isLegacyShader = IsLegacyShader(rendererCache->m_BasicDescription.m_PipelineStateKey.m_UsedShader); + const u32 elementCount = isLegacyShader ? particleCount * 3 : particleCount * 4; + #if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 - AZ::RHI::Ptr buff = emissiveColor->BuildBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, particleCount * 3, sizeof(float))); + AZ::RHI::Ptr buff = emissiveColor->BuildBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, elementCount, sizeof(float))); #else - AZ::RHI::Ptr buff = emissiveColor->GetBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, particleCount * 3, sizeof(float))); + AZ::RHI::Ptr buff = emissiveColor->GetBufferView(AZ::RHI::BufferViewDescriptor::CreateStructured(0, elementCount, sizeof(float))); #endif m_PipelineCaches[0].SetRibbonSrgBuffer(RibbonSrg::ParticleEmissiveColor_ShaderRead, buff); } @@ -411,11 +416,16 @@ bool CRibbonBatchDrawer::EmitDrawCall(SRenderContext &ctx, const SDrawCallDesc & dc.m_BoundingBox = toEmit.m_BBox; // Draw call description: +#if O3DE_VERSION_MAJOR >= 4 && O3DE_VERSION_MINOR >= 2 + dc.m_InstanceCount = 1; + dc.m_GeometryView.SetDrawArguments(AZ::RHI::DrawIndexed(0, toEmit.m_TotalIndexCount, toEmit.m_IndexOffset)); +#else dc.m_DrawIndexed.m_indexCount = toEmit.m_TotalIndexCount; // Sliced draw calls can draw < drawPass.m_TotalIndexCount dc.m_DrawIndexed.m_indexOffset = toEmit.m_IndexOffset; // Sliced draw calls can have a non-zero offset dc.m_DrawIndexed.m_instanceCount = 1; dc.m_DrawIndexed.m_instanceOffset = 0; dc.m_DrawIndexed.m_vertexOffset = 0; +#endif // Draw instance indices and tex-coords: return PK_VERIFY(m_RenderContext->m_DrawCalls.PushBack(dc).Valid()); diff --git a/README.md b/README.md index 40b3163..11c15f5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # O3DE PopcornFX Plugin Integrates the **PopcornFX Runtime SDK** into **O3DE** as a Gem. -* **Version:** `v2.20.1` +* **Version:** `v2.20.2` * **O3DE:** `23.05`, `23.10` * **Supported platforms:** `Windows`, `MacOS`, `Linux`, `iOS`, `Android` diff --git a/gem.json b/gem.json index 5c1e66b..6179a31 100644 --- a/gem.json +++ b/gem.json @@ -1,13 +1,13 @@ { "gem_name": "PopcornFX", - "display_name": "PopcornFX 2.20.1", + "display_name": "PopcornFX 2.20.2", "license": "Community", "license_url": "https://www.popcornfx.com/popcornfx-community-license", "origin": "Persistant Studios - popcornfx.com", "repo_uri": "https://downloads.popcornfx.com/o3de-repo", - "origin_uri": "https://downloads.popcornfx.com/o3de-repo/PopcornFX-2.20/O3DE_PopcornFXGem_v2.20.1_Win64_Linux64_LinuxARM64_Mac64.zip", - "version": "2.20.1", - "last_updated": "2024-09-13", + "origin_uri": "https://downloads.popcornfx.com/o3de-repo/PopcornFX-2.20/O3DE_PopcornFXGem_v2.20.2_Win64_Linux64_LinuxARM64_Mac64.zip", + "version": "2.20.2", + "last_updated": "2024-10-07", "type": "Code", "summary": "The PopcornFX Gem provides real-time FX solution for particle effects.", "canonical_tags": [