diff options
Diffstat (limited to 'servers/visual/rasterizer/shaders')
-rw-r--r-- | servers/visual/rasterizer/shaders/SCsub | 6 | ||||
-rw-r--r-- | servers/visual/rasterizer/shaders/canvas.glsl | 372 | ||||
-rw-r--r-- | servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl | 84 |
3 files changed, 462 insertions, 0 deletions
diff --git a/servers/visual/rasterizer/shaders/SCsub b/servers/visual/rasterizer/shaders/SCsub new file mode 100644 index 0000000000..62a4c2a0ba --- /dev/null +++ b/servers/visual/rasterizer/shaders/SCsub @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +Import('env') + +if 'RD_GLSL' in env['BUILDERS']: + env.RD_GLSL('canvas.glsl'); diff --git a/servers/visual/rasterizer/shaders/canvas.glsl b/servers/visual/rasterizer/shaders/canvas.glsl new file mode 100644 index 0000000000..67d6ab9d78 --- /dev/null +++ b/servers/visual/rasterizer/shaders/canvas.glsl @@ -0,0 +1,372 @@ +/* clang-format off */ +[vertex] +/* clang-format on */ + +#version 450 + +/* clang-format off */ +VERSION_DEFINES +/* clang-format on */ + +#ifdef USE_VERTEX_ARRAYS +layout(location = 0) in vec2 vertex_attrib; +layout(location = 3) in vec4 color_attrib; +layout(location = 4) in vec2 uv_attrib; + +layout(location = 6) in uvec4 bone_indices_attrib; +layout(location = 7) in vec4 bone_weights_attrib; +#endif + +#include "canvas_uniforms_inc.glsl" + + +layout(location=0) out vec2 uv_interp; +layout(location=1) out vec4 color_interp; + +#ifdef USE_NINEPATCH + +layout(location=3) out vec2 pixel_size_interp; + +#endif + +/* clang-format off */ +MATERIAL_UNIFORMS +/* clang-format on */ + + +/* clang-format off */ +VERTEX_SHADER_GLOBALS +/* clang-format on */ + + +void main() { + + vec4 instance_custom = vec4(0.0); + +#ifdef USE_VERTEX_ARRAYS + + vec2 vertex = vertex_attrib; + vec4 color = color_attrib; + vec2 uv = uv_attrib; + uvec4 bone_indices = bone_indices_attrib; + vec4 bone_weights = bone_weights_attrib; +#else + + vec2 vertex_base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0)); + vec2 vertex_base = vertex_base_arr[gl_VertexIndex]; + + vec2 uv = draw_data.src_rect.xy + draw_data.src_rect.zw * ((draw_data.flags&FLAGS_TRANSPOSE_RECT)!=0 ? vertex_base.xy : vertex_base.yx); + vec4 color = vec4(1.0); + vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0))); + uvec4 bone_indices = uvec4(0,0,0,0); + vec4 bone_weights = vec4(0,0,0,0); + +#endif + + mat4 world_matrix = mat4(draw_data.world[0],draw_data.world[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0)); +#if 0 + if (draw_data.flags&FLAGS_INSTANCING_ENABLED) { + + uint offset = draw_data.flags&FLAGS_INSTANCING_STRIDE_MASK; + offset *= gl_InstanceIndex; + mat4 instance_xform = mat4( + vec4( texelFetch(instancing_buffer,offset+0),texelFetch(instancing_buffer,offset+1),0.0,texelFetch(instancing_buffer,offset+3) ), + vec4( texelFetch(instancing_buffer,offset+4),texelFetch(instancing_buffer,offset+5),0.0,texelFetch(instancing_buffer,offset+7) ), + vec4( 0.0,0.0,1.0,0.0), + vec4( 0.0,0.0,0.0,1.0 ) ); + offset+=8; + if ( draw_data.flags&FLAGS_INSTANCING_HAS_COLORS ) { + vec4 instance_color; + if (draw_data.flags&FLAGS_INSTANCING_COLOR_8_BIT ) { + uint bits = floatBitsToUint(texelFetch(instancing_buffer,offset)); + instance_color = unpackUnorm4x8(bits); + offset+=1; + } else { + instance_color = vec4(texelFetch(instancing_buffer,offset+0),texelFetch(instancing_buffer,offset+1),texelFetch(instancing_buffer,offset+2),texelFetch(instancing_buffer,offset+3)); + offser+=4; + } + + color*=instance_color; + } + if ( draw_data.flags&FLAGS_INSTANCING_HAS_CUSTOM_DATA ) { + if (draw_data.flags&FLAGS_INSTANCING_CUSTOM_DATA_8_BIT ) { + uint bits = floatBitsToUint(texelFetch(instancing_buffer,offset)); + instance_custom = unpackUnorm4x8(bits); + } else { + instance_custom = vec4(texelFetch(instancing_buffer,offset+0),texelFetch(instancing_buffer,offset+1),texelFetch(instancing_buffer,offset+2),texelFetch(instancing_buffer,offset+3)); + } + } + + } + +#endif + + if (bool(draw_data.flags&FLAGS_USING_PARTICLES)) { + //scale by texture size + vertex /= draw_data.color_texture_pixel_size; + } +#ifdef USE_POINT_SIZE + float point_size = 1.0; +#endif + { + /* clang-format off */ +VERTEX_SHADER_CODE + /* clang-format on */ + } + + + +#ifdef USE_NINEPATCH + pixel_size_interp = abs(draw_data.dst_rect.zw) * vertex; +#endif + +#if !defined(SKIP_TRANSFORM_USED) + vertex = (world_matrix * vec4(vertex,0.0,1.0)).xy; +#endif + + color_interp = color; + + if (bool(draw_data.flags&FLAGS_USE_PIXEL_SNAP)) { + + vertex = floor(vertex + 0.5); + // precision issue on some hardware creates artifacts within texture + // offset uv by a small amount to avoid + uv += 1e-5; + } + +#if 0 + if (bool(draw_data.flags&FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone + //skeleton transform + + ivec4 bone_indicesi = ivec4(bone_indices); + + uvec2 tex_ofs = bone_indicesi.x *2; + + mat2x4 m; + m = mat2x4( + texelFetch(skeleton_buffer, tex_ofs+0), + texelFetch(skeleton_buffer, tex_ofs+1) ) * + bone_weights.x; + + tex_ofs = bone_indicesi.y * 2; + + m += mat2x4( + texelFetch(skeleton_buffer, tex_ofs+0), + texelFetch(skeleton_buffer, tex_ofs+1) ) * + bone_weights.y; + + tex_ofs = bone_indicesi.z * 2; + + m += mat2x4( + texelFetch(skeleton_buffer, tex_ofs+0), + texelFetch(skeleton_buffer, tex_ofs+1) ) * + bone_weights.z; + + tex_ofs = bone_indicesi.w * 2; + + m += mat2x4( + texelFetch(skeleton_buffer, tex_ofs+0), + texelFetch(skeleton_buffer, tex_ofs+1) ) * + bone_weights.w; + + mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse; + + //outvec = bone_matrix * outvec; + } +#endif + +#if !defined(SKIP_TRANSFORM_USED) + gl_Position = (canvas_data.screen_transform * canvas_data.canvas_transform) * vec4(vertex,0.0,1.0); +#else + gl_Position = vec4(vertex,0.0,1.0); +#endif + +#ifdef USE_POINT_SIZE + gl_PointSize=point_size; +#endif + +} + +/* clang-format off */ +[fragment] + +#version 450 + +/* clang-format off */ +VERSION_DEFINES +/* clang-format on */ + +#include "canvas_uniforms_inc.glsl" + +layout(location=0) in vec2 uv_interp; +layout(location=1) in vec4 color_interp; + +#ifdef USE_NINEPATCH + +layout(location=3) in vec2 pixel_size_interp; + +#endif + +layout(location = 0) out vec4 frag_color; + +/* clang-format off */ +MATERIAL_UNIFORMS +/* clang-format on */ + + +/* clang-format off */ +FRAGMENT_SHADER_GLOBALS +/* clang-format on */ + + +void light_compute( + inout vec4 light, + inout vec2 light_vec, + inout float light_height, + inout vec4 light_color, + vec2 light_uv, + inout vec4 shadow_color, + vec3 normal, + vec2 uv, + vec2 screen_uv, + vec4 color) { + + /* clang-format off */ +LIGHT_SHADER_CODE + /* clang-format on */ +} + + +#ifdef USE_NINEPATCH + +float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) { + + float tex_size = 1.0 / tex_pixel_size; + + if (pixel < margin_begin) { + return pixel * tex_pixel_size; + } else if (pixel >= draw_size - margin_end) { + return (tex_size - (draw_size - pixel)) * tex_pixel_size; + } else { + if (!bool(draw_data.flags&FLAGS_NINEPACH_DRAW_CENTER)) { + draw_center--; + } + + if (np_repeat == 0) { //stretch + //convert to ratio + float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end); + //scale to source texture + return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size; + } else if (np_repeat == 1) { //tile + //convert to ratio + float ofs = mod((pixel - margin_begin), tex_size - margin_begin - margin_end); + //scale to source texture + return (margin_begin + ofs) * tex_pixel_size; + } else if (np_repeat == 2) { //tile fit + //convert to ratio + float src_area = draw_size - margin_begin - margin_end; + float dst_area = tex_size - margin_begin - margin_end; + float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5)); + + //convert to ratio + float ratio = (pixel - margin_begin) / src_area; + ratio = mod(ratio * scale, 1.0); + return (margin_begin + ratio * dst_area) * tex_pixel_size; + } + } +} + + +#endif + +void main() { + + vec4 color = color_interp; + vec2 uv = uv_interp; + +#ifdef USE_TEXTURE_RECT + +#ifdef USE_NINEPATCH + + int draw_center = 2; + uv = vec2( + map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, (draw_data.ninepatch_repeat>>16), draw_center), + map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, (draw_data.ninepatch_repeat&0xFFFF), draw_center)); + + if (draw_center == 0) { + color.a = 0.0; + } + + uv = uv * draw_data.src_rect.zw + draw_data.src_rect.xy; //apply region if needed +#endif + + if (bool(draw_data.flags&FLAGS_CLIP_RECT_UV)) { + + uv = clamp(uv, draw_data.src_rect.xy, draw_data.src_rect.xy + abs(draw_data.src_rect.zw)); + } + +#endif + +#if !defined(COLOR_USED) + //default behavior, texture by color + + color *= texture(sampler2D(color_texture,texture_sampler), uv); + +#endif + + + + vec3 normal; + +#if defined(NORMAL_USED) + + bool normal_used = true; +#else + bool normal_used = false; +#endif + +#if 0 + if (false /*normal_used || canvas_data.light_count > 0*/ ) { + normal.xy = texture(sampler2D(normal_texture,texture_sampler ), uv).xy * 2.0 - 1.0; + normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); + normal_used = true; + } else { +#endif + normal = vec3(0.0, 0.0, 1.0); +#if 0 + } +#endif + +#if defined(SCREEN_UV_USED) + vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; +#endif + + { + float normal_depth = 1.0; + +#if defined(NORMALMAP_USED) + vec3 normal_map = vec3(0.0, 0.0, 1.0); + normal_used = true; +#endif + + /* clang-format off */ + +FRAGMENT_SHADER_CODE + + /* clang-format on */ + +#if defined(NORMALMAP_USED) + normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth); +#endif + } + + color *= draw_data.modulation; +#if 0 + if (canvas_data.light_count > 0 ) { + //do lighting + + } +#endif + //color.rgb *= color.a; + frag_color = color; +} diff --git a/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl b/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl new file mode 100644 index 0000000000..51769bbdc3 --- /dev/null +++ b/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl @@ -0,0 +1,84 @@ + +/* SET0: Per draw primitive settings */ + + +#define MAX_LIGHTS 128 + +#define FLAGS_INSTANCING_STRIDE_MASK 0xF +#define FLAGS_INSTANCING_ENABLED (1<<4) +#define FLAGS_INSTANCING_HAS_COLORS (1 << 5) +#define FLAGS_INSTANCING_COLOR_8BIT (1 << 6) +#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 7) +#define FLAGS_INSTANCING_CUSTOM_DATA_8_BIT (1 << 8) + +#define FLAGS_CLIP_RECT_UV (1 << 9) +#define FLAGS_TRANSPOSE_RECT (1 << 10) +#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12) +#define FLAGS_USING_PARTICLES (1 << 13) +#define FLAGS_USE_PIXEL_SNAP (1 << 14) + +#define FLAGS_USE_SKELETON (1 << 16) + +layout(push_constant, binding = 0, std140) uniform DrawData { + mat2x4 world; + vec4 modulation; + vec4 ninepatch_margins; + vec4 dst_rect; //for built-in rect and UV + vec4 src_rect; + uint flags; + uint ninepatch_repeat; + vec2 color_texture_pixel_size; +} draw_data; + +// The values passed per draw primitives are cached within it + +layout(set = 0, binding = 1) uniform texture2D color_texture; +layout(set = 0, binding = 2) uniform texture2D normal_texture; +layout(set = 0, binding = 3) uniform texture2D specular_texture; +layout(set = 0, binding = 4) uniform sampler texture_sampler; + +layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer; + +/* SET1: Is reserved for the material */ + +// + +/* SET2: Per Canvas Item Settings */ + +layout(set = 1, binding = 1) uniform textureBuffer skeleton_buffer; + +layout(set = 1, binding = 2, std140) uniform SkeletonData { + mat4 skeleton_transform; + mat4 skeleton_transform_inverse; +} skeleton_data; + +// this set (set 2) is also used for instance specific uniforms + +/* SET3: Per Scene settings */ + +layout(set = 3, binding = 0, std140) uniform CanvasData { + mat4 canvas_transform; + mat4 screen_transform; + //uint light_count; +} canvas_data; + +struct Light { + // light matrices + mat4 light_matrix; + mat4 light_local_matrix; + mat4 shadow_matrix; + vec4 light_color; + vec4 light_shadow_color; + vec2 light_pos; + float shadowpixel_size; + float shadow_gradient; + float light_height; + float light_outside_alpha; + float shadow_distance_mult; +}; + +layout(set = 3, binding = 1, std140) uniform LightData { + Light lights[MAX_LIGHTS]; +} light_data; + +layout(set = 3, binding = 2) uniform texture2D light_textures[MAX_LIGHTS]; |