Skip to content

Commit

Permalink
Add double precision support for World Triplanar Mapping
Browse files Browse the repository at this point in the history
This commit adds emulated doubles support for the World UV Triplanar Mapping.
It also adds some QoL features to both ease the "integration" with the double
precision pipeline and also to allow greater flexibility when dealing
with Triplanar UVs.

Features:
  - New mat4 TRIPLANAR_MATRIX vertex-only property (the same as MODEL_MATRIX by default).
  - New "hint_triplanar_mat" hint for mat4 uniforms, which allow users
    to specify a custom TRIPLANAR_MATRIX. Naturally, only a single
    instance of the hint is allowed per shader.
  - New vec3 TRIPLANAR_POSITION vertex-only property, which holds the
    VERTEX transformed by the TRIPLANAR_MATRIX (With emulated doubles, if
    applicable).
  - Updated Standard 3D Material to make use of the above features.
  - Updated VisualShader to include the TRIPLANAR_MATRIX and
    TRIPLANAR_POSITION as valid Inputs.
  - Added a "hint_triplanar_enabled" toggle to the VisualShaderNodeTransformParameter to allow
    the new "hint_triplanar_mat" hint to be set.

Note: The shader related changes were applied to all renderers (Forward+,
Mobile and Compatibility).

Note²: Given the lack of emulated doubles support for the Compatibility
renderer, only the single precision path was implemented.

Co-Authored-By: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Braz?= <brazjoaopedro@ymail.com>
  • Loading branch information
