Skip to content

Commit cce8630

Browse files
authored
Merge pull request #10727 from devloglogan/asymmetrical-fov-doc
Create xr full screen effects doc page
2 parents 6b576a7 + 58a5b50 commit cce8630

5 files changed

+74
-0
lines changed
Binary file not shown.
Binary file not shown.
Binary file not shown.

tutorials/xr/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Advanced topics
2929
openxr_settings
3030
xr_action_map
3131
xr_room_scale
32+
xr_full_screen_effects
3233
openxr_composition_layers
3334
openxr_hand_tracking
3435
openxr_body_tracking
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
.. _doc_xr_full_screen_effects:
2+
3+
XR full screen effects
4+
======================
5+
6+
When adding custom full screen effects to your XR application, one approach is
7+
using a full screen quad and applying effects to that quad's shader.
8+
Add a :ref:`MeshInstance3D <class_MeshInstance3D>` node
9+
to your scene as a child of your :ref:`XRCamera3D <class_XRCamera3D>`,
10+
and set the ``mesh`` property to a :ref:`QuadMesh <class_QuadMesh>`.
11+
Set the width and height of the quad to ``2``.
12+
13+
.. image:: img/xr_full_screen_effects_starting_quad.webp
14+
15+
You can then add a shader to your quad to make it cover the screen. This is done by setting the
16+
vertex shader's ``POSITION`` built-in to ``vec4(VERTEX.xy, 1.0, 1.0)``.
17+
However, when creating an effect that is centered straight ahead in the user's view
18+
(such as a vignette effect), the end result may look incorrect in XR.
19+
20+
Below shows captures of the right-eye view with a vignette shader, both from the headset and the render target itself.
21+
The left captures are an unmodified shader; the right captures adjust the full screen quad using the projection matrix.
22+
While the capture on the left is centered in the render target, it is off-center in the headset view.
23+
But, after applying the projection matrix, we see that the effect is centered in the headset itself.
24+
25+
.. image:: img/xr_full_screen_effects_vignette_before_after.webp
26+
27+
Applying the projection matrix
28+
------------------------------
29+
30+
To properly center the effect, the ``POSITION`` of the full screen quad
31+
needs to take the asymmetric field of view into account. To do this while also ensuring the quad
32+
has full coverage of the entire render target, we can subdivide the quad and apply the projection matrix
33+
to the inner vertices. Let's increase the subdivide width and depth of the quad.
34+
35+
.. image:: img/xr_full_screen_effects_ending_quad.webp
36+
37+
Then, in the vertex function of our shader, we apply an offset from the projection matrix to
38+
the inner vertices. Here's an example of how you might do this with the above simple vignette shader:
39+
40+
.. code-block:: glsl
41+
42+
shader_type spatial;
43+
render_mode depth_test_disabled, skip_vertex_transform, unshaded, cull_disabled;
44+
45+
// Modify VERTEX.xy using the projection matrix to correctly center the effect.
46+
void vertex() {
47+
vec2 vert_pos = VERTEX.xy;
48+
49+
if (length(vert_pos) < 0.99) {
50+
vec4 offset = PROJECTION_MATRIX * vec4(0.0, 0.0, 1.0, 1.0);
51+
vert_pos += (offset.xy / offset.w);
52+
}
53+
54+
POSITION = vec4(vert_pos, 1.0, 1.0);
55+
}
56+
57+
void fragment() {
58+
ALBEDO = vec3(0.0);
59+
ALPHA = dot(UV * 2.0 - 1.0, UV * 2.0 - 1.0) * 2.0;
60+
}
61+
62+
63+
.. note:: For more info on asymmetric FOV and its purpose, see this
64+
`Meta Asymmetric Field of View FAQ <https://developers.meta.com/horizon/documentation/unity/unity-asymmetric-fov-faq/>`_.
65+
66+
Limitations
67+
-----------
68+
69+
This full screen effect method has no performance concerns for per-pixel effects such as the above vignette shader.
70+
However, it is not recommended to read from the screen texture when using this technique.
71+
Full screen effects that require reading from the screen texture effectively disable all rendering performance optimizations in XR.
72+
This is because, when reading from the screen texture, Godot makes a full copy of the render buffer;
73+
this drastically increases the workload for the GPU and can create performance concerns.

0 commit comments

Comments
 (0)