Skip to content

Add support for multiple custom post-processing effects - #92

Open
filipppavlov wants to merge 5 commits into
mainfrom
post-processing-effects
Open

filipppavlov wants to merge 5 commits into
mainfrom
post-processing-effects

Conversation

@filipppavlov

Copy link
Copy Markdown
Member

Summary

Add support for multiple custom post-processing effects. This feature expands on the previous implementation
of custom post-process effects that was limited to a single effect.
Custom post-process effects are now specified in post-process volumes. See documentation included in this PR
for more information.

https://fenriscreations.atlassian.net/browse/PLAT-11862

- add generic effects to post-processing volumes
- mix multiple effects together
- expose two places in post-processing pipeline to execute these effects
Copilot AI lite review requested due to automatic review settings September 16, 2026 11:29
github-actions[bot]

This comment was marked as outdated.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A potential null dereference and unresolved ordering, blending, compatibility, performance, and configuration issues remain.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds support for multiple custom post-processing effects configured through post-process volumes, including blending, ordering, execution slots, and pipeline integration.

Changes:

  • Adds effect accumulation, grouping, hashing, and parameter blending.
  • Executes effects before upscaling and after tonemapping.
  • Exposes configuration through Blue and documents setup.
File summaries
File Reviewed changes and findings
trinity/Shader/Tr2Effect.h Declares parameter-aware hashing support.
trinity/Shader/Tr2Effect.cpp Implements effect hashing. moderate (1 vote): unsupported blendable parameter kinds are excluded from the hash.
trinity/PostProcess/Tr2PostProcessRenderer.h Declares multi-effect rendering.
trinity/PostProcess/Tr2PostProcessRenderer.cpp Executes effects in pipeline slots. critical (3 votes): guard null GetPostProcess() results at lines 821 and 842.
trinity/PostProcess/Tr2PostProcessAttributes.h Adds generic effect attributes.
trinity/PostProcess/Tr2PostProcessAttributes.cpp Accumulates generic effects. moderate (1 vote): legacy effect updates can lag by one frame.
trinity/PostProcess/Tr2PostProcessAttributes_Blue.cpp Exposes generic effect collections. moderate (1 vote): make genericEffects editable and persistent.
trinity/PostProcess/Tr2PostProcess2.h Stores accumulated effects.
trinity/PostProcess/Effects/Tr2PPGenericEffect.h Defines effect metadata and instances. moderate (2 votes): preserve the previous MEDIUM quality default.
trinity/PostProcess/Effects/Tr2PPGenericEffect.cpp Groups and blends effects. moderate: deduplicate stage constants (3 votes), include m_order in merge checks (2 votes), avoid full per-frame hashing (1 vote), and fix legacy accumulation timing (2 votes).
trinity/PostProcess/Effects/Tr2PPGenericEffect_Blue.cpp Exposes execution configuration.
doc/source/eve/generic-pp-effects.rst Documents custom effects. nit: correct execututionSlot (3 votes) and “effect instanced” grammar (1 vote).
Review details

Suppressed comments (7)

doc/source/eve/generic-pp-effects.rst:32

  • This sentence contains a duplicated word, the the, which makes the shader input description unpolished.
The effect may use the the output of the previous post-processing step as the input texture. For that, the shader needs to define a texture 2D object

doc/source/eve/generic-pp-effects.rst:42

  • effect instanced is grammatically incorrect here; the sentence should refer to each effect instance.
Trinity will blend these parameters based on the volume intensity/relative weight. For each effect instanced it will interpolate such parameters between their

trinity/PostProcess/Effects/Tr2PPGenericEffect.cpp:155

  • Tr2Effect::GetHashValue() is explicitly documented as non-lightweight and unsuitable for per-frame calls (Shader/Tr2Effect.cpp:1516-1519), but UpdatePostProcessAttributes() invokes UpdateEffectParameters() for every active volume every frame and this line recomputes the full effect hash before every cache check. With multiple effects this adds a full parameter/resource traversal per effect per frame; use mutation/dirty tracking or another invalidation mechanism instead of polling the full hash.
	auto hash = m_effect->GetHashValue();
	if( hash == m_lastHashValue && m_lastShader == shader )

