BumpOffset VisualShaderNode 4.4

A visual shader node for a simple one-step UV distortion effect meant to clone the functionality of the BumpOffset node in Unreal. Added output for offset only in case user would like to use it directly (eg add parallax effect to another texture with unique tiling without recomputing) and a channel selector for which heightmap channel to use for the parallax.

Craters texture is just an example of how you would use it with a heightmap.

To use this script, copy paste it into a .gd file. It will show up in the Addons/UV category when adding a new visual shader node

Shader code
@tool
extends VisualShaderNodeCustom
class_name VSNode_BumpOffset

const HEIGHT_CONSTANT_SCALE : float = 0.1

#########################
### Editor Shader Props
#########################
func _get_name() -> String:
	return "BumpOffset"


func _get_category() -> String:
	return "UV"


func _get_description() -> String:
	return "Distorts the uvs to appear to have parallax based on a heightmap. UE equivalent is BumpOffset node."


func _get_return_icon_type() -> PortType:
	return VisualShaderNode.PORT_TYPE_VECTOR_2D



#########################
### Input Ports
#########################
func _get_input_port_count() -> int:
	return 4

func _get_input_port_name(port: int) -> String:
	match port:
		0: return "UV"
		1: return "Height Map T2D"
		2: return "Depth Scale"
		3: return "Midpoint"
	return ""

func _get_input_port_type(port: int) -> PortType:
	match port:
		0: return VisualShaderNode.PORT_TYPE_VECTOR_2D
		1: return VisualShaderNode.PORT_TYPE_SAMPLER
		2: return VisualShaderNode.PORT_TYPE_SCALAR
		3: return VisualShaderNode.PORT_TYPE_SCALAR
	return VisualShaderNode.PORT_TYPE_VECTOR_2D

func _get_input_port_default_value(port: int) -> Variant:
	match port:
		0: return Vector2(0, 0)
		1: return ImageTexture.new()
		2: return 0.1
		3: return 0.5
	return Vector2(0, 0)

func _get_property_count() -> int:
	return 1

func _get_property_name(index: int) -> String:
	match index:
		0: return "Heightmap Channel"
	return ""

func _get_property_options(index: int) -> PackedStringArray:
	match index:
		0: return ["R", "G", "B", "A"]
	return []

##########################
### Output Ports
##########################
func _get_output_port_count() -> int:
	return 2

func _get_output_port_name(port: int) -> String:
	match port:
		0: return "UV"
		1: return "Offset"
	return "UV"

func _get_output_port_type(port: int) -> PortType:
	match port:
		0: return VisualShaderNode.PORT_TYPE_VECTOR_2D
		1: return VisualShaderNode.PORT_TYPE_VECTOR_2D
	return VisualShaderNode.PORT_TYPE_VECTOR_2D

###########################
### Global code
###########################
func _get_global_code(mode: Shader.Mode) -> String:
	return """
	"""

###########################
### Insert Code
###########################
func _get_code(input_vars: Array[String], output_vars: Array[String],
		mode: Shader.Mode, type: VisualShader.Type) -> String:
	var channel_idx : int = get_option_index(0)
	var height_name : String = "r"
	match channel_idx:
		0: height_name = "r"
		1: height_name = "g"
		2: height_name = "b"
		3: height_name = "a"
	if type == VisualShader.TYPE_FRAGMENT:
		return """
		{
		vec2 uv = %s; // inputted uv - s is the uv coord
		vec3 view_direction = normalize( -VERTEX + EYE_OFFSET ); // View direction in world space
		mat3 tbn =  mat3(-TANGENT, BINORMAL, NORMAL); // Tangent Binormal Normal matrix
		vec3 view_tangent_space = view_direction * tbn; // Transform view direction to tangent space
		float height = %s - texture( %s, uv ).%s; // Sample the height map, invert
		vec2 uv_offset = view_tangent_space.xy * height * %s * %s; // Calculate the uv offset
		vec2 distorted_uv = uv + uv_offset; // Add the offset to the original uv
		%s = distorted_uv; // Output the distorted uv
		%s = uv_offset; // Output the offset
		}
		""" % [input_vars[0], input_vars[3], input_vars[1], height_name, input_vars[2], HEIGHT_CONSTANT_SCALE, output_vars[0], output_vars[1]]

	else:
		return ""

func _is_available(mode: Shader.Mode, type: VisualShader.Type) -> bool:
	return type == VisualShader.TYPE_FRAGMENT
Tags
4.4, 4.x
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from wendallhitherd

AlphaMerge VisualShaderNode 4.4

WorldPosition VisualShaderNode 4.4

WorldPlanarProjection3D VisualShaderNode 4.4

Related shaders

WorldPosition VisualShaderNode 4.4

WorldPlanarProjection3D VisualShaderNode 4.4

Alpha Erosion VisualShaderNode 4.4

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments