Gradient Fog

This commit is contained in:
Josef 2026-01-24 14:39:35 +01:00
parent 338073361f
commit 90d5759d26
9 changed files with 509 additions and 6 deletions

View File

@ -0,0 +1,13 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/FogCompositorEffect.svg")]
public abstract partial class FogCompositorEffect:RDGraphCompositorEffect
{
}
}

View File

@ -0,0 +1 @@
uid://cuaweg0ohqox8

View File

@ -0,0 +1,133 @@
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class GradientFogEffect:FogCompositorEffect
{
public GradientFogEffect():base()
{
Initialize();
}
[ExportGroup( "Main")]
[Export( PropertyHint.Range, "0,1") ]
public float amount = 1f;
[Export]
public float zStart = 1f;
[Export]
public float zEnd = 1f;
[Export( PropertyHint.Range, "-1,1") ]
public float zSpread = 0f;
[Export]
public GradientTexture1D gradient = new GradientTexture1D();
[Export]
public float gradientUVScale = 1f;
[Export]
public float gradientUVOffset = 0f;
[Export]
public float gradientUVScroll = 0f;
[Export]
public float gradientUVScrollFPS = 0f;
[Export]
public TimeLine gradientUVScrollTimeline = null;
[Export]
public CurveTexture opacity = new CurveTexture().WithCurve( new Curve().WithValues( 1, 1 ) );
RG_ScreenColorTexure screenColorTexture;
RG_ScreenDepthTexture screenDepthTexture;
RG_ImageTexture gradientTexture;
RG_ImageTexture opacityTexture;
RG_GradientFog gradientFog;
void Initialize()
{
screenColorTexture = new RG_ScreenColorTexure( graph );
screenDepthTexture = new RG_ScreenDepthTexture( graph );
gradientTexture = new RG_ImageTexture( graph );
opacityTexture = new RG_ImageTexture( graph );
gradientFog = new RG_GradientFog( graph );
graph.InitializeNodes();
gradientFog.SetTextureSlotInputs( screenColorTexture, screenColorTexture );
gradientFog.AddTextureSlotInput( screenDepthTexture ).UseLinearSamplerEdgeClamped();
gradientFog.AddTextureSlotInput( gradientTexture ).UseLinearSamplerEdgeClamped();
gradientFog.AddTextureSlotInput( opacityTexture ).UseLinearSamplerEdgeClamped();
graph.SetProcessOrder(
screenColorTexture,
screenDepthTexture,
gradientTexture,
opacityTexture,
gradientFog
);
}
protected override void ForAllViews()
{
gradientTexture.SetImageTexture( gradient );
opacityTexture.SetImageTexture( opacity );
var projection = context.GetCameraProjection().Inverse();
var tl = TimeLineManager.Ensure( gradientUVScrollTimeline );
float tlPosition = tl.position;
if ( gradientUVScrollFPS > 0f )
{
float stepTime = 1.0f / gradientUVScrollFPS;
tlPosition = MathX.SnapFloored( tlPosition, stepTime );
}
var gradientOffset = ( tlPosition * gradientUVScroll + gradientUVOffset ) % 1f;
gradientFog.constants.Set(
projection.X,
projection.Y,
projection.Z,
projection.W,
amount,
Mathf.Pow( 10f, zSpread ),
zStart,
zEnd,
gradientUVScale,
gradientOffset,
0f,
0f
);
}
}
}

View File

@ -0,0 +1 @@
uid://dqgedhwm3die2

View File

