rj-action-library/Runtime/Rendering/Assets/Foliage/GPUFoliageShader.gdshader

98 lines
3.5 KiB
Plaintext
Raw Normal View History

2025-07-17 11:50:37 +00:00
shader_type particles;
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc"
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc"
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Textures.gdshaderinc"
uniform vec3 cameraPosition;
uniform float yaw;
uniform float cellSize = 1.0;
uniform int width = 10;
uniform int height = 10;
uniform sampler2D positionVariance;
uniform vec3 maxPositionOffset = vec3(0,0,0);
uniform vec2 positionUVScale = vec2( 1.0, 1.0 );
uniform vec2 positionUVOffset = vec2( 1.0, 1.0 );
uniform float heightOffset = 0;
uniform sampler2D rotationVariance;
uniform vec3 minRotation = vec3( 0, 0, 0 );
uniform vec3 maxRotation = vec3( 0, 1, 0 );
uniform vec2 rotationUVScale = vec2( 1.0, 1.0 );
uniform vec2 rotationUVOffset = vec2( 1.0, 1.0 );
uniform sampler2D scaleVariance;
uniform vec3 minScale = vec3( 1, 1, 1 );
uniform vec3 maxScale = vec3( 1, 1, 1 );
uniform vec2 scaleUVScale = vec2( 1.0, 1.0 );
uniform vec2 scaleUVOffset = vec2( 1.0, 1.0 );
uniform float occupancyAmount = 0;
uniform float occupancyPower = 0;
uniform float occupancyTreshold = 0.5;
uniform float occupancyHideOffset = -3;
uniform float occupancyHideScale = 0.1;
uniform sampler2D occupancyVariance;
uniform vec2 occupancyUVScale = vec2( 1.0, 1.0 );
uniform vec2 occupancyUVOffset = vec2( 1.0, 1.0 );
uniform float hideStart = 40;
uniform float hideMax = 60;
uniform float hideOffset = -0.6;
uniform vec2 mapSize = vec2(1024,1024);
uniform vec2 mapCenter = vec2(0,0);
vec2 indexToPosition( int index )
{
int x = index % width;
int y = index / height;
return vec2( float(x), float(y) );
}
void process()
{
vec2 position = indexToPosition( int(INDEX) );
float rotation = round( 4.0 * yaw / 360.0 ) * PI / 2.0;
vec3 snappedCameraPosition = vec3(
floor( cameraPosition.x / cellSize ) * cellSize,
0,
floor( cameraPosition.z / cellSize ) * cellSize
);
vec2 origin = vec2( float(width)/2.0, float(height)/2.0 );
position -= origin;
position = rotate_v2( position, rotation ) * cellSize;
vec3 position3D = vec3( position.x, heightOffset, position.y ) + snappedCameraPosition;
float d = length( position3D - cameraPosition );
float yOffset = mapClamped( d, hideStart, hideMax, 0, hideOffset );
position3D.y += yOffset;
vec2 mapOffset = mapCenter - mapSize/2.0;
vec2 uv = ( vec2( position3D.x, position3D.z ) - mapOffset ) / mapSize;
vec3 offset = (textureLod( positionVariance, tilingOffset( uv, positionUVScale, positionUVOffset ), 0 ).rgb - vec3(0.5,0.5,0.5) ) * maxPositionOffset;
position3D += offset;
vec3 rotSampled = textureLod( rotationVariance, tilingOffset( uv, rotationUVScale, rotationUVOffset ), 0 ).rgb;
vec3 rot = ( rotSampled * ( maxRotation - minRotation ) + minRotation ) * PI * 2.0;
// rot.y = round( 4.0 * rot.y / PI * 2.0 ) / 4.0 * PI * 2.0;
vec3 sca = textureLod( scaleVariance, tilingOffset( uv, scaleUVScale, scaleUVOffset ), 0 ).rgb;
sca = sca * ( maxScale - minScale ) + minScale;
vec2 uv2 = ( vec2( position3D.x, position3D.z ) - mapOffset ) / mapSize;
float occ = textureLod( occupancyVariance, tilingOffset( uv2, occupancyUVScale, occupancyUVOffset ), 0 ).r;
occ = clamp( ( occ - occupancyTreshold ) * occupancyPower + occupancyTreshold, 0.0, 1.0 );
sca *= mix( 1.0, occupancyHideScale , ( 1.0 - occ ) * occupancyAmount );
position3D.y += ( 1.0 - occ ) * occupancyAmount * occupancyHideOffset;
TRANSFORM = TRS( position3D, rot, vec3( sca.x , sca.y, sca.z ) );
}