fire and joao-pedro-braz committed Aug 21, 2024
1 parent 5ca419e commit a9d22cd
Show file tree
Hide file tree
Showing 18 changed files with 266 additions and 8 deletions.
5 changes: 5 additions & 0 deletions doc/classes/VisualShaderNodeTextureParameterTriplanar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@
</description>
<tutorials>
</tutorials>
<members>
<member name="world_triplanar_enabled" type="bool" setter="set_world_triplanar_enabled" getter="is_world_triplanar_enabled" default="false">
If [code]true[/code], triplanar mapping is calculated in world space rather than object local space. See also [member BaseMaterial3D.uv1_world_triplanar].
</member>
</members>
</class>
3 changes: 3 additions & 0 deletions doc/classes/VisualShaderNodeTransformParameter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@
<member name="default_value_enabled" type="bool" setter="set_default_value_enabled" getter="is_default_value_enabled" default="false">
Enables usage of the [member default_value].
</member>
<member name="hint_triplanar_enabled" type="bool" setter="set_hint_triplanar_enabled" getter="is_hint_triplanar_enabled" default="false">
If enabled, adds the "hint_triplanar_mat" hint to the uniform.
</member>
</members>
</class>
15 changes: 15 additions & 0 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,21 @@ void main() {

float point_size = 1.0;

#if defined(TRIPLANAR_MATRIX_USED) || defined(TRIPLANAR_POSITION_USED)
mat4 triplanar_matrix;

#ifdef TRIPLANAR_MATRIX
triplanar_matrix = TRIPLANAR_MATRIX;
#else
triplanar_matrix = model_matrix;
#endif

#ifdef TRIPLANAR_POSITION_USED
vec3 triplanar_position = (triplanar_matrix * vec4(vertex, 1.0)).xyz;
#endif

#endif

{
#CODE : VERTEX
}
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles3/storage/material_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["MODELVIEW_MATRIX"] = "modelview";
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix";
actions.renames["TRIPLANAR_MATRIX"] = "triplanar_matrix";

actions.renames["VERTEX"] = "vertex";
actions.renames["NORMAL"] = "normal";
Expand Down Expand Up @@ -1276,6 +1277,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["LIGHT_VERTEX"] = "light_vertex";

actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
actions.renames["TRIPLANAR_POSITION"] = "triplanar_position";
actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.inv_view_matrix[2].xyz";
actions.renames["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers";
Expand Down Expand Up @@ -1321,6 +1323,8 @@ MaterialStorage::MaterialStorage() {
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
actions.usage_defines["LIGHT_VERTEX"] = "#define LIGHT_VERTEX_USED\n";
actions.usage_defines["TRIPLANAR_POSITION"] = "#define TRIPLANAR_POSITION_USED\n";
actions.usage_defines["TRIPLANAR_MATRIX"] = "#define TRIPLANAR_MATRIX_USED\n";

actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n";
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
Expand Down
2 changes: 2 additions & 0 deletions editor/plugins/visual_shader_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6608,6 +6608,8 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("ViewRight", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("EyeOffset", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("NodePositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("TriplanarPosition", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "triplanar_position", "TRIPLANAR_POSITION"), { "triplanar_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("TriplanarMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "triplanar_matrix", "TRIPLANAR_MATRIX"), { "triplanar_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("CameraPositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("CameraDirectionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("CameraVisibleLayers", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
Expand Down
8 changes: 4 additions & 4 deletions scene/resources/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,8 @@ void vertex() {)";
if (flags[FLAG_UV1_USE_WORLD_TRIPLANAR]) {
code += R"(
// UV1 Triplanar: Enabled (with World Triplanar)
uv1_power_normal = pow(abs(normal), vec3(uv1_blend_sharpness));
uv1_triplanar_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz * uv1_scale + uv1_offset;
uv1_power_normal = pow(abs(mat3(TRIPLANAR_MATRIX) * normal), vec3(uv1_blend_sharpness));
uv1_triplanar_pos = TRIPLANAR_POSITION * uv1_scale + uv1_offset;
)";
} else {
code += R"(
Expand All @@ -1273,8 +1273,8 @@ void vertex() {)";
if (flags[FLAG_UV2_USE_WORLD_TRIPLANAR]) {
code += R"(
// UV2 Triplanar: Enabled (with World Triplanar)
uv2_power_normal = pow(abs(mat3(MODEL_MATRIX) * NORMAL), vec3(uv2_blend_sharpness));
uv2_triplanar_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz * uv2_scale + uv2_offset;
uv2_power_normal = pow(abs(mat3(TRIPLANAR_MATRIX) * NORMAL), vec3(uv2_blend_sharpness));
uv2_triplanar_pos = TRIPLANAR_POSITION * uv2_scale + uv2_offset;
)";
} else {
code += R"(
Expand Down
8 changes: 8 additions & 0 deletions scene/resources/visual_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2549,6 +2549,12 @@ void VisualShader::_update_shader() const {
if (parameter_ref.is_valid()) {
used_parameter_names.insert(parameter_ref->get_parameter_name());
}
// Given the side effects "hint_triplanar_mat" has, we can save our users
// some trouble and code_gen this even if it's not directly used.
Ref<VisualShaderNodeTransformParameter> transform_parameter_ref = E.value.node;
if (transform_parameter_ref.is_valid() && transform_parameter_ref->is_hint_triplanar_enabled()) {
used_parameter_names.insert(transform_parameter_ref->get_parameter_name());
}
Ref<VisualShaderNodeParameter> parameter = E.value.node;
if (parameter.is_valid()) {
parameters.push_back(parameter.ptr());
Expand Down Expand Up @@ -3033,6 +3039,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eye_offset", "EYE_OFFSET" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "triplanar_position", "TRIPLANAR_POSITION" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "triplanar_matrix", "TRIPLANAR_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS" },
Expand Down
54 changes: 52 additions & 2 deletions scene/resources/visual_shader_nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6214,6 +6214,15 @@ bool VisualShaderNodeTransformParameter::is_default_value_enabled() const {
return default_value_enabled;
}

void VisualShaderNodeTransformParameter::set_hint_triplanar_enabled(bool p_enabled) {
hint_triplanar_enabled = p_enabled;
emit_changed();
}

bool VisualShaderNodeTransformParameter::is_hint_triplanar_enabled() const {
return hint_triplanar_enabled;
}

void VisualShaderNodeTransformParameter::set_default_value(const Transform3D &p_value) {
default_value = p_value;
emit_changed();
Expand All @@ -6225,6 +6234,9 @@ Transform3D VisualShaderNodeTransformParameter::get_default_value() const {

String VisualShaderNodeTransformParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform mat4 " + get_parameter_name();
if (hint_triplanar_enabled) {
code += " : hint_triplanar_mat";
}
if (default_value_enabled) {
Vector3 row0 = default_value.basis.rows[0];
Vector3 row1 = default_value.basis.rows[1];
Expand All @@ -6244,10 +6256,14 @@ void VisualShaderNodeTransformParameter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeTransformParameter::set_default_value_enabled);
ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeTransformParameter::is_default_value_enabled);

ClassDB::bind_method(D_METHOD("set_hint_triplanar_enabled", "enabled"), &VisualShaderNodeTransformParameter::set_hint_triplanar_enabled);
ClassDB::bind_method(D_METHOD("is_hint_triplanar_enabled"), &VisualShaderNodeTransformParameter::is_hint_triplanar_enabled);

ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeTransformParameter::set_default_value);
ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeTransformParameter::get_default_value);

ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hint_triplanar_enabled"), "set_hint_triplanar_enabled", "is_hint_triplanar_enabled");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "default_value"), "set_default_value", "get_default_value");
}

Expand All @@ -6272,6 +6288,7 @@ bool VisualShaderNodeTransformParameter::is_convertible_to_constant() const {

Vector<StringName> VisualShaderNodeTransformParameter::get_editable_properties() const {
Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("hint_triplanar_enabled");
props.push_back("default_value_enabled");
if (default_value_enabled) {
props.push_back("default_value");
Expand Down Expand Up @@ -6781,9 +6798,14 @@ String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func(Shade
if (p_type == VisualShader::TYPE_VERTEX) {
code += "// " + get_caption() + "\n";
code += " {\n";
code += " triplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n";
if (world_triplanar_enabled) {
code += " triplanar_power_normal = pow(abs(mat3(TRIPLANAR_MATRIX) * NORMAL), vec3(triplanar_sharpness));\n";
code += " triplanar_pos = TRIPLANAR_POSITION * triplanar_scale + triplanar_offset;\n";
} else {
code += " triplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n";
code += " triplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n";
}
code += " triplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n";
code += " triplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n";
code += " triplanar_pos *= vec3(1.0, -1.0, 1.0);\n";
code += " }\n";
}
Expand Down Expand Up @@ -6815,6 +6837,18 @@ String VisualShaderNodeTextureParameterTriplanar::generate_code(Shader::Mode p_m
return code;
}

Vector<StringName> VisualShaderNodeTextureParameterTriplanar::get_editable_properties() const {
auto props = VisualShaderNodeTextureParameter::get_editable_properties();
props.push_back("world_triplanar_enabled");
return props;
}

HashMap<StringName, String> VisualShaderNodeTextureParameterTriplanar::get_editable_properties_names() const {
auto names = VisualShaderNodeTextureParameter::get_editable_properties_names();
names.insert("world_triplanar_enabled", RTR("World Triplanar"));
return names;
}

bool VisualShaderNodeTextureParameterTriplanar::is_input_port_default(int p_port, Shader::Mode p_mode) const {
if (p_port == 0) {
return true;
Expand All @@ -6824,6 +6858,22 @@ bool VisualShaderNodeTextureParameterTriplanar::is_input_port_default(int p_port
return false;
}

void VisualShaderNodeTextureParameterTriplanar::set_world_triplanar_enabled(bool p_enabled) {
world_triplanar_enabled = p_enabled;
emit_changed();
}

bool VisualShaderNodeTextureParameterTriplanar::is_world_triplanar_enabled() const {
return world_triplanar_enabled;
}

void VisualShaderNodeTextureParameterTriplanar::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_triplanar_enabled", "p_enabled"), &VisualShaderNodeTextureParameterTriplanar::set_world_triplanar_enabled);
ClassDB::bind_method(D_METHOD("is_world_triplanar_enabled"), &VisualShaderNodeTextureParameterTriplanar::is_world_triplanar_enabled);

ADD_PROPERTY(PropertyInfo(Variant::BOOL, "world_triplanar_enabled"), "set_world_triplanar_enabled", "is_world_triplanar_enabled");
}

VisualShaderNodeTextureParameterTriplanar::VisualShaderNodeTextureParameterTriplanar() {
}

Expand Down
16 changes: 16 additions & 0 deletions scene/resources/visual_shader_nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2443,6 +2443,7 @@ class VisualShaderNodeTransformParameter : public VisualShaderNodeParameter {

private:
bool default_value_enabled = false;
bool hint_triplanar_enabled = false;
Transform3D default_value = Transform3D(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);

protected:
Expand All @@ -2468,6 +2469,9 @@ class VisualShaderNodeTransformParameter : public VisualShaderNodeParameter {
void set_default_value_enabled(bool p_enabled);
bool is_default_value_enabled() const;

void set_hint_triplanar_enabled(bool p_enabled);
bool is_hint_triplanar_enabled() const;

void set_default_value(const Transform3D &p_value);
Transform3D get_default_value() const;

Expand Down Expand Up @@ -2598,6 +2602,12 @@ class VisualShaderNodeTexture2DParameter : public VisualShaderNodeTextureParamet
class VisualShaderNodeTextureParameterTriplanar : public VisualShaderNodeTextureParameter {
GDCLASS(VisualShaderNodeTextureParameterTriplanar, VisualShaderNodeTextureParameter);

private:
bool world_triplanar_enabled = false;

protected:
static void _bind_methods();

public:
virtual String get_caption() const override;

Expand All @@ -2609,8 +2619,14 @@ class VisualShaderNodeTextureParameterTriplanar : public VisualShaderNodeTexture
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;

Vector<StringName> get_editable_properties() const override;
HashMap<StringName, String> get_editable_properties_names() const override;

virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;

void set_world_triplanar_enabled(bool p_enabled);
bool is_world_triplanar_enabled() const;

virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["MODELVIEW_MATRIX"] = "modelview";
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix";
actions.renames["TRIPLANAR_MATRIX"] = "triplanar_matrix";

actions.renames["VERTEX"] = "vertex";
actions.renames["NORMAL"] = "normal";
Expand Down Expand Up @@ -639,6 +640,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["LIGHT_VERTEX"] = "light_vertex";

actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
actions.renames["TRIPLANAR_POSITION"] = "triplanar_position";
actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.inv_view_matrix[2].xyz";
actions.renames["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers";
Expand Down Expand Up @@ -701,6 +703,8 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n";

actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n";
actions.usage_defines["TRIPLANAR_POSITION"] = "#define TRIPLANAR_POSITION_USED\n";
actions.usage_defines["TRIPLANAR_MATRIX"] = "#define TRIPLANAR_MATRIX_USED\n";

actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["MODELVIEW_MATRIX"] = "modelview";
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix";
actions.renames["TRIPLANAR_MATRIX"] = "triplanar_matrix";

actions.renames["VERTEX"] = "vertex";
actions.renames["NORMAL"] = "normal";
Expand Down Expand Up @@ -543,6 +544,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["LIGHT_VERTEX"] = "light_vertex";

actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
actions.renames["TRIPLANAR_POSITION"] = "triplanar_position";
actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.inv_view_matrix[2].xyz";
actions.renames["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers";
Expand Down Expand Up @@ -605,6 +607,8 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n";

actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n";
actions.usage_defines["TRIPLANAR_POSITION"] = "#define TRIPLANAR_POSITION_USED\n";
actions.usage_defines["TRIPLANAR_MATRIX"] = "#define TRIPLANAR_MATRIX_USED\n";

actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,52 @@ void vertex_shader(vec3 vertex_input,
mat4 read_view_matrix = scene_data.view_matrix;
vec2 read_viewport_size = scene_data.viewport_size;

#if defined(TRIPLANAR_POSITION_USED) || defined(TRIPLANAR_MATRIX_USED)
mat4 triplanar_matrix;

#ifdef TRIPLANAR_POSITION_USED
vec3 triplanar_position = vertex;
#endif

{
#ifdef TRIPLANAR_MATRIX
triplanar_matrix = material.TRIPLANAR_MATRIX;
#else
triplanar_matrix = model_matrix;
#endif

#ifdef TRIPLANAR_POSITION_USED

#ifdef USE_DOUBLE_PRECISION
vec3 triplanar_matrix_precision;

#ifdef TRIPLANAR_MATRIX
triplanar_matrix_precision = vec3(triplanar_matrix[0][3], triplanar_matrix[1][3], triplanar_matrix[2][3]);
triplanar_matrix[0][3] = 0.0;
triplanar_matrix[1][3] = 0.0;
triplanar_matrix[2][3] = 0.0;
#else
triplanar_matrix_precision = model_precision;
#endif

// We separate the basis from the origin because the basis is fine with single point precision.
// We add the result to the triplanar_position and ignore the final lost precision.
vec3 model_origin = triplanar_matrix[3].xyz;
if (is_multimesh) {
triplanar_position = (matrix * vec4(triplanar_position, 1.0)).xyz;
}
triplanar_position = mat3(triplanar_matrix) * triplanar_position;
vec3 temp_precision; // Will be ignored.
triplanar_position += double_add_vec3(model_origin, triplanar_matrix_precision, -vec3(ceil(model_origin.x), ceil(model_origin.y), ceil(model_origin.z)), vec3(0.0), temp_precision);
#else
triplanar_position = (triplanar_matrix * vec4(triplanar_position, 1.0)).xyz;
#endif

#endif
}

#endif

{
#CODE : VERTEX
}
Expand Down
Loading

0 comments on commit a9d22cd

Please sign in to comment.