Selaa lähdekoodia

Initial Stars Feature (#8624)

Signed-off-by: Alex Peterson <[email protected]>
Alex Peterson 3 vuotta sitten
vanhempi
commit
badbcd3eab
38 muutettua tiedostoa jossa 1748 lisäystä ja 4 poistoa
  1. 1 0
      .gitattributes
  2. 1 0
      AutomatedTesting/Gem/Code/enabled_gems.cmake
  3. 1 1
      Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultSceneSrg.azsli
  4. 3 3
      Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h
  5. 140 0
      Gems/Stars/Assets/Shaders/Stars/Stars.azsl
  6. 28 0
      Gems/Stars/Assets/Shaders/Stars/Stars.shader
  7. 3 0
      Gems/Stars/Assets/Stars/default.stars
  8. 13 0
      Gems/Stars/Assets/seedList.seed
  9. 15 0
      Gems/Stars/CMakeLists.txt
  10. 96 0
      Gems/Stars/Code/CMakeLists.txt
  11. 37 0
      Gems/Stars/Code/Include/Stars/StarsFeatureProcessorInterface.h
  12. 114 0
      Gems/Stars/Code/Source/EditorStarsComponent.cpp
  13. 39 0
      Gems/Stars/Code/Source/EditorStarsComponent.h
  14. 39 0
      Gems/Stars/Code/Source/EditorStarsModule.cpp
  15. 44 0
      Gems/Stars/Code/Source/EditorStarsSystemComponent.cpp
  16. 30 0
      Gems/Stars/Code/Source/EditorStarsSystemComponent.h
  17. 58 0
      Gems/Stars/Code/Source/StarsAsset.cpp
  18. 44 0
      Gems/Stars/Code/Source/StarsAsset.h
  19. 27 0
      Gems/Stars/Code/Source/StarsComponent.cpp
  20. 28 0
      Gems/Stars/Code/Source/StarsComponent.h
  21. 34 0
      Gems/Stars/Code/Source/StarsComponentConfig.h
  22. 212 0
      Gems/Stars/Code/Source/StarsComponentController.cpp
  23. 78 0
      Gems/Stars/Code/Source/StarsComponentController.h
  24. 299 0
      Gems/Stars/Code/Source/StarsFeatureProcessor.cpp
  25. 107 0
      Gems/Stars/Code/Source/StarsFeatureProcessor.h
  26. 11 0
      Gems/Stars/Code/Source/StarsModule.cpp
  27. 38 0
      Gems/Stars/Code/Source/StarsModule.h
  28. 50 0
      Gems/Stars/Code/Source/StarsSystemComponent.cpp
  29. 40 0
      Gems/Stars/Code/Source/StarsSystemComponent.h
  30. 14 0
      Gems/Stars/Code/stars_editor_files.cmake
  31. 11 0
      Gems/Stars/Code/stars_editor_shared_files.cmake
  32. 22 0
      Gems/Stars/Code/stars_files.cmake
  33. 11 0
      Gems/Stars/Code/stars_headers_files.cmake
  34. 11 0
      Gems/Stars/Code/stars_shared_files.cmake
  35. 23 0
      Gems/Stars/Registry/assetprocessor_settings.setreg
  36. 22 0
      Gems/Stars/gem.json
  37. 3 0
      Gems/Stars/preview.png
  38. 1 0
      engine.json

+ 1 - 0
.gitattributes

@@ -104,6 +104,7 @@
 *.smtl filter=lfs diff=lfs merge=lfs -text
 *.so filter=lfs diff=lfs merge=lfs -text
 *.sprite filter=lfs diff=lfs merge=lfs -text
+*.stars filter=lfs diff=lfs merge=lfs -text
 *.sub filter=lfs diff=lfs merge=lfs -text
 *.tga filter=lfs diff=lfs merge=lfs -text
 *.tif filter=lfs diff=lfs merge=lfs -text

+ 1 - 0
AutomatedTesting/Gem/Code/enabled_gems.cmake

@@ -59,4 +59,5 @@ set(ENABLED_GEMS
     Multiplayer
     DevTextures
     PrimitiveAssets
+    Stars
 )

+ 1 - 1
Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultSceneSrg.azsli

@@ -12,6 +12,6 @@
 
 partial ShaderResourceGroup SceneSrg
 {
-    float m_time;
+    float m_time; // number of seconds since the application started
 }
 

+ 3 - 3
Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h

@@ -155,6 +155,9 @@ namespace AZ
             bool HasDrawListTag() const;
             bool HasPipelineViewTag() const;
 
+            // Searches this pass's attachment bindings for one with the provided Name (nullptr if none found)
+            PassAttachmentBinding* FindAttachmentBinding(const Name& slotName);
+
             //! Return the set of attachment bindings
             PassAttachmentBindingListView GetAttachmentBindings() const;
 
@@ -307,9 +310,6 @@ namespace AZ
             // Search order: 1.This -> 2.Parent -> 3.Siblings -> 4.Children
             Ptr<Pass> FindAdjacentPass(const Name& passName);
 
-            // Searches this pass's attachment bindings for one with the provided Name (nullptr if none found)
-            PassAttachmentBinding* FindAttachmentBinding(const Name& slotName);
-
             // Searches this pass's attachment bindings for one with the provided Name (nullptr if none found)
             const PassAttachmentBinding* FindAttachmentBinding(const Name& slotName) const;
 

+ 140 - 0
Gems/Stars/Assets/Shaders/Stars/Stars.azsl

@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <Atom/Features/ColorManagement/TransformColor.azsli>
+#include <Atom/Features/SrgSemantics.azsli>
+#include <scenesrg.srgi>
+#include <viewsrg.srgi>
+
+ShaderResourceGroup PerDrawSrg : SRG_PerDraw
+{
+    float3x3 m_rotation;
+
+    struct StarShaderConstants
+    {
+        float2 m_scale;
+        float m_exposureFactor;
+        float m_twinkleRate;
+    };
+    StarShaderConstants m_starParams;
+}
+
+struct VSInput
+{
+    float3 m_position : POSITION;
+    float4 m_color : COLOR0;
+
+    uint m_vertexID : SV_VertexID;
+};
+
+struct VSOutput
+{
+    float4 m_position : SV_Position;
+    float4 m_color : COLOR0;
+    float2 m_quadPos : TEXCOORD;
+};
+
+float GetFlickerAmount(in float3 pos)
+{
+    const float2 StarShimmerTab[8] = 
+    {
+        float2(0.897907815,-0.347608525), float2(0.550299290, 0.273586675), 
+        float2(0.823885965, 0.098853070), float2(0.922739035,-0.122108860),
+        float2(0.800630175,-0.088956800), float2(0.711673375, 0.158864420), 
+        float2(0.870537795, 0.085484560), float2(0.956022355,-0.058114540)
+    };
+
+    const float2 hash = frac(pos.xy * 256);
+    const float timeInSeconds = SceneSrg::m_time;
+    float index = frac(hash.x + (hash.y + 1) * PerDrawSrg::m_starParams.m_twinkleRate * timeInSeconds);
+    index *= 8;
+  
+    const float f = frac(index);
+    const int i = int(index);
+    return StarShimmerTab[i].x + f * StarShimmerTab[i].y;
+}
+
+VSOutput MainVS(VSInput IN)
+{
+    VSOutput OUT;
+    
+    const float4 colorAndMagnitude = IN.m_color;
+
+    // Set the w component to 0 in order to project the stars out to infinity.
+    const float4 pos = float4(mul(PerDrawSrg::m_rotation, IN.m_position), 0.0);
+    OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, pos);    
+
+    // using reverse z, so push depth out to the far plane
+    // if can gaurantee the draw order, then can disable depth check entirely
+    OUT.m_position.z = 0.0; 
+    
+    // apparent magnitude is how bright a star appears from earth 
+    // magnitude is a logarithmic scale and brighter objects have lower numbers
+    // a star of magnitude 2.0 is 2.512 times as bright as a star of magnitude of 3.0
+    // Sirius has a magnitude of -1.46
+    // humans typically see stars with apparent magnitude ranging from -1.44 .. 6.5
+    const float humanMinMag = -1.44;
+    const float humanMaxMag = 6.5;
+
+    // scale colorAndMagnitude.w from 0..1 to 6.5..-1.44
+    const float apparentMagnitude = humanMaxMag + colorAndMagnitude.w * (humanMinMag - humanMaxMag);
+
+    // scale the range from 6.5..-1.44 to 0..1 with a logarithmic scale approximation 
+    // e.g. 6.5 = 0.006, 1 = 0.2, 0 = 0.39, -1.44 =  1
+    // and dim with animated flicker amount
+    const float brightness = GetFlickerAmount(IN.m_position) * pow(5.0, (-apparentMagnitude + humanMinMag) / 2.5);
+    OUT.m_color = float4(brightness * colorAndMagnitude.xyz, brightness);
+
+    const float2 expansion[6] =
+    {
+        float2( 1,  1),
+        float2(-1,  1),
+        float2( 1, -1),
+        float2( 1, -1),
+        float2(-1,  1),
+        float2(-1, -1)
+    };
+
+    const float2 texcoord[6] = 
+    { 
+        float2(1, 0), 
+        float2(0, 0),
+        float2(1, 1),
+        float2(1, 1),
+        float2(0, 0),
+        float2(0, 1)    
+    };
+
+    const uint vertexIndex = uint(IN.m_vertexID) % uint(6);
+    OUT.m_position.xy += expansion[vertexIndex] * PerDrawSrg::m_starParams.m_scale;
+    OUT.m_quadPos = texcoord[vertexIndex];
+    return OUT;
+};
+
+struct PSOutput
+{
+    float4 m_diffuse : SV_Target0;
+};
+
+PSOutput MainPS(VSOutput IN)
+{
+    PSOutput OUT;
+
+    const float2 pos = IN.m_quadPos.xy;
+    const float2 distCenter = 3.5 * pos.xy - 3.5 * float2(0.5, 0.5);
+    const float scale = exp(-dot(distCenter, distCenter));
+
+    const float3 coolColor = IN.m_color.xyz;
+    const float3 hotColor = IN.m_color.www; // always grayscale
+
+    const float3 color = PerDrawSrg::m_starParams.m_exposureFactor * (coolColor * scale + 5.0 * hotColor * pow(scale, 10.0));
+
+    OUT.m_diffuse = float4(color, scale);
+
+    return OUT;
+}; 