trinity/PostProcess/Tr2PostProcessAttributes.cpp:150

  • AccumulateGenericEffects now snapshots the deprecated m_generic effect before EveSpaceScene assigns the current scene-default effect after MergeInto (Eve/EveSpaceScene.cpp:391-399). Since the renderer consumes m_genericEffects instead of reading m_generic directly, the first frame misses a newly assigned legacy effect and subsequent replacements/removals render the previous effect for one frame. Update the legacy effect before accumulation or pass the current legacy effect into the accumulator.
	AccumulateGenericEffects( postprocess, sources );

trinity/PostProcess/Tr2PostProcessAttributes_Blue.cpp:117

  • genericEffects is the user-authored list that the documentation says configures effects on post-process volumes, but it is exposed with Be::READ. Unlike generated lists elsewhere, this attribute has no add/modify API, so Blue cannot configure the new effects through the volume. Expose it as Be::READWRITE | Be::PERSIST, matching the editable postProcessAttributes on EveChildPostProcessVolume.
		MAP_ATTRIBUTE( "genericEffects", genericEffects, "List of generic post-processing effects", Be::READ | Be::PERSIST )

trinity/PostProcess/Tr2PostProcessRenderer.cpp:842

  • This branch has the same null dereference as the upscaling branch: postProcess can be null, but the new after-tonemap call dereferences it before rendering the final output. Use an empty effect list/output when no post-process object exists.
			auto newOutput = RenderGenericEffects( postProcess->m_genericEffects.effects[Tr2PPGenericEffect::AFTER_TONEMAP], output, gpuResourcePool, renderContext );

trinity/Shader/Tr2Effect.cpp:1574

  • This excludes every parameter carrying IsBlendable, but UpdateEffectParameters only recognizes supported scalar/vector float constants (one element, dimensions 1–4). An annotated array, matrix, or non-float parameter is therefore neither accumulated nor included in this hash; effects with different values can merge and the first effect's value wins. Restrict hash exclusion to the supported blendable kinds or include unsupported annotated values.
		if ( GetBool( m_shader, ( *it )->GetParameterName(), "IsBlendable", false ) )
		{
			continue;
  • Files reviewed: 12/12 changed files
  • Comments generated: 6
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

}

{
auto newOutput = RenderGenericEffects( postProcess->m_genericEffects.effects[Tr2PPGenericEffect::AFTER_TONEMAP], output, gpuResourcePool, renderContext );
Comment on lines +74 to +81
if( auto deprecated = postprocess.GetGenericEffectIfAvailable() )
{
if( deprecated->IsActive() )
{
deprecated->UpdateEffectParameters();
if( deprecated->IsValid() )
{
buckets.emplace_back( deprecated, PostProcessEnums::SCENE_DEFAULT_PRIORITY, 1.0f );
Comment on lines +168 to +182
auto& desc = shader->GetEffectDescription();
for( auto& technique : desc.techniques )
{
for( auto& pass : technique.passes )
{
for( auto& stage : pass.stageInputs )
{
for( auto& constant : stage.constants )
{
if( !IsBlendableParameter( constant, *shader ) )
{
continue;
}
AddBlendableParameter( constant, reinterpret_cast<const uint8_t*>( stage.constantValues ) );
}
Comment on lines +203 to +204
if( m_executionSlot != other.m_executionSlot || m_quality != other.m_quality )
{
Comment thread trinity/PostProcess/Effects/Tr2PPGenericEffect.h

- `effect`: The shader effect used for this post-processing pass.
- `quality`: Minimal post-processing quality setting when this effect is visible.
- `execututionSlot`: Place in the post-processing pipeline where this effect should be executed.
@github-actions
github-actions Bot dismissed their stale review September 16, 2026 11:39

outdated suggestion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants