英文:
What is height texture used for?
问题
从资产商店下载了纹理资产。但是有一个名为XX_height.png的纹理,如下所示。
我明白这大约包含高度信息,但我认为这些信息实际上不会在顶点着色器中调整高度,我想知道它在片段着色器中如何使用。
谢谢。
英文:
Downloaded texture asset from asset store. But there's a texture called XX_height.png as shown below.
I understand that there is approximately height information, but I don't think this information will actually adjust the height in the vertex shader, and I'm wondering how it's used in the fragment shader.
Thank you.
答案1
得分: 2
以下是翻译好的内容:
"基于视图,它对UV坐标进行了扭曲,以给你深度的错觉。
描绘(抱歉,由于压缩伪像):
你在这里看到的是一个四边形网格的动画GIF旋转。阿尔贝多纹理是Godot图标,高度纹理是棋盘格。还有一些压缩伪像。
请注意,高度纹理中黑色部分似乎比白色部分更远(它们有额外的视差)。你可以通过改变heightmap_scale
来控制它们看起来有多远。当然,这是在不移动顶点的情况下完成的。
由于Godot允许我们将材质转换为着色器材质,我们可以查看获取此效果的代码(已删除未使用的uniform和额外的空格):
// 注意:着色器自动从Godot Engine 4.1.dev1的StandardMaterial3D转换而来。
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable;
uniform float roughness : hint_range(0, 1);
uniform sampler2D texture_metallic : hint_default_white, filter_linear_mipmap, repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r, filter_linear_mipmap, repeat_enable;
uniform float specular;
uniform float metallic;
uniform sampler2D texture_heightmap : hint_default_black, filter_linear_mipmap, repeat_enable;
uniform float heightmap_scale;
uniform vec2 heightmap_flip;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
void vertex() {
UV = UV * uv1_scale.xy + uv1_offset.xy;
}
void fragment() {
vec2 base_uv = UV;
{
vec3 view_dir = normalize(normalize(-VERTEX) * mat3(TANGENT * heightmap_flip.x, -BINORMAL * heightmap_flip.y, NORMAL));
float depth = 1.0 - texture(texture_heightmap, base_uv).r;
vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale * 0.01;
base_uv = ofs;
}
vec4 albedo_tex = texture(texture_albedo, base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
float metallic_tex = dot(texture(texture_metallic, base_uv), metallic_texture_channel);
METALLIC = metallic_tex * metallic;
vec4 roughness_texture_channel = vec4(1.0, 0.0, 0.0, 0.0);
float roughness_tex = dot(texture(texture_roughness, base_uv), roughness_texture_channel);
ROUGHNESS = roughness_tex * roughness;
SPECULAR = specular;
}
关于heightmap_enabled
的文档说:
> 如果为true
,则启用高度映射(也称为“视差映射”或“深度映射”)。还请参阅[normal_enabled
][2]。高度映射是GPU上的一项要求很高的功能,因此只应在对视觉效果产生显著影响的材质上使用。
如果我们还启用[heightmap_deep_parallax
][3],Godot将填充高度的悬崖... 我不知道如何更好地表达。
再次描绘(对于压缩伪像,我再次表示抱歉):
![enter image description here][4]
这是代码:
// 注意:着色器自动从Godot Engine 4.1.dev1的StandardMaterial3D转换而来。
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable;
uniform float roughness : hint_range(0, 1);
uniform sampler2D texture_metallic : hint_default_white, filter_linear_mipmap, repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r, filter_linear_mipmap, repeat_enable;
uniform float specular;
uniform float metallic;
uniform sampler2D texture_heightmap : hint_default_black, filter_linear_mipmap, repeat_enable;
uniform float heightmap_scale;
uniform int heightmap_min_layers;
uniform int heightmap_max_layers;
uniform vec2 heightmap_flip;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
void vertex() {
UV = UV * uv1_scale.xy + uv1_offset.xy;
}
void fragment() {
vec2 base_uv = UV;
{
vec3 view_dir = normalize(normalize(-VERTEX) * mat3(TANGENT * heightmap_flip.x, -BINORMAL * heightmap_flip.y, NORMAL));
float num_layers = mix(float(heightmap_max_layers), float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));
float layer_depth = 1.0 / num_layers;
vec2 P = view_dir.xy * heightmap_scale * 0.01;
vec2 delta = P / num_layers;
vec2 ofs = base_uv;
float depth = 1.0 - texture(texture_heightmap, ofs).r;
float current_depth = 0.0;
while (current_depth < depth) {
ofs -= delta;
depth = 1.0 - texture(texture_heightmap, ofs).r;
current_depth += layer_depth;
}
vec2 prev_ofs = ofs + delta;
float after_depth = depth - current_depth;
float before_depth = (1.0 - texture(texture_heightmap, prev_ofs).r) - current_depth + layer_depth;
float weight = after_depth / (after_depth - before_depth);
ofs = mix(ofs, prev_ofs, weight);
base_uv = ofs;
}
vec4 albedo_tex = texture(texture_albedo, base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
float metallic_tex = dot(texture(texture_metallic, base_uv), metallic_texture_channel);
METALLIC = metallic_tex * metallic;
vec4 roughness_texture_channel = vec4(1.0, 0.0, 0.
<details>
<summary>英文:</summary>
It warps the uv coordinates based on the view to give you an illusion of depth.
Depicted (sorry by the compression artifacts):
[![enter image description here][1]][1]
What you see here is an animated GIF of a quad mesh rotating. The Albedo texture is the Godot icon, and the height texture is a checkerboard. *Plus compression artifacts.*
Observe that the parts of the height texture that are black appear to be further back (they have extra parallax) than the parts of the height texture that are white. *You can control how back they appear to be by changing the `heightmap_scale`*. This is, of course, accomplished without moving the vertex.
Since Godot allows us to convert the material to a shader material, we can see the code to get this effect (I have removed not used uniforms and extra spacing):
// NOTE: Shader automatically converted from Godot Engine 4.1.dev1's StandardMaterial3D.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
uniform float roughness : hint_range(0,1);
uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable;
uniform float specular;
uniform float metallic;
uniform sampler2D texture_heightmap : hint_default_black,filter_linear_mipmap,repeat_enable;
uniform float heightmap_scale;
uniform vec2 heightmap_flip;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
void vertex() {
UV=UV*uv1_scale.xy+uv1_offset.xy;
}
void fragment() {
vec2 base_uv = UV;
{
vec3 view_dir = normalize(normalize(-VERTEX)mat3(TANGENTheightmap_flip.x,-BINORMAL*heightmap_flip.y,NORMAL));
float depth = 1.0 - texture(texture_heightmap, base_uv).r;
vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale * 0.01;
base_uv=ofs;
}
vec4 albedo_tex = texture(texture_albedo,base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);
METALLIC = metallic_tex * metallic;
vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);
float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);
ROUGHNESS = roughness_tex * roughness;
SPECULAR = specular;
}
The documentation on `heightmap_enabled` says:
> If `true`, height mapping is enabled (also called "parallax mapping" or "depth mapping"). See also [`normal_enabled`][2]. Height mapping is a demanding feature on the GPU, so it should only be used on materials where it makes a significant visual difference.
---
If we also enable [`heightmap_deep_parallax`][3] Godot will fill the cliffs of the height... *I don't know how better to express it*.
Depicted (again, sorry for compression artifacts):
[![enter image description here][4]][4]
This is the code:
// NOTE: Shader automatically converted from Godot Engine 4.1.dev1's StandardMaterial3D.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
uniform float roughness : hint_range(0,1);
uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable;
uniform float specular;
uniform float metallic;
uniform sampler2D texture_heightmap : hint_default_black,filter_linear_mipmap,repeat_enable;
uniform float heightmap_scale;
uniform int heightmap_min_layers;
uniform int heightmap_max_layers;
uniform vec2 heightmap_flip;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
void vertex() {
UV=UV*uv1_scale.xy+uv1_offset.xy;
}
void fragment() {
vec2 base_uv = UV;
{
vec3 view_dir = normalize(normalize(-VERTEX)mat3(TANGENTheightmap_flip.x,-BINORMAL*heightmap_flip.y,NORMAL));
float num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));
float layer_depth = 1.0 / num_layers;
vec2 P = view_dir.xy * heightmap_scale * 0.01;
vec2 delta = P / num_layers;
vec2 ofs = base_uv;
float depth = 1.0 - texture(texture_heightmap, ofs).r;
float current_depth = 0.0;
while(current_depth < depth) {
ofs -= delta;
depth = 1.0 - texture(texture_heightmap, ofs).r;
current_depth += layer_depth;
}
vec2 prev_ofs = ofs + delta;
float after_depth = depth - current_depth;
float before_depth = ( 1.0 - texture(texture_heightmap, prev_ofs).r ) - current_depth + layer_depth;
float weight = after_depth / (after_depth - before_depth);
ofs = mix(ofs,prev_ofs,weight);
base_uv=ofs;
}
vec4 albedo_tex = texture(texture_albedo,base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);
METALLIC = metallic_tex * metallic;
vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);
float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);
ROUGHNESS = roughness_tex * roughness;
SPECULAR = specular;
}
---
This effect does not interact with the lighting model. But you can combine it with normal and occlusion textures.
---
See also:
- [Normal mapping](https://en.wikipedia.org/wiki/Normal_mapping).
- [Bump mapping](https://en.wikipedia.org/wiki/Bump_mapping).
- [Parallax mapping](https://en.wikipedia.org/wiki/Parallax_mapping).
[1]: https://i.stack.imgur.com/ZO4OC.gif
[2]: https://docs.godotengine.org/en/stable/classes/class_basematerial3d.html#class-basematerial3d-property-normal-enabled
[3]: https://docs.godotengine.org/en/stable/classes/class_basematerial3d.html#class-basematerial3d-property-heightmap-enabled
[4]: https://i.stack.imgur.com/6HY90.gif
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论