+ 28 - 0
Gems/Stars/Assets/Shaders/Stars/Stars.shader

@@ -0,0 +1,28 @@
+{
+  "Source": "Stars.azsl",
+  "DepthStencilState": {
+    "Depth": {
+      "Enable": true,
+      "CompareFunc": "GreaterEqual"
+    }
+  },
+  "BlendState" : {
+      "Enable" : true,
+      "BlendSource" : "AlphaSource",
+      "BlendDest" : "One",
+      "BlendOp" : "Add"
+  },
+  "DrawList": "forward",
+  "ProgramSettings": {
+    "EntryPoints": [
+      {
+        "name": "MainVS",
+        "type": "Vertex"
+      },
+      {
+        "name": "MainPS",
+        "type": "Fragment"
+      }
+    ]
+  }
+}

+ 3 - 0
Gems/Stars/Assets/Stars/default.stars

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7a1aeecd89902230c98fbeea34ab0a41f2473d493a037572c5b97d7ffcf06ffb
+size 106956

+ 13 - 0
Gems/Stars/Assets/seedList.seed

@@ -0,0 +1,13 @@
+<ObjectStream version="3">
+	<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
+		<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
+			<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
+				<Class name="AZ::Uuid" field="guid" value="{A2640D6F-A59B-579A-A433-13844CA44859}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
+				<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+			</Class>
+			<Class name="unsigned int" field="platformFlags" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+			<Class name="AZStd::string" field="pathHint" value="shaders/stars/stars.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+		</Class>
+	</Class>
+</ObjectStream>
+

+ 15 - 0
Gems/Stars/CMakeLists.txt

@@ -0,0 +1,15 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(gem_path ${CMAKE_CURRENT_LIST_DIR})
+set(gem_json ${gem_path}/gem.json)
+o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path)
+
+ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty)
+
+add_subdirectory(Code)

+ 96 - 0
Gems/Stars/Code/CMakeLists.txt

@@ -0,0 +1,96 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+ly_add_target(
+    NAME Stars.Static STATIC
+    NAMESPACE Gem
+    FILES_CMAKE
+        stars_files.cmake
+    INCLUDE_DIRECTORIES
+        PUBLIC
+            Include
+        PRIVATE
+            Source
+    BUILD_DEPENDENCIES
+        PUBLIC
+            AZ::AzCore
+            AZ::AzFramework
+            Gem::Atom_RHI.Public
+            Gem::Atom_RPI.Public
+            Gem::Atom_Utils.Static
+)
+
+ly_add_target(
+    NAME Stars.API HEADERONLY
+    NAMESPACE Gem
+    FILES_CMAKE
+        stars_headers_files.cmake
+    INCLUDE_DIRECTORIES
+        INTERFACE
+            include
+)
+
+ly_add_target(
+    NAME Stars ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE}
+    NAMESPACE Gem
+    FILES_CMAKE
+        stars_shared_files.cmake
+    INCLUDE_DIRECTORIES
+        PUBLIC
+            Include
+        PRIVATE
+            Source
+    BUILD_DEPENDENCIES
+        PRIVATE
+            Gem::Stars.Static
+)
+
+ly_create_alias(NAME Stars.Clients NAMESPACE Gem TARGETS Gem::Stars)
+
+if(PAL_TRAIT_BUILD_HOST_TOOLS)
+    ly_add_target(
+        NAME Stars.Editor.Static STATIC
+        NAMESPACE Gem
+        FILES_CMAKE
+            stars_editor_files.cmake
+        INCLUDE_DIRECTORIES
+            PRIVATE
+                Source
+            PUBLIC
+                Include
+        BUILD_DEPENDENCIES
+            PUBLIC
+                AZ::AzToolsFramework
+                Gem::Stars.Static
+                Gem::Atom_Feature_Common.Static
+                Gem::Atom_Feature_Common.Public
+    )
+
+    ly_add_target(
+        NAME Stars.Editor GEM_MODULE
+        NAMESPACE Gem
+        AUTOMOC
+        FILES_CMAKE
+            stars_editor_shared_files.cmake
+        INCLUDE_DIRECTORIES
+            PRIVATE
+                Source
+            PUBLIC
+                Include
+        BUILD_DEPENDENCIES
+            PUBLIC
+                Gem::Stars.Editor.Static
+    )
+
+    ly_create_alias(NAME Stars.Tools    NAMESPACE Gem TARGETS Gem::Stars.Editor)
+    # A Builders alias must exist for Gem Assets to be seen by the Asset Processor.
+    # A Builders alias target must exist for the Prefab .spawnable builder to be able to
+    # load the .dll so the builder can serialize StarComponents to .spawnable files 
+    # which are needed in the game launcher.
+    ly_create_alias(NAME Stars.Builders NAMESPACE Gem TARGETS Gem::Stars.Editor)
+endif()

+ 37 - 0
Gems/Stars/Code/Include/Stars/StarsFeatureProcessorInterface.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <Atom/RPI.Public/FeatureProcessor.h>
+
+namespace AZ::Render
+{
+    static const float StarsDefaultExposure = 1.0f;
+    static const float StarsDefaultTwinkleRate = 0.5f;
+    static const float StarsDefaultRadiusFactor = 7.0f;
+
+    class StarsFeatureProcessorInterface
+        : public RPI::FeatureProcessor
+    {
+    public:
+        AZ_RTTI(AZ::Render::StarsFeatureProcessorInterface, "{7ECE8A5E-366B-4942-B6F9-370DC6017927}"); 
+
+        struct StarVertex 
+        {
+            AZStd::array<float, 3> m_position;
+            uint32_t m_color;
+        };
+
+        virtual void SetStars(const AZStd::vector<StarVertex>& starVertexData) = 0;
+        virtual void SetExposure(float exposure) = 0;
+        virtual void SetRadiusFactor(float radiusFactor) = 0;
+        virtual void SetOrientation(AZ::Quaternion orientation) = 0;
+        virtual void SetTwinkleRate(float rate) = 0;
+    };
+}

