From 385645fbfa29174af08ac1ad7f14fd8e50600210 Mon Sep 17 00:00:00 2001 From: Giwayume Date: Wed, 27 Dec 2023 15:58:50 -0500 Subject: [PATCH] Add custom shader attributes to Canvas Item Shaders Add custom attrs to canvas item visual shader editor --- drivers/gles3/rasterizer_canvas_gles3.cpp | 12 +++--- drivers/gles3/shaders/canvas.glsl | 42 ++++++++++++++----- drivers/gles3/storage/material_storage.cpp | 9 ++++ .../plugins/visual_shader_editor_plugin.cpp | 4 ++ scene/resources/visual_shader.cpp | 4 ++ .../renderer_rd/renderer_canvas_render_rd.cpp | 9 ++++ .../rendering/renderer_rd/shaders/canvas.glsl | 41 +++++++++++++++++- servers/rendering/shader_types.cpp | 4 ++ 8 files changed, 106 insertions(+), 19 deletions(-) diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 5d6cef6e056bae..088045c7066795 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1412,7 +1412,7 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index, Ren GLuint vertex_array_gl = 0; GLuint index_array_gl = 0; - uint64_t input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_COLOR | RS::ARRAY_FORMAT_TEX_UV; // 2D meshes always use the same vertex format. + uint64_t input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_COLOR | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_CUSTOM0 | RS::ARRAY_FORMAT_CUSTOM1; // We could inspect materials to figure this out, but is it worth it? if (mesh_instance.is_valid()) { mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array_gl); } else { @@ -1539,15 +1539,15 @@ void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken) { } void RasterizerCanvasGLES3::_enable_attributes(uint32_t p_start, bool p_primitive, uint32_t p_rate) { - uint32_t split = p_primitive ? 11 : 12; - for (uint32_t i = 6; i < split; i++) { + uint32_t split = p_primitive ? 13 : 14; + for (uint32_t i = 8; i < split; i++) { glEnableVertexAttribArray(i); - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), CAST_INT_TO_UCHAR_PTR(p_start + (i - 6) * 4 * sizeof(float))); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), CAST_INT_TO_UCHAR_PTR(p_start + (i - 8) * 4 * sizeof(float))); glVertexAttribDivisor(i, p_rate); } - for (uint32_t i = split; i <= 13; i++) { + for (uint32_t i = split; i <= 15; i++) { glEnableVertexAttribArray(i); - glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, sizeof(InstanceData), CAST_INT_TO_UCHAR_PTR(p_start + (i - 6) * 4 * sizeof(float))); + glVertexAttribIPointer(i, 4, GL_UNSIGNED_INT, sizeof(InstanceData), CAST_INT_TO_UCHAR_PTR(p_start + (i - 8) * 4 * sizeof(float))); glVertexAttribDivisor(i, p_rate); } } diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index ce8fe25625bf4c..269b67a78d307b 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -32,18 +32,26 @@ layout(location = 5) in highp uvec4 instance_color_custom_data; // Color packed #include "stdlib_inc.glsl" -layout(location = 6) in highp vec4 attrib_A; -layout(location = 7) in highp vec4 attrib_B; -layout(location = 8) in highp vec4 attrib_C; -layout(location = 9) in highp vec4 attrib_D; -layout(location = 10) in highp vec4 attrib_E; +#if defined(CUSTOM0_USED) +layout(location = 6) in highp vec4 custom0_attrib; +#endif + +#if defined(CUSTOM1_USED) +layout(location = 7) in highp vec4 custom1_attrib; +#endif + +layout(location = 8) in highp vec4 attrib_A; +layout(location = 9) in highp vec4 attrib_B; +layout(location = 10) in highp vec4 attrib_C; +layout(location = 11) in highp vec4 attrib_D; +layout(location = 12) in highp vec4 attrib_E; #ifdef USE_PRIMITIVE -layout(location = 11) in highp uvec4 attrib_F; +layout(location = 13) in highp uvec4 attrib_F; #else -layout(location = 11) in highp vec4 attrib_F; +layout(location = 13) in highp vec4 attrib_F; #endif -layout(location = 12) in highp uvec4 attrib_G; -layout(location = 13) in highp uvec4 attrib_H; +layout(location = 14) in highp uvec4 attrib_G; +layout(location = 15) in highp uvec4 attrib_H; #define read_draw_data_world_x attrib_A.xy #define read_draw_data_world_y attrib_A.zw @@ -136,6 +144,10 @@ void main() { varying_G = read_draw_data_lights; vec4 instance_custom = vec4(0.0); + vec4 custom0 = vec4(0.0); + vec4 custom1 = vec4(0.0); + vec4 custom2 = vec4(0.0); // These two are unusable in gles3, but leaving the declaration + vec4 custom3 = vec4(0.0); // here makes switching between renderers relatively harmless #ifdef USE_PRIMITIVE vec2 vertex; @@ -169,9 +181,17 @@ void main() { if (bool(read_draw_data_flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { instance_custom = vec4(unpackHalf2x16(instance_color_custom_data.z), unpackHalf2x16(instance_color_custom_data.w)); } +#endif // !USE_INSTANCING + +#if defined(CUSTOM0_USED) + custom0 = custom0_attrib; #endif -#else +#if defined(CUSTOM1_USED) + custom1 = custom1_attrib; +#endif + +#else // !USE_ATTRIBUTES vec2 vertex_base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(1.0, 1.0)); vec2 vertex_base = vertex_base_arr[gl_VertexID % 6]; @@ -179,7 +199,7 @@ void main() { vec4 color = read_draw_data_modulation; vec2 vertex = read_draw_data_dst_rect.xy + abs(read_draw_data_dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(read_draw_data_src_rect.zw, vec2(0.0, 0.0))); -#endif +#endif // USE_ATTRIBUTES mat4 model_matrix = mat4(vec4(read_draw_data_world_x, 0.0, 0.0), vec4(read_draw_data_world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(read_draw_data_world_ofs, 0.0, 1.0)); diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 13ab05c0a080cd..e3a8204fa7a10a 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1160,6 +1160,11 @@ MaterialStorage::MaterialStorage() { actions.renames["INSTANCE_ID"] = "gl_InstanceID"; actions.renames["VERTEX_ID"] = "gl_VertexID"; + actions.renames["CUSTOM0"] = "custom0"; + actions.renames["CUSTOM1"] = "custom1"; + actions.renames["CUSTOM2"] = "custom2"; + actions.renames["CUSTOM3"] = "custom3"; + actions.renames["LIGHT_POSITION"] = "light_position"; actions.renames["LIGHT_DIRECTION"] = "light_direction"; actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional"; @@ -1180,6 +1185,10 @@ MaterialStorage::MaterialStorage() { actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 5c22e454ab4732..c702e92253be40 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -5786,6 +5786,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("AtLightPass", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass", "AT_LIGHT_PASS"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("CanvasMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "canvas_matrix", "CANVAS_MATRIX"), { "canvas_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Custom0", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom0", "CUSTOM0"), { "custom0" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Custom1", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom1", "CUSTOM1"), { "custom1" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Custom2", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom2", "CUSTOM2"), { "custom2" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Custom3", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom3", "CUSTOM3"), { "custom3" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("InstanceCustom", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("InstanceId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ModelMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "model_matrix", "MODEL_MATRIX"), { "model_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 9fb6b364a7b843..852d04eb1f58fb 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -2952,6 +2952,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "screen_matrix", "SCREEN_MATRIX" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom0", "CUSTOM0" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom1", "CUSTOM1" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom2", "CUSTOM2" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom3", "CUSTOM3" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "instance_custom", "INSTANCE_CUSTOM" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" }, diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 657628111ae0b6..47a3488796934a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2562,6 +2562,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; actions.renames["VERTEX_ID"] = "gl_VertexIndex"; + actions.renames["CUSTOM0"] = "custom0"; + actions.renames["CUSTOM1"] = "custom1"; + actions.renames["CUSTOM2"] = "custom2"; + actions.renames["CUSTOM3"] = "custom3"; + actions.renames["LIGHT_POSITION"] = "light_position"; actions.renames["LIGHT_DIRECTION"] = "light_direction"; actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional"; @@ -2583,6 +2588,10 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n"; actions.usage_defines["POINT_SIZE"] = "#define USE_POINT_SIZE\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0_USED\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index 7a13ac7207963a..f1855cb515282d 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -9,6 +9,22 @@ layout(location = 0) in vec2 vertex_attrib; layout(location = 3) in vec4 color_attrib; layout(location = 4) in vec2 uv_attrib; +#if defined(CUSTOM0_USED) +layout(location = 6) in vec4 custom0_attrib; +#endif + +#if defined(CUSTOM1_USED) +layout(location = 7) in vec4 custom1_attrib; +#endif + +#if defined(CUSTOM2_USED) +layout(location = 8) in vec4 custom2_attrib; +#endif + +#if defined(CUSTOM3_USED) +layout(location = 9) in vec4 custom3_attrib; +#endif + layout(location = 10) in uvec4 bone_attrib; layout(location = 11) in vec4 weight_attrib; @@ -44,6 +60,11 @@ vec3 srgb_to_linear(vec3 color) { void main() { vec4 instance_custom = vec4(0.0); + vec4 custom0 = vec4(0.0); + vec4 custom1 = vec4(0.0); + vec4 custom2 = vec4(0.0); + vec4 custom3 = vec4(0.0); + #ifdef USE_PRIMITIVE //weird bug, @@ -78,9 +99,25 @@ void main() { color *= draw_data.modulation; vec2 uv = uv_attrib; +#if defined(CUSTOM0_USED) + custom0 = custom0_attrib; +#endif + +#if defined(CUSTOM1_USED) + custom1 = custom1_attrib; +#endif + +#if defined(CUSTOM2_USED) + custom2 = custom2_attrib; +#endif + +#if defined(CUSTOM3_USED) + custom3 = custom3_attrib; +#endif + uvec4 bones = bone_attrib; vec4 bone_weights = weight_attrib; -#else +#else // !USE_ATTRIBUTES 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]; @@ -90,7 +127,7 @@ void main() { 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 bones = uvec4(0, 0, 0, 0); -#endif +#endif // USE_ATTRIBUTES mat4 model_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0)); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 3e19e8f01a6581..cc6d275095530f 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -250,6 +250,10 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX_ID"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM0"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM1"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM2"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CUSTOM3"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false; shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].main_function = true;