Полноэкранные эффекты XR
При добавлении пользовательских полноэкранных эффектов в приложение XR один из подходов — использовать полноэкранный квадрат и применять эффекты к шейдеру этого квадрата. Добавьте узел MeshInstance3D в сцену как дочерний узел XRCamera3D и задайте свойству mesh значение QuadMesh. Задайте ширину и высоту квадрата равными 2.
Затем вы можете добавить шейдер к своему квадрату, чтобы он покрывал весь экран. Это делается путём установки встроенного параметра POSITION вершинного шейдера в значение vec4(VERTEX.xy, 1.0, 1.0). Однако при создании эффекта, центрированного прямо перед пользователем (например, эффекта виньетки), конечный результат может выглядеть некорректно в XR.
Ниже представлены скриншоты правого глаза с шейдером vignette, как с гарнитуры, так и с самого целевого рендера. Снимки слева — это неизменённый шейдер; снимки справа корректируют полноэкранный квадрат с помощью проекционной матрицы. В то время как скриншот слева центрирован в целевом рендере, он смещен в режиме просмотра гарнитуры. Однако после применения проекционной матрицы мы видим, что эффект центрирован в самом шлеме.
Применение проекционной матрицы
Для правильного центрирования эффекта необходимо, чтобы POSITION полноэкранного квадрата учитывало асимметричное поле зрения. Чтобы добиться этого, а также обеспечить полное покрытие квадратом всей целевой области рендеринга, мы можем разделить квадрат и применить матрицу проекции к внутренним вершинам. Увеличим ширину и глубину разделения квадрата.
Затем в вершинной функции нашего шейдера мы применяем смещение от матрицы проекции к внутренним вершинам. Вот пример того, как это можно сделать с помощью простого шейдера виньетирования, представленного выше:
shader_type spatial;
render_mode depth_test_disabled, skip_vertex_transform, unshaded, cull_disabled;
// Modify VERTEX.xy using the projection matrix to correctly center the effect.
void vertex() {
vec2 vert_pos = VERTEX.xy;
if (length(vert_pos) < 0.99) {
vec4 offset = PROJECTION_MATRIX * vec4(0.0, 0.0, 1.0, 1.0);
vert_pos += (offset.xy / offset.w);
}
POSITION = vec4(vert_pos, 1.0, 1.0);
}
void fragment() {
ALBEDO = vec3(0.0);
ALPHA = dot(UV * 2.0 - 1.0, UV * 2.0 - 1.0) * 2.0;
}
Примечание
Более подробную информацию об асимметричном поле зрения и его назначении см. в этом разделе Часто задаваемые вопросы о метаасимметричном поле зрения.
Ограничения
Этот метод полноэкранных эффектов не влияет на производительность попиксельных эффектов, таких как шейдер виньетирования, описанный выше. Однако при использовании этой техники не рекомендуется считывать данные из экранной текстуры. Полноэкранные эффекты, требующие считывания данных из экранной текстуры, фактически отключают все оптимизации производительности рендеринга в XR. Это связано с тем, что при считывании данных из экранной текстуры Godot создаёт полную копию буфера рендеринга; это значительно увеличивает нагрузку на графический процессор и может привести к проблемам с производительностью.