+ 114 - 0
Gems/Stars/Code/Source/EditorStarsComponent.cpp

@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include "EditorStarsComponent.h"
+#include <AzCore/Serialization/EditContext.h>
+#include <Atom/RPI.Public/Scene.h>
+#include <StarsFeatureProcessor.h>
+
+namespace AZ::Render 
+{
+    void EditorStarsComponent::Reflect(AZ::ReflectContext* context)
+    {
+        BaseClass::Reflect(context);
+
+        if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<EditorStarsComponent, BaseClass>()
+                ->Version(1)
+                ;
+            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
+            {
+                editContext->Class<StarsComponentConfig>("Stars Config", "Star Config Data")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector<AZ::Crc32>({ AZ_CRC_CE("Game") }))
+                    ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
+                    ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+                    ->DataElement(AZ::Edit::UIHandlers::Slider, &StarsComponentConfig::m_exposure, "Exposure", "Exposure")
+                        ->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f)
+                        ->Attribute(AZ::Edit::Attributes::SoftMax, 10.0f)
+                        ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
+                        ->Attribute(AZ::Edit::Attributes::Max, 32.0f)
+                    ->DataElement(AZ::Edit::UIHandlers::Slider, &StarsComponentConfig::m_radiusFactor, "Radius factor", "Star radius factor")
+                        ->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f)
+                        ->Attribute(AZ::Edit::Attributes::SoftMax, 10.0f)
+                        ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
+                        ->Attribute(AZ::Edit::Attributes::Max, 64.0f)
+                    ->DataElement(AZ::Edit::UIHandlers::Slider, &StarsComponentConfig::m_twinkleRate, "Twinkle rate", "How quickly the stars twinkle")
+                        ->Attribute(AZ::Edit::Attributes::SoftMin, 0.0f)
+                        ->Attribute(AZ::Edit::Attributes::SoftMax, 3.0f)
+                        ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
+                        ->Attribute(AZ::Edit::Attributes::Max, 10.0f)
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &StarsComponentConfig::m_starsAsset, "Stars Asset", "Stars asset")
+                    ;
+
+                editContext->Class<StarsComponentController>(
+                    "StarsComponentController", "")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &StarsComponentController::m_configuration, "Configuration", "")
+                        ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
+                    ;
+
+                editContext->Class<EditorStarsComponent>(
+                    "Stars", "Renders stars in the background")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                    ->Attribute(AZ::Edit::Attributes::Category, "Atom")
+                    ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg")
+                    ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg")
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c));
+            }
+        }
+    }
+
+    void EditorStarsComponent::Init()
+    {
+        StarsComponentConfig& config = m_controller.m_configuration;
+
+        // prefill with the default stars asset if no other is specified
+        if (!config.m_starsAsset.GetId().IsValid())
+        {
+            Data::AssetId assetId;
+            const auto type = azrtti_typeid<StarsAsset>();
+            const auto path = m_defaultAssetPath.c_str();
+            Data::AssetCatalogRequestBus::BroadcastResult( assetId, &Data::AssetCatalogRequests::GetAssetIdByPath, path, type, false);
+            if (assetId.IsValid())
+            {
+                config.m_starsAsset = Data::AssetManager::Instance().FindOrCreateAsset<StarsAsset>(assetId, Data::AssetLoadBehavior::Default);
+            }
+        }
+
+        // remember the stars asset id so we can detect when it changes
+        m_prevAssetId = config.m_starsAsset.GetId();
+    }
+
+    u32 EditorStarsComponent::OnConfigurationChanged()
+    {
+        if (m_prevAssetId != m_controller.GetConfiguration().m_starsAsset.GetId())
+        {
+            m_controller.OnStarsAssetChanged();
+            m_prevAssetId = m_controller.GetConfiguration().m_starsAsset.GetId();
+        }
+
+        m_controller.OnConfigChanged();
+
+        return Edit::PropertyRefreshLevels::AttributesAndValues;
+    }
+
+    void EditorStarsComponent::OnEntityVisibilityChanged(bool visibility)
+    {
+        if (visibility)
+        {
+            m_controller.RegisterFeatureProcessor(GetEntityId());
+        }
+        else
+        {
+            m_controller.UnregisterFeatureProcessor();
+        }
+    }
+}

+ 39 - 0
Gems/Stars/Code/Source/EditorStarsComponent.h

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <Atom/Feature/Utils/EditorRenderComponentAdapter.h>
+#include <StarsComponent.h>
+
+namespace AZ::Render
+{
+    class EditorStarsComponent final
+        : public EditorRenderComponentAdapter<StarsComponentController, StarsComponent, StarsComponentConfig>
+    {
+    public:
+        using BaseClass = EditorRenderComponentAdapter<StarsComponentController, StarsComponent, StarsComponentConfig>;
+        AZ_EDITOR_COMPONENT(AZ::Render::EditorStarsComponent, EditorStarsComponentTypeId, BaseClass);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        EditorStarsComponent() = default;
+
+    protected:
+        void Init() override;
+
+    private:
+        //! EditorRenderComponentAdapter
+        //! we override OnConfigurationChanged to avoid deactivating and activating unnecessarily
+        AZ::u32 OnConfigurationChanged() override;
+        void OnEntityVisibilityChanged(bool visibility) override;
+
+        AZ::Data::AssetId m_prevAssetId;
+        AZStd::string m_defaultAssetPath{ "stars/default.stars" };
+    };
+} // namespace AZ::Render

+ 39 - 0
Gems/Stars/Code/Source/EditorStarsModule.cpp

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <StarsModule.h>
+#include <EditorStarsSystemComponent.h>
+#include <EditorStarsComponent.h>
+
+namespace AZ::Render
+{
+    class EditorStarsModule
+        : public StarsModule
+    {
+    public:
+        AZ_RTTI(EditorStarsModule, "{3D5FD4A5-4405-408A-BD64-F3B27006DB4A}", StarsModule);
+        AZ_CLASS_ALLOCATOR(EditorStarsModule, AZ::SystemAllocator, 0);
+
+        EditorStarsModule()
+        {
+            m_descriptors.insert(m_descriptors.end(), {
+                EditorStarsSystemComponent::CreateDescriptor(),
+                EditorStarsComponent::CreateDescriptor(),
+            });
+        }
+
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override
+        {
+            return AZ::ComponentTypeList {
+                azrtti_typeid<EditorStarsSystemComponent>(),
+            };
+        }
+    };
+}// namespace AZ::Render 
+
+AZ_DECLARE_MODULE_CLASS(Gem_Stars, AZ::Render::EditorStarsModule)

+ 44 - 0
Gems/Stars/Code/Source/EditorStarsSystemComponent.cpp

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <AzCore/Serialization/SerializeContext.h>
+#include <EditorStarsSystemComponent.h>
+#include <AzCore/Serialization/EditContext.h>
+
+namespace AZ::Render 
+{
+    void EditorStarsSystemComponent::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<EditorStarsSystemComponent, StarsSystemComponent>()
+                ->Version(0);
+
+            if (AZ::EditContext* ec = serializeContext->GetEditContext())
+            {
+                ec->Class<StarsSystemComponent>("Stars", "Stars system component")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                        ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System"))
+                        ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
+                    ;
+            }
+        }
+    }
+
+    void EditorStarsSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        BaseSystemComponent::GetProvidedServices(provided);
+        provided.push_back(AZ_CRC_CE("EditorStarsService"));
+    }
+
+    void EditorStarsSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        BaseSystemComponent::GetIncompatibleServices(incompatible);
+        incompatible.push_back(AZ_CRC_CE("EditorStarsService"));
+    }
+} // namespace Stars

