Post-processing in VR
Asked Answered
C

1

0

Heya,

I've been looking into custom post-processing shaders for later use in-game events or for stylistic purposes, such as a nearest-neighbor downscaler for a pixelated look. However, I've been experiencing difficulties when trying to apply this screen-reading shader in VR. Instead of the desired effect, a black rectangle appears in the top left corner of the "screen," the size of which depends on the size of the former game window. I'm wondering if this is an expected behavior, or if I'm missing something. Is there a workaround to make screen-reading shaders work in VR?

Here are some visual examples to illustrate the issue:
The unprocessed image:

What it should look like (rendered with a normal 3D camera):

What it looks like when applied to the XR camera (the black rectangle seems to be the ColorRect/CanvasLayer):

The setup for the XR-rig + CanvasLayer and the settings for the ColorRect:

The code for the nearest-neighbour downscaling:

shader_type canvas_item;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, repeat_disable, filter_nearest;
void fragment() {
        vec2 screen_size = 1.0/SCREEN_PIXEL_SIZE;
        // converts UV-coordinates (0-1) to pixel-coordinates (e.g. 0-1920, 0-1080), scales them down by 25%
        // afterwards those "stepped" coordinates are converted back to uv-coordinates
        vec2 uv = vec2(floor((SCREEN_UV.x*screen_size.x)/4.0)/screen_size.x, 
                floor((SCREEN_UV.y*screen_size.y)/4.0)/screen_size.y)*4.0;
        // takes one square of 16x16px and paints it with the mean colour.
        vec3 col = texture(SCREEN_TEXTURE, uv).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x	, 0.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(0.0					, SCREEN_PIXEL_SIZE.y)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x	, SCREEN_PIXEL_SIZE.y)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*2.0, 0.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*2.0, SCREEN_PIXEL_SIZE.y)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*2.0, SCREEN_PIXEL_SIZE.y*2.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(0.0					, SCREEN_PIXEL_SIZE.x*2.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x	, SCREEN_PIXEL_SIZE.x*2.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*3.0, 0.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*3.0, SCREEN_PIXEL_SIZE.y)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*3.0, SCREEN_PIXEL_SIZE.y*2.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(0.0					, SCREEN_PIXEL_SIZE.y*3.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x	, SCREEN_PIXEL_SIZE.y*3.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*2.0, SCREEN_PIXEL_SIZE.y*3.0)).xyz*0.0625;
        col += texture(SCREEN_TEXTURE, uv + vec2(SCREEN_PIXEL_SIZE.x*3.0, SCREEN_PIXEL_SIZE.y*3.0)).xyz*0.0625;
    COLOR.xyz = col;
}
Chemesh answered 7/5, 2023 at 18:26 Comment(0)
D
0

2D shaders don't work that way in VR. You can find examples of working screen space shaders at godotshaders. Maybe there is some way to convert yours to 3D/VR by looking at their code, not sure.

https://godotshaders.com/shader/godotcity-xr-vr-shader/

Deanedeaner answered 23/6, 2023 at 11:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.