Skip to content

Commit 8847300

Browse files
committed
Create xr full screen effects page
1 parent 721603d commit 8847300

File tree

5 files changed

+82
-0
lines changed

5 files changed

+82
-0
lines changed
7.75 KB
Loading
44.2 KB
Loading
45.5 KB
Loading

tutorials/xr/index.rst

Lines changed: 1 addition & 0 deletions
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
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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 valid approach is
7+
applying a full screen quad to the XR camera and applying effects to that quad's shader.
8+
9+
.. image:: img/xr_full_screen_effects_starting_quad.webp
10+
11+
Here is a simple vignette shader that you might apply to the quad, darkening the edges
12+
of a user's screen:
13+
14+
.. code-block:: glsl
15+
16+
shader_type spatial;
17+
render_mode depth_test_disabled, skip_vertex_transform, unshaded, cull_disabled;
18+
19+
void vertex() {
20+
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
21+
}
22+
23+
void fragment() {
24+
ALBEDO = vec3(0.0);
25+
ALPHA = dot(UV * 2.0 - 1.0, UV * 2.0 - 1.0) * 2.0;
26+
}
27+
28+
29+
However, when creating an effect that is centered straight ahead in the user's view
30+
(such as the above vignette effect), the end result may look incorrect in XR.
31+
Below shows two captures of the right-eye view with a vignette shader. The left capture is an
32+
unmodified shader; the right capture adjusts the full screen quad using the projection matrix.
33+
This adjustment is what we're looking for.
34+
35+
.. image:: img/xr_full_screen_effects_vignette_before_after.webp
36+
37+
Applying the projection matrix
38+
------------------------------
39+
40+
To properly center the effect, the ``POSITION`` of the full screen quad
41+
needs to take the asymmetric field of view into account. To do this while also ensuring the quad
42+
has full coverage of the entire render target, we can subdivide the quad and apply the projection matrix
43+
to the inner vertices. Let's increase the subdivide width and depth of the quad.
44+
45+
.. image:: img/xr_full_screen_effects_ending_quad.webp
46+
47+
Then, in the vertex function of our shader, we apply an offset from the projection matrix to
48+
the inner vertices. Here's an example of how you might do this with the above simple vignette shader:
49+
50+
.. code-block:: glsl
51+
52+
shader_type spatial;
53+
render_mode depth_test_disabled, skip_vertex_transform, unshaded, cull_disabled;
54+
55+
void vertex() {
56+
vec2 vert_pos = VERTEX.xy;
57+
58+
if (length(vert_pos) < 0.99) {
59+
vec4 offset = PROJECTION_MATRIX * vec4(0.0, 0.0, 1.0, 1.0);
60+
vert_pos += (offset.xy / offset.w);
61+
}
62+
63+
POSITION = vec4(vert_pos, 1.0, 1.0);
64+
}
65+
66+
void fragment() {
67+
ALBEDO = vec3(0.0);
68+
ALPHA = dot(UV * 2.0 - 1.0, UV * 2.0 - 1.0) * 2.0;
69+
}
70+
71+
72+
.. note:: For more info on asymmetric FOV and its purpose, see this
73+
`Meta Asymmetric Field of View FAQ <https://developers.meta.com/horizon/documentation/unity/unity-asymmetric-fov-faq/>`_.
74+
75+
Limitations
76+
-----------
77+
78+
Currently, full screen effects that require reading from the screen texture effectively disable all
79+
rendering performance optimizations in XR. This is because, when reading from the screen texture,
80+
Godot makes a full copy of the render buffer. Since this may create performance issues, it is recommended
81+
that custom effects be limited to per-pixel ones such as the above vignette shader.

0 commit comments

Comments
 (0)