@ -16,7 +16,7 @@ script = ExtResource("2_ysy1a")
script = ExtResource("3_fp4l4") script = ExtResource("3_fp4l4")
owner = SubResource("Resource_fy8er") owner = SubResource("Resource_fy8er")
[sub_resource type="CompositorEffect" id="CompositorEffect_i5utj"] [sub_resource type="CompositorEffect" id="CompositorEffect_ifhyp"]
resource_local_to_scene = false resource_local_to_scene = false
resource_name = "" resource_name = ""
enabled = true enabled = true
@ -47,7 +47,7 @@ metadata/_custom_type_script = "uid://dvvfvlutisecy"
script = ExtResource("3_fp4l4") script = ExtResource("3_fp4l4")
owner = SubResource("Resource_fy8er") owner = SubResource("Resource_fy8er")
[sub_resource type="CompositorEffect" id="CompositorEffect_gxlxg"] [sub_resource type="CompositorEffect" id="CompositorEffect_wx28p"]
resource_local_to_scene = false resource_local_to_scene = false
resource_name = "" resource_name = ""
enabled = true enabled = true
@ -55,7 +55,7 @@ effect_callback_type = 4
needs_motion_vectors = false needs_motion_vectors = false
needs_normal_roughness = false needs_normal_roughness = false
script = ExtResource("6_kwewy") script = ExtResource("6_kwewy")
amount = 0.05 amount = 0.0
scale = 5.0619 scale = 5.0619
smearingSteps = 5 smearingSteps = 5
smearing = 1.2095 smearing = 1.2095
@ -72,7 +72,7 @@ metadata/_custom_type_script = "uid://cidk0x7sb1pxl"
script = ExtResource("3_fp4l4") script = ExtResource("3_fp4l4")
owner = SubResource("Resource_fy8er") owner = SubResource("Resource_fy8er")
[sub_resource type="CompositorEffect" id="CompositorEffect_ixn1d"] [sub_resource type="CompositorEffect" id="CompositorEffect_ysy1a"]
resource_local_to_scene = false resource_local_to_scene = false
resource_name = "" resource_name = ""
enabled = true enabled = true
@ -98,7 +98,7 @@ metadata/_custom_type_script = "uid://b2oxy6ln560ys"
script = ExtResource("3_fp4l4") script = ExtResource("3_fp4l4")
owner = SubResource("Resource_fy8er") owner = SubResource("Resource_fy8er")
[sub_resource type="CompositorEffect" id="CompositorEffect_y3g14"] [sub_resource type="CompositorEffect" id="CompositorEffect_fp4l4"]
resource_local_to_scene = false resource_local_to_scene = false
resource_name = "" resource_name = ""
enabled = true enabled = true
@ -106,10 +106,11 @@ effect_callback_type = 4
needs_motion_vectors = false needs_motion_vectors = false
needs_normal_roughness = false needs_normal_roughness = false
script = ExtResource("7_wx28p") script = ExtResource("7_wx28p")
smearingFrames = 10.0
compositorEffectID = SubResource("Resource_3tnad") compositorEffectID = SubResource("Resource_3tnad")
metadata/_custom_type_script = "uid://cowk70ifagygb" metadata/_custom_type_script = "uid://cowk70ifagygb"
[resource] [resource]
script = ExtResource("9_srrpj") script = ExtResource("9_srrpj")
effects = [SubResource("CompositorEffect_i5utj"), SubResource("CompositorEffect_gxlxg"), SubResource("CompositorEffect_ixn1d"), SubResource("CompositorEffect_y3g14")] effects = [SubResource("CompositorEffect_ifhyp"), SubResource("CompositorEffect_wx28p"), SubResource("CompositorEffect_ysy1a"), SubResource("CompositorEffect_fp4l4")]
metadata/_custom_type_script = "uid://ckixweetchlo0" metadata/_custom_type_script = "uid://ckixweetchlo0"

View File

