Skip to content

Commit d0693d6

Browse files
committed
Merge pull request #89988 from LunaCapra/specular-occlusion
Add support for bent normal maps for specular occlusion and indirect lighting
2 parents b28d5a3 + 9828c36 commit d0693d6

File tree

16 files changed

+240
-92
lines changed

16 files changed

+240
-92
lines changed

doc/classes/BaseMaterial3D.xml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@
120120
<member name="backlight_texture" type="Texture2D" setter="set_texture" getter="get_texture">
121121
Texture used to control the backlight effect per-pixel. Added to [member backlight].
122122
</member>
123+
<member name="bent_normal_enabled" type="bool" setter="set_feature" getter="get_feature" default="false">
124+
If [code]true[/code], the bent normal map is enabled. This allows for more accurate indirect lighting and specular occlusion.
125+
</member>
126+
<member name="bent_normal_texture" type="Texture2D" setter="set_texture" getter="get_texture">
127+
Texture that specifies the average direction of incoming ambient light at a given pixel. The [member bent_normal_texture] only uses the red and green channels; the blue and alpha channels are ignored. The normal read from [member bent_normal_texture] is oriented around the surface normal provided by the [Mesh].
128+
[b]Note:[/b] A bent normal map is different from a regular normal map. When baking a bent normal map make sure to use [b]a cosine distribution[/b] for the bent normal map to work correctly.
129+
[b]Note:[/b] The mesh must have both normals and tangents defined in its vertex data. Otherwise, the shading produced by the bent normal map will not look correct. If creating geometry with [SurfaceTool], you can use [method SurfaceTool.generate_normals] and [method SurfaceTool.generate_tangents] to automatically generate normals and tangents respectively.
130+
[b]Note:[/b] Godot expects the bent normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
131+
</member>
123132
<member name="billboard_keep_scale" type="bool" setter="set_flag" getter="get_flag" default="false">
124133
If [code]true[/code], the shader will keep the scale set for the mesh. Otherwise, the scale is lost when billboarding. Only applies when [member billboard_mode] is not [constant BILLBOARD_DISABLED].
125134
</member>
@@ -461,6 +470,9 @@
461470
<constant name="TEXTURE_NORMAL" value="4" enum="TextureParam">
462471
Texture specifying per-pixel normal vector.
463472
</constant>
473+
<constant name="TEXTURE_BENT_NORMAL" value="18" enum="TextureParam">
474+
Texture specifying per-pixel bent normal vector.
475+
</constant>
464476
<constant name="TEXTURE_RIM" value="5" enum="TextureParam">
465477
Texture specifying per-pixel rim value.
466478
</constant>
@@ -500,7 +512,7 @@
500512
<constant name="TEXTURE_ORM" value="17" enum="TextureParam">
501513
Texture holding ambient occlusion, roughness, and metallic.
502514
</constant>
503-
<constant name="TEXTURE_MAX" value="18" enum="TextureParam">
515+
<constant name="TEXTURE_MAX" value="19" enum="TextureParam">
504516
Represents the size of the [enum TextureParam] enum.
505517
</constant>
506518
<constant name="TEXTURE_FILTER_NEAREST" value="0" enum="TextureFilter">
@@ -596,7 +608,10 @@
596608
<constant name="FEATURE_DETAIL" value="11" enum="Feature">
597609
Constant for setting [member detail_enabled].
598610
</constant>
599-
<constant name="FEATURE_MAX" value="12" enum="Feature">
611+
<constant name="FEATURE_BENT_NORMAL_MAPPING" value="12" enum="Feature">
612+
Constant for setting [member bent_normal_enabled].
613+
</constant>
614+
<constant name="FEATURE_MAX" value="13" enum="Feature">
600615
Represents the size of the [enum Feature] enum.
601616
</constant>
602617
<constant name="BLEND_MODE_MIX" value="0" enum="BlendMode">