+ 30 - 0
Gems/Stars/Code/Source/EditorStarsSystemComponent.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <StarsSystemComponent.h>
+
+namespace AZ::Render
+{
+    class EditorStarsSystemComponent
+        : public StarsSystemComponent
+    {
+        using BaseSystemComponent = StarsSystemComponent;
+    public:
+        AZ_COMPONENT(EditorStarsSystemComponent, "{346580C8-6084-4439-87B6-7DF1F734ED86}", BaseSystemComponent);
+        static void Reflect(AZ::ReflectContext* context);
+
+        EditorStarsSystemComponent() = default;
+        ~EditorStarsSystemComponent() = default;
+
+    private:
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+    };
+} // namespace Stars

+ 58 - 0
Gems/Stars/Code/Source/StarsAsset.cpp

@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <StarsAsset.h>
+
+namespace AZ::Render
+{
+    StarsAssetHandler::StarsAssetHandler()
+        : AzFramework::GenericAssetHandler<StarsAsset>(StarsAsset::DisplayName, StarsAsset::Group, StarsAsset::Extension)
+    {
+    }
+
+    AZ::Data::AssetHandler::LoadResult StarsAssetHandler::LoadAssetData(
+        const AZ::Data::Asset<AZ::Data::AssetData>& asset,
+        AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
+        [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB)
+    {
+        StarsAsset* assetData = asset.GetAs<StarsAsset>();
+        if(assetData && stream->GetLength() > 0)
+        {
+            assetData->m_data.resize(stream->GetLength());
+            stream->Read(stream->GetLength(), assetData->m_data.data());
+
+            // use a memory stream instead of AssetDataStream to validate the data,
+            // AssetDataStream does not allow reverse seek
+            AZ::IO::MemoryStream memStream(assetData->m_data.data(), assetData->m_data.size());
+
+            constexpr uint32_t starsfileTag(0x52415453); // "STAR"
+            uint32_t fileTag{0};
+            if (!memStream.Read(sizeof(fileTag), &fileTag) || fileTag != starsfileTag)
+            {
+                return AZ::Data::AssetHandler::LoadResult::Error;
+            }
+
+            constexpr uint32_t starsfileVersion(0x00010001);
+            uint32_t fileVersion{0};
+            if (!memStream.Read(sizeof(fileVersion), &fileVersion) || fileVersion != starsfileVersion)
+            {
+                return AZ::Data::AssetHandler::LoadResult::Error;
+            }
+
+            uint32_t numStars{0};
+            if(!memStream.Read(sizeof(numStars), &numStars))
+            {
+                return AZ::Data::AssetHandler::LoadResult::Error;
+            }
+
+            return AZ::Data::AssetHandler::LoadResult::LoadComplete;
+        }
+
+        return AZ::Data::AssetHandler::LoadResult::Error;
+    }
+} // AZ::Render

+ 44 - 0
Gems/Stars/Code/Source/StarsAsset.h

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Asset/AssetCommon.h>
+#include <AzCore/Asset/AssetSerializer.h>
+#include <AzFramework/Asset/GenericAssetHandler.h>
+
+namespace AZ::Render
+{
+    class StarsAsset final
+        : public AZ::Data::AssetData
+    {
+    public:
+        static constexpr inline const char* DisplayName = "StarsAsset";
+        static constexpr inline const char* Extension = "stars";
+        static constexpr inline const char* Group = "Rendering";
+        static constexpr inline const size_t HeaderSize = sizeof(uint32_t) * 3;
+
+        AZ_RTTI(StarsAsset, "{211938C1-C54D-417D-977A-9928D7C630B1}", AZ::Data::AssetData)
+        AZ_CLASS_ALLOCATOR(StarsAsset, AZ::SystemAllocator, 0);
+
+        AZStd::vector<AZ::u8> m_data;
+    };
+
+    class StarsAssetHandler final
+        : public AzFramework::GenericAssetHandler<StarsAsset>
+    {
+    public:
+        StarsAssetHandler();
+
+    private:
+        AZ::Data::AssetHandler::LoadResult LoadAssetData(
+            const AZ::Data::Asset<AZ::Data::AssetData>& asset,
+            AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
+            const AZ::Data::AssetFilterCB& assetLoadFilterCB) override;
+    };
+} // AZ::Render

+ 27 - 0
Gems/Stars/Code/Source/StarsComponent.cpp

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include "StarsComponent.h"
+
+namespace AZ::Render 
+{
+    StarsComponent::StarsComponent(const StarsComponentConfig& config)
+        : BaseClass(config)
+    {
+    }
+
+    void StarsComponent::Reflect(AZ::ReflectContext* context)
+    {
+        BaseClass::Reflect(context);
+
+        if (AZ::SerializeContext * serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<StarsComponent, BaseClass>();
+        }
+    }
+} // namespace AtomSampleViewer

+ 28 - 0
Gems/Stars/Code/Source/StarsComponent.h

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzFramework/Components/ComponentAdapter.h>
+#include <StarsComponentController.h>
+
+namespace AZ::Render 
+{
+    class StarsComponent final
+        : public AzFramework::Components::ComponentAdapter<StarsComponentController, StarsComponentConfig>
+    {
+    public:
+        using BaseClass = AzFramework::Components::ComponentAdapter<StarsComponentController, StarsComponentConfig>;
+        AZ_COMPONENT(AZ::Render::StarsComponent, StarsComponentTypeId , BaseClass);
+
+        StarsComponent() = default;
+        StarsComponent(const StarsComponentConfig& config);
+
+        static void Reflect(AZ::ReflectContext* context);
+    };
+} // namespace AZ::Render 

+ 34 - 0
Gems/Stars/Code/Source/StarsComponentConfig.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <StarsAsset.h>
+#include <Stars/StarsFeatureProcessorInterface.h>
+
+namespace AZ::Render
+{
+    static constexpr const char* const StarsComponentTypeId = "{A0DC17A5-9494-47EF-AD6D-BC563739A02B}";
+    static constexpr const char* const EditorStarsComponentTypeId = "{460B0A4E-6A6F-4AFF-9668-4B5AA2F33C09}";
+
+    class StarsComponentConfig final
+        : public ComponentConfig
+    {
+    public:
+        AZ_RTTI(AZ::Render::StarsComponentConfig, "{10E6A838-3A66-4518-BF53-FCA8325C4759}", AZ::ComponentConfig);
+
+        static void Reflect(ReflectContext* context);
+
+        float m_exposure = StarsDefaultExposure;
+        float m_radiusFactor = StarsDefaultRadiusFactor;
+        float m_twinkleRate = StarsDefaultTwinkleRate;
+
+        AZ::Data::Asset<StarsAsset> m_starsAsset;
+    };
+}

+ 212 - 0
Gems/Stars/Code/Source/StarsComponentController.cpp

@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include "StarsComponentController.h"
+#include <Atom/RPI.Public/Scene.h>
+#include <StarsFeatureProcessor.h>
+
+namespace AZ::Render
+{
+    void StarsComponentConfig::Reflect(AZ::ReflectContext* context)
+    {
+        if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serializeContext->Class<StarsComponentConfig, AZ::ComponentConfig>()
+                ->Version(0)
+                ->Field("Exposure", &StarsComponentConfig::m_exposure)
+                ->Field("RadiusFactor", &StarsComponentConfig::m_radiusFactor)
+                ->Field("StarsAsset", &StarsComponentConfig::m_starsAsset)
+                ->Field("TwinkleRate", &StarsComponentConfig::m_twinkleRate)
+                ;
+        }
+    }
+
+    void StarsComponentController::Reflect(ReflectContext* context)
+    {
+        StarsComponentConfig::Reflect(context);
+
+        if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
+        {
+            serializeContext->Class<StarsComponentController>()
+                ->Version(0)
+                ->Field("Configuration", &StarsComponentController::m_configuration);
+        }
+    }
+
+    void StarsComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        provided.push_back(AZ_CRC("StarsService"));
+    }
+
+    void StarsComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        incompatible.push_back(AZ_CRC("StarsService"));
+        incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
+    }
+
+    void StarsComponentController::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
+    {
+        dependent.push_back(AZ_CRC("TransformService"));
+    }
+
+    StarsComponentController::StarsComponentController(const StarsComponentConfig& config)
+        : m_configuration(config)
+    {
+    }
+
+    void StarsComponentController::Activate(EntityId entityId)
+    {
+        RegisterFeatureProcessor(entityId);
+
+        TransformNotificationBus::Handler::BusConnect(entityId);
+    }
+
+    void StarsComponentController::RegisterFeatureProcessor(EntityId entityId)
+    {
+        RPI::FeatureProcessorFactory::Get()->RegisterFeatureProcessorWithInterface<StarsFeatureProcessor, StarsFeatureProcessorInterface>();
+        m_scene = RPI::Scene::GetSceneForEntityId(entityId);
+        if (m_scene)
+        {
+            m_starsFeatureProcessor = m_scene->EnableFeatureProcessor<StarsFeatureProcessor>();
+        }
+
+        if (m_starsFeatureProcessor)
+        {
+            if (m_configuration.m_starsAsset.IsReady())
+            {
+                UpdateStarsFromAsset(m_configuration.m_starsAsset);
+            }
+            else
+            {
+                OnStarsAssetChanged();
+            }
+
+            if(auto transformInterface = TransformBus::FindFirstHandler(entityId))
+            {
+                m_starsFeatureProcessor->SetOrientation(transformInterface->GetWorldRotationQuaternion());
+            }
+        }
+
+        OnConfigChanged();
+    }
+
+    void StarsComponentController::UnregisterFeatureProcessor()
+    {
+        if (m_scene && m_starsFeatureProcessor)
+        {
+            m_scene->DisableFeatureProcessor<StarsFeatureProcessor>();
+
+            m_starsFeatureProcessor = nullptr;
+
+            RPI::FeatureProcessorFactory::Get()->UnregisterFeatureProcessor<StarsFeatureProcessor>();
+        }
+    }
+
+    void StarsComponentController::OnStarsAssetChanged()
+    {
+        Data::AssetBus::MultiHandler::BusDisconnect();
+        if (m_configuration.m_starsAsset.GetId().IsValid())
+        {
+            Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_starsAsset.GetId());
+            m_configuration.m_starsAsset.QueueLoad();
+        }
+    }
+
+    void StarsComponentController::OnAssetReady(Data::Asset<Data::AssetData> asset)
+    {
+        UpdateStarsFromAsset(asset);
+    }
+
+    void StarsComponentController::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
+    {
+        UpdateStarsFromAsset(asset);
+    }
+
+    void StarsComponentController::UpdateStarsFromAsset(Data::Asset<Data::AssetData> asset)
+    {
+        if (asset.GetId() != m_configuration.m_starsAsset.GetId())
+        {
+            return;
+        }
+
+        m_configuration.m_starsAsset = asset;
+
+        StarsAsset *starsAsset = asset.GetAs<StarsAsset>();
+        if (starsAsset && starsAsset->m_data.size() > StarsAsset::HeaderSize && m_starsFeatureProcessor)
+        {
+            Star star{ 0 };
+            AZStd::array<float,3> position;
+            constexpr int verticesPerStar{ 6 };
+            const size_t starsAssetSize = starsAsset->m_data.size();
+            const size_t starSize = sizeof(star);
+            const size_t numStars = (starsAssetSize - StarsAsset::HeaderSize) / starSize;
+
+            AZStd::vector<StarsFeatureProcessorInterface::StarVertex> stars;
+            stars.resize(numStars * verticesPerStar);
+
+            IO::MemoryStream stream(starsAsset->m_data.data(), starsAssetSize);
+
+            // skip the header
+            stream.Seek(AZ::IO::OffsetType(StarsAsset::HeaderSize), IO::GenericStream::SeekMode::ST_SEEK_BEGIN);
+
+            for (uint32_t i = 0; i < numStars; ++i)
+            {
+                stream.Read(starSize, &star);
+                
+                position[0] = -cosf(AZ::DegToRad(star.declination)) * sinf(AZ::DegToRad(star.ascension * 15.0f));
+                position[1] = cosf(AZ::DegToRad(star.declination)) * cosf(AZ::DegToRad(star.ascension * 15.0f));
+                position[2] = sinf(AZ::DegToRad(star.declination));
+
+                for (int k = 0; k < verticesPerStar; k++)
+                {
+                    stars[verticesPerStar * i + k].m_position = position;
+                    stars[verticesPerStar * i + k].m_color = (star.magnitude << 24) + (star.blue << 16) + (star.green << 8) + star.red;
+                }
+            }
+
+            m_starsFeatureProcessor->SetStars(stars);
+        }
+    }
+
+    void StarsComponentController::Deactivate()
+    {
+        TransformNotificationBus::Handler::BusDisconnect();
+        Data::AssetBus::MultiHandler::BusDisconnect();
+
+        UnregisterFeatureProcessor();
+    }
+
+    void StarsComponentController::SetConfiguration(const StarsComponentConfig& config)
+    {
+        m_configuration = config;
+        OnConfigChanged();
+    }
+
+    void StarsComponentController::OnConfigChanged()
+    {
+        if (m_starsFeatureProcessor)
+        {
+            m_starsFeatureProcessor->SetExposure(m_configuration.m_exposure);
+            m_starsFeatureProcessor->SetRadiusFactor(m_configuration.m_radiusFactor);
+            m_starsFeatureProcessor->SetTwinkleRate(m_configuration.m_twinkleRate);
+        }
+    }
+
+    const StarsComponentConfig& StarsComponentController::GetConfiguration() const
+    {
+        return m_configuration;
+    }
+
+    void StarsComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
+    {
+        if (m_starsFeatureProcessor)
+        {
+            m_starsFeatureProcessor->SetOrientation(world.GetRotation());
+        }
+    }
+}

