diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 2c323ef587..2fda292906 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -604,6 +604,7 @@ void register_scene_types() { ClassDB::register_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); + ClassDB::register_class(); SceneTree::add_idle_callback(SpatialMaterial::flush_changes); SpatialMaterial::init_shaders(); diff --git a/scene/resources/material/spatial_material.cpp b/scene/resources/material/spatial_material.cpp index f1d5b05b7f..ba66b3fe0c 100644 --- a/scene/resources/material/spatial_material.cpp +++ b/scene/resources/material/spatial_material.cpp @@ -113,6 +113,7 @@ void SpatialMaterial::init_shaders() { shader_names->texture_names[TEXTURE_DETAIL_MASK] = "texture_detail_mask"; shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo"; shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal"; + shader_names->texture_names[TEXTURE_ORM] = "texture_orm"; } HashMap> SpatialMaterial::materials_for_2d; @@ -286,15 +287,31 @@ void SpatialMaterial::_update_shader() { code += "uniform float roughness : hint_range(0,1);\n"; code += "uniform float point_size : hint_range(0,128);\n"; - if (textures[TEXTURE_METALLIC] != nullptr) { - code += "uniform sampler2D texture_metallic : hint_white;\n"; - code += "uniform vec4 metallic_texture_channel;\n"; - } + if (orm) { + if (textures[TEXTURE_ORM] != nullptr) { + code += "uniform sampler2D texture_orm : hint_white;\n"; + if (features[FEATURE_AMBIENT_OCCLUSION]) { + code += "uniform float ao_light_affect;\n"; + } + } + } else { + if (textures[TEXTURE_METALLIC] != nullptr) { + code += "uniform sampler2D texture_metallic : hint_white;\n"; + code += "uniform vec4 metallic_texture_channel;\n"; + } + + if (textures[TEXTURE_ROUGHNESS] != nullptr) { + code += "uniform sampler2D texture_roughness : hint_white;\n"; + code += "uniform vec4 roughness_texture_channel;\n"; + } - if (textures[TEXTURE_ROUGHNESS] != nullptr) { - code += "uniform sampler2D texture_roughness : hint_white;\n"; - code += "uniform vec4 roughness_texture_channel;\n"; + if (features[FEATURE_AMBIENT_OCCLUSION]) { + code += "uniform sampler2D texture_ambient_occlusion : hint_white;\n"; + code += "uniform vec4 ao_texture_channel;\n"; + code += "uniform float ao_light_affect;\n"; + } } + if (billboard_mode == BILLBOARD_PARTICLES) { code += "uniform int particles_anim_h_frames;\n"; code += "uniform int particles_anim_v_frames;\n"; @@ -331,11 +348,6 @@ void SpatialMaterial::_update_shader() { code += "uniform float anisotropy_ratio : hint_range(0,256);\n"; code += "uniform sampler2D texture_flowmap : hint_aniso;\n"; } - if (features[FEATURE_AMBIENT_OCCLUSION]) { - code += "uniform sampler2D texture_ambient_occlusion : hint_white;\n"; - code += "uniform vec4 ao_texture_channel;\n"; - code += "uniform float ao_light_affect;\n"; - } if (features[FEATURE_DETAIL]) { code += "uniform sampler2D texture_detail_albedo : hint_albedo;\n"; @@ -593,26 +605,75 @@ void SpatialMaterial::_update_shader() { } code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n"; - if (textures[TEXTURE_METALLIC] != nullptr) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tfloat metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n"; + + if (orm) { + if (textures[TEXTURE_ORM] != nullptr) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec4 orm_tex = triplanar_texture(texture_orm,uv1_power_normal,uv1_triplanar_pos);\n"; + } else { + code += "\tvec4 orm_tex = texture(texture_orm,base_uv);\n"; + } + code += "\tMETALLIC = orm_tex.b;\n"; + code += "\tROUGHNESS = orm_tex.g;\n"; } else { - code += "\tfloat metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n"; + code += "\tMETALLIC = metallic;\n"; + code += "\tROUGHNESS = roughness;\n"; + } + + // AO + if (features[FEATURE_AMBIENT_OCCLUSION]) { + if (flags[FLAG_AO_ON_UV2]) { + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tAO = triplanar_texture(texture_orm,uv2_power_normal,uv2_triplanar_pos).r;\n"; + } else { + code += "\tAO = texture(texture_orm,base_uv2).r;\n"; + } + } else { + code += "\tAO = orm_tex.r;\n"; + } + + code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n"; } - code += "\tMETALLIC = metallic_tex * metallic;\n"; } else { - code += "\tMETALLIC = metallic;\n"; - } + if (textures[TEXTURE_METALLIC] != nullptr) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n"; + } else { + code += "\tfloat metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n"; + } + code += "\tMETALLIC = metallic_tex * metallic;\n"; + } else { + code += "\tMETALLIC = metallic;\n"; + } - if (textures[TEXTURE_ROUGHNESS] != nullptr) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tfloat roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n"; + if (textures[TEXTURE_ROUGHNESS] != nullptr) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n"; + } else { + code += "\tfloat roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n"; + } + code += "\tROUGHNESS = roughness_tex * roughness;\n"; } else { - code += "\tfloat roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n"; + code += "\tROUGHNESS = roughness;\n"; + } + + if (features[FEATURE_AMBIENT_OCCLUSION]) { + if (flags[FLAG_AO_ON_UV2]) { + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; + } + } else { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; + } + } + + code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n"; } - code += "\tROUGHNESS = roughness_tex * roughness;\n"; - } else { - code += "\tROUGHNESS = roughness;\n"; } code += "\tSPECULAR = specular;\n"; @@ -735,24 +796,6 @@ void SpatialMaterial::_update_shader() { code += "\tANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n"; } - if (features[FEATURE_AMBIENT_OCCLUSION]) { - if (flags[FLAG_AO_ON_UV2]) { - if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n"; - } else { - code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; - } - } else { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n"; - } else { - code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; - } - } - - code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n"; - } - if (features[FEATURE_SUBSURACE_SCATTERING]) { if (flags[FLAG_UV1_USE_TRIPLANAR]) { code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n"; @@ -1264,6 +1307,20 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } } + + if (orm) { + if (property.name == "shading_mode") { + // Vertex not supported in ORM mode, since no individual roughness. + property.hint_string = "Unshaded,Per-Pixel"; + } + if (property.name.begins_with("roughness") || property.name.begins_with("metallic") || property.name.begins_with("ao_texture")) { + property.usage = 0; + } + } else { + if (property.name == "orm_texture") { + property.usage = 0; + } + } } void SpatialMaterial::set_line_width(float p_line_width) { @@ -1857,6 +1914,9 @@ void SpatialMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); + ADD_GROUP("ORM", "orm_"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orm_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ORM); + ADD_GROUP("Metallic", "metallic_"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_metallic", "get_metallic"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular", "get_specular"); @@ -2067,8 +2127,10 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(ASYNC_MODE_HIDDEN); } -SpatialMaterial::SpatialMaterial() : +SpatialMaterial::SpatialMaterial(bool p_orm) : element(this) { + orm = p_orm; + // Initialize to the same values as the shader set_albedo(Color(1.0, 1.0, 1.0, 1.0)); set_specular(0.5); diff --git a/scene/resources/material/spatial_material.h b/scene/resources/material/spatial_material.h index a3a5171c56..e7b695a687 100644 --- a/scene/resources/material/spatial_material.h +++ b/scene/resources/material/spatial_material.h @@ -62,6 +62,7 @@ class SpatialMaterial : public Material { TEXTURE_DETAIL_MASK, TEXTURE_DETAIL_ALBEDO, TEXTURE_DETAIL_NORMAL, + TEXTURE_ORM, TEXTURE_MAX }; @@ -311,6 +312,7 @@ class SpatialMaterial : public Material { _FORCE_INLINE_ bool _is_shader_dirty() const; bool is_initialized = false; + bool orm; Color albedo; float specular; float metallic; @@ -578,7 +580,7 @@ class SpatialMaterial : public Material { virtual Shader::Mode get_shader_mode() const; - SpatialMaterial(); + SpatialMaterial(bool p_orm = false); virtual ~SpatialMaterial(); }; @@ -599,4 +601,11 @@ VARIANT_ENUM_CAST(SpatialMaterial::AsyncMode) ////////////////////// +class ORMSpatialMaterial : public SpatialMaterial { + GDCLASS(ORMSpatialMaterial, SpatialMaterial) +public: + ORMSpatialMaterial() : + SpatialMaterial(true) {} +}; + #endif