Repository navigation
Conversation
Move jitter, reprojection, mip LOD bias, and upscaling setup out of `EveSpaceScene` and into the render driver so render state is prepared explicitly per view. This also splits execution into old/new render routes, adds shared feature-gated buffer allocation helpers, and exposes a post-process jitter helper for TAA. The change also wires in reflection quality/probe settings and keeps cached upscaling info in sync when contexts are created or destroyed.
Unify space scene view rendering and drive reflection faces through it Collapse RenderOld/RenderNew into a single RenderView that renders one view (the main view or a reflection probe face) and returns its targets. Execute now does the per-frame work (settings, light manager, render target push/pop, post process, 3D UI, tools, FPS) once. m_newRoute only chooses who renders the reflection faces: the driver through RenderView, or the scene's RenderReflectionPass from within the main view. Replace the main-view checks in the scene and the driver with explicit SceneRender::ViewInfo flags (sceneObjects, temporal, reflection, subsurfaceScattering, gpuParticles, lensflares), built by ViewInfo::MainView and ViewInfo::ReflectionFace. RenderInfo now carries the ViewInfo, so distortion is stored in one place instead of two, and a FeatureSet::background and overlay flags gate the background and overlay render nodes. GatherBatches is split into GatherSceneObjectRenderables and GatherReflectionRenderables, and reflection shadows and reflection fog move into RenderReflectionShadows and RegisterReflectionFog. Share the reflection rules between the old and new paths: the reflection-in-reflection intensity damping, the reflection shadow setup, and the probe's finishing step (Tr2ReflectionProbe::FinishFaces, now also used by EndRenderPass, replacing the Filter overload and AdvanceFrame). The volumetrics reflection flag is set per view in BeginView instead of being set and reset in separate places. The main view now also honours the caller's named outputs on the new route.
Split EveSpaceScene::Update into UpdateFrame (animation, object updates and post process attributes, once per frame) and UpdateView (frustum and detail thresholds from the current camera). Execute now does the frame's work explicitly, in order: bind the main view's color target, update the scene from the main camera (UpdateSceneFrame, which also updates the GPU particles), BeginFrame, the reflection faces, then the main view. BeginFrame no longer guards itself with a frame counter.
from GetFrustum in Tr2ReflectionProbe
and the ability to show light shadows in the reflection probe
Reflection probe faces get their own dynamic lights. Each face is lit by the lights tagged for the current reflection quality, and face fog uses the face's own volumetric lights. Light manager: - One light store per view (Tr2LightManager::View): the main view plus one per face rendered in a frame (1 or 6, by the probe's render frequency). Face views are only recreated when that count changes. - AddLight tests each light against every view and keeps a separate copy per view (fade, flags). Face views take only lights tagged for the current reflection quality and never cast shadows. - Resolve, list building and the getters work on the active view. SetActiveView binds that view's buffers; SetViewFrustum sets a frustum without activating the view. - Face views: 16 volumetric lights, no shadow casters, 1M-entry index buffer. Lights: - Tr2LightTags on LightData. The reflectionMode attribute is exposed on point, spot, textured point and faction lights. ReflectionQuality gains OFF and ULTRA. Removed the unused reflectionShadowCaster attribute and the duplicate castsShadows registrations. Scene and driver: - SceneRender::View and Features replace the driver's RenderInfo/FeatureSet and the scene's ViewInfo parameters. The view's frustum is computed when the view is built, not taken from the bound viewport. - Lights are gathered once per frame, by the driver, for the main view and the faces, instead of once per view in BeginView. - The driver sets the reflection quality on the light manager, prepares the reflection faces before the gather and activates each view's lights in RenderView. - The probe's first pass only draws the background into the faces. Tr2ReflectionProbe gets GetRenderFrequency() and IsFirstPass().
So now the reflections always get Iights
Removing reflection rendering code from the EveSpaceScene. In turn there were unneeded functions in Tr2ReflectionProbe removed as well
- Faces render into the cube's slices; the six face targets and the copy are gone. The cube is unbound before filtering (DX12 fix). - The probe's first pass renders all faces as normal faces; removed Features::ReflectionBackground. - Tr2LightManager::SetViews replaces the per-view count and frustum calls; a view's index is its position in the list.
Fixing lensflares in the reflections. They rendered into opposite faces (f.ex -y and +y) and would dissappear if the main view looks away from the lensflare
Renaming EndRenderto EndView
Fixing the way we time frame, mainview and reflection views. So it now shows up correctly
fixing a compiler error...
fixing calls to EveInstancedMeshManager::CollectMeshes for every view
forgot to move the CollectMeshes (last commit only deleted it). lupdatePostProcessAttrributes is now only called once
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved rendering regressions can leave camera and post-process state incorrect, make camera-attached objects lag, and let reflection passes overwrite the main view’s occlusion history.
6 open issues
Refresh post-process settings on same-frame updates · New Preserve camera initialization for direct update entry points · New Update camera-attached transforms before gathering renderables · New Restore view camera after background node rendering · New Gate occlusion queries to temporal main views · New Avoid normal maps for raytraced shadows in reflections · New
What changed in this PR
Unifies main-view and reflection-probe rendering in the space-scene driver, separating per-frame updates from per-view rendering.
Changes:
- Renders reflection faces directly into the probe cubemap through the shared render path.
- Adds per-view light lists, reflection-quality filters, and lens-flare visibility updates.
- Introduces explicit view settings, extracts projection jitter generation, and reorganizes profiling timers.
| File | Description |
|---|---|
| trinity/Tr2ReflectionProbe.h | Exposes face cameras, cube target, and filtering API. |
| trinity/Tr2ReflectionProbe.cpp | Removes intermediate face targets and adapts filtering. |
| trinity/Tr2LightManager.h | Defines reflection quality and per-view light storage. |
| trinity/Tr2LightManager.cpp | Gathers, filters, and uploads lights per view. |
| trinity/PostProcess/Tr2PostProcessRenderer.h | Declares reusable projection jitter helper. |
| trinity/PostProcess/Tr2PostProcessRenderer.cpp | Implements projection jitter generation. |
| trinity/Lights/Tr2TexturedPointLight_Blue.cpp | Exposes textured-light reflection filtering. |
| trinity/Lights/Tr2SpotLight_Blue.cpp | Exposes spotlight reflection filtering. |
| trinity/Lights/Tr2PointLight_Blue.cpp | Exposes point-light reflection filtering. |
| trinity/Lights/Tr2Light.h | Adds light reflection tags and chooser declaration. |
| trinity/Lights/Tr2Light.cpp | Passes reflection tags to the light manager. |
| trinity/Lights/Tr2Light_Blue.cpp | Registers reflection-quality filter options. |
| trinity/Lights/Tr2FactionLight_Blue.cpp | Exposes faction-light reflection filtering. |
| trinity/Eve/EveSpaceSceneRenderDriver.h | Defines shared rendering structures and per-view timers. |
| trinity/Eve/EveSpaceSceneRenderDriver.cpp | Coordinates frame setup and shared view rendering. |
| trinity/Eve/EveSpaceScene.h | Declares frame/view lifecycle and camera APIs. |
| trinity/Eve/EveSpaceScene.cpp | Separates frame updates from view-specific scene work. |
| trinity/Eve/EveSceneView.h | Defines camera and scene-view settings. |
| trinity/Eve/EveSceneView.cpp | Builds frustums and main/reflection view defaults. |
| trinity/CMakeLists.txt | Adds the new scene-view source files. |
Review effort: Balanced
There was a problem hiding this comment.
Cpp-linter Review
Used clang-format v21.1.8
Click here for the full clang-format patch
diff --git a/trinity/Eve/EveSpaceScene.cpp b/trinity/Eve/EveSpaceScene.cpp
--- a/trinity/Eve/EveSpaceScene.cpp
+++ b/trinity/Eve/EveSpaceScene.cpp
@@ -1356 +1356 @@ void EveSpaceScene::BeginFrame( Tr2RenderContext& renderContext )
- // Ensure that the camera attachment parent is updated to the current view transform,
+ // Ensure that the camera attachment parent is updated to the current view transform,
diff --git a/trinity/Eve/EveSpaceScene.h b/trinity/Eve/EveSpaceScene.h
--- a/trinity/Eve/EveSpaceScene.h
+++ b/trinity/Eve/EveSpaceScene.h
@@ -149 +149 @@ public:
- void BeginFrame( Tr2RenderContext& renderContext );
+ void BeginFrame( Tr2RenderContext & renderContext );
@@ -153 +153 @@ public:
- void PopulateAndApplyPerFrameData( Tr2RenderContext& renderContext );
+ void PopulateAndApplyPerFrameData( Tr2RenderContext & renderContext );
@@ -614 +614 @@ protected:
- void GatherDynamicLights( Tr2RenderContext& renderContext );
+ void GatherDynamicLights( Tr2RenderContext & renderContext );
@@ -616,2 +616,2 @@ protected:
- void GatherSceneObjectRenderables( std::vector<IEveSpaceObject2*>& allObjects, std::vector<ITr2Renderable*>& renderables, Tr2RenderContext& renderContext );
- void GatherReflectionRenderables( std::vector<ITr2Renderable*>& renderables );
+ void GatherSceneObjectRenderables( std::vector<IEveSpaceObject2*> & allObjects, std::vector<ITr2Renderable*> & renderables, Tr2RenderContext & renderContext );
+ void GatherReflectionRenderables( std::vector<ITr2Renderable*> & renderables );
@@ -619 +619 @@ protected:
-
+
diff --git a/trinity/Eve/EveSpaceSceneRenderDriver.h b/trinity/Eve/EveSpaceSceneRenderDriver.h
--- a/trinity/Eve/EveSpaceSceneRenderDriver.h
+++ b/trinity/Eve/EveSpaceSceneRenderDriver.h
@@ -156 +156 @@ private:
- ReflectionFaces PrepareReflectionFaces( Tr2RenderContext& renderContext );
+ ReflectionFaces PrepareReflectionFaces( Tr2RenderContext & renderContext );
✨ Powered by cpp-linter -- ⭐ Star • ❤️ Sponsor • 💬 Feedback
Making render attachments only early out if the texture and slice are the same as the bound attachment. Also removed the use of depthPlane from ResolveMsaa and replaced it with slice
…ttps://github.com/carbonengine/trinity into dynamicexposure-and-reflection-probe-improvements
…ttps://github.com/carbonengine/trinity into dynamicexposure-and-reflection-probe-improvements
| case TR2RENDERREASON_REFLECTION: | ||
| froxelFogTextures = RenderReflectionVolumetrics( depthMap, gpuResourcePool, renderContext ); | ||
| break; | ||
| case TR2RENDERREASON_VOLUMETRIC: |
There was a problem hiding this comment.
Seems like this is not used anymore, maybe purge?
| // and before it is rendered. Only depends on the camera, so it is safe to call more than | ||
| // once for a view. | ||
| // -------------------------------------------------------------------------------------- | ||
| void EveSpaceScene::SetCamera( const EveSceneView::Camera& camera ) |
There was a problem hiding this comment.
Would it make more sense to pass the camera around, instead of having camera-related variables in the space scene?
|
|
||
| virtual bool OnPrepareResources(); | ||
|
|
||
| View& GetActiveView(); |
There was a problem hiding this comment.
Instead of storing an active view, might be better to just pass it in to the light manager when needed, to avoid persistent/"global" state in the light manager.
| if( auto lightManager = Tr2LightManager::GetInstance() ) | ||
| { | ||
| Tr2LightManager::DeleteInstance(); | ||
| lightManager->SetActiveView( view.lightView ); |
| @@ -217,8 +216,8 @@ EveSpaceScene::EveSpaceScene( IRoot* lockobj ) : | |||
| m_projectionLast( IdentityMatrix() ), | |||
There was a problem hiding this comment.
Ideally it would be nice to get rid of these persistent camera-related variables in EveSpaceScene (as well as references to Tr2Renderer when possible) and simply pass around the Camera to places that need this information.
| m_volumetricsRenderer->UpdateFogSettings( *m_componentRegistry, m_updateContext ); | ||
| UpdateVariableStore(); | ||
| m_volumetricsRenderer->UpdateFogEnvironmentMap( renderContext ); | ||
| m_volumetricsRenderer->SetIsReflectionProbe( view.IsReflection() ); |
There was a problem hiding this comment.
I added this SetIsReflectionProbe() "hack" while trying to implement a different fog intensity for the reflection probe, since there was no way to figure out if it was a reflection probe or not at the time Render() was called. Since we now have this exact information in view.IsReflection(), it would be better to remove this persistent state from Tr2VolumetricsRenderer and simply pass it in where needed.
|
|
||
| FinalizeBatches( m_primaryBatches ); | ||
|
|
||
| UpdateShLighting( allObjects ); |

Summary
Space scene: one render path for the main view and the reflection probe faces
AI assistance
AI helped