summaryrefslogtreecommitdiff
path: root/servers/visual/rasterizer/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/rasterizer/shaders')
-rw-r--r--servers/visual/rasterizer/shaders/SCsub6
-rw-r--r--servers/visual/rasterizer/shaders/canvas.glsl372
-rw-r--r--servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl84
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];