GODOT Shader 类似 glsl 语法.
着色器类型 shader_type canvas_item;
处理函数 不同着色器you固定的着色器入口,其中 particles
仅支持 vertex
;
- vertex 定点处理
- fragment 片段处理,根据输入的材质处理
- light 光照处理
渲染模式 不同类型着色器支持模式不同 查看渲染模式
- blend_mix 混合混合模式(alpha是透明度),默认.
- unshaded 结果只是反照率。 材质中不会发生照明/阴影。
- cull_disabled
语法 查看支持的类型
一些常用类型
- vec2, vec3, vec4, float
- sampler2D 2d材质
- sampler3D 3d材质
uniform float some_value;
在 gdscript 中可以调用,来设置参数,以来变动效果。
material.set_shader_param("some_value", some_value)
能量盾 Space Marine Shield
shader_type spatial;
render_mode unshaded, cull_back;
uniform float rimWidth : hint_range(1.0, 3.0) = 2.0;
uniform vec4 rimColor : hint_color;
uniform vec4 outerRimColor : hint_color;
uniform sampler2D normalMap : hint_normal;
uniform float normalStrength : hint_range(0.0, 1.0);
uniform vec2 normalTiling = vec2(1.0, 1.0);
uniform vec2 normalOffset = vec2(0.0, 0.0);
void fragment(){
vec2 uvModifier = (texture(normalMap, (UV * normalTiling) + (normalOffset * TIME)).xy * normalStrength) - normalStrength * 0.5;
vec3 color = texture(SCREEN_TEXTURE, SCREEN_UV + uvModifier).rgb;
float rim = 1.0 - abs(dot(VIEW, NORMAL));
float outerRim = pow(rim, 4.0);
rim = pow(rim, rimWidth);
color = color + rim * rimColor.rgb;
color = color + outerRim * outerRimColor.rgb;
ALBEDO = color;
}
dancing
参数:
- Time Factor (float) 时间 2
- Amplitude (Vec2) 振幅 10,10
shader_type canvas_item;
uniform float time_factor = 2;
uniform vec2 amplitude = vec2(10, 10);
void vertex() {
VERTEX.x += sin(TIME * time_factor) * amplitude.x;
VERTEX.y += cos(TIME * time_factor) * amplitude.y;
}
water01 水波纹
shader_type canvas_item;
uniform float initialize = 0.0;
void fragment()
{
// GET THE HEIGHT AND VELOCITY OF THIS UV
float h = texture( SCREEN_TEXTURE, SCREEN_UV ).r - 0.5;
float v = texture( SCREEN_TEXTURE, SCREEN_UV ).g - 0.5;
// COMPUTE NEW VELOCITY AND HEIGHT
vec2 ps = SCREEN_PIXEL_SIZE;
v -= 0.1 * h; // velocity of a point depends on the height of that point, to have a spring effect
// velocity of a point also depends on the height of the points around it
v += (
( texture( SCREEN_TEXTURE, SCREEN_UV + vec2( 0, -ps.y ) ).x - 0.5 ) +
( texture( SCREEN_TEXTURE, SCREEN_UV + vec2( 0, ps.y ) ).x - 0.5 ) +
( texture( SCREEN_TEXTURE, SCREEN_UV + vec2( -ps.x, 0 ) ).x - 0.5 ) +
( texture( SCREEN_TEXTURE, SCREEN_UV + vec2( ps.x, 0 ) ).x - 0.5 ) -
4.0 * h ) * 0.2;
v *= 0.98; // Dampen the velocity, otherwise it would oscillate forever
h += v; // change the height with the new velocity - NOT FRAME RATE INDEPENDENT!
// Generate drops
if ( mod( TIME, 1.0 ) < .05 && initialize < 0.5 )
{
vec2 drop_pos = vec2( 0.5 + 0.5 * sin( floor( TIME * 5.0 ) * 20.0 ), 0.5 );
if( length( UV - drop_pos ) < 0.01 )
{
h = -0.5;
}
}
// INITIALIZATION
if( initialize > 0.5 )
{
h *= 0.0;
v *= 0.0;
}
// SET FRAGMENT COLOR BASED ON HEIGHT (RED) AND VELOCITY (GREEN)
COLOR = vec4( h + 0.5, v + 0.5, 0.0, 1.0 );
}
water shadow
水中倒影
shader_type canvas_item;
void fragment()
{
//vec2 uv = UV;
//float r = TEXTURE_PIXEL_SIZE.y / SCREEN_PIXEL_SIZE.y;
//vec2 suv = vec2( SCREEN_UV.x, 1.0-SCREEN_UV.y );
//float mix_ratio = 0.5;
//float vstretch = 1.0;
// compute ration between the screen uv and the texture uv
vec2 tex_to_screen_uv_ratio = SCREEN_PIXEL_SIZE / TEXTURE_PIXEL_SIZE;
// compute UV of the flipped screen
vec2 flipped_screen_uv = vec2( SCREEN_UV.x,
SCREEN_UV.y + 2.0 * UV.y * tex_to_screen_uv_ratio.y );
vec2 suv = vec2( SCREEN_UV.x, SCREEN_UV.y + 2.0 * UV.y * tex_to_screen_uv_ratio.y );
suv.x += 10.0 * SCREEN_PIXEL_SIZE.x * sin( 20.0 * UV.y + TIME ) * UV.y;
vec4 c1 = textureLod( SCREEN_TEXTURE, suv, 0.0 );
//vec4 c2 = textureLod( SCREEN_TEXTURE, SCREEN_UV, 0.0 );
c1 = mix( c1, vec4( 0.1, 0.1, 0.25, 1.0 ), 0.3 );
COLOR = c1;//mix( c1, c2, 0.0 );
}
clock shader
通过遮罩环形显示,显示类似钟表效果。
脚本中控制参数 max_angle
从 0.1
到 0.5 (material.set_shader_param( "max_angle", ang )
)。
shader_type canvas_item;
uniform float max_angle = 0.1;
void fragment()
{
vec2 pos = UV - vec2( 0.5 );
float r = length( pos );
float a = atan( pos.y,pos.x );
float alpha = step( a, ( max_angle - 0.5 ) * 6.28318530718 );
vec4 c = texture( TEXTURE, UV );
COLOR = vec4( c.rgb, c.a * alpha );
}
snow shader
粒子效果
shader_type particles;
float rand_from_seed(inout uint seed) {
int k;
int s = int(seed);
if (s == 0)
s = 305420679;
k = s / 127773;
s = 16807 * (s - k * 127773) - 2836 * k;
if (s < 0)
s += 2147483647;
seed = uint(s);
return float(seed % uint(65536)) / 65535.0;
}
float rand_from_seed_m1_p1(inout uint seed) {
return rand_from_seed(seed) * 2.0 - 1.0;
}
uint hash(uint x) {
x = ((x >> uint(16)) ^ x) * uint(73244475);
x = ((x >> uint(16)) ^ x) * uint(73244475);
x = (x >> uint(16)) ^ x;
return x;
}
float pos2vel_x( float pos0 )
{
float half_block = 32.0;
float pos = mod( pos0, 2.0 * half_block ) - half_block;
float vel = sin( pos / half_block );
return vel;
}
void vertex() {
vec2 Extents = vec2( 320, 0 );
vec2 InitVelXRange = vec2( 5, 20 );
uint base_number = NUMBER;// / uint(trail_divisor);
uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);
if( RESTART )
{
// place particles randomly on top
TRANSFORM[3].x = Extents.x * ( 2.0 * rand_from_seed( alt_seed ) - 1.0 );
TRANSFORM[3].xy += EMISSION_TRANSFORM[3].xy;
VELOCITY.y = InitVelXRange.x + ( InitVelXRange.y - InitVelXRange.x ) * rand_from_seed( alt_seed );// + 3.0 * rand_from_seed( alt_seed );
CUSTOM.w = rand_from_seed( alt_seed ) * 100.0; // random initial phase
//VELOCITY.x = pos2vel_x( TRANSFORM[3].x ) * 20.0;
if( rand_from_seed( alt_seed ) < 0.5 )
{
COLOR = vec4( 0.7254901960784314, 0.7490196078431373, 0.9843137254901961, 1.0 );
}
}
else
{
//VELOCITY.x += 5.0 * ( rand_from_seed( alt_seed ) - 0.5 );
//VELOCITY.x *= 0.9;
VELOCITY.x += 0.2 * cos( ( TRANSFORM[3].y - CUSTOM.w ) * 0.5 );
}
}
cave light
为 light2D 追加摇曳效果
shader_type canvas_item;
void light()
{
vec4 c = texture( TEXTURE, UV ).rgba;
if( c.r > 0.5 || c.b > 0.5 )
{
//LIGHT *= 1.0;
if( LIGHT.a > 0.3 )
{
LIGHT = LIGHT_COLOR;
}
else
{
LIGHT *= 0.0;
}
}
else
{
LIGHT *= 0.0;
}
}
border shader
shader_type canvas_item;
uniform float outline_width = 2.0;
uniform vec4 outline_color: hint_color;
void fragment() {
vec4 col = texture(TEXTURE, UV);
vec2 ps = TEXTURE_PIXEL_SIZE;
float a;
float maxa = col.a;
float mina = col.a;
a = texture(TEXTURE, UV + vec2(0.0, -outline_width) * ps).a;
maxa = max(a, maxa);
mina = min(a, mina);
a = texture(TEXTURE, UV + vec2(0.0, outline_width) * ps).a;
maxa = max(a, maxa);
mina = min(a, mina);
a = texture(TEXTURE, UV + vec2(-outline_width, 0.0) * ps).a;
maxa = max(a, maxa);
mina = min(a, mina);
a = texture(TEXTURE, UV + vec2(outline_width, 0.0) * ps).a;
maxa = max(a, maxa);
mina = min(a, mina);
COLOR = mix(col, outline_color, maxa - mina);
}
shadow
shader_type canvas_item;
render_mode blend_mix;
uniform vec2 offset = vec2(8.0, 8.0);
uniform vec4 modulate : hint_color;
void fragment() {
vec2 ps = TEXTURE_PIXEL_SIZE;
# 偏移处理
vec4 shadow = vec4(modulate.rgb, texture(TEXTURE, UV - offset * ps).a * modulate.a);
vec4 col = texture(TEXTURE, UV);
COLOR = mix(shadow, col, col.a);
}
silhouette 剪影
shader_type canvas_item;
render_mode blend_mix;
uniform vec4 modulate: hint_color;
void fragment() {
# 直接覆盖
COLOR = vec4(modulate.rgb, texture(TEXTURE, UV).a * modulate.a);
}
光效处理
shader_type canvas_item;
// 材质输入
uniform sampler2D emission_teture;
// 色彩输入
uniform vec4 glow_color : hint_color = vec4(1.0);
void fragment()
{
// 精灵当前像素
vec4 current_color = texture(TEXTURE,UV);
// 要覆盖的材质
vec4 emission_color = texture(emission_teture,UV);
// 检查在材质中不是黑色的部分
if(emission_color.r > 0f)
{
// 在当前材质部分追加亮度
COLOR = (emission_color + glow_color)
}
else
{
// 未覆盖的部分默认当前
COLOR = current_color;
}
}