+ 78 - 0
Gems/Stars/Code/Source/StarsComponentController.h

@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+#include <AzCore/Component/TransformBus.h>
+#include <AzCore/Asset/AssetCommon.h>
+#include <StarsComponentConfig.h>
+
+namespace AZ::RPI
+{
+    class Scene;
+}
+
+namespace AZ::Render
+{
+    class StarsFeatureProcessor;
+
+    class StarsComponentController final
+        : private TransformNotificationBus::Handler
+        , private Data::AssetBus::MultiHandler
+    {
+    public:
+        friend class EditorStarsComponent;
+
+        AZ_TYPE_INFO(AZ::Render::StarsComponentController, "{774F8FA2-3465-46FA-B635-DBF573230643}");
+        static void Reflect(AZ::ReflectContext* context);
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+        static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
+
+        StarsComponentController() = default;
+        StarsComponentController(const StarsComponentConfig& config);
+
+        void Activate(EntityId entityId);
+        void Deactivate();
+        void SetConfiguration(const StarsComponentConfig& config);
+        const StarsComponentConfig& GetConfiguration() const;
+
+    private:
+        AZ_DISABLE_COPY(StarsComponentController);
+
+        //! TransformNotificationBus
+        void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
+
+        //! Data::AssetBus interface
+        void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
+        void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
+
+        void OnConfigChanged();
+        void OnStarsAssetChanged();
+        void UpdateStarsFromAsset(Data::Asset<Data::AssetData> asset);
+        void RegisterFeatureProcessor(EntityId entityId);
+        void UnregisterFeatureProcessor();
+
+        StarsComponentConfig m_configuration;
+
+        AZ::Render::StarsFeatureProcessor* m_starsFeatureProcessor = nullptr;
+
+        struct Star
+        {
+            float ascension;
+            float declination;
+            uint8_t red;
+            uint8_t green;
+            uint8_t blue;
+            uint8_t magnitude;
+        };
+
+        RPI::Scene* m_scene;
+    };
+} // AZ::Render

