This commit is contained in:
sharpoff
2026-01-14 13:01:37 +09:00
commit 49d7e22132
660 changed files with 41243 additions and 0 deletions

View 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)

View File

@@ -0,0 +1 @@
uid://ook5rcwquue

View 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;
}

View File

@@ -0,0 +1 @@
uid://crgou0mlv2l0s

View 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")

View 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

View File

@@ -0,0 +1 @@
uid://4ehwuml4mp5k

View 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);
}

View File

@@ -0,0 +1 @@
uid://dxjwjsisjug3u

View 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

View 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")