-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Based on https://docs.godotengine.org/en/stable/classes/class_webxrinterface.html and https://www.snopekgames.com/tutorial/2023/how-make-vr-game-webxr-godot-4 Co-Authored-By: David Snopek <[email protected]>
- Loading branch information
Showing
9 changed files
with
283 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Godot 4+ specific ignores | ||
.godot/ | ||
/android/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# WebXR demo | ||
|
||
This is a minimalist demo of WebXR rendering and controller support. | ||
|
||
Language: GDScript | ||
|
||
Renderer: Compatibility |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
[remap] | ||
|
||
importer="texture" | ||
type="CompressedTexture2D" | ||
uid="uid://b8qswdbhoi3ks" | ||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" | ||
metadata={ | ||
"vram_texture": false | ||
} | ||
|
||
[deps] | ||
|
||
source_file="res://icon.svg" | ||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] | ||
|
||
[params] | ||
|
||
compress/mode=0 | ||
compress/high_quality=false | ||
compress/lossy_quality=0.7 | ||
compress/hdr_compression=1 | ||
compress/normal_map=0 | ||
compress/channel_pack=0 | ||
mipmaps/generate=false | ||
mipmaps/limit=-1 | ||
roughness/mode=0 | ||
roughness/src_normal="" | ||
process/fix_alpha_border=true | ||
process/premult_alpha=false | ||
process/normal_map_invert_y=false | ||
process/hdr_as_srgb=false | ||
process/hdr_clamp_exposure=false | ||
process/size_limit=0 | ||
detect_3d/compress_to=1 | ||
svg/scale=1.0 | ||
editor/scale_with_editor_scale=false | ||
editor/convert_colors_with_editor_theme=false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
extends Node3D | ||
|
||
var webxr_interface: XRInterface | ||
var vr_supported: bool = false | ||
|
||
|
||
func _ready() -> void: | ||
$CanvasLayer/EnterVRButton.pressed.connect(self._on_enter_vr_button_pressed) | ||
|
||
webxr_interface = XRServer.find_interface("WebXR") | ||
if webxr_interface: | ||
# WebXR uses a lot of asynchronous callbacks, so we connect to various | ||
# signals in order to receive them. | ||
webxr_interface.session_supported.connect(self._webxr_session_supported) | ||
webxr_interface.session_started.connect(self._webxr_session_started) | ||
webxr_interface.session_ended.connect(self._webxr_session_ended) | ||
webxr_interface.session_failed.connect(self._webxr_session_failed) | ||
|
||
webxr_interface.select.connect(self._webxr_on_select) | ||
webxr_interface.selectstart.connect(self._webxr_on_select_start) | ||
webxr_interface.selectend.connect(self._webxr_on_select_end) | ||
|
||
webxr_interface.squeeze.connect(self._webxr_on_squeeze) | ||
webxr_interface.squeezestart.connect(self._webxr_on_squeeze_start) | ||
webxr_interface.squeezeend.connect(self._webxr_on_squeeze_end) | ||
|
||
# This returns immediately - our _webxr_session_supported() method | ||
# (which we connected to the "session_supported" signal above) will | ||
# be called sometime later to let us know if it's supported or not. | ||
webxr_interface.is_session_supported("immersive-vr") | ||
|
||
$XROrigin3D/LeftController.button_pressed.connect(self._on_left_controller_button_pressed) | ||
$XROrigin3D/LeftController.button_released.connect(self._on_left_controller_button_released) | ||
|
||
|
||
|
||
func _webxr_session_supported(session_mode: String, supported: bool) -> void: | ||
if session_mode == 'immersive-vr': | ||
vr_supported = supported | ||
|
||
|
||
func _on_enter_vr_button_pressed() -> void: | ||
if not vr_supported: | ||
OS.alert("Your browser doesn't support VR") | ||
return | ||
|
||
# We want an immersive VR session, as opposed to AR ('immersive-ar') or a | ||
# simple 3DoF viewer ('viewer'). | ||
webxr_interface.session_mode = 'immersive-vr' | ||
# 'bounded-floor' is room scale, 'local-floor' is a standing or sitting | ||
# experience (it puts you 1.6m above the ground if you have 3DoF headset), | ||
# whereas as 'local' puts you down at the ARVROrigin. | ||
# This list means it'll first try to request 'bounded-floor', then | ||
# fallback on 'local-floor' and ultimately 'local', if nothing else is | ||
# supported. | ||
webxr_interface.requested_reference_space_types = 'bounded-floor, local-floor, local' | ||
# In order to use 'local-floor' or 'bounded-floor' we must also | ||
# mark the features as required or optional. | ||
webxr_interface.required_features = 'local-floor' | ||
webxr_interface.optional_features = 'bounded-floor' | ||
|
||
# This will return false if we're unable to even request the session, | ||
# however, it can still fail asynchronously later in the process, so we | ||
# only know if it's really succeeded or failed when our | ||
# _webxr_session_started() or _webxr_session_failed() methods are called. | ||
if not webxr_interface.initialize(): | ||
OS.alert("Failed to initialize WebXR") | ||
return | ||
|
||
|
||
func _webxr_session_started() -> void: | ||
$CanvasLayer.visible = false | ||
# This tells Godot to start rendering to the headset. | ||
get_viewport().use_xr = true | ||
# This will be the reference space type you ultimately got, out of the | ||
# types that you requested above. This is useful if you want the game to | ||
# work a little differently in 'bounded-floor' versus 'local-floor'. | ||
print ("Reference space type: " + webxr_interface.reference_space_type) | ||
# This will be the list of features that were successfully enabled | ||
# (except on browsers that don't support this property). | ||
print("Enabled features: ", webxr_interface.enabled_features) | ||
|
||
|
||
func _webxr_session_ended() -> void: | ||
$CanvasLayer.visible = true | ||
# If the user exits immersive mode, then we tell Godot to render to the web | ||
# page again. | ||
get_viewport().use_xr = false | ||
|
||
|
||
func _webxr_session_failed(message: String) -> void: | ||
OS.alert("Failed to initialize: " + message) | ||
|
||
|
||
func _on_left_controller_button_pressed(button: String) -> void: | ||
print ("Button pressed: " + button) | ||
|
||
|
||
func _on_left_controller_button_released(button: String) -> void: | ||
print ("Button release: " + button) | ||
|
||
|
||
func _process(_delta: float) -> void: | ||
var thumbstick_vector: Vector2 = $XROrigin3D/LeftController.get_vector2("thumbstick") | ||
if thumbstick_vector != Vector2.ZERO: | ||
print ("Left thumbstick position: " + str(thumbstick_vector)) | ||
|
||
|
||
func _webxr_on_select(input_source_id: int) -> void: | ||
print("Select: " + str(input_source_id)) | ||
|
||
var tracker: XRPositionalTracker = webxr_interface.get_input_source_tracker(input_source_id) | ||
var xform = tracker.get_pose('default').transform | ||
print (xform.origin) | ||
|
||
|
||
func _webxr_on_select_start(input_source_id: int) -> void: | ||
print("Select Start: " + str(input_source_id)) | ||
|
||
|
||
func _webxr_on_select_end(input_source_id: int) -> void: | ||
print("Select End: " + str(input_source_id)) | ||
|
||
|
||
func _webxr_on_squeeze(input_source_id: int) -> void: | ||
print("Squeeze: " + str(input_source_id)) | ||
|
||
|
||
func _webxr_on_squeeze_start(input_source_id: int) -> void: | ||
print("Squeeze Start: " + str(input_source_id)) | ||
|
||
|
||
func _webxr_on_squeeze_end(input_source_id: int) -> void: | ||
print("Squeeze End: " + str(input_source_id)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
[gd_scene load_steps=7 format=3 uid="uid://dismxfxe7wvdn"] | ||
|
||
[ext_resource type="Script" path="res://main.gd" id="1_ig7tw"] | ||
|
||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_lins3"] | ||
sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) | ||
ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) | ||
|
||
[sub_resource type="Sky" id="Sky_wiqav"] | ||
sky_material = SubResource("ProceduralSkyMaterial_lins3") | ||
|
||
[sub_resource type="Environment" id="Environment_6ff2h"] | ||
background_mode = 2 | ||
sky = SubResource("Sky_wiqav") | ||
tonemap_mode = 2 | ||
|
||
[sub_resource type="BoxMesh" id="BoxMesh_gv5m4"] | ||
size = Vector3(0.1, 0.1, 0.1) | ||
|
||
[sub_resource type="BoxMesh" id="BoxMesh_f3sb7"] | ||
size = Vector3(0.1, 0.1, 0.1) | ||
|
||
[node name="Main" type="Node3D"] | ||
script = ExtResource("1_ig7tw") | ||
|
||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] | ||
environment = SubResource("Environment_6ff2h") | ||
|
||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] | ||
transform = Transform3D(-0.866025, -0.433013, 0.25, 0, 0.5, 0.866025, -0.5, 0.75, -0.433013, 0, 0, 0) | ||
shadow_enabled = true | ||
|
||
[node name="XROrigin3D" type="XROrigin3D" parent="."] | ||
|
||
[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7, 0) | ||
|
||
[node name="LeftController" type="XRController3D" parent="XROrigin3D"] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 1, 0) | ||
tracker = &"left_hand" | ||
|
||
[node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/LeftController"] | ||
mesh = SubResource("BoxMesh_gv5m4") | ||
|
||
[node name="RightController" type="XRController3D" parent="XROrigin3D"] | ||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 1, 0) | ||
tracker = &"right_hand" | ||
|
||
[node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/RightController"] | ||
mesh = SubResource("BoxMesh_f3sb7") | ||
|
||
[node name="CanvasLayer" type="CanvasLayer" parent="."] | ||
|
||
[node name="EnterVRButton" type="Button" parent="CanvasLayer"] | ||
anchors_preset = 8 | ||
anchor_left = 0.5 | ||
anchor_top = 0.5 | ||
anchor_right = 0.5 | ||
anchor_bottom = 0.5 | ||
offset_left = -50.0 | ||
offset_top = -25.0 | ||
offset_right = 50.0 | ||
offset_bottom = 25.0 | ||
grow_horizontal = 2 | ||
grow_vertical = 2 | ||
text = "Enter VR" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
; Engine configuration file. | ||
; It's best edited using the editor UI and not directly, | ||
; since the parameters that go here are not all obvious. | ||
; | ||
; Format: | ||
; [section] ; section goes between [] | ||
; param=value ; assign values to parameters | ||
|
||
config_version=5 | ||
|
||
[application] | ||
|
||
config/name="WebXR demo" | ||
run/main_scene="res://main.tscn" | ||
config/features=PackedStringArray("4.3", "GL Compatibility") | ||
config/icon="res://icon.svg" | ||
|
||
[physics] | ||
|
||
common/enable_object_picking=false | ||
|
||
[rendering] | ||
|
||
renderer/rendering_method="gl_compatibility" | ||
renderer/rendering_method.mobile="gl_compatibility" | ||
textures/vram_compression/import_etc2_astc=true | ||
|
||
[xr] | ||
|
||
shaders/enabled=true |