+ 299 - 0
Gems/Stars/Code/Source/StarsFeatureProcessor.cpp

@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <StarsFeatureProcessor.h>
+
+#include <Atom/RHI/DrawPacketBuilder.h>
+#include <Atom/RHI.Reflect/InputStreamLayoutBuilder.h>
+
+#include <Atom/RPI.Public/RenderPipeline.h>
+#include <Atom/RPI.Public/RPIUtils.h>
+#include <Atom/RPI.Public/Pass/PassFilter.h>
+#include <Atom/RPI.Public/Shader/Shader.h>
+#include <Atom/RPI.Public/Scene.h>
+#include <Atom/RPI.Public/View.h>
+#include <Atom/RPI.Public/ViewportContext.h>
+#include <Atom/RPI.Public/ViewportContextBus.h>
+
+namespace AZ::Render
+{
+    void StarsFeatureProcessor::Reflect(ReflectContext* context)
+    {
+        if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
+        {
+            serializeContext
+                ->Class<StarsFeatureProcessor, FeatureProcessor>()
+                ->Version(1);
+        }
+    }
+
+    void StarsFeatureProcessor::Activate()
+    {
+        const char* shaderFilePath = "Shaders/stars/stars.azshader";
+        m_shader = RPI::LoadCriticalShader(shaderFilePath);
+        if (!m_shader)
+        {
+            AZ_Error("StarsFeatureProcessor", false, "Failed to load required stars shader.");
+            return;
+        }
+        Data::AssetBus::Handler::BusConnect(m_shader->GetAssetId());
+
+        auto drawSrgLayout = m_shader->GetAsset()->GetDrawSrgLayout(m_shader->GetSupervariantIndex());
+        AZ_Error("StarsFeatureProcessor", drawSrgLayout, "Failed to get the draw shader resource group layout for the stars shader.");
+
+        if (drawSrgLayout)
+        {
+            m_drawSrg = RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), m_shader->GetSupervariantIndex(), drawSrgLayout->GetName());
+        }
+
+        m_drawListTag = m_shader->GetDrawListTag();
+
+        m_starParamsIndex.Reset();
+        m_rotationIndex.Reset();
+
+        auto viewportContextInterface = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
+        auto viewportContext = viewportContextInterface->GetViewportContextByScene(GetParentScene());
+        m_viewportSize = viewportContext->GetViewportSize();
+
+        EnableSceneNotification();
+
+        RPI::ViewportContextIdNotificationBus::Handler::BusConnect(viewportContext->GetId());
+    }
+
+    void StarsFeatureProcessor::Deactivate()
+    {
+        Data::AssetBus::Handler::BusDisconnect(m_shader->GetAssetId());
+
+        RPI::ViewportContextIdNotificationBus::Handler::BusDisconnect();
+
+        DisableSceneNotification();
+
+        m_shader = nullptr;
+    }
+
+    void StarsFeatureProcessor::Simulate([[maybe_unused]] const FeatureProcessor::SimulatePacket& packet)
+    {
+        AZ_PROFILE_SCOPE(RPI, "StarsFeatureProcessor: Simulate");
+
+        if (m_updateShaderConstants)
+        {
+            m_updateShaderConstants = false;
+
+            UpdateShaderConstants();
+        }
+    }
+
+    void StarsFeatureProcessor::UpdateShaderConstants()
+    {
+        const float width = static_cast<float>(m_viewportSize.m_width);
+        const float height = static_cast<float>(m_viewportSize.m_height);
+        constexpr float minWidth = 1280.f;
+        constexpr float minHeight = 720.f;
+        const float size = m_radiusFactor * AZStd::min<float>(1.f, AZStd::min<float>(width / minWidth, height / minHeight));
+
+        m_shaderConstants.m_scaleX = size / width;
+        m_shaderConstants.m_scaleY = size / height;
+        m_shaderConstants.m_scaledExposure = pow(2.f, m_exposure) * AZStd::min(1.f, size);
+
+        if (m_drawSrg)
+        {
+            m_drawSrg->SetConstant(m_starParamsIndex, m_shaderConstants);
+            m_drawSrg->SetConstant(m_rotationIndex, m_orientation);
+            m_drawSrg->Compile();
+        }
+    }
+
+    void StarsFeatureProcessor::UpdateDrawPacket()
+    {
+        if(m_meshPipelineState && m_drawSrg && m_meshStreamBufferViews[0].GetByteCount() != 0)
+        {
+            m_drawPacket = BuildDrawPacket(m_drawSrg, m_meshPipelineState, m_drawListTag, m_meshStreamBufferViews, m_numStarsVertices);
+        }
+    }
+
+    void StarsFeatureProcessor::Render(const FeatureProcessor::RenderPacket& packet)
+    {
+        AZ_PROFILE_FUNCTION(AzRender);
+
+        if (m_drawPacket)
+        {
+            for (auto& view : packet.m_views)
+            {
+                if (!view->HasDrawListTag(m_drawListTag))
+                {
+                   continue;
+                }
+
+                constexpr float depth = 0.f;
+                view->AddDrawPacket(m_drawPacket.get(), depth);
+            }
+        }
+    }
+
+    void StarsFeatureProcessor::SetStars(const AZStd::vector<StarVertex>& starVertexData)
+    {
+        const uint32_t elementCount = static_cast<uint32_t>(starVertexData.size());
+        const uint32_t elementSize = sizeof(StarVertex);
+        const uint32_t bufferSize = elementCount * elementSize; // bytecount
+
+        m_starsMeshData = starVertexData;
+        m_numStarsVertices = elementCount;
+
+        if (!m_starsVertexBuffer)
+        {
+            RPI::CommonBufferDescriptor desc;
+            desc.m_poolType = RPI::CommonBufferPoolType::StaticInputAssembly;
+            desc.m_bufferName = "StarsMeshBuffer";
+            desc.m_byteCount = bufferSize;
+            desc.m_elementSize = elementSize;
+            desc.m_bufferData = m_starsMeshData.data();
+            m_starsVertexBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
+        }
+        else
+        {
+            if (m_starsVertexBuffer->GetBufferSize() != bufferSize)
+            {
+                m_starsVertexBuffer->Resize(bufferSize);
+            }
+
+            m_starsVertexBuffer->UpdateData(m_starsMeshData.data(), bufferSize);
+        }
+
+        m_meshStreamBufferViews[0] = RHI::StreamBufferView(*m_starsVertexBuffer->GetRHIBuffer(), 0, bufferSize, elementSize);
+
+        UpdateDrawPacket();
+    }
+
+    void StarsFeatureProcessor::SetExposure(float exposure)
+    {
+        m_exposure = exposure;
+        m_updateShaderConstants = true;
+    }
+
+    void StarsFeatureProcessor::SetRadiusFactor(float radiusFactor)
+    {
+        m_radiusFactor = radiusFactor;
+        m_updateShaderConstants = true;
+    }
+
+    void StarsFeatureProcessor::SetOrientation(AZ::Quaternion orientation)
+    {
+        m_orientation = AZ::Matrix3x3::CreateFromQuaternion(orientation);
+        m_updateShaderConstants = true;
+    }
+
+    void StarsFeatureProcessor::SetTwinkleRate(float twinkleRate)
+    {
+        m_shaderConstants.m_twinkleRate = twinkleRate;
+        m_updateShaderConstants = true;
+    }
+
+    void StarsFeatureProcessor::OnRenderPipelineAdded([[maybe_unused]] RPI::RenderPipelinePtr renderPipeline)
+    {
+        if(!m_meshPipelineState)
+        {
+            m_meshPipelineState = aznew RPI::PipelineStateForDraw;
+            m_meshPipelineState->Init(m_shader);
+
+
+            RHI::InputStreamLayoutBuilder layoutBuilder;
+            layoutBuilder.AddBuffer()
+                ->Channel("POSITION", RHI::Format::R32G32B32_FLOAT)
+                ->Channel("COLOR", RHI::Format::R8G8B8A8_UNORM);
+            layoutBuilder.SetTopology(RHI::PrimitiveTopology::TriangleList);
+            auto inputStreamLayout = layoutBuilder.End();
+
+            m_meshPipelineState->SetInputStreamLayout(inputStreamLayout);
+            m_meshPipelineState->SetOutputFromScene(GetParentScene());
+            m_meshPipelineState->Finalize();
+
+            UpdateDrawPacket();
+            UpdateBackgroundClearColor();
+        }
+    }
+
+    void StarsFeatureProcessor::OnRenderPipelinePassesChanged([[maybe_unused]] RPI::RenderPipeline* renderPipeline)
+    {
+        if(m_meshPipelineState)
+        {
+            m_meshPipelineState->SetOutputFromScene(GetParentScene());
+            m_meshPipelineState->Finalize();
+
+            UpdateDrawPacket();
+            UpdateBackgroundClearColor();
+        }
+    }
+
+    void StarsFeatureProcessor::OnViewportSizeChanged(AzFramework::WindowSize size)
+    {
+        m_viewportSize = size;
+        m_updateShaderConstants = true;
+    }
+
+    void StarsFeatureProcessor::OnAssetReloaded([[maybe_unused]] Data::Asset<Data::AssetData> asset)
+    {
+        UpdateDrawPacket();
+    }
+
+    void StarsFeatureProcessor::UpdateBackgroundClearColor()
+    {
+        // This function is only necessary for now because the default clear value
+        // color is not black, and is set in various .pass files in places a user
+        // is unlikely to find.  Unfortunately, the viewport will revert to the
+        // grey color when resizing momentarily.
+        const RHI::ClearValue blackClearValue = RHI::ClearValue::CreateVector4Float(0.f, 0.f, 0.f, 0.f);
+        RPI::PassFilter passFilter;
+        AZStd::string slot;
+
+        auto setClearValue = [&](RPI::Pass* pass)-> RPI::PassFilterExecutionFlow
+        {
+            Name slotName = Name::FromStringLiteral(slot);
+            if (auto binding = pass->FindAttachmentBinding(slotName))
+            {
+                binding->m_unifiedScopeDesc.m_loadStoreAction.m_clearValue = blackClearValue;
+            }
+            return RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
+        };
+
+        slot = "SpecularOutput";
+        passFilter= RPI::PassFilter::CreateWithTemplateName(Name("ForwardPassTemplate"), GetParentScene());
+        RPI::PassSystemInterface::Get()->ForEachPass(passFilter, setClearValue);
+        passFilter = RPI::PassFilter::CreateWithTemplateName(Name("ForwardMSAAPassTemplate"), GetParentScene());
+        RPI::PassSystemInterface::Get()->ForEachPass(passFilter, setClearValue);
+
+        slot = "ReflectionOutput";
+        passFilter = RPI::PassFilter::CreateWithTemplateName(Name("ReflectionGlobalFullscreenPassTemplate"), GetParentScene());
+        RPI::PassSystemInterface::Get()->ForEachPass(passFilter, setClearValue);
+    }
+
+    RHI::ConstPtr<RHI::DrawPacket> StarsFeatureProcessor::BuildDrawPacket(
+                const Data::Instance<RPI::ShaderResourceGroup>& srg,
+                const RPI::Ptr<RPI::PipelineStateForDraw>& pipelineState,
+                const RHI::DrawListTag& drawListTag,
+                const AZStd::span<const AZ::RHI::StreamBufferView>& streamBufferViews,
+                uint32_t vertexCount)
+    {
+        RHI::DrawLinear drawLinear;
+        drawLinear.m_vertexCount = vertexCount;
+        drawLinear.m_vertexOffset = 0;
+        drawLinear.m_instanceCount = 1;
+        drawLinear.m_instanceOffset = 0;
+
+        RHI::DrawPacketBuilder drawPacketBuilder;
+        drawPacketBuilder.Begin(nullptr);
+        drawPacketBuilder.SetDrawArguments(drawLinear);
+        drawPacketBuilder.AddShaderResourceGroup(srg->GetRHIShaderResourceGroup());
+
+        RHI::DrawPacketBuilder::DrawRequest drawRequest;
+        drawRequest.m_listTag = drawListTag;
+        drawRequest.m_pipelineState = pipelineState->GetRHIPipelineState();
+        drawRequest.m_streamBufferViews = streamBufferViews;
+        drawPacketBuilder.AddDrawItem(drawRequest);
+        return drawPacketBuilder.End();
+    }
+} // namespace AZ::Render

