mirror of
https://github.com/DigvijaysinhGohil/Godot-Shader-Lib.git
synced 2025-01-05 00:53:36 +08:00
Merge branch 'godot-4.2'
This commit is contained in:
commit
6576785b47
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
tests/
|
||||
*.import
|
||||
|
@ -0,0 +1,4 @@
|
||||
float chebyshev_distance_2d(vec2 point1, vec2 point2, float power) {
|
||||
vec2 p = abs(point1 - point2);
|
||||
return pow(pow(p.x, power) + pow(p.y, power), 1. / power);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
float chebyshev_distance_3d(vec3 point1, vec3 point2, float power) {
|
||||
vec3 p = abs(point1 - point2);
|
||||
return pow(pow(p.x, power) + pow(p.y, power) + pow(p.z, power), 1. / power);
|
||||
}
|
102
addons/ShaderLib/Maths/Vector/Distance/ChebyshevDistance.gd
Normal file
102
addons/ShaderLib/Maths/Vector/Distance/ChebyshevDistance.gd
Normal file
@ -0,0 +1,102 @@
|
||||
@tool
|
||||
class_name VisualShaderNodeMathsChebyshevDistance extends VisualShaderNodeCustom
|
||||
|
||||
func _get_name() -> String:
|
||||
return "ChebyshevDistance"
|
||||
|
||||
func _get_category() -> String:
|
||||
return "Maths/Vector/Distance"
|
||||
|
||||
func _get_description() -> String:
|
||||
return "Returns the distance between two points using Chebyshev distance matrix."
|
||||
|
||||
func _get_return_icon_type() -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_count() -> int:
|
||||
return 3
|
||||
|
||||
func _get_input_port_name(port: int) -> String:
|
||||
match port:
|
||||
0:
|
||||
return "a"
|
||||
1:
|
||||
return "b"
|
||||
_:
|
||||
return "power"
|
||||
|
||||
func _get_input_port_type(port: int) -> PortType:
|
||||
var vector_index: int = get_option_index(0)
|
||||
match port:
|
||||
2:
|
||||
return PORT_TYPE_SCALAR
|
||||
_:
|
||||
match vector_index:
|
||||
0:
|
||||
return PORT_TYPE_VECTOR_2D
|
||||
_:
|
||||
return PORT_TYPE_VECTOR_3D
|
||||
|
||||
func _get_input_port_default_value(port: int) -> Variant:
|
||||
match port:
|
||||
2:
|
||||
return 2.0
|
||||
_:
|
||||
return null
|
||||
|
||||
func _get_output_port_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_output_port_name(port: int) -> String:
|
||||
return "distance"
|
||||
|
||||
func _get_output_port_type(port: int) -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_property_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_property_name(index: int) -> String:
|
||||
return ""
|
||||
|
||||
func _get_property_default_index(index: int) -> int:
|
||||
return 0
|
||||
|
||||
func _get_property_options(index: int) -> PackedStringArray:
|
||||
return ["Vector2", "Vector3"]
|
||||
|
||||
func _get_global_code(mode: Shader.Mode) -> String:
|
||||
var code: String
|
||||
var vector_index: int = get_option_index(0)
|
||||
match vector_index:
|
||||
0:
|
||||
code = preload("Chebyshev2D.gdshaderinc").code
|
||||
_:
|
||||
code = preload("Chebyshev3D.gdshaderinc").code
|
||||
return code
|
||||
|
||||
func _get_code(input_vars: Array[String], output_vars: Array[String], mode: Shader.Mode, type: VisualShader.Type) -> String:
|
||||
var point_a: String
|
||||
var point_b: String
|
||||
var power: String = input_vars[2]
|
||||
var vector_index: int = get_option_index(0)
|
||||
match vector_index:
|
||||
0:
|
||||
point_a = "vec2(0)"
|
||||
point_b = "vec2(0)"
|
||||
_:
|
||||
point_b = "vec3(0)"
|
||||
point_a = "vec3(0)"
|
||||
|
||||
if input_vars[0]:
|
||||
point_a = input_vars[0]
|
||||
|
||||
if input_vars[1]:
|
||||
point_b = input_vars[1]
|
||||
|
||||
match vector_index:
|
||||
0:
|
||||
return output_vars[0] + " = chebyshev_distance_2d(%s, %s, %s);" % [point_a, point_b, power]
|
||||
_:
|
||||
return output_vars[0] + " = chebyshev_distance_3d(%s, %s, %s);" % [point_a, point_b, power]
|
||||
|
@ -0,0 +1,4 @@
|
||||
float manhattan_distance_2d(vec2 point1, vec2 point2) {
|
||||
vec2 d = point1 - point2;
|
||||
return abs(d.x) + abs(d.y);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
float manhattan_distance_3d(vec3 point1, vec3 point2) {
|
||||
vec3 d = point1 - point2;
|
||||
return abs(d.x) + abs(d.y) + abs(d.z);
|
||||
}
|
88
addons/ShaderLib/Maths/Vector/Distance/ManhattanDistance.gd
Normal file
88
addons/ShaderLib/Maths/Vector/Distance/ManhattanDistance.gd
Normal file
@ -0,0 +1,88 @@
|
||||
@tool
|
||||
class_name VisualShaderNodeMathsManhattanDistance extends VisualShaderNodeCustom
|
||||
|
||||
func _get_name() -> String:
|
||||
return "ManhattanDistance"
|
||||
|
||||
func _get_category() -> String:
|
||||
return "Maths/Vector/Distance"
|
||||
|
||||
func _get_description() -> String:
|
||||
return "Returns the distance between two points using Manhattan distance matrix."
|
||||
|
||||
func _get_return_icon_type() -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_count() -> int:
|
||||
return 2
|
||||
|
||||
func _get_input_port_name(port: int) -> String:
|
||||
match port:
|
||||
0:
|
||||
return "a"
|
||||
_:
|
||||
return "b"
|
||||
|
||||
func _get_input_port_type(port: int) -> PortType:
|
||||
var vector_index: int = get_option_index(0)
|
||||
match vector_index:
|
||||
0:
|
||||
return PORT_TYPE_VECTOR_2D
|
||||
_:
|
||||
return PORT_TYPE_VECTOR_3D
|
||||
|
||||
func _get_output_port_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_output_port_name(port: int) -> String:
|
||||
return "distance"
|
||||
|
||||
func _get_output_port_type(port: int) -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_property_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_property_name(index: int) -> String:
|
||||
return ""
|
||||
|
||||
func _get_property_default_index(index: int) -> int:
|
||||
return 0
|
||||
|
||||
func _get_property_options(index: int) -> PackedStringArray:
|
||||
return ["Vector2", "Vector3"]
|
||||
|
||||
func _get_global_code(mode: Shader.Mode) -> String:
|
||||
var code: String
|
||||
var vector_index: int = get_option_index(0)
|
||||
match vector_index:
|
||||
0:
|
||||
code = preload("Manhattan2D.gdshaderinc").code
|
||||
_:
|
||||
code = preload("Manhattan3D.gdshaderinc").code
|
||||
return code
|
||||
|
||||
func _get_code(input_vars: Array[String], output_vars: Array[String], mode: Shader.Mode, type: VisualShader.Type) -> String:
|
||||
var point_a: String
|
||||
var point_b: String
|
||||
var vector_index: int = get_option_index(0)
|
||||
match vector_index:
|
||||
0:
|
||||
point_a = "vec2(0)"
|
||||
point_b = "vec2(0)"
|
||||
_:
|
||||
point_b = "vec3(0)"
|
||||
point_a = "vec3(0)"
|
||||
|
||||
if input_vars[0]:
|
||||
point_a = input_vars[0]
|
||||
|
||||
if input_vars[1]:
|
||||
point_b = input_vars[1]
|
||||
|
||||
match vector_index:
|
||||
0:
|
||||
return output_vars[0] + " = manhattan_distance_2d(%s, %s);" % [point_a, point_b]
|
||||
_:
|
||||
return output_vars[0] + " = manhattan_distance_3d(%s, %s);" % [point_a, point_b]
|
||||
|
@ -1,14 +1,14 @@
|
||||
vec3 vector_transform_world_to_local(mat4 model_matrix, vec3 vector){
|
||||
return (transpose(model_matrix) * vec4(vector, 0.0)).xyz;
|
||||
return (inverse(model_matrix) * vec4(vector, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec3 vector_transform_world_to_view(mat4 view_matrix, vec3 vector){
|
||||
return (view_matrix * vec4(vector, 0.0)).xyz;
|
||||
return (view_matrix * vec4(vector, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec3 vector_transform_world_to_screen(mat4 view_matrix, mat4 projection_matrix, vec3 vector){
|
||||
vec3 vector_view = vector_transform_world_to_view(view_matrix, vector);
|
||||
return (projection_matrix * vec4(vector_view, 0.0)).xyz;
|
||||
return (projection_matrix * vec4(vector_view, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec3 vector_transform_world_to_tangent(mat4 model_matrix, vec3 normal, vec3 binormal, vec3 tangent, vec3 vector){
|
||||
@ -18,17 +18,17 @@ vec3 vector_transform_world_to_tangent(mat4 model_matrix, vec3 normal, vec3 bino
|
||||
}
|
||||
|
||||
vec3 vector_transform_local_to_world(mat4 model_matrix, vec3 vector){
|
||||
return (model_matrix * vec4(vector, 0.0)).xyz;
|
||||
return (model_matrix * vec4(vector, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec3 vector_transform_local_to_view(mat4 model_matrix, mat4 view_matrix, vec3 vector){
|
||||
vec3 vector_world = vector_transform_local_to_world(model_matrix, vector);
|
||||
return (view_matrix * vec4(vector_world, 0.0)).xyz;
|
||||
return (view_matrix * vec4(vector_world, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec3 vector_transform_local_to_screen(mat4 model_matrix, mat4 view_matrix, mat4 projection_matrix, vec3 vector){
|
||||
vec3 vector_view = vector_transform_local_to_view(model_matrix, view_matrix, vector);
|
||||
return (projection_matrix * vec4(vector_view, 0.0)).xyz;
|
||||
return (projection_matrix * vec4(vector_view, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec3 vector_transform_local_to_tangent(vec3 normal, vec3 binormal, vec3 tangent, vec3 vector){
|
||||
@ -37,7 +37,7 @@ vec3 vector_transform_local_to_tangent(vec3 normal, vec3 binormal, vec3 tangent,
|
||||
}
|
||||
|
||||
vec3 vector_transform_view_to_world(mat4 inv_view_matrix, vec3 vector){
|
||||
return (inv_view_matrix * vec4(vector, 0.0)).xyz;;
|
||||
return (inv_view_matrix * vec4(vector, 1.0)).xyz;;
|
||||
}
|
||||
|
||||
vec3 vector_transform_view_to_local(mat4 inv_view_matrix, mat4 model_matrix, vec3 vector){
|
||||
@ -46,7 +46,7 @@ vec3 vector_transform_view_to_local(mat4 inv_view_matrix, mat4 model_matrix, vec
|
||||
}
|
||||
|
||||
vec3 vector_transform_view_to_screen(mat4 projection_matrix, vec3 vector){
|
||||
return (projection_matrix * vec4(vector, 0.0)).xyz;
|
||||
return (projection_matrix * vec4(vector, 1.0)).xyz;
|
||||
}
|
||||
|
||||
vec3 vector_transform_view_to_tangent(mat4 inv_view_matrix, mat4 model_matrix, vec3 normal, vec3 binormal, vec3 tangent, vec3 vector){
|
||||
@ -56,7 +56,7 @@ vec3 vector_transform_view_to_tangent(mat4 inv_view_matrix, mat4 model_matrix, v
|
||||
}
|
||||
|
||||
vec3 vector_transform_screen_to_view(mat4 inv_projection_matrix, vec3 vector){
|
||||
return (inv_projection_matrix * vec4(vector, 0.0)).xyz;;
|
||||
return (inv_projection_matrix * vec4(vector, 1.0)).xyz;;
|
||||
}
|
||||
|
||||
vec3 vector_transform_screen_to_local(mat4 inv_projection_matrix, mat4 inv_view_matrix, mat4 model_matrix, vec3 vector){
|
||||
@ -76,24 +76,24 @@ vec3 vector_transform_screen_to_tangent(mat4 inv_projection_matrix, mat4 inv_vie
|
||||
}
|
||||
|
||||
vec3 vector_transform_tangent_to_local(vec3 normal, vec3 binormal, vec3 tangent, vec3 vector){
|
||||
mat3 tangent_to_local_matrix = transpose(mat3(tangent, binormal, normal));
|
||||
mat3 tangent_to_local_matrix = inverse(mat3(tangent, binormal, normal));
|
||||
return tangent_to_local_matrix * vector;
|
||||
}
|
||||
|
||||
vec3 vector_transform_tangent_to_world(mat4 model_matrix, vec3 normal, vec3 binormal, vec3 tangent, vec3 vector){
|
||||
mat3 tangent_to_local_matrix = transpose(mat3(tangent, binormal, normal));
|
||||
mat3 tangent_to_local_matrix = inverse(mat3(tangent, binormal, normal));
|
||||
vec3 vector_local = tangent_to_local_matrix * vector;
|
||||
return vector_transform_local_to_world(model_matrix, vector_local);
|
||||
}
|
||||
|
||||
vec3 vector_transform_tangent_to_view(mat4 model_matrix, mat4 view_matrix, vec3 normal, vec3 binormal, vec3 tangent, vec3 vector){
|
||||
mat3 tangent_to_local_matrix = transpose(mat3(tangent, binormal, normal));
|
||||
mat3 tangent_to_local_matrix = inverse(mat3(tangent, binormal, normal));
|
||||
vec3 vector_local = tangent_to_local_matrix * vector;
|
||||
return vector_transform_local_to_view(model_matrix, view_matrix, vector_local);
|
||||
}
|
||||
|
||||
vec3 vector_transform_tangent_to_screen(mat4 model_matrix, mat4 view_matrix, mat4 projection_matrix, vec3 normal, vec3 binormal, vec3 tangent, vec3 vector){
|
||||
mat3 tangent_to_local_matrix = transpose(mat3(tangent, binormal, normal));
|
||||
mat3 tangent_to_local_matrix = inverse(mat3(tangent, binormal, normal));
|
||||
vec3 vector_local = tangent_to_local_matrix * vector;
|
||||
return vector_transform_local_to_screen(model_matrix, view_matrix, projection_matrix, vector_local);
|
||||
}
|
||||
|
79
addons/ShaderLib/Procedural/Noise/GyroidNoise.gd
Normal file
79
addons/ShaderLib/Procedural/Noise/GyroidNoise.gd
Normal file
@ -0,0 +1,79 @@
|
||||
@tool
|
||||
class_name VisualShaderNodeProceduralGyroidNoise extends VisualShaderNodeCustom
|
||||
|
||||
func _init() -> void:
|
||||
output_port_for_preview = 0
|
||||
|
||||
func _get_name() -> String:
|
||||
return "GyroidNoise"
|
||||
|
||||
func _get_category() -> String:
|
||||
return "Procedural/Noise"
|
||||
|
||||
func _get_description() -> String:
|
||||
return "Generates a gyroid noise based on input UV."
|
||||
|
||||
func _get_return_icon_type() -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_count() -> int:
|
||||
return 5
|
||||
|
||||
func _get_input_port_name(port: int) -> String:
|
||||
match port:
|
||||
0:
|
||||
return "uv"
|
||||
1:
|
||||
return "scale"
|
||||
2:
|
||||
return "ratio"
|
||||
3:
|
||||
return "height"
|
||||
_:
|
||||
return "thickness"
|
||||
|
||||
func _get_input_port_type(port: int) -> PortType:
|
||||
match port:
|
||||
0, 2:
|
||||
return PORT_TYPE_VECTOR_2D
|
||||
_:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_default_value(port: int) -> Variant:
|
||||
match port:
|
||||
1:
|
||||
return 2.0
|
||||
2:
|
||||
return Vector2(1, 1)
|
||||
3:
|
||||
return 0.5
|
||||
4:
|
||||
return 0.0
|
||||
_:
|
||||
return null
|
||||
|
||||
func _get_output_port_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_output_port_name(port: int) -> String:
|
||||
return "output"
|
||||
|
||||
func _get_output_port_type(port: int) -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_global_code(mode: Shader.Mode) -> String:
|
||||
var code: String = preload("GyroidNoise.gdshaderinc").code
|
||||
return code
|
||||
|
||||
func _get_code(input_vars: Array[String], output_vars: Array[String], mode: Shader.Mode, type: VisualShader.Type) -> String:
|
||||
var uv: String = "UV"
|
||||
|
||||
if input_vars[0]:
|
||||
uv = input_vars[0]
|
||||
|
||||
var scale: String = input_vars[1]
|
||||
var ratio: String = input_vars[2]
|
||||
var height: String = input_vars[3]
|
||||
var thickness: String = input_vars[4]
|
||||
|
||||
return output_vars[0] + " = gyroid_noise(%s, %s, %s, %s, %s);" % [uv, scale, ratio, height, thickness]
|
@ -0,0 +1,7 @@
|
||||
float gyroid_noise(vec2 uv, float scale, vec2 ratio, float height, float thickness) {
|
||||
scale *= 10.;
|
||||
thickness = clamp(thickness, 0., 1.);
|
||||
vec3 vector = vec3(uv, height);
|
||||
vector *= scale;
|
||||
return abs(dot(sin(vector * ratio.x), cos(vector.zxy * ratio.y))) - thickness;
|
||||
}
|
@ -17,7 +17,7 @@ func _get_return_icon_type() -> VisualShaderNode.PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_count() -> int:
|
||||
return 2
|
||||
return 3
|
||||
|
||||
func _get_input_port_name(port: int) -> String:
|
||||
match port:
|
||||
@ -25,7 +25,8 @@ func _get_input_port_name(port: int) -> String:
|
||||
return "uv"
|
||||
1:
|
||||
return "scale"
|
||||
return ""
|
||||
_:
|
||||
return "octaves"
|
||||
|
||||
func _get_input_port_type(port: int) -> VisualShaderNode.PortType:
|
||||
match port:
|
||||
@ -33,12 +34,15 @@ func _get_input_port_type(port: int) -> VisualShaderNode.PortType:
|
||||
return PORT_TYPE_VECTOR_2D
|
||||
1:
|
||||
return PORT_TYPE_SCALAR
|
||||
return PORT_TYPE_SCALAR
|
||||
_:
|
||||
return PORT_TYPE_SCALAR_INT
|
||||
|
||||
func _get_input_port_default_value(port: int) -> Variant:
|
||||
match port:
|
||||
1:
|
||||
return 10.0
|
||||
2:
|
||||
return 6
|
||||
_:
|
||||
return null
|
||||
|
||||
@ -62,5 +66,6 @@ func _get_code(input_vars: Array[String], output_vars: Array[String], mode: Shad
|
||||
uv = input_vars[0]
|
||||
|
||||
var scale: String = input_vars[1]
|
||||
var octaves: String = input_vars[2]
|
||||
|
||||
return output_vars[0] + " = simple_noise(%s, %s);" % [uv, scale]
|
||||
return output_vars[0] + " = simple_noise(%s, %s, %s);" % [uv, scale, octaves]
|
||||
|
@ -1,32 +1,33 @@
|
||||
float noise_random_value(vec2 uv){
|
||||
return fract(sin(dot(uv.xy, vec2(12.9898,78.233))) * 43758.5453123);
|
||||
float simple_noise_random(vec2 point) {
|
||||
return fract(sin(point.x * 100. + point.y * 654.125) * 55647.8745);
|
||||
}
|
||||
|
||||
float value_noise(vec2 uv){
|
||||
vec2 _floor = floor(uv);
|
||||
vec2 _fraction = fract(uv);
|
||||
_fraction = _fraction * _fraction * (3.0 - 2.0 * _fraction);
|
||||
vec2 _corner = vec2(1.0, 0.0);
|
||||
float value_noise(vec2 uv) {
|
||||
vec2 grid_uv = fract(uv);
|
||||
vec2 grid_id = floor(uv);
|
||||
grid_uv = grid_uv * grid_uv * (3. - 2. * grid_uv);
|
||||
|
||||
float _c0 = noise_random_value(_floor + _corner.yy);
|
||||
float _c1 = noise_random_value(_floor + _corner.xy);
|
||||
float _c2 = noise_random_value(_floor + _corner.yx);
|
||||
float _c3 = noise_random_value(_floor + _corner.xx);
|
||||
float bottom_left = simple_noise_random(grid_id);
|
||||
float bottom_right = simple_noise_random(grid_id + vec2(1, 0));
|
||||
float bottom = mix(bottom_left, bottom_right, grid_uv.x);
|
||||
|
||||
vec2 _blur = smoothstep(0.0, 1.0, _fraction);
|
||||
float mix_one = mix(_c0, _c1, _blur.x) + (_c2 - _c0) * _blur.y * (1.0 - _blur.x) + (_c3 - _c1) * _blur.x * _blur.y;
|
||||
return mix_one;
|
||||
float top_left = simple_noise_random(grid_id + vec2(0, 1));
|
||||
float top_right = simple_noise_random(grid_id + vec2(1, 1));
|
||||
float top = mix(top_left, top_right, grid_uv.x);
|
||||
|
||||
return mix(bottom, top, grid_uv.y);
|
||||
}
|
||||
|
||||
float simple_noise(vec2 uv, float scale){
|
||||
int octaves = 6;
|
||||
float amplitude = 0.25;
|
||||
float value = 0.0;
|
||||
float simple_noise(vec2 uv, float scale, int octaves) {
|
||||
octaves = clamp(octaves, 1, 6);
|
||||
float noise = value_noise(uv * scale);
|
||||
float amplitude = 1.;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
value += amplitude * value_noise(scale * uv);
|
||||
amplitude *= 0.85;
|
||||
scale *= 3.0;
|
||||
for(int i = 1; i < octaves; i++) {
|
||||
scale *= 2.;
|
||||
amplitude /= 2.;
|
||||
noise += value_noise(uv * scale) * amplitude;
|
||||
}
|
||||
return value;
|
||||
|
||||
return noise / 2.;
|
||||
}
|
@ -17,34 +17,63 @@ func _get_return_icon_type() -> VisualShaderNode.PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_count() -> int:
|
||||
return 3
|
||||
var distance_index: int = get_option_index(0)
|
||||
match distance_index:
|
||||
2:
|
||||
return 4
|
||||
_:
|
||||
return 3
|
||||
|
||||
func _get_input_port_name(port: int) -> String:
|
||||
match port:
|
||||
0:
|
||||
return "uv"
|
||||
1:
|
||||
return "cell density"
|
||||
var distance_index: int = get_option_index(0)
|
||||
match distance_index:
|
||||
2:
|
||||
return "angle offset"
|
||||
return ""
|
||||
match port:
|
||||
0:
|
||||
return "uv"
|
||||
1:
|
||||
return "cell density"
|
||||
2:
|
||||
return "angle offset"
|
||||
_:
|
||||
return "chebyshev power"
|
||||
_:
|
||||
match port:
|
||||
0:
|
||||
return "uv"
|
||||
1:
|
||||
return "cell density"
|
||||
_:
|
||||
return "angle offset"
|
||||
|
||||
func _get_input_port_type(port: int) -> VisualShaderNode.PortType:
|
||||
match port:
|
||||
0:
|
||||
return PORT_TYPE_VECTOR_2D
|
||||
1, 2:
|
||||
_:
|
||||
return PORT_TYPE_SCALAR
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_default_value(port: int) -> Variant:
|
||||
match port:
|
||||
1:
|
||||
return 5.0
|
||||
var distance_index: int = get_option_index(0)
|
||||
match distance_index:
|
||||
2:
|
||||
return 2.0
|
||||
match port:
|
||||
1:
|
||||
return 5.0
|
||||
2:
|
||||
return 2.0
|
||||
3:
|
||||
return 2.0
|
||||
_:
|
||||
return null
|
||||
_:
|
||||
return null
|
||||
match port:
|
||||
1:
|
||||
return 5.0
|
||||
2:
|
||||
return 2.0
|
||||
_:
|
||||
return null
|
||||
|
||||
func _get_output_port_count() -> int:
|
||||
return 2
|
||||
@ -53,13 +82,24 @@ func _get_output_port_name(port: int) -> String:
|
||||
match port:
|
||||
0:
|
||||
return "output"
|
||||
1:
|
||||
_:
|
||||
return "cells"
|
||||
return ""
|
||||
|
||||
func _get_output_port_type(port: int) -> VisualShaderNode.PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_property_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_property_name(index: int) -> String:
|
||||
return "Distance"
|
||||
|
||||
func _get_property_default_index(index: int) -> int:
|
||||
return 0
|
||||
|
||||
func _get_property_options(index: int) -> PackedStringArray:
|
||||
return ["Euclidean", "Manhattan", "Chebyshev"]
|
||||
|
||||
func _get_global_code(mode: Shader.Mode) -> String:
|
||||
var code: String = preload("Voronoi.gdshaderinc").code
|
||||
return code
|
||||
@ -70,9 +110,17 @@ func _get_code(input_vars: Array[String], output_vars: Array[String], mode: Shad
|
||||
if input_vars[0]:
|
||||
uv = input_vars[0]
|
||||
|
||||
var distance_index: int = get_option_index(0)
|
||||
|
||||
var cell_density: String = input_vars[1]
|
||||
var angle_offset: String = input_vars[2]
|
||||
var chebyshev_power: String = "0."
|
||||
|
||||
if distance_index == 2:
|
||||
if input_vars[3]:
|
||||
chebyshev_power = input_vars[3]
|
||||
|
||||
var output: String = output_vars[0]
|
||||
var cells: String = output_vars[1]
|
||||
|
||||
return "voronoi_noise(%s,%s, %s, %s, %s);" % [uv, cell_density, angle_offset, output, cells]
|
||||
return "voronoi_noise(%s, %s, %s, %s, %s, %s, %s);" % [uv, cell_density, angle_offset, distance_index, chebyshev_power, output, cells]
|
||||
|
@ -1,24 +1,43 @@
|
||||
void voronoi_noise(vec2 uv, float cell_density, float angle_offset, out float output, out float cells){
|
||||
vec2 _g = floor(uv * cell_density);
|
||||
vec2 _f = fract(uv * cell_density);
|
||||
vec3 _res = vec3(8.0, 0.0, 0.0);
|
||||
mat2 _matrix = mat2(vec2(15.27, 47.63), vec2(99.41, 89.98));
|
||||
|
||||
for(int y=-1; y<=1; y++)
|
||||
{
|
||||
for(int x=-1; x<=1; x++)
|
||||
{
|
||||
vec2 lattice = vec2(float(x), float(y));
|
||||
vec2 new_uv = lattice + _g;
|
||||
new_uv = fract(sin(new_uv * _matrix) * 46839.32);
|
||||
vec2 offset = vec2(sin(new_uv.y * angle_offset) * 0.5 + 0.5, cos(new_uv.x * angle_offset) * 0.5 + 0.5);
|
||||
float d = distance(lattice + offset, _f);
|
||||
if(d < _res.x)
|
||||
{
|
||||
_res = vec3(d, offset.x, offset.y);
|
||||
output = _res.x;
|
||||
cells = _res.y;
|
||||
#include "res://addons/ShaderLib/Maths/Vector/Distance/Manhattan2D.gdshaderinc"
|
||||
#include "res://addons/ShaderLib/Maths/Vector/Distance/Chebyshev2D.gdshaderinc"
|
||||
|
||||
vec2 voronoi_random_vector(vec2 p) {
|
||||
mat2 matrix = mat2(vec2(15.27, 47.63), vec2(99.41, 89.98));
|
||||
return fract(sin(p * matrix) * 46839.32);
|
||||
}
|
||||
|
||||
void voronoi_noise(vec2 uv, float cell_density, float angle_offset, int distance_index, float chebyshev_power, out float output, out float cells){
|
||||
vec2 grid_uv = fract(uv * cell_density);
|
||||
vec2 grid_id = floor(uv * cell_density);
|
||||
vec2 cell_id = vec2(0);
|
||||
float min_dist = 100.;
|
||||
|
||||
for(float y = -1.; y <= 1.; y++) {
|
||||
for(float x = -1.; x <= 1.; x++) {
|
||||
vec2 offset = vec2(x, y);
|
||||
vec2 n = voronoi_random_vector(grid_id + offset);
|
||||
vec2 p = offset + vec2(sin(n.x + angle_offset) * .5 + .5, cos(n.y + angle_offset) * .5 + .5);
|
||||
float d = min_dist;
|
||||
|
||||
switch(distance_index){
|
||||
case 1:
|
||||
d = manhattan_distance_2d(grid_uv, p);
|
||||
break;
|
||||
case 2:
|
||||
d = chebyshev_distance_2d(grid_uv, p, chebyshev_power);
|
||||
break;
|
||||
default:
|
||||
d = distance(grid_uv, p);
|
||||
break;
|
||||
}
|
||||
|
||||
if(d < min_dist) {
|
||||
min_dist = d;
|
||||
cell_id = voronoi_random_vector(grid_id + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output = min_dist;
|
||||
cells = cell_id.y;
|
||||
}
|
239
addons/ShaderLib/RayMarching/RayMarch.gd
Normal file
239
addons/ShaderLib/RayMarching/RayMarch.gd
Normal file
@ -0,0 +1,239 @@
|
||||
@tool
|
||||
class_name VisualShaderNodeRayMarch extends VisualShaderNodeCustom
|
||||
|
||||
func _get_name() -> String:
|
||||
return "RayMarch"
|
||||
|
||||
func _get_category() -> String:
|
||||
return "RayMarching"
|
||||
|
||||
func _get_description() -> String:
|
||||
return "A simple ray marcher for primitive shapes."
|
||||
|
||||
func _get_return_icon_type() -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_count() -> int:
|
||||
var sdf_index: int = get_option_index(0)
|
||||
match sdf_index:
|
||||
2, 3, 4:
|
||||
return 9
|
||||
_:
|
||||
return 8
|
||||
|
||||
func _get_input_port_name(port: int) -> String:
|
||||
var sdf_index: int = get_option_index(0)
|
||||
match sdf_index:
|
||||
0, 1:
|
||||
match port:
|
||||
0:
|
||||
return "ray origin"
|
||||
1:
|
||||
return "ray direction"
|
||||
2:
|
||||
return "max steps"
|
||||
3:
|
||||
return "max distance"
|
||||
4:
|
||||
return "distance threshold"
|
||||
5:
|
||||
return "cube pos" if sdf_index == 0 else "sphere pos"
|
||||
6:
|
||||
return "cube eulers" if sdf_index == 0 else "sphere eulers"
|
||||
_:
|
||||
return "cube scale" if sdf_index == 0 else "sphere scale"
|
||||
2, 3:
|
||||
match port:
|
||||
0:
|
||||
return "ray origin"
|
||||
1:
|
||||
return "ray direction"
|
||||
2:
|
||||
return "max steps"
|
||||
3:
|
||||
return "max distance"
|
||||
4:
|
||||
return "distance threshold"
|
||||
5:
|
||||
return "capsule pos" if sdf_index == 2 else "cylinder pos"
|
||||
6:
|
||||
return "capsule eulers" if sdf_index == 2 else "cylinder eulers"
|
||||
7:
|
||||
return "capsule height" if sdf_index == 2 else "cylinder height"
|
||||
_:
|
||||
return "capsule radius" if sdf_index == 2 else "cylinder radius"
|
||||
_:
|
||||
match port:
|
||||
0:
|
||||
return "ray origin"
|
||||
1:
|
||||
return "ray direction"
|
||||
2:
|
||||
return "max steps"
|
||||
3:
|
||||
return "max distance"
|
||||
4:
|
||||
return "distance threshold"
|
||||
5:
|
||||
return "torus pos"
|
||||
6:
|
||||
return "torus eulers"
|
||||
7:
|
||||
return "torus small radius"
|
||||
_:
|
||||
return "torus big radius"
|
||||
|
||||
func _get_input_port_type(port: int) -> PortType:
|
||||
var sdf_index: int = get_option_index(0)
|
||||
match sdf_index:
|
||||
0, 1:
|
||||
match port:
|
||||
0, 1, 5, 6, 7:
|
||||
return PORT_TYPE_VECTOR_3D
|
||||
2:
|
||||
return PORT_TYPE_SCALAR_INT
|
||||
_:
|
||||
return PORT_TYPE_SCALAR
|
||||
2, 3:
|
||||
match port:
|
||||
0, 1, 5, 6:
|
||||
return PORT_TYPE_VECTOR_3D
|
||||
2:
|
||||
return PORT_TYPE_SCALAR_INT
|
||||
_:
|
||||
return PORT_TYPE_SCALAR
|
||||
_:
|
||||
match port:
|
||||
0, 1, 5, 6:
|
||||
return PORT_TYPE_VECTOR_3D
|
||||
2:
|
||||
return PORT_TYPE_SCALAR_INT
|
||||
_:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_input_port_default_value(port: int) -> Variant:
|
||||
var sdf_index: int = get_option_index(0)
|
||||
match sdf_index:
|
||||
0, 1:
|
||||
match port:
|
||||
0, 5, 6:
|
||||
return Vector3(0, 0, 0)
|
||||
1:
|
||||
return Vector3(0 ,0 ,-1)
|
||||
2:
|
||||
return 15
|
||||
3:
|
||||
return 15.0
|
||||
7:
|
||||
return Vector3(0.3, 0.3, 0.3)
|
||||
_:
|
||||
return 1e-2
|
||||
2, 3:
|
||||
match port:
|
||||
0, 5, 6:
|
||||
return Vector3(0, 0, 0)
|
||||
1:
|
||||
return Vector3(0 ,0 ,-1)
|
||||
2:
|
||||
return 15
|
||||
3:
|
||||
return 15.0
|
||||
4:
|
||||
return 1e-2
|
||||
7:
|
||||
return .5 if sdf_index == 2 else 1.0
|
||||
_:
|
||||
return .3
|
||||
_:
|
||||
match port:
|
||||
0, 5, 6:
|
||||
return Vector3(0, 0, 0)
|
||||
1:
|
||||
return Vector3(0 ,0 ,-1)
|
||||
2:
|
||||
return 15
|
||||
3:
|
||||
return 15.0
|
||||
4:
|
||||
return 1e-2
|
||||
7:
|
||||
return 0.1
|
||||
_:
|
||||
return 0.4
|
||||
|
||||
func _get_property_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_property_default_index(index: int) -> int:
|
||||
return 0
|
||||
|
||||
func _get_property_name(index: int) -> String:
|
||||
return "SDF"
|
||||
|
||||
func _get_property_options(index: int) -> PackedStringArray:
|
||||
return ["SDBox", "SDSphere", "SDCapsule", "SDCylinder", "SDTorus"]
|
||||
|
||||
func _get_output_port_count() -> int:
|
||||
return 1
|
||||
|
||||
func _get_output_port_name(port: int) -> String:
|
||||
return "distance"
|
||||
|
||||
func _get_output_port_type(port: int) -> PortType:
|
||||
return PORT_TYPE_SCALAR
|
||||
|
||||
func _get_global_code(mode: Shader.Mode) -> String:
|
||||
var code: String
|
||||
var sdf_index: int = get_option_index(0)
|
||||
code = preload("RayMarchRotation.gdshaderinc").code
|
||||
match sdf_index:
|
||||
0:
|
||||
code += preload("SDBox.gdshaderinc").code
|
||||
1:
|
||||
code += preload("SDSphere.gdshaderinc").code
|
||||
2:
|
||||
code += preload("SDCapsule.gdshaderinc").code
|
||||
3:
|
||||
code += preload("SDCylinder.gdshaderinc").code
|
||||
_:
|
||||
code += preload("SDTorus.gdshaderinc").code
|
||||
return code
|
||||
|
||||
func _get_code(input_vars: Array[String], output_vars: Array[String], mode: Shader.Mode, type: VisualShader.Type) -> String:
|
||||
var sdf_index: int = get_option_index(0)
|
||||
var ray_origin: String = input_vars[0]
|
||||
var ray_direction: String = input_vars[1]
|
||||
var max_steps: String = input_vars[2]
|
||||
var max_dist: String = input_vars[3]
|
||||
var dist_threshold: String = input_vars[4]
|
||||
|
||||
match sdf_index:
|
||||
0:
|
||||
var cube_pos: String = input_vars[5]
|
||||
var eulers: String = input_vars[6]
|
||||
var size: String = input_vars[7]
|
||||
return output_vars[0] + " = ray_march_sd_box(%s, %s, %s, %s, %s, %s, %s, %s);" % [ray_origin, ray_direction, max_steps, max_dist, dist_threshold, cube_pos, eulers, size]
|
||||
1:
|
||||
var sphere_pos: String = input_vars[5]
|
||||
var eulers: String = input_vars[6]
|
||||
var scale: String = input_vars[7]
|
||||
return output_vars[0] + " = ray_march_sd_sphere(%s, %s, %s, %s, %s, %s, %s, %s);" % [ray_origin, ray_direction, max_steps, max_dist, dist_threshold, sphere_pos, eulers, scale]
|
||||
2:
|
||||
var capsule_pos: String = input_vars[5]
|
||||
var capsule_eulers: String = input_vars[6]
|
||||
var capsule_height: String = input_vars[7]
|
||||
var capsule_radius: String = input_vars[8]
|
||||
return output_vars[0] + " = ray_march_sd_capsule(%s, %s, %s, %s, %s, %s, %s, %s, %s);" % [ray_origin, ray_direction, max_steps, max_dist, dist_threshold, capsule_pos, capsule_height, capsule_radius, capsule_eulers]
|
||||
3:
|
||||
var cylinder_pos: String = input_vars[5]
|
||||
var cylinder_eulers: String = input_vars[6]
|
||||
var cylinder_height: String = input_vars[7]
|
||||
var cylinder_radius: String = input_vars[8]
|
||||
return output_vars[0] + " = ray_march_sd_cylinder(%s, %s, %s, %s, %s, %s, %s, %s, %s);" % [ray_origin, ray_direction, max_steps, max_dist, dist_threshold, cylinder_pos, cylinder_height, cylinder_radius, cylinder_eulers]
|
||||
_:
|
||||
var torus_pos: String = input_vars[5]
|
||||
var eulers: String = input_vars[6]
|
||||
var small_radius: String = input_vars[7]
|
||||
var big_radius: String = input_vars[8]
|
||||
return output_vars[0] + " = ray_march_sd_torus(%s, %s, %s, %s, %s, %s, %s, %s, %s);" % [ray_origin, ray_direction, max_steps, max_dist, dist_threshold, torus_pos, eulers, small_radius, big_radius]
|
||||
|
21
addons/ShaderLib/RayMarching/RayMarchCustom.gdshaderinc
Normal file
21
addons/ShaderLib/RayMarching/RayMarchCustom.gdshaderinc
Normal file
@ -0,0 +1,21 @@
|
||||
float sdf_custom(vec3 p) {
|
||||
// Basic example of Sphere SDF with radius of .3
|
||||
// Put your custom logic here
|
||||
float radius = .3;
|
||||
return length(p) - radius;
|
||||
}
|
||||
|
||||
float ray_march_custom(vec3 ray_origin, vec3 ray_dir, int max_steps, float max_dist, float dist_threshold) {
|
||||
ray_dir = normalize(ray_dir);
|
||||
dist_threshold = abs(dist_threshold);
|
||||
float dist_from_origin = 0.;
|
||||
float dist_to_surface;
|
||||
for(int i = 0; i < max_steps; i++) {
|
||||
vec3 point = ray_origin + dist_from_origin * ray_dir;
|
||||
dist_to_surface = sdf_custom(point);
|
||||
dist_from_origin += dist_to_surface;
|
||||
if(dist_to_surface < dist_threshold || dist_to_surface > max_dist)
|
||||
break;
|
||||
}
|
||||
return dist_from_origin;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
mat2 rm_rotation(float angle) {
|
||||
angle = -angle * (3.1415926 / 180.);
|
||||
return mat2(
|
||||
vec2(cos(angle), -sin(angle)),
|
||||
vec2(sin(angle), cos(angle))
|
||||
);
|
||||
}
|
21
addons/ShaderLib/RayMarching/SDBox.gdshaderinc
Normal file
21
addons/ShaderLib/RayMarching/SDBox.gdshaderinc
Normal file
@ -0,0 +1,21 @@
|
||||
float sd_box(vec3 point, vec3 size, vec3 eulers) {
|
||||
point.yz *= rm_rotation(eulers.x);
|
||||
point.xy *= rm_rotation(eulers.z);
|
||||
point.xz *= rm_rotation(-eulers.y);
|
||||
return length(max(abs(point) - size, vec3(0)));
|
||||
}
|
||||
|
||||
float ray_march_sd_box(vec3 ray_origin, vec3 ray_dir, int max_steps, float max_dist, float dist_threshold, vec3 cube_pos, vec3 eulers, vec3 size) {
|
||||
ray_dir = normalize(ray_dir);
|
||||
dist_threshold = abs(dist_threshold);
|
||||
float dist_from_origin = 0.;
|
||||
float dist_to_surface;
|
||||
for(int i = 0; i < max_steps; i++) {
|
||||
vec3 point = ray_origin + dist_from_origin * ray_dir;
|
||||
dist_to_surface = sd_box(point - cube_pos, size, eulers);
|
||||
dist_from_origin += dist_to_surface;
|
||||
if(dist_to_surface < dist_threshold || dist_to_surface > max_dist)
|
||||
break;
|
||||
}
|
||||
return dist_from_origin;
|
||||
}
|
33
addons/ShaderLib/RayMarching/SDCapsule.gdshaderinc
Normal file
33
addons/ShaderLib/RayMarching/SDCapsule.gdshaderinc
Normal file
@ -0,0 +1,33 @@
|
||||
float sd_capsule(vec3 point, vec3 capsule_pos, float height, float radius, vec3 eulers) {
|
||||
vec3 orientation = vec3(0, 1, 0);
|
||||
orientation.yz *= rm_rotation(eulers.x);
|
||||
orientation.xy *= rm_rotation(eulers.z);
|
||||
orientation.xz *= rm_rotation(-eulers.y);
|
||||
|
||||
vec3 top_point = point + orientation * (height * .5);
|
||||
vec3 bottom_point = point - orientation * (height * .5);
|
||||
|
||||
vec3 height_vector = bottom_point - top_point;
|
||||
vec3 top_distance = capsule_pos - top_point;
|
||||
|
||||
float t = dot(height_vector, top_distance) / dot(height_vector, height_vector);
|
||||
t = clamp(t, 0., 1.);
|
||||
vec3 hit_point = top_point + t * height_vector;
|
||||
|
||||
return length(capsule_pos - hit_point) - radius;
|
||||
}
|
||||
|
||||
float ray_march_sd_capsule(vec3 ray_origin, vec3 ray_dir, int max_steps, float max_dist, float dist_threshold, vec3 capsule_pos, float capsule_height, float capsule_radius, vec3 eulers) {
|
||||
ray_dir = normalize(ray_dir);
|
||||
dist_threshold = abs(dist_threshold);
|
||||
float dist_from_origin = 0.;
|
||||
float dist_to_surface;
|
||||
for(int i = 0; i < max_steps; i++) {
|
||||
vec3 point = ray_origin + dist_from_origin * ray_dir;
|
||||
dist_to_surface = sd_capsule(point, capsule_pos, capsule_height, capsule_radius, eulers);
|
||||
dist_from_origin += dist_to_surface;
|
||||
if(dist_to_surface < dist_threshold || dist_to_surface > max_dist)
|
||||
break;
|
||||
}
|
||||
return dist_from_origin;
|
||||
}
|
37
addons/ShaderLib/RayMarching/SDCylinder.gdshaderinc
Normal file
37
addons/ShaderLib/RayMarching/SDCylinder.gdshaderinc
Normal file
@ -0,0 +1,37 @@
|
||||
float sd_cylinder(vec3 point, vec3 cylinder_pos, float height, float radius, vec3 eulers) {
|
||||
vec3 orientation = vec3(0, 1, 0);
|
||||
orientation.yz *= rm_rotation(eulers.x);
|
||||
orientation.xy *= rm_rotation(eulers.z);
|
||||
orientation.xz *= rm_rotation(-eulers.y);
|
||||
|
||||
vec3 top_point = point + orientation * (height * .5);
|
||||
vec3 bottom_point = point - orientation * (height * .5);
|
||||
|
||||
vec3 height_vector = bottom_point - top_point;
|
||||
vec3 top_distance = cylinder_pos - top_point;
|
||||
|
||||
float t = dot(height_vector, top_distance) / dot(height_vector, height_vector);
|
||||
vec3 hit_point = top_point + t * height_vector;
|
||||
|
||||
float x = length(cylinder_pos - hit_point) - radius;
|
||||
float y = (abs(t - .5) - .5) * length(height_vector);
|
||||
float e = length(max(vec2(x, y), 0));
|
||||
float i = min(max(x, y), 0.);
|
||||
|
||||
return e + i;
|
||||
}
|
||||
|
||||
float ray_march_sd_cylinder(vec3 ray_origin, vec3 ray_dir, int max_steps, float max_dist, float dist_threshold, vec3 cylinder_pos, float cylinder_height, float cylinder_radius, vec3 eulers) {
|
||||
ray_dir = normalize(ray_dir);
|
||||
dist_threshold = abs(dist_threshold);
|
||||
float dist_from_origin = 0.;
|
||||
float dist_to_surface;
|
||||
for(int i = 0; i < max_steps; i++) {
|
||||
vec3 point = ray_origin + dist_from_origin * ray_dir;
|
||||
dist_to_surface = sd_cylinder(point, cylinder_pos, cylinder_height, cylinder_radius, eulers);
|
||||
dist_from_origin += dist_to_surface;
|
||||
if(dist_to_surface < dist_threshold || dist_to_surface > max_dist)
|
||||
break;
|
||||
}
|
||||
return dist_from_origin;
|
||||
}
|
23
addons/ShaderLib/RayMarching/SDSphere.gdshaderinc
Normal file
23
addons/ShaderLib/RayMarching/SDSphere.gdshaderinc
Normal file
@ -0,0 +1,23 @@
|
||||
float sd_sphere(vec3 point, vec3 eulers, vec3 scale) {
|
||||
float radius = 1.;
|
||||
point.yz *= rm_rotation(eulers.x);
|
||||
point.xy *= rm_rotation(eulers.z);
|
||||
point.xz *= rm_rotation(-eulers.y);
|
||||
point /= scale;
|
||||
return (length(point) - radius) * min(scale.x, min(scale.y, scale.z));
|
||||
}
|
||||
|
||||
float ray_march_sd_sphere(vec3 ray_origin, vec3 ray_dir, int max_steps, float max_dist, float dist_threshold, vec3 sphere_pos, vec3 eulers, vec3 scale) {
|
||||
ray_dir = normalize(ray_dir);
|
||||
dist_threshold = abs(dist_threshold);
|
||||
float dist_from_origin = 0.;
|
||||
float dist_to_surface;
|
||||
for(int i = 0; i < max_steps; i++) {
|
||||
vec3 point = ray_origin + dist_from_origin * ray_dir;
|
||||
dist_to_surface = sd_sphere(point - sphere_pos, eulers, scale);
|
||||
dist_from_origin += dist_to_surface;
|
||||
if(dist_to_surface < dist_threshold || dist_to_surface > max_dist)
|
||||
break;
|
||||
}
|
||||
return dist_from_origin;
|
||||
}
|
21
addons/ShaderLib/RayMarching/SDTorus.gdshaderinc
Normal file
21
addons/ShaderLib/RayMarching/SDTorus.gdshaderinc
Normal file
@ -0,0 +1,21 @@
|
||||
float sd_torus(vec3 point, float small_radius, float big_radius, vec3 eulers) {
|
||||
point.yz *= rm_rotation(eulers.x);
|
||||
point.xy *= rm_rotation(eulers.z);
|
||||
point.xz *= rm_rotation(-eulers.y);
|
||||
return length(vec2(length(point.xz) - big_radius, point.y)) - small_radius;
|
||||
}
|
||||
|
||||
float ray_march_sd_torus(vec3 ray_origin, vec3 ray_dir, int max_steps, float max_dist, float dist_threshold, vec3 torus_pos, vec3 eulers, float small_radius, float big_radius) {
|
||||
ray_dir = normalize(ray_dir);
|
||||
dist_threshold = abs(dist_threshold);
|
||||
float dist_from_origin = 0.;
|
||||
float dist_to_surface;
|
||||
for(int i = 0; i < max_steps; i++) {
|
||||
vec3 point = ray_origin + dist_from_origin * ray_dir;
|
||||
dist_to_surface = sd_torus(point - torus_pos, small_radius, big_radius, eulers);
|
||||
dist_from_origin += dist_to_surface;
|
||||
if(dist_to_surface < dist_threshold || dist_to_surface > max_dist)
|
||||
break;
|
||||
}
|
||||
return dist_from_origin;
|
||||
}
|
@ -32,6 +32,11 @@ For example if you want to rotate UV in your **_.gdshader_** file, you can use `
|
||||
|
||||
<h3> Vector</h3>
|
||||
|
||||
<h3>  Distance</h3>
|
||||
|
||||
<h4><a href="/documentation/Nodes/Maths/Vector/Distance/ChebyshevDistance.md">   Chebyshev Distance node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Maths/Vector/Distance/ManhattanDistance.md">   Manhattan Distance node</a></h4>
|
||||
|
||||
<h4><a href="/documentation/Nodes/Maths/Vector/Project.md">  Project node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Maths/Vector/ProjectOnPlane.md">  Project On Plane node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Maths/Vector/VectorTransform.md">  Vector Transform node</a></h4>
|
||||
@ -54,6 +59,7 @@ For example if you want to rotate UV in your **_.gdshader_** file, you can use `
|
||||
<h3> Noise</h3>
|
||||
|
||||
<h4><a href="/documentation/Nodes/Procedural/Noise/GradientNoise.md">  Gradient Noise node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Procedural/Noise/GyroidNoise.md">  Gyroid Noise node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Procedural/Noise/PseudoRandomNoise.md">  Pseudo Random Noise node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Procedural/Noise/SimpleNoise.md">  Simple Noise node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Procedural/Noise/Voronoi.md">  Voronoi node</a></h4>
|
||||
@ -66,6 +72,10 @@ For example if you want to rotate UV in your **_.gdshader_** file, you can use `
|
||||
<h4><a href="/documentation/Nodes/Procedural/Shapes/RoundedPolygon.md">  Rounded Polygon node</a></h4>
|
||||
<h4><a href="/documentation/Nodes/Procedural/Shapes/RoundedRectangle.md">  Rounded Rectangle node</a></h4>
|
||||
|
||||
<h2>Ray marching nodes</h2>
|
||||
|
||||
<h4><a href="/documentation/Nodes/RayMarching/RayMarch.md"> Ray March node</a></h4>
|
||||
|
||||
<h2>UV nodes</h2>
|
||||
|
||||
<h4><a href="/documentation/Nodes/UV/Flipbook.md"> Flipbook node</a></h4>
|
||||
|
@ -0,0 +1,21 @@
|
||||
# Chebyshev Distance node
|
||||
Returns the distance between two points using Chebyshev distance matrix.
|
||||
<hr>
|
||||
|
||||
**Controls**
|
||||
|Options|Description|
|
||||
|---|---|
|
||||
|Vector2, Vector3|Vector type to use for calculation|
|
||||
|
||||
**Inputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|a|Dynamic vector|none|Point a|
|
||||
|b|Dynamic vector|none|Point b|
|
||||
|power|float|none|Power to use for Chebyshev distance|
|
||||
|
||||
**Outputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|distance|float|None|Distance between 2 points|
|
||||
___
|
@ -0,0 +1,20 @@
|
||||
# Manhattan Distance node
|
||||
Returns the distance between two points using Manhattan distance matrix.
|
||||
<hr>
|
||||
|
||||
**Controls**
|
||||
|Options|Description|
|
||||
|---|---|
|
||||
|Vector2, Vector3|Vector type to use for calculation|
|
||||
|
||||
**Inputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|a|Dynamic vector|none|Point a|
|
||||
|b|Dynamic vector|none|Point b|
|
||||
|
||||
**Outputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|distance|float|None|Distance between 2 points|
|
||||
___
|
18
documentation/Nodes/Procedural/Noise/GyroidNoise.md
Normal file
18
documentation/Nodes/Procedural/Noise/GyroidNoise.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Gyroid Noise node
|
||||
Generates a gyroid noise based on input UV. The resulting <b><i>output</i></b> values will be between 0 and 1.
|
||||
<hr>
|
||||
|
||||
**Inputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|uv|vec2|UV|Input UV value|
|
||||
|scale|float|none|Noise scale|
|
||||
|ratio|vec2|none|Noise ratio for X and Y Axes|
|
||||
|height|float|none|Noise height|
|
||||
|thickness|float|none|Noise thickness, clamped between 0 and 1|
|
||||
|
||||
**Outputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|output|float|None|Output noise value|
|
||||
___
|
@ -7,6 +7,7 @@ Generates a simplex, or value noise based on input UV. The resulting <b><i>outpu
|
||||
|---|---|---|---|
|
||||
|uv|vec2|UV|Input UV value|
|
||||
|scale|float|none|Noise scale|
|
||||
|octaves|int|none|Octaves/Layers of noise, <b><i>octaves</i></b> input is clamped between 1 and 6.|
|
||||
|
||||
**Outputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|
@ -2,12 +2,18 @@
|
||||
Generates a Voronoi or Worley noise based on input UV. Voronoi noise is generated by calculating distances between a pixel and a lattice of points. By offsetting these points by a pseudo-random number, controlled by <b><i>angle offset</i></b>, a cluster of cells can be generated.
|
||||
<hr>
|
||||
|
||||
**Controls**
|
||||
|Name|Options|Description|
|
||||
|---|---|---|
|
||||
|Distance|Euclidean, Manhattan, Chebyshev|Distance matrix used to calculate the noise|
|
||||
|
||||
**Inputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|uv|vec2|UV|Input UV value|
|
||||
|cell density|float|none|Density of generated cells|
|
||||
|angle offset|float|none|Offset values for points|
|
||||
|chebyshev power|float|none|Power values for Chebyshev distance matrix|
|
||||
|
||||
**Outputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|
BIN
documentation/Nodes/RayMarching/Expression.jpg
Normal file
BIN
documentation/Nodes/RayMarching/Expression.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
BIN
documentation/Nodes/RayMarching/GlobalExpression.jpg
Normal file
BIN
documentation/Nodes/RayMarching/GlobalExpression.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
58
documentation/Nodes/RayMarching/RayMarch.md
Normal file
58
documentation/Nodes/RayMarching/RayMarch.md
Normal file
@ -0,0 +1,58 @@
|
||||
# Ray March node
|
||||
A simple ray marcher for primitive shapes.
|
||||
<hr>
|
||||
|
||||
**Controls**
|
||||
|Name|Options|Description|
|
||||
|---|---|---|
|
||||
|SDF (Signed Distance Function)|SDBox, SDSphere, SDCapsule, SDCylinder, SDTorus|Signed Distance Functions for the space to draw.|
|
||||
|
||||
**Inputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|signed distance|float|none|Signed distance calculated from Signed Distance Functions (SDFs)|
|
||||
|ray origin|vec3|none|Ray origin|
|
||||
|ray direction|vec3|none|Normalized ray direction|
|
||||
|max steps|int|none|Maximum number of steps for ray marching|
|
||||
|max distance|float|none|Maximum distance to march along the <b><i>ray direction</i></b>|
|
||||
|distance threshold|float|none|Threshold to check against <b><i>signed distance</i></b> to determine the ray intersection point.|
|
||||
|
||||
**SDFs Inputs**
|
||||
|Name|Type|Availability|Description|
|
||||
|---|---|---|---|
|
||||
|cube pos|vec3|SDBox|Position offset of the box shape|
|
||||
|cube eulers|vec3|SDBox|Rotation of the box shape in Degrees|
|
||||
|cube scale|vec3|SDBox|Scale of the box shape|
|
||||
|sphere pos|vec3|SDSphere|Position offset of the sphere shape|
|
||||
|sphere eulers|vec3|SDSphere|Rotation of the box sphere in Degrees|
|
||||
|sphere scale|vec3|SDSphere|Scale of the sphere shape|
|
||||
|capsule pos|vec3|SDCapsule|Position offset of the capsule shape|
|
||||
|capsule eulers|vec3|SDCapsule|Rotation of the capsule shape in Degrees|
|
||||
|capsule height|float|SDCapsule|Height of the capsule shape|
|
||||
|capsule radius|float|SDCapsule|Radius of the capsule shape|
|
||||
|cylinder pos|vec3|SDCylinder|Position offset of the cylinder shape|
|
||||
|cylinder eulers|vec3|SDCylinder|Rotation of the cylinder shape in Degrees|
|
||||
|cylinder height|float|SDCylinder|Height of the cylinder shape|
|
||||
|cylinder radius|float|SDCylinder|Radius of the cylinder shape|
|
||||
|torus pos|vec3|SDTorus|Position offset of the torus shape|
|
||||
|torus eulers|vec3|SDTorus|Rotation of the torus shape in Degrees|
|
||||
|torus small radius|float|SDTorus|Small radius of the torus shape|
|
||||
|torus big radius|float|SDTorus|Big radius of the torus shape|
|
||||
|
||||
**Outputs**
|
||||
|Name|Type|Binding|Description|
|
||||
|---|---|---|---|
|
||||
|distance|float|None|Ray intersection distance|
|
||||
|
||||
<hr>
|
||||
<h3>Extras</h3>
|
||||
This node is only simple ray marching example, the true power of raymarching can only be achieved by custom SDFs. At the moment I am unable to inject the custom code via visual shaders, so I have provided the custom template at the following location.<br><br>
|
||||
|
||||
The default location can be found at<br>
|
||||
`res://addons/ShaderLib/RayMarching/RayMarchCustom.gdshaderinc`
|
||||
|
||||
You can copy the code from `RayMarchCustom.gdshaderinc` and then create a <b><i>Global Expression</i></b> node and paste it in your visual shader.<br><br>
|
||||
![Global Expression Node](GlobalExpression.jpg)<br><br>
|
||||
Lastly you also need to create an <b><i>Expression</i></b> node, define required input and output parameters and call the custom ray marching function as below.<br><br>
|
||||
![Expression Node](Expression.jpg)<br>
|
||||
___
|
Loading…
x
Reference in New Issue
Block a user