@ -0,0 +1,322 @@
#[compute]
#version 450
float clamp01( float value )
{
return clamp( value, 0.0, 1.0 );
}
float normalizeToRange( float value, float min, float max )
{
return ( value - min ) / ( max - min );
}
float normalizeToRange01( float value, float min, float max )
{
return clamp01( normalizeToRange( value, min, max ) );
}
float map( float value, float inMin, float inMax, float outMin, float outMax )
{
return mix( outMin, outMax, normalizeToRange( value, inMin, inMax ) );
}
float mapClamped( float value, float inMin, float inMax, float outMin, float outMax )
{
return mix( outMin, outMax, normalizeToRange01( value, inMin, inMax ) );
}
vec3 applyMatrix( vec3 v, mat4 m )
{
return ( m * vec4( v, 1.0 ) ).xyz;
}
vec3 applyMatrixWithoutTranslation( vec3 v, mat4 m )
{
return ( m * vec4( v, 0.0 ) ).xyz;
}
vec3 applyMatrix( vec3 v, mat3 m )
{
return ( m * v ).xyz;
}
vec3 localToWorld( vec3 local, mat4 _MODEL_MATRIX )
{
return applyMatrix( local, _MODEL_MATRIX );
}
vec3 localToWorldDirection( vec3 local, mat4 _MODEL_MATRIX )
{
return applyMatrixWithoutTranslation( local, _MODEL_MATRIX );
}
vec3 localToView( vec3 local, mat4 _MODELVIEW_MATRIX )
{
return applyMatrix( local, _MODELVIEW_MATRIX );
}
vec3 localToViewDirection( vec3 local, mat4 _MODELVIEW_MATRIX )
{
return applyMatrixWithoutTranslation( local, _MODELVIEW_MATRIX );
}
vec3 localToViewDirection( vec3 local, mat3 _MODELVIEW_NORMAL_MATRIX )
{
return applyMatrix( local, _MODELVIEW_NORMAL_MATRIX );
}
vec3 worldToLocal( vec3 world, mat4 _MODEL_MATRIX )
{
mat4 inversedMatrix = inverse( _MODEL_MATRIX );
return applyMatrix( world, inversedMatrix );
}
vec3 worldToLocalDirection( vec3 world, mat4 _MODEL_MATRIX )
{
mat4 inversedMatrix = inverse( _MODEL_MATRIX );
return applyMatrixWithoutTranslation( world, inversedMatrix );
}
vec3 worldToView( vec3 world, mat4 _VIEW_MATRIX )
{
return applyMatrix( world, _VIEW_MATRIX );
}
vec3 worldToViewDirection( vec3 worldDirection, mat4 _VIEW_MATRIX )
{
return applyMatrixWithoutTranslation( worldDirection, _VIEW_MATRIX );
}
vec3 viewToWorld( vec3 view, mat4 _INV_VIEW_MATRIX )
{
return applyMatrix( view, _INV_VIEW_MATRIX );
}
vec3 viewToWorldDirection( vec3 viewDirection, mat4 _INV_VIEW_MATRIX )
{
return applyMatrixWithoutTranslation( viewDirection, _INV_VIEW_MATRIX );
}
vec3 viewToLocal( vec3 view, mat4 _INV_VIEW_MATRIX, mat4 _MODEL_MATRIX )
{
vec3 world = viewToWorld( view, _INV_VIEW_MATRIX );
return worldToLocal( world, _MODEL_MATRIX );
}
vec3 viewToLocal( vec3 view, mat4 _MODELVIEW_MATRIX )
{
mat4 inversedMatrix = inverse( _MODELVIEW_MATRIX );
return applyMatrix( view, inversedMatrix );
}
vec3 viewToLocalDirection( vec3 viewDirection, mat4 _MODELVIEW_MATRIX )
{
mat4 inversedMatrix = inverse( _MODELVIEW_MATRIX );
return applyMatrixWithoutTranslation( viewDirection, inversedMatrix );
}
vec3 viewToLocalDirection( vec3 view, mat4 _INV_VIEW_MATRIX, mat4 _MODEL_MATRIX )
{
vec3 world = viewToWorldDirection( view, _INV_VIEW_MATRIX );
return worldToLocalDirection( world, _MODEL_MATRIX );
}
vec4 viewToClip( vec3 view, mat4 _PROJECTION_MATRIX )
{
vec4 clip = _PROJECTION_MATRIX * vec4( view, 1.0 );
clip /= clip.w;
return clip;
}
vec2 clipToScreen( vec4 clip )
{
return ( clip.xy / clip.w ) * 0.5 + vec2( 0.5 );
}
vec4 screenToClip( vec2 screen, float z )
{
return vec4( screen * 2.0 - 1.0, z, 1.0 );
}
vec4 clipToView( vec4 clip, mat4 _INV_PROJECTION_MATRIX )
{
vec4 view = _INV_PROJECTION_MATRIX * clip;
view /= view.w;
return view;
}
vec4 screenToView( vec2 screen, float z, mat4 _INV_PROJECTION_MATRIX )
{
vec4 clip = screenToClip( screen, z );
vec4 view = clipToView( clip, _INV_PROJECTION_MATRIX );
return view;
}
vec3 screenToWorld( vec2 screen, float z, mat4 _INV_PROJECTION_MATRIX, mat4 _INV_VIEW_MATRIX )
{
vec4 view = screenToView( screen, z, _INV_PROJECTION_MATRIX );
return viewToWorld( view.xyz, _INV_VIEW_MATRIX );
}
vec3 screenToLocal( vec2 screen_point, float z, mat4 _PROJECTION_MATRIX, mat4 _VIEW_MATRIX, mat4 _MODEL_MATRIX )
{
vec4 clip = vec4( screen_point * 2.0 - 1.0, z, 1.0 );
vec4 view4 = inverse( _PROJECTION_MATRIX ) * clip;
view4 /= view4.w;
vec3 view = view4.xyz;
mat4 m = inverse( _VIEW_MATRIX * _MODEL_MATRIX );
return ( m * vec4( view, 1.0 ) ).xyz;
}
vec2 viewToScreen( vec3 view, mat4 _PROJECTION_MATRIX )
{
vec4 clip = viewToClip( view, _PROJECTION_MATRIX );
return clipToScreen( clip );
}
vec2 localToScreen( vec3 local, mat4 _MODELVIEW_MATRIX, mat4 _PROJECTION_MATRIX )
{
vec3 view = localToView( local, _MODELVIEW_MATRIX );
return viewToScreen( view, _PROJECTION_MATRIX );
}
vec2 worldToScreen( vec3 world, mat4 _VIEW_MATRIX, mat4 _PROJECTION_MATRIX )
{
vec3 view = worldToView( world, _VIEW_MATRIX );
vec4 clip = viewToClip( view, _PROJECTION_MATRIX );
vec2 screen = clipToScreen( clip );
return screen;
}
vec3 extractTranslation( mat4 matrix )
{
return vec3( matrix[ 3 ][ 0 ], matrix[ 3 ][ 1 ], matrix[ 3 ][ 2 ] );
}
vec3 extractScale( mat3 matrix )
{
mat3 m = matrix;
float x = length( vec3( m[ 0 ][ 0 ], m[ 1 ][ 0 ], m[ 2 ][ 0 ] ) );
float y = length( vec3( m[ 0 ][ 1 ], m[ 1 ][ 1 ], m[ 2 ][ 1 ] ) );
float z = length( vec3( m[ 0 ][ 2 ], m[ 1 ][ 2 ], m[ 2 ][ 2 ] ) );
return vec3( x, y, z );
}
vec3 extractScale( mat4 matrix )
{
mat4 m = matrix;
float x = length( vec3( m[ 0 ][ 0 ], m[ 1 ][ 0 ], m[ 2 ][ 0 ] ) );
float y = length( vec3( m[ 0 ][ 1 ], m[ 1 ][ 1 ], m[ 2 ][ 1 ] ) );
float z = length( vec3( m[ 0 ][ 2 ], m[ 1 ][ 2 ], m[ 2 ][ 2 ] ) );
return vec3( x, y, z );
}
mat3 extractRotationMatrix( mat4 m )
{
vec3 x = normalize( m[ 0 ].xyz );
vec3 y = normalize( m[ 1 ].xyz );
vec3 z = normalize( m[ 2 ].xyz );
return mat3( x, y, z );
}
vec3 SRGBtoLINEAR( vec3 sRGB )
{
return mix( pow( (sRGB + vec3( 0.055 )) * ( 1.0 / ( 1.0 + 0.055 )),vec3( 2.4 )),sRGB * ( 1.0 / 12.92 ),lessThan( sRGB,vec3( 0.04045 )) );
}
vec4 SRGBtoLINEAR( vec4 sRGB )
{
return vec4( SRGBtoLINEAR( sRGB.rgb ), sRGB.a );
}
layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in;
layout( rgba16, set = 0, binding = 0 )
uniform image2D inputImage;
layout( rgba16, set = 1, binding = 0 )
uniform restrict writeonly image2D outputImage;
layout( set = 2, binding = 0 )
uniform sampler2D depthSampler;
layout( set = 3, binding = 0 )
uniform sampler2D gradientSampler;
layout( set = 4, binding = 0 )
uniform sampler2D opacitySampler;
layout( push_constant, std430 )
uniform Parameters
{
vec4 m0;
vec4 m1;
vec4 m2;
vec4 m3;
float amount;
float zSpread;
float zStart;
float zEnd;
float gradientUVScale;
float gradientUVOffset;
float p0;
float p1;
} parameters;
float getZ( vec2 uv, float depth, mat4 INV_PROJ )
{
vec4 position = screenToView( uv, depth, INV_PROJ );
return max( 0.0, -position.z );
}
void main()
{
ivec2 size = imageSize( outputImage );
ivec2 xy = ivec2( gl_GlobalInvocationID.xy );
if ( any( greaterThanEqual( xy, size ) ) )
{
return;
}
vec2 uv = ( vec2( xy ) + vec2( 0.5 ) ) / vec2( size );
mat4 INV_PROJ = mat4( parameters.m0, parameters.m1, parameters.m2, parameters.m3 );
float depth = texture( depthSampler, uv ).r;
float z = getZ( uv, depth, INV_PROJ );
float mappedZ = normalizeToRange01( z, parameters.zStart, parameters.zEnd );
mappedZ = pow( mappedZ, parameters.zSpread );
vec2 gradientUV = vec2( mappedZ * parameters.gradientUVScale + parameters.gradientUVOffset, 0.0 );
gradientUV.x = fract( gradientUV.x );
vec4 gradientColor = SRGBtoLINEAR( textureLod( gradientSampler, gradientUV, 0 ) );
vec4 opacity = textureLod( opacitySampler, vec2( mappedZ, 0.0 ), 0 );
gradientColor.a *= opacity.r;
vec4 color = imageLoad( inputImage, xy );
color = mix( color, vec4( gradientColor.rgb, color.a ), gradientColor.a * parameters.amount );
imageStore( outputImage, xy, color );
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://57k6v5nde7nt"
path="res://.godot/imported/GradientFog.glsl-c786da44a43475e54892406d1370a236.res"
[deps]
source_file="res://addons/rokojori_action_library/Runtime/Rendering/RenderGraph/Nodes/Processors/Fog/GradientFog/GradientFog.glsl"
dest_files=["res://.godot/imported/GradientFog.glsl-c786da44a43475e54892406d1370a236.res"]
[params]

View File

@ -0,0 +1,17 @@
using Godot;
using System.Collections.Generic;
namespace Rokojori
{
public class RG_GradientFog:RG_ImageProcessor
{
public static readonly string shaderPath =
RDGraph.Path( "Nodes/Processors/Fog/GradientFog/GradientFog.glsl" );
public RG_GradientFog( RDGraph graph ):base( graph, shaderPath )
{}
}
}

View File

@ -0,0 +1 @@
uid://dyoo2wrv34ods