+ 107 - 0
Gems/Stars/Code/Source/StarsFeatureProcessor.h

@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <Stars/StarsFeatureProcessorInterface.h>
+
+#include <Atom/RPI.Public/Buffer/Buffer.h>
+#include <Atom/RPI.Public/PipelineState.h>
+#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
+#include <Atom/RPI.Public/ViewportContextBus.h>
+
+namespace AZ::Render
+{
+    class Scene;
+    class Shader;
+
+    class StarsFeatureProcessor final
+        : public StarsFeatureProcessorInterface
+        , protected RPI::ViewportContextIdNotificationBus::Handler
+        , protected Data::AssetBus::Handler
+    {
+    public:
+        AZ_RTTI(AZ::Render::StarsFeatureProcessor, "{34B9EE52-2893-4D02-AC19-8C5DCAFFE608}", AZ::Render::StarsFeatureProcessorInterface);
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        StarsFeatureProcessor() = default;
+        virtual ~StarsFeatureProcessor() = default;
+
+        //! FeatureProcessor
+        void Activate() override;
+        void Deactivate() override;
+        void Simulate(const FeatureProcessor::SimulatePacket& packet) override;
+        void Render(const FeatureProcessor::RenderPacket& packet) override;
+
+        //! StarsFeatureProcessorInterface
+        void SetStars(const AZStd::vector<StarVertex>& starVertexData) override;
+        void SetExposure(float exposure) override;
+        void SetRadiusFactor(float radius) override;
+        void SetOrientation(AZ::Quaternion orientation) override;
+        void SetTwinkleRate(float twinkleRate) override;
+
+    protected:
+        //! RPI::SceneNotificationBus
+        void OnRenderPipelineAdded(RPI::RenderPipelinePtr renderPipeline) override;
+        void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) override;
+
+        //! RPI::ViewportContextIdNotificationBus
+        void OnViewportSizeChanged(AzFramework::WindowSize size) override;
+
+        //! Data::AssetBus
+        void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
+
+    private:
+        static constexpr const char* FeatureProcessorName = "StarsFeatureProcessor";
+
+        StarsFeatureProcessor(const StarsFeatureProcessor&) = delete;
+
+        void UpdateShaderConstants();
+        void UpdateDrawPacket();
+        void UpdateBackgroundClearColor();
+
+        //! build a draw packet to draw the star mesh
+        RHI::ConstPtr<RHI::DrawPacket> BuildDrawPacket(
+            const Data::Instance<RPI::ShaderResourceGroup>& srg,
+            const RPI::Ptr<RPI::PipelineStateForDraw>& pipelineState,
+            const RHI::DrawListTag& drawListTag,
+            const AZStd::span<const AZ::RHI::StreamBufferView>& streamBufferViews,
+            uint32_t vertexCount);
+
+        RPI::Ptr<RPI::PipelineStateForDraw> m_meshPipelineState;
+        AZStd::array<AZ::RHI::StreamBufferView, 1> m_meshStreamBufferViews;
+
+        Data::Instance<RPI::ShaderResourceGroup> m_drawSrg = nullptr;
+        Data::Instance<RPI::Shader> m_shader = nullptr;
+
+        RHI::ShaderInputNameIndex m_starParamsIndex = "m_starParams";
+        RHI::ShaderInputNameIndex m_rotationIndex = "m_rotation";
+
+        Data::Instance<RPI::Buffer> m_starsVertexBuffer = nullptr;
+        RHI::DrawListTag m_drawListTag;
+        RHI::ConstPtr<RHI::DrawPacket> m_drawPacket;
+
+        bool m_updateShaderConstants = false;
+        AZ::Matrix3x3 m_orientation = AZ::Matrix3x3::CreateIdentity();
+        float m_exposure = StarsDefaultExposure;
+        float m_radiusFactor = StarsDefaultRadiusFactor;
+
+        struct StarShaderConstants
+        {
+            float m_scaleX = 1.f;
+            float m_scaleY = 1.f;
+            float m_scaledExposure = StarsDefaultExposure;
+            float m_twinkleRate = StarsDefaultTwinkleRate;
+        };
+        StarShaderConstants m_shaderConstants;
+        AZStd::vector<StarVertex> m_starsMeshData;
+        uint32_t m_numStarsVertices = 0;
+        AzFramework::WindowSize m_viewportSize{0,0};
+    };
+} // namespace AZ::Render

