MetaBalls/MetaBalls.gdshader

77 lines
2.3 KiB
Plaintext

shader_type spatial;
uniform vec4 metaBallA;
uniform vec4 metaBallB;
uniform vec4 metaBallC;
uniform vec4 metaBallD;
uniform vec4 metaBallE;
uniform vec4 metaBallF;
uniform float maxReach = 2;
uniform float metaSize = 1;
uniform float maxInfluence = 0.1;
uniform float dotInfluence:hint_range(0.0,1.0) = 0.1;
uniform sampler2D dotInfluenceCurve;
uniform float pointVSdirectionalAttraction:hint_range(0.0,1.0) = 0.5;
uniform sampler2D curve;
vec3 getInfluence( vec3 position, vec3 normal, vec4 metaBall, vec3 ownCenter )
{
vec3 metaPosition = metaBall.xyz;
vec3 centerTowardsMeta = metaPosition - ownCenter;
vec3 direction = length( centerTowardsMeta ) == 0.0 ? vec3( 0, 0, 0 ) : normalize( centerTowardsMeta );
vec3 towardsMeta = position - metaPosition;
float distance = length( towardsMeta );
vec3 directectedMetaPosition = position + direction * distance;
vec3 influencePosition = mix( metaPosition, directectedMetaPosition, pointVSdirectionalAttraction );
float dotProduct = max( 0, dot( normal, normalize( -towardsMeta ) ) );
dotProduct = texture( dotInfluenceCurve, vec2( dotProduct, 0.0 ) ).r;
float sd = distance - metaSize;
sd = sd/maxReach;
sd = clamp( sd, 0.0, 1.0 );
float amount = 1.0 - texture( curve, vec2( sd, 0.0 ) ).r;
vec3 influence = mix( influencePosition, position, amount ) - position;
//influence = vec3( 0, 0, 0 );
return influence * ( mix( 1.0, dotProduct, dotInfluence ) );
}
void vertex()
{
vec3 influence = vec3( 0, 0, 0 );
vec3 worldPosition = ( MODEL_MATRIX * vec4( VERTEX, 1.0 ) ).xyz;
vec3 worldNormal = NORMAL;
vec3 ownCenter = ( MODEL_MATRIX * vec4( 0.00000, 0.00000, 0.00000, 1.0 ) ).xyz;
influence += getInfluence( worldPosition, worldNormal, metaBallA, ownCenter );
influence += getInfluence( worldPosition, worldNormal, metaBallB, ownCenter );
influence += getInfluence( worldPosition, worldNormal, metaBallC, ownCenter );
influence += getInfluence( worldPosition, worldNormal, metaBallD, ownCenter );
influence += getInfluence( worldPosition, worldNormal, metaBallE, ownCenter );
influence += getInfluence( worldPosition, worldNormal, metaBallF, ownCenter );
worldPosition += influence * maxInfluence;
VERTEX = ( inverse( MODEL_MATRIX ) * vec4( worldPosition, 1.0 ) ).xyz;
}
void fragment()
{
}
void light()
{
}