rokojori_action_library/Runtime/Procedural/HeightMaps/Shaders/HeightMapShapeMaterial.cs

163 lines
7.8 KiB
C#
Raw Normal View History

using Godot;
using System;
using Rokojori.Extensions;
namespace Rokojori
{
/** Which primitive HeightMapShape.gdshader draws.
Int values are switched on in the shader - do not renumber.
*/
public enum HeightMapShapeType
{
Circle = 0,
Image = 1
}
public class HeightMapShapeShader
{
public static readonly CachedResource<Shader> shader = new CachedResource<Shader>(
"res://addons/rokojori_action_library/Runtime/Procedural/HeightMaps/Shaders/HeightMapShape.gdshader"
);
public static readonly Vector2PropertyName rectWorldMin = Vector2PropertyName.Create( "shape_rect_world_min" );
public static readonly Vector2PropertyName rectWorldSize = Vector2PropertyName.Create( "shape_rect_world_size" );
public static readonly IntPropertyName shapeType = IntPropertyName.Create( "shape_type" );
public static readonly IntPropertyName blendMode = IntPropertyName.Create( "shape_blend_mode" );
public static readonly FloatPropertyName valueBase = FloatPropertyName.Create( "shape_value_base" );
public static readonly FloatPropertyName valueScale = FloatPropertyName.Create( "shape_value_scale" );
public static readonly Vector2PropertyName center = Vector2PropertyName.Create( "shape_center" );
public static readonly FloatPropertyName innerRadius = FloatPropertyName.Create( "shape_inner_radius" );
public static readonly FloatPropertyName outerRadius = FloatPropertyName.Create( "shape_outer_radius" );
public static readonly BoolPropertyName smoothFalloff = BoolPropertyName.Create( "shape_smooth_falloff" );
public static readonly Vector2PropertyName axisX = Vector2PropertyName.Create( "shape_axis_x" );
public static readonly Vector2PropertyName axisZ = Vector2PropertyName.Create( "shape_axis_z" );
public static readonly Vector2PropertyName imageSize = Vector2PropertyName.Create( "shape_size" );
public static readonly IntPropertyName imageChannel = IntPropertyName.Create( "shape_image_channel" );
public static readonly BoolPropertyName imageTiling = BoolPropertyName.Create( "shape_image_tiling" );
public static readonly IntPropertyName maskChannel = IntPropertyName.Create( "shape_mask_channel" );
public static readonly Vector2PropertyName maskCenter = Vector2PropertyName.Create( "shape_mask_center" );
public static readonly Vector2PropertyName maskAxisX = Vector2PropertyName.Create( "shape_mask_axis_x" );
public static readonly Vector2PropertyName maskAxisZ = Vector2PropertyName.Create( "shape_mask_axis_z" );
public static readonly Vector2PropertyName maskSize = Vector2PropertyName.Create( "shape_mask_size" );
}
/** Material for HeightMapShape.gdshader.
One instance per HeightMapGenerator, re-set per layer. The TextureStack's
session-2 live test already proved that re-setting a shared blit material
between queued blits is safe - the earlier blits do not pick up the later
values - which is why every layer can share one material instead of
allocating its own.
The image texture is <marked>not</marked> a property here: it arrives as
the blit's source, which is what hint_blit_source0 binds to.
*/
[Tool]
public partial class HeightMapShapeMaterial:CustomMaterial
{
public readonly CustomMaterialProperty<Vector2> rectWorldMin;
public readonly CustomMaterialProperty<Vector2> rectWorldSize;
public readonly CustomMaterialProperty<int> shapeType;
public readonly CustomMaterialProperty<int> blendMode;
public readonly CustomMaterialProperty<float> valueBase;
public readonly CustomMaterialProperty<float> valueScale;
public readonly CustomMaterialProperty<Vector2> center;
public readonly CustomMaterialProperty<float> innerRadius;
public readonly CustomMaterialProperty<float> outerRadius;
public readonly CustomMaterialProperty<bool> smoothFalloff;
public readonly CustomMaterialProperty<Vector2> axisX;
public readonly CustomMaterialProperty<Vector2> axisZ;
public readonly CustomMaterialProperty<Vector2> imageSize;
public readonly CustomMaterialProperty<int> imageChannel;
public readonly CustomMaterialProperty<bool> imageTiling;
public readonly CustomMaterialProperty<int> maskChannel;
public readonly CustomMaterialProperty<Vector2> maskCenter;
public readonly CustomMaterialProperty<Vector2> maskAxisX;
public readonly CustomMaterialProperty<Vector2> maskAxisZ;
public readonly CustomMaterialProperty<Vector2> maskSize;
public HeightMapShapeMaterial()
{
Shader = HeightMapShapeShader.shader.Get();
rectWorldMin = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.rectWorldMin );
rectWorldSize = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.rectWorldSize );
shapeType = new CustomMaterialProperty<int>( this, HeightMapShapeShader.shapeType );
blendMode = new CustomMaterialProperty<int>( this, HeightMapShapeShader.blendMode );
valueBase = new CustomMaterialProperty<float>( this, HeightMapShapeShader.valueBase );
valueScale = new CustomMaterialProperty<float>( this, HeightMapShapeShader.valueScale );
center = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.center );
innerRadius = new CustomMaterialProperty<float>( this, HeightMapShapeShader.innerRadius );
outerRadius = new CustomMaterialProperty<float>( this, HeightMapShapeShader.outerRadius );
smoothFalloff = new CustomMaterialProperty<bool>( this, HeightMapShapeShader.smoothFalloff );
axisX = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.axisX );
axisZ = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.axisZ );
imageSize = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.imageSize );
imageChannel = new CustomMaterialProperty<int>( this, HeightMapShapeShader.imageChannel );
imageTiling = new CustomMaterialProperty<bool>( this, HeightMapShapeShader.imageTiling );
maskChannel = new CustomMaterialProperty<int>( this, HeightMapShapeShader.maskChannel );
maskCenter = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.maskCenter );
maskAxisX = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.maskAxisX );
maskAxisZ = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.maskAxisZ );
maskSize = new CustomMaterialProperty<Vector2>( this, HeightMapShapeShader.maskSize );
}
/** The mask rect, for a layer that has no opinion about it: anything the
mask's own rect does not cover takes its border value, so a 1x1 rect
centered on the shape is a flat multiplier over the whole shape.
*/
public void SetMaskRect( Vector2 center, Vector2 axisX, Vector2 axisZ, Vector2 size )
{
maskCenter.Set( center );
maskAxisX.Set( axisX );
maskAxisZ.Set( axisZ );
maskSize.Set( size );
}
/** Back to a shape that contributes nothing, so a layer that only sets some
of the uniforms does not inherit the previous layer's.
The rect uniforms are deliberately not reset - HeightMapGenerator.DrawShape
owns those and sets them after the layer has configured the shape.
*/
public void Reset()
{
shapeType.Set( (int) HeightMapShapeType.Circle );
blendMode.Set( (int) HeightMapBlendMode.Add );
valueBase.Set( 0 );
valueScale.Set( 0 );
center.Set( Vector2.Zero );
innerRadius.Set( 0 );
outerRadius.Set( 0 );
smoothFalloff.Set( true );
axisX.Set( new Vector2( 1, 0 ) );
axisZ.Set( new Vector2( 0, 1 ) );
imageSize.Set( Vector2.One );
imageChannel.Set( (int) HeightMapChannel.R );
imageTiling.Set( false );
maskChannel.Set( (int) HeightMapChannel.A );
SetMaskRect( Vector2.Zero, new Vector2( 1, 0 ), new Vector2( 0, 1 ), Vector2.One );
}
}
}