diff --git a/addons/VisualShaderExtras/AddonAssets/examples.tscn b/addons/VisualShaderExtras/AddonAssets/examples.tscn index cb2ef7f..f8d9e92 100644 --- a/addons/VisualShaderExtras/AddonAssets/examples.tscn +++ b/addons/VisualShaderExtras/AddonAssets/examples.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=302 format=3 uid="uid://dhonmus7cuhkx"] +[gd_scene load_steps=309 format=3 uid="uid://bptntdpwwdm42"] [ext_resource type="Texture2D" uid="uid://dkwktkcfupn2y" path="res://addons/VisualShaderExtras/AddonAssets/icon.svg" id="1_cgkaa"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/BlendModes/lighter_color_blend.gd" id="2_0j8nr"] @@ -15,7 +15,6 @@ [ext_resource type="Script" path="res://addons/VisualShaderExtras/BlendModes/lighten_blend.gd" id="11_n0wvd"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/BlendModes/darken_blend.gd" id="12_6hew4"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/BlendModes/difference_blend.gd" id="13_dcg01"] -[ext_resource type="Script" path="res://addons/VisualShaderExtras/Procedural/Checkerboard.gd" id="13_ptn0e"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/BlendModes/additive_blend.gd" id="14_8yep8"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/Shapes/Box.gd" id="14_jc8jc"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/ColorAdjustment/HSVAdjustment.gd" id="14_o4k34"] @@ -44,6 +43,7 @@ [ext_resource type="Script" path="res://addons/VisualShaderExtras/Wave/SquareWave.gd" id="25_srj7y"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/Wave/SawtoothWave.gd" id="26_777un"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/Wave/SineWave.gd" id="27_5a8eg"] +[ext_resource type="Script" path="res://addons/VisualShaderExtras/Procedural/PSRD-Noise2D.gd" id="27_fgvk5"] [ext_resource type="Script" path="res://addons/VisualShaderExtras/UV/UVRotate.gd" id="41_5yrmd"] [sub_resource type="VisualShaderNodeTexture" id="67"] @@ -1898,10 +1898,83 @@ nodes/fragment/connections = PackedInt32Array(6, 0, 7, 0, 4, 0, 7, 1, 7, 0, 0, 0 [sub_resource type="ShaderMaterial" id="ShaderMaterial_uvepn"] shader = SubResource("VisualShader_8l46s") +[sub_resource type="GDScript" id="GDScript_xqgp2"] +script/source = "@tool +extends VisualShaderNodeCustom +class_name VisualShaderNodeCheckerboard + +func _get_name(): + return \"Checkerboard\" + +func _init() -> void: + set_input_port_default_value(1, Vector2(8.0, 8.0)) + +func _get_category(): + return \"VisualShaderExtras/Procedural\" + +func _get_description(): + return \"Checkerboard Pattern with two given input colors\" + +func _get_return_icon_type(): + return VisualShaderNode.PORT_TYPE_VECTOR_3D + +func _get_input_port_count(): + return 4 + +func _get_input_port_name(port): + match port: + 0: + return \"UV\" + 1: + return \"Tiling\" + 2: + return \"Color\" + 3: + return \"Color\" + +func _get_input_port_type(port): + match port: + 0: + return VisualShaderNode.PORT_TYPE_VECTOR_2D + 1: + return VisualShaderNode.PORT_TYPE_VECTOR_2D + 2: + return VisualShaderNode.PORT_TYPE_VECTOR_3D + 3: + return VisualShaderNode.PORT_TYPE_VECTOR_3D + +func _get_output_port_count(): + return 1 + +func _get_output_port_name(port: int) -> String: + return \"\" + +func _get_output_port_type(port): + return VisualShaderNode.PORT_TYPE_VECTOR_3D + +func _get_global_code(mode): + return \"\"\" + vec3 checkerboard(vec2 _uv, vec2 _tiling, vec3 _color1, vec3 _color2) { + float _tiling_x = floor(mod((_uv.x / (1.0 / _tiling.x)), 2.0)); + float _tiling_y = floor(mod((_uv.y / (1.0 / _tiling.y)), 2.0)); + bool _compare_bool = (abs(_tiling_x - _tiling_y) < 0.00001); + return mix(_color1.xyz, _color2.xyz, (_compare_bool ? 1.0 : 0.0)); + } + \"\"\" + +func _get_code(input_vars, output_vars, mode, type): + var uv = \"UV\" + + if input_vars[0]: + uv = input_vars[0] + + return \"%s.xyz = checkerboard(%s.xy, %s.xy, %s, %s);\" % [output_vars[0], uv, input_vars[1], input_vars[2], input_vars[3]] +" + [sub_resource type="VisualShaderNodeCustom" id="VisualShaderNodeCustom_e0cta"] default_input_values = [1, Vector2(8, 8)] initialized = true -script = ExtResource("13_ptn0e") +script = SubResource("GDScript_xqgp2") [sub_resource type="VisualShaderNodeColorConstant" id="VisualShaderNodeColorConstant_cc80l"] @@ -1959,6 +2032,123 @@ nodes/fragment/connections = PackedInt32Array(2, 0, 0, 0, 3, 0, 2, 2, 4, 0, 2, 3 [sub_resource type="ShaderMaterial" id="ShaderMaterial_ijt06"] shader = SubResource("VisualShader_bbxpt") +[sub_resource type="VisualShaderNodeCustom" id="VisualShaderNodeCustom_iuo5i"] +default_input_values = [0, Vector2(0.195, 0.142), 1, Vector2(10, 10), 2, 0.0] +initialized = true +script = ExtResource("27_fgvk5") + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_0k1tk"] +input_name = "uv" + +[sub_resource type="VisualShaderNodeUVFunc" id="VisualShaderNodeUVFunc_7u225"] +default_input_values = [1, Vector2(4, 4), 2, Vector2(0, 0)] +function = 1 + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_hacq2"] +input_name = "time" + +[sub_resource type="VisualShader" id="VisualShader_nrxtj"] +code = "shader_type canvas_item; + + +// PSRDNoise2D + + float psrdnoise2_with_gradient(vec2 x, vec2 period, float alpha, out vec2 gradient) { + vec2 uv = vec2(x.x+x.y*0.5, x.y); + vec2 i0 = floor(uv), f0 = fract(uv); + float cmp = step(f0.y, f0.x); + vec2 o1 = vec2(cmp, 1.0-cmp); + vec2 i1 = i0 + o1, i2 = i0 + 1.0; + vec2 v0 = vec2(i0.x - i0.y*0.5, i0.y); + vec2 v1 = vec2(v0.x + o1.x - o1.y*0.5, v0.y + o1.y); + vec2 v2 = vec2(v0.x + 0.5, v0.y + 1.0); + vec2 x0 = x - v0, x1 = x - v1, x2 = x - v2; + vec3 iu, iv, xw, yw; + if(any(greaterThan(period, vec2(0.0)))) { + xw = vec3(v0.x, v1.x, v2.x); + yw = vec3(v0.y, v1.y, v2.y); + if(period.x > 0.0) + xw = mod(vec3(v0.x, v1.x, v2.x), period.x); + if(period.y > 0.0) + yw = mod(vec3(v0.y, v1.y, v2.y), period.y); + iu = floor(xw + 0.5*yw + 0.5); iv = floor(yw + 0.5); + } else { + iu = vec3(i0.x, i1.x, i2.x); iv = vec3(i0.y, i1.y, i2.y); + } + vec3 hash = mod(iu, 289.0); + hash = mod((hash*51.0 + 2.0)*hash + iv, 289.0); + hash = mod((hash*34.0 + 10.0)*hash, 289.0); + vec3 psi = hash*0.07482 + alpha; + vec3 gx = cos(psi); vec3 gy = sin(psi); + vec2 g0 = vec2(gx.x, gy.x); + vec2 g1 = vec2(gx.y, gy.y); + vec2 g2 = vec2(gx.z, gy.z); + vec3 w = 0.8 - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)); + w = max(w, 0.0); vec3 w2 = w*w; vec3 w4 = w2*w2; + vec3 gdotx = vec3(dot(g0, x0), dot(g1, x1), dot(g2, x2)); + float n = dot(w4, gdotx); + vec3 w3 = w2*w; vec3 dw = -8.0*w3*gdotx; + vec2 dn0 = w4.x*g0 + dw.x*x0; + vec2 dn1 = w4.y*g1 + dw.y*x1; + vec2 dn2 = w4.z*g2 + dw.z*x2; + gradient = 10.9*(dn0 + dn1 + dn2); + return 10.9*n; + } + + float psrdnoise2(vec2 x, vec2 period, float alpha) { + vec2 gradient; + return psrdnoise2_with_gradient(x, period, alpha, gradient); + } + + + +void fragment() { +// Input:4 + vec2 n_out4p0 = UV; + + +// UVFunc:5 + vec2 n_in5p1 = vec2(4.00000, 4.00000); + vec2 n_in5p2 = vec2(0.00000, 0.00000); + vec2 n_out5p0 = (n_out4p0 - n_in5p2) * n_in5p1 + n_in5p2; + + +// Input:6 + float n_out6p0 = TIME; + + + float n_out2p0; +// PSRDNoise2D:2 + vec2 n_in2p1 = vec2(10.00000, 10.00000); + { + n_out2p0 = psrdnoise2(n_out5p0.xy, n_in2p1.xy, n_out6p0); + } + + +// Output:0 + COLOR.rgb = vec3(n_out2p0); + COLOR.a = n_out2p0; + + +} +" +graph_offset = Vector2(-459.364, 39.6364) +mode = 1 +flags/light_only = false +nodes/fragment/0/position = Vector2(340, 160) +nodes/fragment/2/node = SubResource("VisualShaderNodeCustom_iuo5i") +nodes/fragment/2/position = Vector2(60, 180) +nodes/fragment/4/node = SubResource("VisualShaderNodeInput_0k1tk") +nodes/fragment/4/position = Vector2(-540, 80) +nodes/fragment/5/node = SubResource("VisualShaderNodeUVFunc_7u225") +nodes/fragment/5/position = Vector2(-200, 80) +nodes/fragment/6/node = SubResource("VisualShaderNodeInput_hacq2") +nodes/fragment/6/position = Vector2(-260, 280) +nodes/fragment/connections = PackedInt32Array(4, 0, 5, 0, 5, 0, 2, 0, 6, 0, 2, 2, 2, 0, 0, 0, 2, 0, 0, 1) + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_qqdvx"] +shader = SubResource("VisualShader_nrxtj") + [sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_5d2we"] texture = ExtResource("1_cgkaa") texture_type = 1 @@ -3448,7 +3638,6 @@ text = "Darker Color" horizontal_alignment = 1 [node name="Procedural" type="Control" parent="."] -visible = false layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -3482,6 +3671,19 @@ layout_mode = 2 text = "Checkerboard" horizontal_alignment = 1 +[node name="PSRDNoise2D" type="VBoxContainer" parent="Procedural/VBoxContainer/HBoxContainer"] +layout_mode = 2 + +[node name="TextureRect" type="TextureRect" parent="Procedural/VBoxContainer/HBoxContainer/PSRDNoise2D"] +material = SubResource("ShaderMaterial_qqdvx") +layout_mode = 2 +texture = ExtResource("1_cgkaa") + +[node name="Label" type="Label" parent="Procedural/VBoxContainer/HBoxContainer/PSRDNoise2D"] +layout_mode = 2 +text = "PSRD Noise2D" +horizontal_alignment = 1 + [node name="ColorAdjustment" type="Control" parent="."] visible = false layout_mode = 1 @@ -3662,6 +3864,7 @@ horizontal_alignment = 1 vertical_alignment = 1 [node name="UV" type="Control" parent="."] +visible = false layout_mode = 1 anchors_preset = 0 offset_right = 40.0 diff --git a/addons/VisualShaderExtras/Procedural/PSRD-Noise2D.gd b/addons/VisualShaderExtras/Procedural/PSRD-Noise2D.gd new file mode 100644 index 0000000..6f7a5d3 --- /dev/null +++ b/addons/VisualShaderExtras/Procedural/PSRD-Noise2D.gd @@ -0,0 +1,127 @@ +# Copyright 2021, Stefan Gustavson and Ian MacEwan (stefan.gustavson@gmail.com, ijm567@gmail.com) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# // psrdnoise (c) Stefan Gustavson and Ian McEwan, +# // ver. 2021-12-02, published under the MIT license: +# // https://github.com/stegu/psrdnoise/ + +@tool +extends VisualShaderNodeCustom +class_name VisualShaderNodePSRDNoise2D + +func _get_name(): + return "PSRDNoise2D" + +func _init() -> void: + set_input_port_default_value(0, Vector2(0.0, 0.0)) + set_input_port_default_value(1, Vector2(1.0, 1.0)) + set_input_port_default_value(2, 1.0) + +func _get_category(): + return "VisualShaderExtras/Procedural" + +func _get_description(): + return "Seamless performant 2D noise for shaders" + +func _get_return_icon_type(): + return VisualShaderNode.PORT_TYPE_SCALAR + +func _get_input_port_count(): + return 3 + +func _get_input_port_name(port): + match port: + 0: + return "Coordinates" + 1: + return "Period" + 2: + return "Alpha" + +func _get_input_port_type(port): + match port: + 0: + return VisualShaderNode.PORT_TYPE_VECTOR_2D + 1: + return VisualShaderNode.PORT_TYPE_VECTOR_2D + 2: + return VisualShaderNode.PORT_TYPE_SCALAR + +func _get_output_port_count(): + return 1 + +func _get_output_port_name(port: int) -> String: + return "Output" + +func _get_output_port_type(port): + return VisualShaderNode.PORT_TYPE_SCALAR + +func _get_global_code(mode): + return """ + float psrdnoise2_with_gradient(vec2 x, vec2 period, float alpha, out vec2 gradient) { + vec2 uv = vec2(x.x+x.y*0.5, x.y); + vec2 i0 = floor(uv), f0 = fract(uv); + float cmp = step(f0.y, f0.x); + vec2 o1 = vec2(cmp, 1.0-cmp); + vec2 i1 = i0 + o1, i2 = i0 + 1.0; + vec2 v0 = vec2(i0.x - i0.y*0.5, i0.y); + vec2 v1 = vec2(v0.x + o1.x - o1.y*0.5, v0.y + o1.y); + vec2 v2 = vec2(v0.x + 0.5, v0.y + 1.0); + vec2 x0 = x - v0, x1 = x - v1, x2 = x - v2; + vec3 iu, iv, xw, yw; + if(any(greaterThan(period, vec2(0.0)))) { + xw = vec3(v0.x, v1.x, v2.x); + yw = vec3(v0.y, v1.y, v2.y); + if(period.x > 0.0) + xw = mod(vec3(v0.x, v1.x, v2.x), period.x); + if(period.y > 0.0) + yw = mod(vec3(v0.y, v1.y, v2.y), period.y); + iu = floor(xw + 0.5*yw + 0.5); iv = floor(yw + 0.5); + } else { + iu = vec3(i0.x, i1.x, i2.x); iv = vec3(i0.y, i1.y, i2.y); + } + vec3 hash = mod(iu, 289.0); + hash = mod((hash*51.0 + 2.0)*hash + iv, 289.0); + hash = mod((hash*34.0 + 10.0)*hash, 289.0); + vec3 psi = hash*0.07482 + alpha; + vec3 gx = cos(psi); vec3 gy = sin(psi); + vec2 g0 = vec2(gx.x, gy.x); + vec2 g1 = vec2(gx.y, gy.y); + vec2 g2 = vec2(gx.z, gy.z); + vec3 w = 0.8 - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)); + w = max(w, 0.0); vec3 w2 = w*w; vec3 w4 = w2*w2; + vec3 gdotx = vec3(dot(g0, x0), dot(g1, x1), dot(g2, x2)); + float n = dot(w4, gdotx); + vec3 w3 = w2*w; vec3 dw = -8.0*w3*gdotx; + vec2 dn0 = w4.x*g0 + dw.x*x0; + vec2 dn1 = w4.y*g1 + dw.y*x1; + vec2 dn2 = w4.z*g2 + dw.z*x2; + gradient = 10.9*(dn0 + dn1 + dn2); + return 10.9*n; + } + + float psrdnoise2(vec2 x, vec2 period, float alpha) { + vec2 gradient; + return psrdnoise2_with_gradient(x, period, alpha, gradient); + } + + """ + +func _get_code(input_vars, output_vars, mode, type): + + return "%s = psrdnoise2(%s.xy, %s.xy, %s);" % [output_vars[0], input_vars[0], input_vars[1], input_vars[2]] diff --git a/addons/VisualShaderExtras/Procedural/PSRD-Noise3D.gd b/addons/VisualShaderExtras/Procedural/PSRD-Noise3D.gd new file mode 100644 index 0000000..69d9c35 --- /dev/null +++ b/addons/VisualShaderExtras/Procedural/PSRD-Noise3D.gd @@ -0,0 +1,149 @@ +# Copyright 2021, Stefan Gustavson and Ian MacEwan (stefan.gustavson@gmail.com, ijm567@gmail.com) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# // psrdnoise (c) Stefan Gustavson and Ian McEwan, +# // ver. 2021-12-02, published under the MIT license: +# // https://github.com/stegu/psrdnoise/ + +@tool +extends VisualShaderNodeCustom +class_name VisualShaderNodePSRDNoise3D + +func _get_name(): + return "PSRDNoise3D" + +func _init() -> void: + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)) + set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)) + set_input_port_default_value(2, 1.0) + +func _get_category(): + return "VisualShaderExtras/Procedural" + +func _get_description(): + return "Seamless performant 3D noise for shaders" + +func _get_return_icon_type(): + return VisualShaderNode.PORT_TYPE_SCALAR + +func _get_input_port_count(): + return 3 + +func _get_input_port_name(port): + match port: + 0: + return "Coordinates" + 1: + return "Period" + 2: + return "Alpha" + +func _get_input_port_type(port): + match port: + 0: + return VisualShaderNode.PORT_TYPE_VECTOR_3D + 1: + return VisualShaderNode.PORT_TYPE_VECTOR_3D + 2: + return VisualShaderNode.PORT_TYPE_SCALAR + +func _get_output_port_count(): + return 1 + +func _get_output_port_name(port: int) -> String: + return "Output" + +func _get_output_port_type(port): + return VisualShaderNode.PORT_TYPE_SCALAR + +func _get_global_code(mode): + return """ + vec4 __psrdnoise3_permute(vec4 i) { + vec4 im = mod(i, 289.0); + return mod(((im*34.0)+10.0)*im, 289.0); + } + + float psrdnoise3_with_gradient(vec3 x, vec3 period, float alpha, out vec3 gradient) { + const mat3 M = mat3(vec3(0.0, 1.0, 1.0), vec3(1.0, 0.0, 1.0), vec3(1.0, 1.0, 0.0)); + const mat3 Mi = mat3(vec3(-0.5, 0.5, 0.5), vec3(0.5,-0.5, 0.5), vec3(0.5, 0.5,-0.5)); + vec3 uvw = M * x; + vec3 i0 = floor(uvw), f0 = fract(uvw); + vec3 g_ = step(f0.xyx, f0.yzz), l_ = 1.0 - g_; + vec3 g = vec3(l_.z, g_.xy), l = vec3(l_.xy, g_.z); + vec3 o1 = min( g, l ), o2 = max( g, l ); + vec3 i1 = i0 + o1, i2 = i0 + o2, i3 = i0 + vec3(1.0); + vec3 v0 = Mi * i0, v1 = Mi * i1, v2 = Mi * i2, v3 = Mi * i3; + vec3 x0 = x - v0, x1 = x - v1, x2 = x - v2, x3 = x - v3; + if(any(greaterThan(period, vec3(0.0)))) { + vec4 vx = vec4(v0.x, v1.x, v2.x, v3.x); + vec4 vy = vec4(v0.y, v1.y, v2.y, v3.y); + vec4 vz = vec4(v0.z, v1.z, v2.z, v3.z); + if(period.x > 0.0) vx = mod(vx, period.x); + if(period.y > 0.0) vy = mod(vy, period.y); + if(period.z > 0.0) vz = mod(vz, period.z); + i0 = floor(M * vec3(vx.x, vy.x, vz.x) + 0.5); + i1 = floor(M * vec3(vx.y, vy.y, vz.y) + 0.5); + i2 = floor(M * vec3(vx.z, vy.z, vz.z) + 0.5); + i3 = floor(M * vec3(vx.w, vy.w, vz.w) + 0.5); + } + + vec4 hash = __psrdnoise3_permute( __psrdnoise3_permute( __psrdnoise3_permute( + vec4(i0.z, i1.z, i2.z, i3.z )) + + vec4(i0.y, i1.y, i2.y, i3.y )) + + vec4(i0.x, i1.x, i2.x, i3.x )); + vec4 theta = hash * 3.883222077; + vec4 sz = hash * -0.006920415 + 0.996539792; + vec4 psi = hash * 0.108705628; + vec4 Ct = cos(theta), St = sin(theta); + vec4 sz_prime = sqrt( 1.0 - sz*sz ); + vec4 gx, gy, gz; + if(alpha != 0.0) { + vec4 px = Ct * sz_prime, py = St * sz_prime, pz = sz; + vec4 Sp = sin(psi), Cp = cos(psi), Ctp = St*Sp - Ct*Cp; + vec4 qx = mix( Ctp*St, Sp, sz), qy = mix(-Ctp*Ct, Cp, sz); + vec4 qz = -(py*Cp + px*Sp); + vec4 Sa = vec4(sin(alpha)), Ca = vec4(cos(alpha)); + gx = Ca*px + Sa*qx; gy = Ca*py + Sa*qy; gz = Ca*pz + Sa*qz; + } else { + gx = Ct * sz_prime; gy = St * sz_prime; gz = sz; + } + vec3 g0 = vec3(gx.x, gy.x, gz.x), g1 = vec3(gx.y, gy.y, gz.y); + vec3 g2 = vec3(gx.z, gy.z, gz.z), g3 = vec3(gx.w, gy.w, gz.w); + vec4 w = 0.5-vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)); + w = max(w, 0.0); vec4 w2 = w * w, w3 = w2 * w; + vec4 gdotx = vec4(dot(g0,x0), dot(g1,x1), dot(g2,x2), dot(g3,x3)); + float n = dot(w3, gdotx); + vec4 dw = -6.0 * w2 * gdotx; + vec3 dn0 = w3.x * g0 + dw.x * x0; + vec3 dn1 = w3.y * g1 + dw.y * x1; + vec3 dn2 = w3.z * g2 + dw.z * x2; + vec3 dn3 = w3.w * g3 + dw.w * x3; + gradient = 39.5 * (dn0 + dn1 + dn2 + dn3); + return 39.5 * n; + } + + float psrdnoise3(vec3 x, vec3 period, float alpha) { + vec3 gradient; + return psrdnoise3_with_gradient(x, period, alpha, gradient); + } + + """ + +func _get_code(input_vars, output_vars, mode, type): + + return "%s = psrdnoise3(%s.xyz, %s.xyz, %s);" % [output_vars[0], input_vars[0], input_vars[1], input_vars[2]]