rj-action-library/Runtime/Rendering/Objects/RokojoriCompositorEffect.cs

291 lines
7.0 KiB
C#
Raw Normal View History

2025-04-23 12:00:43 +00:00
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class RokojoriCompositorEffect:CompositorEffect
{
protected RenderingDevice _rd;
public RenderingDevice rd => _rd;
protected int _groupSize = 16;
protected List<RenderingObject> _cleanUps = new List<RenderingObject>();
protected List<string> _cleanUpInfo = new List<string>();
EditableRokojoriCompositorContext _context;
protected bool _hasContext = false;
public RokojoriCompositorContext context => _hasContext ? _context : null;
protected List<Message> _messages = new List<Message>();
public List<Message> messages => _messages;
public bool logMessages = true;
public int messageLogLevel = Messages.GetLevel( MessageType.Verbose );
protected virtual void OnConfigure(){}
protected virtual void OnInitialize(){}
protected virtual void ForAllViews(){}
protected virtual void RenderView(){}
public RokojoriCompositorEffect():base()
{
RenderingServer.CallOnRenderThread( Callable.From( _InitializeCompositorEffect ) );
}
protected void _InitializeCompositorEffect()
{
OnConfigure();
_rd = RenderingServer.Singleton.GetRenderingDevice();
if ( _rd == null )
{
Error( "Found no rendering device" );
return;
}
_context = new EditableRokojoriCompositorContext();
_context.SetEffect( this );
_hasContext = true;
OnInitialize();
_hasContext = false;
}
public override void _RenderCallback( int effectCallbackType, RenderData renderData )
{
_hasContext = false;
if ( rd == null )
{
Error( "No render device" );
return;
}
var sceneBuffers = ( RenderSceneBuffersRD ) renderData.GetRenderSceneBuffers();
var sceneData = ( RenderSceneDataRD ) renderData.GetRenderSceneData();
if ( sceneBuffers == null && sceneData == null )
{
Error( "sceneBuffers == null && sceneData == null" );
return;
}
var size = sceneBuffers.GetInternalSize();
if ( size.X == 0 || size.Y == 0 )
{
Warning( "InternalSize.X == 0 || InternalSize.Y == 0" );
return;
}
_context.SetRenderData( renderData, sceneBuffers, sceneData );
_context.SetView( -1 );
_context.SetGroups( new Vector3I( 1, 1, 1 ) );
_hasContext = true;
var groups = ComputeGroups();
_context.SetGroups( groups );
ForAllViews();
int viewCount = ( int ) sceneBuffers.GetViewCount();
for ( int i = 0; i < viewCount; i++ )
{
_context.SetView( i );
RenderView();
}
_hasContext = false;
}
protected virtual Vector3I ComputeGroups()
{
var size = context.sceneBuffers.GetInternalSize();
var xGroups = Mathf.CeilToInt( size.X / (float) _groupSize );
var yGroups = Mathf.CeilToInt( size.Y / (float) _groupSize );
return new Vector3I( xGroups, yGroups, 1 );
}
public override void _Notification( int what )
{
var _shader = context.shader;
Verbose( "Got notification: ", what );
if ( what != NotificationPredelete || ( _shader == null || !_shader.valid ) || rd == null )
{
Verbose(
"what != NotificationPredelete", what != NotificationPredelete,
"( _shader == null || !_shader.valid )", ( _shader == null || !_shader.valid ),
"rd == null", rd == null
);
return;
}
CleanUp( _shader, "Shader" );
var index = 0;
_cleanUps.ForEach(
c =>
{
CleanUp( c, "_cleanUps[" + index + "]");
index ++;
}
);
_cleanUps.Clear();
}
public void AddToCleanUp( RenderingObject ro, string info = null )
{
var _shader = context.shader;
if ( _cleanUps.Contains( ro ) || _shader == ro )
{
return;
}
_cleanUps.Add( ro );
_cleanUpInfo.Add( info );
}
public void AddToCleanUp( List<RenderingObject> ro, string info = null )
{
var index = 0;
info = info == null ? "" : info;
ro.ForEach(
r =>
{
AddToCleanUp( r, info + "["+ index + "]" );
index ++;
}
);
}
void CleanUp( RenderingObject ro, string info )
{
if ( ro == null )
{
Warning( "ro == null, couldn't clean up: ", info );
return;
}
Verbose( "Cleaning up: ", info, ro.rid );
rd.FreeRid( ro.rid );
}
// ---------------------------------------------
// ---------------------------------------------
// CONVINIENCE
// ---------------------------------------------
// ---------------------------------------------
public RDSampler Sampler( RDSamplerState state = null)
{
if ( state == null )
{
state = new RDSamplerState();
state.MinFilter = RenderingDevice.SamplerFilter.Linear;
state.MagFilter = RenderingDevice.SamplerFilter.Linear;
state.RepeatU = RenderingDevice.SamplerRepeatMode.Repeat;
state.RepeatV = RenderingDevice.SamplerRepeatMode.Repeat;
}
var sampler = RDSampler.Create( this, state );
return sampler;
}
public RDSampler Sampler( RenderingDevice.SamplerFilter filter, RenderingDevice.SamplerRepeatMode repeatMode)
{
var state = new RDSamplerState();
state.MinFilter = filter;
state.MagFilter = filter;
state.RepeatU = repeatMode;
state.RepeatV = repeatMode;
return Sampler( state );
}
// ---------------------------------------------
// ---------------------------------------------
// MESSAGES
// ---------------------------------------------
// ---------------------------------------------
public void Error( params object[] messages )
{
var message = RJLog.GetLogString( messages );
Messages.Error( _messages, message );
if ( logMessages )
{
this.LogError( message );
}
}
public void Warning( params object[] messages )
{
var message = RJLog.GetLogString( messages );
Messages.Warning( _messages, message );
if ( logMessages && Messages.GetLevel( MessageType.Warning ) >= messageLogLevel )
{
this.LogInfo( message );
}
}
public void Info( params object[] messages )
{
var message = RJLog.GetLogString( messages );
Messages.Info( _messages, message );
if ( logMessages && Messages.GetLevel( MessageType.Info ) >= messageLogLevel )
{
this.LogInfo( message );
}
}
public void Verbose( params object[] messages )
{
var message = RJLog.GetLogString( messages );
Messages.Verbose( _messages, message );
if ( logMessages && Messages.GetLevel( MessageType.Verbose ) >= messageLogLevel )
{
this.LogInfo( message );
}
}
}
}