Gradient Fog
This commit is contained in:
parent
338073361f
commit
90d5759d26
|
|
@ -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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://cuaweg0ohqox8
|
||||
|
|
@ -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
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dqgedhwm3die2
|
||||
|
|
@ -16,7 +16,7 @@ script = ExtResource("2_ysy1a")
|
|||
script = ExtResource("3_fp4l4")
|
||||
owner = SubResource("Resource_fy8er")
|
||||
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_i5utj"]
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_ifhyp"]
|
||||
resource_local_to_scene = false
|
||||
resource_name = ""
|
||||
enabled = true
|
||||
|
|
@ -47,7 +47,7 @@ metadata/_custom_type_script = "uid://dvvfvlutisecy"
|
|||
script = ExtResource("3_fp4l4")
|
||||
owner = SubResource("Resource_fy8er")
|
||||
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_gxlxg"]
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_wx28p"]
|
||||
resource_local_to_scene = false
|
||||
resource_name = ""
|
||||
enabled = true
|
||||
|
|
@ -55,7 +55,7 @@ effect_callback_type = 4
|
|||
needs_motion_vectors = false
|
||||
needs_normal_roughness = false
|
||||
script = ExtResource("6_kwewy")
|
||||
amount = 0.05
|
||||
amount = 0.0
|
||||
scale = 5.0619
|
||||
smearingSteps = 5
|
||||
smearing = 1.2095
|
||||
|
|
@ -72,7 +72,7 @@ metadata/_custom_type_script = "uid://cidk0x7sb1pxl"
|
|||
script = ExtResource("3_fp4l4")
|
||||
owner = SubResource("Resource_fy8er")
|
||||
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_ixn1d"]
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_ysy1a"]
|
||||
resource_local_to_scene = false
|
||||
resource_name = ""
|
||||
enabled = true
|
||||
|
|
@ -98,7 +98,7 @@ metadata/_custom_type_script = "uid://b2oxy6ln560ys"
|
|||
script = ExtResource("3_fp4l4")
|
||||
owner = SubResource("Resource_fy8er")
|
||||
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_y3g14"]
|
||||
[sub_resource type="CompositorEffect" id="CompositorEffect_fp4l4"]
|
||||
resource_local_to_scene = false
|
||||
resource_name = ""
|
||||
enabled = true
|
||||
|
|
@ -106,10 +106,11 @@ effect_callback_type = 4
|
|||
needs_motion_vectors = false
|
||||
needs_normal_roughness = false
|
||||
script = ExtResource("7_wx28p")
|
||||
smearingFrames = 10.0
|
||||
compositorEffectID = SubResource("Resource_3tnad")
|
||||
metadata/_custom_type_script = "uid://cowk70ifagygb"
|
||||
|
||||
[resource]
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
||||
|
|
@ -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 )
|
||||
{}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dyoo2wrv34ods
|
||||
Loading…
Reference in New Issue