init
This commit is contained in:
97
addons/godot-xr-tools/effects/fade.gd
Normal file
97
addons/godot-xr-tools/effects/fade.gd
Normal file
@@ -0,0 +1,97 @@
|
||||
@tool
|
||||
class_name XRToolsFade
|
||||
extends Node3D
|
||||
|
||||
|
||||
## XR Tools Fade Script
|
||||
##
|
||||
## This script manages fading the view.
|
||||
|
||||
@export_flags_3d_render var layers = 2:
|
||||
set(value):
|
||||
layers = value
|
||||
if _mesh:
|
||||
_mesh.layers = layers
|
||||
|
||||
# Dictionary of fade requests
|
||||
var _faders : Dictionary = {}
|
||||
|
||||
# Fade update flag
|
||||
var _update : bool = false
|
||||
|
||||
# Fade mesh
|
||||
var _mesh : MeshInstance3D
|
||||
|
||||
# Fade shader material
|
||||
var _material : ShaderMaterial
|
||||
|
||||
|
||||
# Add support for is_xr_class on XRTools classes
|
||||
func is_xr_class(xr_name: String) -> bool:
|
||||
return xr_name == "XRToolsFade"
|
||||
|
||||
|
||||
# Called when the fade node is ready
|
||||
func _ready() -> void:
|
||||
# Add to the fade_mesh group - in the future this should be replaced with
|
||||
# static instances.
|
||||
add_to_group("fade_mesh")
|
||||
|
||||
# Get the mesh and material
|
||||
_mesh = $FadeMesh
|
||||
if _mesh:
|
||||
_mesh.layers = layers
|
||||
_material = _mesh.get_surface_override_material(0)
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(_delta : float) -> void:
|
||||
# Skip if nothing to update
|
||||
if not _update:
|
||||
return
|
||||
|
||||
# Calculate the cumulative shade color
|
||||
var fade := Color(1, 1, 1, 0)
|
||||
var show := false
|
||||
for whom in _faders:
|
||||
var color := _faders[whom] as Color
|
||||
fade = fade.blend(color)
|
||||
show = true
|
||||
|
||||
# Set the shader and show if necessary
|
||||
_material.set_shader_parameter("albedo", fade)
|
||||
_mesh.visible = show
|
||||
_update = false
|
||||
|
||||
|
||||
# Set the fade level
|
||||
func set_fade_level(p_whom : Variant, p_color : Color) -> void:
|
||||
# Test if fading is needed
|
||||
if p_color.a > 0:
|
||||
# Set the fade level
|
||||
_faders[p_whom] = p_color
|
||||
_update = true
|
||||
elif _faders.erase(p_whom):
|
||||
# Fade erased
|
||||
_update = true
|
||||
|
||||
|
||||
## Returns our first current fade node
|
||||
static func get_fade_node() -> XRToolsFade:
|
||||
# In the future this use of groups should be replaced by static instances.
|
||||
var tree := Engine.get_main_loop() as SceneTree
|
||||
for node in tree.get_nodes_in_group("fade_mesh"):
|
||||
var fade := node as XRToolsFade
|
||||
if fade:
|
||||
return fade
|
||||
|
||||
return null
|
||||
|
||||
## Set the fade level on the fade instance
|
||||
static func set_fade(p_whom : Variant, p_color : Color) -> void:
|
||||
# In the future this use of groups should be replaced by static instances.
|
||||
var tree := Engine.get_main_loop() as SceneTree
|
||||
for node in tree.get_nodes_in_group("fade_mesh"):
|
||||
var fade := node as XRToolsFade
|
||||
if fade:
|
||||
fade.set_fade_level(p_whom, p_color)
|
||||
1
addons/godot-xr-tools/effects/fade.gd.uid
Normal file
1
addons/godot-xr-tools/effects/fade.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ook5rcwquue
|
||||
13
addons/godot-xr-tools/effects/fade.gdshader
Normal file
13
addons/godot-xr-tools/effects/fade.gdshader
Normal file
@@ -0,0 +1,13 @@
|
||||
shader_type spatial;
|
||||
render_mode depth_test_disabled, skip_vertex_transform, unshaded, cull_disabled;
|
||||
|
||||
uniform vec4 albedo : source_color;
|
||||
|
||||
void vertex() {
|
||||
POSITION = vec4(VERTEX.x, -VERTEX.y, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = albedo.rgb;
|
||||
ALPHA = albedo.a;
|
||||
}
|
||||
1
addons/godot-xr-tools/effects/fade.gdshader.uid
Normal file
1
addons/godot-xr-tools/effects/fade.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://crgou0mlv2l0s
|
||||
22
addons/godot-xr-tools/effects/fade.tscn
Normal file
22
addons/godot-xr-tools/effects/fade.tscn
Normal file
@@ -0,0 +1,22 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://wtpox7m5vu2b"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ook5rcwquue" path="res://addons/godot-xr-tools/effects/fade.gd" id="1_6667f"]
|
||||
[ext_resource type="Shader" uid="uid://crgou0mlv2l0s" path="res://addons/godot-xr-tools/effects/fade.gdshader" id="1_tjen8"]
|
||||
|
||||
[sub_resource type="QuadMesh" id="QuadMesh_aqp6r"]
|
||||
custom_aabb = AABB(-5000, -5000, -5000, 10000, 10000, 10000)
|
||||
size = Vector2(2, 2)
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_xjgy8"]
|
||||
render_priority = 50
|
||||
shader = ExtResource("1_tjen8")
|
||||
shader_parameter/albedo = Color(0, 0, 0, 1)
|
||||
|
||||
[node name="Fade" type="Node3D"]
|
||||
script = ExtResource("1_6667f")
|
||||
cull_mask = 1
|
||||
|
||||
[node name="FadeMesh" type="MeshInstance3D" parent="."]
|
||||
visible = false
|
||||
mesh = SubResource("QuadMesh_aqp6r")
|
||||
surface_material_override/0 = SubResource("ShaderMaterial_xjgy8")
|
||||
202
addons/godot-xr-tools/effects/vignette.gd
Normal file
202
addons/godot-xr-tools/effects/vignette.gd
Normal file
@@ -0,0 +1,202 @@
|
||||
@tool
|
||||
class_name XRToolsVignette
|
||||
extends Node3D
|
||||
|
||||
@export var radius : float = 1.0: set = set_radius
|
||||
@export var fade : float = 0.05: set = set_fade
|
||||
@export var steps : int = 32: set = set_steps
|
||||
|
||||
@export var auto_adjust : bool = true: set = set_auto_adjust
|
||||
@export var auto_inner_radius : float = 0.35
|
||||
@export var auto_fade_out_factor : float = 1.5
|
||||
@export var auto_fade_delay : float = 1.0
|
||||
@export var auto_rotation_limit : float = 20.0: set = set_auto_rotation_limit
|
||||
@export var auto_velocity_limit : float = 10.0
|
||||
|
||||
@export_flags_3d_render var layers = 2:
|
||||
set(value):
|
||||
layers = value
|
||||
if is_inside_tree():
|
||||
$Mesh.layers = layers
|
||||
|
||||
var material : ShaderMaterial = preload("res://addons/godot-xr-tools/effects/vignette.tres")
|
||||
|
||||
var auto_first = true
|
||||
var fade_delay = 0.0
|
||||
var origin_node = null
|
||||
var last_origin_basis : Basis
|
||||
var last_location : Vector3
|
||||
@onready var auto_rotation_limit_rad = deg_to_rad(auto_rotation_limit)
|
||||
|
||||
func set_radius(new_radius : float) -> void:
|
||||
radius = new_radius
|
||||
if is_inside_tree():
|
||||
_update_radius()
|
||||
|
||||
func _update_radius() -> void:
|
||||
if radius < 1.0:
|
||||
if material:
|
||||
material.set_shader_parameter("radius", radius * sqrt(2))
|
||||
$Mesh.visible = true
|
||||
else:
|
||||
$Mesh.visible = false
|
||||
|
||||
func set_fade(new_fade : float) -> void:
|
||||
fade = new_fade
|
||||
if is_inside_tree():
|
||||
_update_fade()
|
||||
|
||||
func _update_fade() -> void:
|
||||
if material:
|
||||
material.set_shader_parameter("fade", fade)
|
||||
|
||||
|
||||
func set_steps(new_steps : int) -> void:
|
||||
steps = new_steps
|
||||
if is_inside_tree():
|
||||
_update_mesh()
|
||||
|
||||
func _update_mesh() -> void:
|
||||
var vertices : PackedVector3Array
|
||||
var indices : PackedInt32Array
|
||||
|
||||
vertices.resize(2 * steps)
|
||||
indices.resize(6 * steps)
|
||||
for i in steps:
|
||||
var v : Vector3 = Vector3.RIGHT.rotated(Vector3.FORWARD, deg_to_rad((360.0 * i) / steps))
|
||||
vertices[i] = v
|
||||
vertices[steps+i] = v * 2.0
|
||||
|
||||
var off = i * 6
|
||||
var i2 = ((i + 1) % steps)
|
||||
indices[off + 0] = steps + i
|
||||
indices[off + 1] = steps + i2
|
||||
indices[off + 2] = i2
|
||||
indices[off + 3] = steps + i
|
||||
indices[off + 4] = i2
|
||||
indices[off + 5] = i
|
||||
|
||||
# update our mesh
|
||||
var arr_mesh = ArrayMesh.new()
|
||||
var arr : Array
|
||||
arr.resize(ArrayMesh.ARRAY_MAX)
|
||||
arr[ArrayMesh.ARRAY_VERTEX] = vertices
|
||||
arr[ArrayMesh.ARRAY_INDEX] = indices
|
||||
arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arr)
|
||||
arr_mesh.custom_aabb = AABB(Vector3(-1.0, -1.0, -1.0), Vector3(1.0, 1.0, 1.0))
|
||||
|
||||
$Mesh.mesh = arr_mesh
|
||||
$Mesh.layers = layers
|
||||
$Mesh.set_surface_override_material(0, material)
|
||||
|
||||
func set_auto_adjust(new_auto_adjust : bool) -> void:
|
||||
auto_adjust = new_auto_adjust
|
||||
if is_inside_tree() and !Engine.is_editor_hint():
|
||||
_update_auto_adjust()
|
||||
|
||||
func _update_auto_adjust() -> void:
|
||||
# Turn process on if auto adjust is true.
|
||||
# Note we don't turn it off here, we want to finish fading out the vignette if needed
|
||||
if auto_adjust:
|
||||
set_process(true)
|
||||
|
||||
func set_auto_rotation_limit(new_auto_rotation_limit : float) -> void:
|
||||
auto_rotation_limit = new_auto_rotation_limit
|
||||
auto_rotation_limit_rad = deg_to_rad(auto_rotation_limit)
|
||||
|
||||
|
||||
# Add support for is_xr_class on XRTools classes
|
||||
func is_xr_class(xr_name: String) -> bool:
|
||||
return xr_name == "XRToolsVignette"
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
if !Engine.is_editor_hint():
|
||||
origin_node = XRHelpers.get_xr_origin(self)
|
||||
_update_mesh()
|
||||
_update_radius()
|
||||
_update_fade()
|
||||
_update_auto_adjust()
|
||||
else:
|
||||
set_process(false)
|
||||
|
||||
# Called on process
|
||||
func _process(delta):
|
||||
if Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
if !origin_node:
|
||||
return
|
||||
|
||||
if !auto_adjust:
|
||||
# set to true for next time this is enabled
|
||||
auto_first = true
|
||||
|
||||
# We are done, turn off process
|
||||
set_process(false)
|
||||
|
||||
return
|
||||
|
||||
if auto_first:
|
||||
# first time we run process since starting, just record transform
|
||||
last_origin_basis = origin_node.global_transform.basis
|
||||
last_location = global_transform.origin
|
||||
auto_first = false
|
||||
return
|
||||
|
||||
# Get our delta transform
|
||||
var delta_b = origin_node.global_transform.basis * last_origin_basis.inverse()
|
||||
var delta_v = global_transform.origin - last_location
|
||||
|
||||
# Adjust radius based on rotation speed of our origin point (not of head movement).
|
||||
# We convert our delta rotation to a quaterion.
|
||||
# A quaternion represents a rotation around an angle.
|
||||
var q = delta_b.get_rotation_quaternion()
|
||||
|
||||
# We get our angle from our w component and then adjust to get a
|
||||
# rotation speed per second by dividing by delta
|
||||
var angle = (2 * acos(q.w)) / delta
|
||||
|
||||
# Calculate what our radius should be for our rotation speed
|
||||
var target_radius = 1.0
|
||||
if auto_rotation_limit > 0:
|
||||
target_radius = 1.0 - (
|
||||
clamp(angle / auto_rotation_limit_rad, 0.0, 1.0) * (1.0 - auto_inner_radius))
|
||||
|
||||
# Now do the same for speed, this includes players physical speed but there
|
||||
# isn't much we can do there.
|
||||
if auto_velocity_limit > 0:
|
||||
var velocity = delta_v.length() / delta
|
||||
target_radius = min(target_radius, 1.0 - (
|
||||
clamp(velocity / auto_velocity_limit, 0.0, 1.0) * (1.0 - auto_inner_radius)))
|
||||
|
||||
# if our radius is small then our current we apply it
|
||||
if target_radius < radius:
|
||||
set_radius(target_radius)
|
||||
fade_delay = auto_fade_delay
|
||||
elif fade_delay > 0.0:
|
||||
fade_delay -= delta
|
||||
else:
|
||||
set_radius(clamp(radius + delta / auto_fade_out_factor, 0.0, 1.0))
|
||||
|
||||
last_origin_basis = origin_node.global_transform.basis
|
||||
last_location = global_transform.origin
|
||||
|
||||
# This method verifies the vignette has a valid configuration.
|
||||
# Specifically it checks the following:
|
||||
# - XROrigin3D is a parent
|
||||
# - XRCamera3D is our parent
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
var warnings := PackedStringArray()
|
||||
|
||||
# Check the origin node
|
||||
if !XRHelpers.get_xr_origin(self):
|
||||
warnings.append("Parent node must be in a branch from XROrigin3D")
|
||||
|
||||
# check camera node
|
||||
var parent = get_parent()
|
||||
if !parent or !parent is XRCamera3D:
|
||||
warnings.append("Parent node must be an XRCamera3D")
|
||||
|
||||
return warnings
|
||||
1
addons/godot-xr-tools/effects/vignette.gd.uid
Normal file
1
addons/godot-xr-tools/effects/vignette.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://4ehwuml4mp5k
|
||||
34
addons/godot-xr-tools/effects/vignette.gdshader
Normal file
34
addons/godot-xr-tools/effects/vignette.gdshader
Normal file
@@ -0,0 +1,34 @@
|
||||
shader_type spatial;
|
||||
render_mode depth_test_disabled, skip_vertex_transform, unshaded, cull_disabled;
|
||||
|
||||
uniform vec4 color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
uniform float radius = 1.0;
|
||||
uniform float fade = 0.05;
|
||||
|
||||
varying float dist;
|
||||
|
||||
void vertex() {
|
||||
vec2 v = VERTEX.xy;
|
||||
dist = length(v);
|
||||
|
||||
// outer ring is 2.0, inner ring is 1.0, so this scales purely the inner ring
|
||||
if (dist < 1.5) {
|
||||
// Adjust by radius
|
||||
dist = radius;
|
||||
v *= dist;
|
||||
|
||||
// We don't know our eye center, projecting a center point in the distance gives us a good enough approximation
|
||||
vec4 eye = PROJECTION_MATRIX * vec4(0.0, 0.0, 100.0, 1.0);
|
||||
|
||||
// and we offset our inner circle
|
||||
v += eye.xy / eye.w;
|
||||
}
|
||||
|
||||
float z = PROJECTION_MATRIX[2][2] < 0.0 ? 0.0 : 1.0;
|
||||
POSITION = vec4(v, z, 1.0);
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = color.rgb;
|
||||
ALPHA = clamp((dist - radius) / fade, 0.0, 1.0);
|
||||
}
|
||||
1
addons/godot-xr-tools/effects/vignette.gdshader.uid
Normal file
1
addons/godot-xr-tools/effects/vignette.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dxjwjsisjug3u
|
||||
10
addons/godot-xr-tools/effects/vignette.tres
Normal file
10
addons/godot-xr-tools/effects/vignette.tres
Normal file
@@ -0,0 +1,10 @@
|
||||
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://cesiqdvdfojle"]
|
||||
|
||||
[ext_resource type="Shader" path="res://addons/godot-xr-tools/effects/vignette.gdshader" id="1_x02h0"]
|
||||
|
||||
[resource]
|
||||
render_priority = 99
|
||||
shader = ExtResource("1_x02h0")
|
||||
shader_parameter/color = Color(0, 0, 0, 1)
|
||||
shader_parameter/radius = 0.282843
|
||||
shader_parameter/fade = 0.05
|
||||
29
addons/godot-xr-tools/effects/vignette.tscn
Normal file
29
addons/godot-xr-tools/effects/vignette.tscn
Normal file
@@ -0,0 +1,29 @@
|
||||
[gd_scene load_steps=4 format=4 uid="uid://cc6ngdqie8o8c"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://4ehwuml4mp5k" path="res://addons/godot-xr-tools/effects/vignette.gd" id="1"]
|
||||
[ext_resource type="Material" uid="uid://cesiqdvdfojle" path="res://addons/godot-xr-tools/effects/vignette.tres" id="2_djtaj"]
|
||||
|
||||
[sub_resource type="ArrayMesh" id="ArrayMesh_yyajy"]
|
||||
_surfaces = [{
|
||||
"aabb": AABB(-2, -2, 0, 4, 4, 1e-05),
|
||||
"format": 34359742465,
|
||||
"index_count": 192,
|
||||
"index_data": PackedByteArray("IAAhAAEAIAABAAAAIQAiAAIAIQACAAEAIgAjAAMAIgADAAIAIwAkAAQAIwAEAAMAJAAlAAUAJAAFAAQAJQAmAAYAJQAGAAUAJgAnAAcAJgAHAAYAJwAoAAgAJwAIAAcAKAApAAkAKAAJAAgAKQAqAAoAKQAKAAkAKgArAAsAKgALAAoAKwAsAAwAKwAMAAsALAAtAA0ALAANAAwALQAuAA4ALQAOAA0ALgAvAA8ALgAPAA4ALwAwABAALwAQAA8AMAAxABEAMAARABAAMQAyABIAMQASABEAMgAzABMAMgATABIAMwA0ABQAMwAUABMANAA1ABUANAAVABQANQA2ABYANQAWABUANgA3ABcANgAXABYANwA4ABgANwAYABcAOAA5ABkAOAAZABgAOQA6ABoAOQAaABkAOgA7ABsAOgAbABoAOwA8ABwAOwAcABsAPAA9AB0APAAdABwAPQA+AB4APQAeAB0APgA/AB8APgAfAB4APwAgAAAAPwAAAB8A"),
|
||||
"primitive": 3,
|
||||
"uv_scale": Vector4(0, 0, 0, 0),
|
||||
"vertex_count": 64,
|
||||
"vertex_data": PackedByteArray("AACAPwAAAAAAAAAAvhR7P8LFR74AAAAAXoNsPxbvw74AAAAAMdtUP9o5Dr8AAAAA8wQ1P/MENb8AAAAA2jkOPzHbVL8AAAAAFe/DPl6DbL8AAAAAxMVHPr4Ue78AAAAALr07swAAgL8AAAAAwsVHvr4Ue78AAAAAFO/Dvl+DbL8AAAAA2TkOvzLbVL8AAAAA8wQ1v/MENb8AAAAAMttUv9k5Dr8AAAAAXoNsvxfvw74AAAAAvxR7v8HFR74AAAAAAACAvy69uzMAAAAAvxR7v73FRz4AAAAAXoNsvxXvwz4AAAAAMNtUv9s5Dj8AAAAA9AQ1v/IENT8AAAAA3TkOvy/bVD8AAAAAGu/Dvl6DbD8AAAAAxsVHvr4Uez8AAAAALt5MMgAAgD8AAAAAyMVHPr4Uez8AAAAAG+/DPl2DbD8AAAAA1zkOPzPbVD8AAAAA8gQ1P/UENT8AAAAAMdtUP9s5Dj8AAAAAX4NsPxXvwz4AAAAAvxR7P7zFRz4AAAAAAAAAQAAAAAAAAAAAvhT7P8LFx74AAAAAXoPsPxbvQ78AAAAAMdvUP9o5jr8AAAAA8wS1P/MEtb8AAAAA2jmOPzHb1L8AAAAAFe9DP16D7L8AAAAAxMXHPr4U+78AAAAALr27swAAAMAAAAAAwsXHvr4U+78AAAAAFO9Dv1+D7L8AAAAA2TmOvzLb1L8AAAAA8wS1v/MEtb8AAAAAMtvUv9k5jr8AAAAAXoPsvxfvQ78AAAAAvxT7v8HFx74AAAAAAAAAwC69OzQAAAAAvxT7v73Fxz4AAAAAXoPsvxXvQz8AAAAAMNvUv9s5jj8AAAAA9AS1v/IEtT8AAAAA3TmOvy/b1D8AAAAAGu9Dv16D7D8AAAAAxsXHvr4U+z8AAAAALt7MMgAAAEAAAAAAyMXHPr4U+z8AAAAAG+9DP12D7D8AAAAA1zmOPzPb1D8AAAAA8gS1P/UEtT8AAAAAMdvUP9s5jj8AAAAAX4PsPxXvQz8AAAAAvxT7P7zFxz4AAAAA")
|
||||
}]
|
||||
custom_aabb = AABB(-1, -1, -1, 1, 1, 1)
|
||||
|
||||
[node name="Vignette" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Mesh" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1)
|
||||
visible = false
|
||||
layers = 2
|
||||
cast_shadow = 0
|
||||
ignore_occlusion_culling = true
|
||||
mesh = SubResource("ArrayMesh_yyajy")
|
||||
surface_material_override/0 = ExtResource("2_djtaj")
|
||||
Reference in New Issue
Block a user