drivers/gles3/shaders/scene.glsl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,6 +1842,10 @@ void main() {
18421842
vec3 normal_map = vec3(0.5);
18431843
#endif
18441844

1845+
#if defined(BENT_NORMAL_MAP_USED)
1846+
vec3 bent_normal_map = vec3(0.5);
1847+
#endif
1848+
18451849
float normal_map_depth = 1.0;
18461850

18471851
vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size;

drivers/gles3/storage/material_storage.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,7 @@ MaterialStorage::MaterialStorage() {
12531253
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
12541254
actions.renames["NORMAL_MAP"] = "normal_map";
12551255
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
1256+
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map";
12561257
actions.renames["ALBEDO"] = "albedo";
12571258
actions.renames["ALPHA"] = "alpha";
12581259
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha";
@@ -1330,6 +1331,7 @@ MaterialStorage::MaterialStorage() {
13301331
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
13311332
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
13321333
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
1334+
actions.usage_defines["BENT_NORMAL_MAP"] = "#define BENT_NORMAL_MAP_USED\n";
13331335
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
13341336
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
13351337
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
@@ -2904,6 +2906,7 @@ void SceneShaderData::set_code(const String &p_code) {
29042906
uses_screen_texture_mipmaps = false;
29052907
uses_depth_texture = false;
29062908
uses_normal_texture = false;
2909+
uses_bent_normal_texture = false;
29072910
uses_time = false;
29082911
uses_vertex_time = false;
29092912
uses_fragment_time = false;
@@ -2977,6 +2980,7 @@ void SceneShaderData::set_code(const String &p_code) {
29772980
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
29782981
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
29792982
actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
2983+
actions.usage_flag_pointers["BENT_NORMAL_MAP"] = &uses_bent_normal_texture;
29802984

29812985
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
29822986
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;

drivers/gles3/storage/material_storage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ struct SceneShaderData : public ShaderData {
305305
bool uses_screen_texture_mipmaps;
306306
bool uses_depth_texture;
307307
bool uses_normal_texture;
308+
bool uses_bent_normal_texture;
308309
bool uses_time;
309310
bool uses_vertex_time;
310311
bool uses_fragment_time;

scene/resources/material.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ void BaseMaterial3D::init_shaders() {
646646
shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness";
647647
shader_names->texture_names[TEXTURE_EMISSION] = "texture_emission";
648648
shader_names->texture_names[TEXTURE_NORMAL] = "texture_normal";
649+
shader_names->texture_names[TEXTURE_BENT_NORMAL] = "texture_bent_normal";
649650
shader_names->texture_names[TEXTURE_RIM] = "texture_rim";
650651
shader_names->texture_names[TEXTURE_CLEARCOAT] = "texture_clearcoat";
651652
shader_names->texture_names[TEXTURE_FLOWMAP] = "texture_flowmap";
@@ -1022,6 +1023,12 @@ uniform vec4 refraction_texture_channel;
10221023
code += vformat(R"(
10231024
uniform sampler2D texture_normal : hint_roughness_normal, %s;
10241025
uniform float normal_scale : hint_range(-16.0, 16.0);
1026+
)",
1027+
texfilter_str);
1028+
}
1029+
if (features[FEATURE_BENT_NORMAL_MAPPING]) {
1030+
code += vformat(R"(
1031+
uniform sampler2D texture_bent_normal : hint_roughness_normal, %s;
10251032
)",
10261033
texfilter_str);
10271034
}
@@ -1641,6 +1648,13 @@ void fragment() {)";
16411648
code += " NORMAL_MAP_DEPTH = normal_scale;\n";
16421649
}
16431650

1651+
if (features[FEATURE_BENT_NORMAL_MAPPING]) {
1652+
code += R"(
1653+
// Bent Normal Map: Enabled
1654+
BENT_NORMAL_MAP = texture(texture_bent_normal, base_uv).rgb;
1655+
)";
1656+
}
1657+
16441658
if (features[FEATURE_EMISSION]) {
16451659
code += R"(
16461660
// Emission: Enabled
@@ -2440,6 +2454,7 @@ void BaseMaterial3D::_validate_feature(const String &text, Feature feature, Prop
24402454

24412455
void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const {
24422456
_validate_feature("normal", FEATURE_NORMAL_MAPPING, p_property);
2457+
_validate_feature("bent_normal", FEATURE_BENT_NORMAL_MAPPING, p_property);
24432458
_validate_feature("emission", FEATURE_EMISSION, p_property);
24442459
_validate_feature("rim", FEATURE_RIM, p_property);
24452460
_validate_feature("clearcoat", FEATURE_CLEARCOAT, p_property);
@@ -2585,6 +2600,10 @@ void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const {
25852600
p_property.usage = PROPERTY_USAGE_NONE;
25862601
}
25872602

2603+
if (p_property.name.begins_with("bent_normal")) {
2604+
p_property.usage = PROPERTY_USAGE_NONE;
2605+
}
2606+
25882607
if (p_property.name.begins_with("backlight")) {
25892608
p_property.usage = PROPERTY_USAGE_NONE;
25902609
}
@@ -3251,6 +3270,10 @@ void BaseMaterial3D::_bind_methods() {
32513270
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale");
32523271
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_NORMAL);
32533272

3273+
ADD_GROUP("Bent Normal Map", "bent_normal_");
3274+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "bent_normal_enabled", PROPERTY_HINT_GROUP_ENABLE), "set_feature", "get_feature", FEATURE_BENT_NORMAL_MAPPING);
3275+
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "bent_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_BENT_NORMAL);
3276+
32543277
ADD_GROUP("Rim", "rim_");
32553278
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "rim_enabled", PROPERTY_HINT_GROUP_ENABLE), "set_feature", "get_feature", FEATURE_RIM);
32563279
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rim", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim", "get_rim");
@@ -3377,6 +3400,7 @@ void BaseMaterial3D::_bind_methods() {
33773400
BIND_ENUM_CONSTANT(TEXTURE_ROUGHNESS);
33783401
BIND_ENUM_CONSTANT(TEXTURE_EMISSION);
33793402
BIND_ENUM_CONSTANT(TEXTURE_NORMAL);
3403+
BIND_ENUM_CONSTANT(TEXTURE_BENT_NORMAL);
33803404
BIND_ENUM_CONSTANT(TEXTURE_RIM);
33813405
BIND_ENUM_CONSTANT(TEXTURE_CLEARCOAT);
33823406
BIND_ENUM_CONSTANT(TEXTURE_FLOWMAP);
@@ -3427,6 +3451,7 @@ void BaseMaterial3D::_bind_methods() {
34273451
BIND_ENUM_CONSTANT(FEATURE_BACKLIGHT);
34283452
BIND_ENUM_CONSTANT(FEATURE_REFRACTION);
34293453
BIND_ENUM_CONSTANT(FEATURE_DETAIL);
3454+
BIND_ENUM_CONSTANT(FEATURE_BENT_NORMAL_MAPPING);
34303455
BIND_ENUM_CONSTANT(FEATURE_MAX);
34313456

34323457
BIND_ENUM_CONSTANT(BLEND_MODE_MIX);

scene/resources/material.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ class BaseMaterial3D : public Material {
162162
TEXTURE_DETAIL_ALBEDO,
163163
TEXTURE_DETAIL_NORMAL,
164164
TEXTURE_ORM,
165+
TEXTURE_BENT_NORMAL,
165166
TEXTURE_MAX
166-
167167
};
168168

169169
enum TextureFilter {
@@ -218,6 +218,7 @@ class BaseMaterial3D : public Material {
218218
FEATURE_BACKLIGHT,
219219
FEATURE_REFRACTION,
220220
FEATURE_DETAIL,
221+
FEATURE_BENT_NORMAL_MAPPING,
221222
FEATURE_MAX
222223
};
223224

scene/resources/visual_shader.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3977,6 +3977,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
39773977
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal Map", "NORMAL_MAP" },
39783978
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Normal Map Depth", "NORMAL_MAP_DEPTH" },
39793979

3980+
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Bent Normal Map", "BENT_NORMAL_MAP" },
3981+
39803982
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Rim", "RIM" },
39813983
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Rim Tint", "RIM_TINT" },
39823984
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Clearcoat", "CLEARCOAT" },

servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
6767
uses_normal = false;
6868
uses_tangent = false;
6969
uses_normal_map = false;
70+
uses_bent_normal_map = false;
7071
wireframe = false;
7172

7273
unshaded = false;
@@ -125,6 +126,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
125126
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
126127
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
127128
actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal_map;
129+
actions.usage_flag_pointers["BENT_NORMAL_MAP"] = &uses_bent_normal_map;
128130

129131
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
130132
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
@@ -169,7 +171,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
169171
uses_vertex_time = gen_code.uses_vertex_time;
170172
uses_fragment_time = gen_code.uses_fragment_time;
171173
uses_normal |= uses_normal_map;
174+
uses_normal |= uses_bent_normal_map;
172175
uses_tangent |= uses_normal_map;
176+
uses_tangent |= uses_bent_normal_map;
173177

174178
#if 0
175179
print_line("**compiling shader:");
@@ -630,6 +634,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
630634
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
631635
actions.renames["NORMAL_MAP"] = "normal_map";
632636
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
637+
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map";
633638
actions.renames["ALBEDO"] = "albedo";
634639
actions.renames["ALPHA"] = "alpha";
635640
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha";
@@ -707,6 +712,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
707712
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
708713
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
709714
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
715+
actions.usage_defines["BENT_NORMAL_MAP"] = "#define BENT_NORMAL_MAP_USED\n";
710716
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
711717
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
712718
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";

servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ class SceneShaderForwardClustered {
228228
bool uses_tangent = false;
229229
bool uses_particle_trails = false;
230230
bool uses_normal_map = false;
231+
bool uses_bent_normal_map = false;
231232
bool wireframe = false;
232233

233234
bool unshaded = false;

servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
6969
uses_normal = false;
7070
uses_tangent = false;
7171
uses_normal_map = false;
72+
uses_bent_normal_map = false;
7273
wireframe = false;
7374

7475
unshaded = false;
@@ -126,6 +127,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
126127
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
127128
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
128129
actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal_map;
130+
actions.usage_flag_pointers["BENT_NORMAL_MAP"] = &uses_bent_normal_map;
129131

130132
actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
131133
actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
@@ -165,7 +167,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
165167
uses_depth_texture = gen_code.uses_depth_texture;
166168
uses_normal_texture = gen_code.uses_normal_roughness_texture;
167169
uses_normal |= uses_normal_map;
170+
uses_normal |= uses_bent_normal_map;
168171
uses_tangent |= uses_normal_map;
172+
uses_tangent |= uses_bent_normal_map;
169173

170174
#ifdef DEBUG_ENABLED
171175
if (uses_sss) {
@@ -563,6 +567,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
563567
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
564568
actions.renames["NORMAL_MAP"] = "normal_map";
565569
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
570+
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map";
566571
actions.renames["ALBEDO"] = "albedo";
567572
actions.renames["ALPHA"] = "alpha";
568573
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha";
@@ -640,6 +645,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
640645
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
641646
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
642647
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
648+
actions.usage_defines["BENT_NORMAL_MAP"] = "#define BENT_NORMAL_MAP_USED\n";
643649
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
644650
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
645651
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";

0 commit comments

Comments
 (0)