+ 11 - 0
Gems/Stars/Code/Source/StarsModule.cpp

@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <StarsModule.h>
+
+AZ_DECLARE_MODULE_CLASS(Gem_Stars, AZ::Render::StarsModule)

+ 38 - 0
Gems/Stars/Code/Source/StarsModule.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <AzCore/Memory/SystemAllocator.h>
+#include <AzCore/Module/Module.h>
+#include <StarsSystemComponent.h>
+#include <StarsComponent.h>
+
+namespace AZ::Render
+{
+    class StarsModule
+        : public AZ::Module
+    {
+    public:
+        AZ_RTTI(StarsModule, "{1C13B38B-BAD5-4C42-AB75-9038596CBF3E}", AZ::Module);
+        AZ_CLASS_ALLOCATOR(StarsModule, AZ::SystemAllocator, 0);
+
+        StarsModule()
+        {
+            m_descriptors.insert(m_descriptors.end(), {
+                StarsSystemComponent::CreateDescriptor(),
+                StarsComponent::CreateDescriptor(),
+                });
+        }
+
+        AZ::ComponentTypeList GetRequiredSystemComponents() const override
+        {
+            return AZ::ComponentTypeList{
+                azrtti_typeid<StarsSystemComponent>()
+            };
+        }
+    };
+}// namespace AZ::Render

+ 50 - 0
Gems/Stars/Code/Source/StarsSystemComponent.cpp

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include <StarsSystemComponent.h>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <StarsAsset.h>
+#include <StarsFeatureProcessor.h>
+
+namespace AZ::Render
+{
+    void StarsSystemComponent::Reflect(AZ::ReflectContext* context)
+    {
+        StarsFeatureProcessor::Reflect(context);
+
+        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serialize->Class<StarsSystemComponent, AZ::Component>()
+                ->Version(0)
+                ;
+        }
+    }
+
+    void StarsSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
+    {
+        provided.push_back(AZ_CRC_CE("StarsSystemService"));
+    }
+
+    void StarsSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        incompatible.push_back(AZ_CRC_CE("StarsSystemService"));
+    }
+
+    void StarsSystemComponent::Activate()
+    {
+        m_starsAssetHandler = aznew AZ::Render::StarsAssetHandler();
+        m_starsAssetHandler->Register();
+    }
+
+    void StarsSystemComponent::Deactivate()
+    {
+        m_starsAssetHandler->Unregister();
+        delete m_starsAssetHandler;
+    }
+
+} // namespace Stars

+ 40 - 0
Gems/Stars/Code/Source/StarsSystemComponent.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include <AzCore/Component/Component.h>
+
+namespace AZ::Render
+{
+    class StarsAssetHandler;
+
+    class StarsSystemComponent
+        : public AZ::Component
+    {
+    public:
+        AZ_COMPONENT(StarsSystemComponent, "{ce10f0f9-5fe3-4376-8ccf-d56ec780005d}");
+
+        static void Reflect(AZ::ReflectContext* context);
+
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+
+        StarsSystemComponent() = default;
+        ~StarsSystemComponent() = default;
+
+    protected:
+        //! AZ::Component
+        void Activate() override;
+        void Deactivate() override;
+
+    private:
+        AZ::Render::StarsAssetHandler* m_starsAssetHandler;
+    };
+
+} // namespace AZ::Render 

+ 14 - 0
Gems/Stars/Code/stars_editor_files.cmake

@@ -0,0 +1,14 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+    Source/EditorStarsSystemComponent.cpp
+    Source/EditorStarsSystemComponent.h
+    Source/EditorStarsComponent.cpp
+    Source/EditorStarsComponent.h
+)

+ 11 - 0
Gems/Stars/Code/stars_editor_shared_files.cmake

@@ -0,0 +1,11 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+    Source/EditorStarsModule.cpp
+)

+ 22 - 0
Gems/Stars/Code/stars_files.cmake

@@ -0,0 +1,22 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+    Source/StarsAsset.cpp
+    Source/StarsAsset.h
+    Source/StarsComponent.cpp
+    Source/StarsComponent.h
+    Source/StarsComponentConfig.h
+    Source/StarsComponentController.cpp
+    Source/StarsComponentController.h
+    Source/StarsFeatureProcessor.cpp
+    Source/StarsFeatureProcessor.h
+    Source/StarsModule.h
+    Source/StarsSystemComponent.cpp
+    Source/StarsSystemComponent.h
+)

+ 11 - 0
Gems/Stars/Code/stars_headers_files.cmake

@@ -0,0 +1,11 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+    Include/Stars/StarsFeatureProcessorInterface.h
+)

+ 11 - 0
Gems/Stars/Code/stars_shared_files.cmake

@@ -0,0 +1,11 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+set(FILES
+    Source/StarsModule.cpp
+)

+ 23 - 0
Gems/Stars/Registry/assetprocessor_settings.setreg

@@ -0,0 +1,23 @@
+{
+    "Amazon": {
+        "AssetProcessor": {
+            "Settings": {
+                "RC Stars Asset": {
+                  "glob": "*.stars",
+                  "params": "copy",
+                  "productAssetType": "{211938C1-C54D-417D-977A-9928D7C630B1}"
+                },
+                "ScanFolder Stars/Assets": {
+                  "watch": "@GEMROOT:Stars@/Assets",
+                  "recursive": 1,
+                  "order": 101
+                },
+                "ScanFolder Stars/Registry": {
+                  "watch": "@GEMROOT:Stars@/Registry",
+                  "recursive": 1,
+                  "order": 102
+                }
+            }
+        }
+    }
+}

+ 22 - 0
Gems/Stars/gem.json

@@ -0,0 +1,22 @@
+{
+    "gem_name": "Stars",
+    "display_name": "Stars",
+    "license": "Apache-2.0 Or MIT",
+    "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt",
+    "origin": "Open 3D Engine - o3de.org",
+    "origin_url": "https://github.com/o3de/o3de",
+    "type": "Code",
+    "summary": "The Stars gem provides ability to render physically-based animated resolution-independant distant stars.",
+    "canonical_tags": [
+        "Gem"
+    ],
+    "user_tags": [
+        "Stars",
+        "Rendering"
+    ],
+    "icon_path": "preview.png",
+    "requirements": "",
+    "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/stars/",
+    "dependencies": [],
+    "restricted": "Stars"
+}

+ 3 - 0
Gems/Stars/preview.png

@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:66b5937013fa344c3a5e3f53ef7096b192766a3f451e2c0cf156bcc96f7ff8a1
+size 1657

+ 1 - 0
engine.json

@@ -71,6 +71,7 @@
         "Gems/ScriptedEntityTweener",
         "Gems/ScriptEvents",
         "Gems/SliceFavorites",
+        "Gems/Stars",
         "Gems/StartingPointCamera",
         "Gems/StartingPointInput",
         "Gems/StartingPointMovement",