[postprocess shaders] Disable texture() interpolation?

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

[postprocess shaders] Disable texture() interpolation?

Postby William Claydock » Tue Oct 12, 2021 2:01 pm

Hey, i've been working with gzd shaders recently and I ran into a pretty weird issue, I'm not sure if this is the right forum to ask this question, and I hope it's not too vague, but
I have the following shader definition:

HardwareShader PostProcess scene {
Name "zoomtest"
Shader "shaders/zoomtest.fsh" 330
}

And the shader looks like this, it's just a generic zoom shader.
void main() {
vec2 coord = TexCoord;
coord -= 0.5;
coord *= 1.5;
coord += 0.5;
FragColor = texture(InputTexture, coord);
}

However, when I test it ingame using a low scale (like 0.25, in video settings), it is all blurry for some reason. I'm assuming this would be because texture() has interpolation enabled on it or something, is there any way to disable it? I've also tried:
void main() {
ivec2 texSize = textureSize(InputTexture, 0);
vec2 coord = TexCoord;
coord -= 0.5;
coord *= 1.5;
coord += 0.5;
coord = vec2(floor(coord.x * texSize.x), floor(coord.y * texSize.y)) / texSize;
FragColor = texture(InputTexture, coord);
}

Which I thought would fix the issue, since it's rounding to the nearest pixel, it does help, but it still looks blurry/interpolated. How do I do this?
William Claydock
 

Re: [postprocess shaders] Disable texture() interpolation?

Postby dpJudas » Tue Oct 12, 2021 2:33 pm

In GZDoom the entire scene and the following post processing is done at the video scale chosen. For example, if it is 0.25 and you're running at 1920x1080, then all scene rendering and post processing will be done at 480x270. After that it is upscaled in the present shader (when letterboxing, gamma and dithering is also applied) and drawn to the screen.

The upscaling part has a setting that can be accessed via Options->Full options menu->Set Video Mode->Use Linear Scaling (or using vid_scale_linear in the console). If it is set to true it will become blurry, if it is false it is pixelated. You cannot control this setting from your mod.
dpJudas
 
 
 
Joined: 28 May 2016

Re: [postprocess shaders] Disable texture() interpolation?

Postby William Claydock » Tue Oct 12, 2021 2:48 pm

vid_scale_linear is false. The graphics look normal/crispy as expected, but when I enable that shader I mentioned that zooms the screen, the screen becomes blurry (except for the HUD, just the viewport.) Sorry if I didn't explain correctly. It seems to be something relatedto how texture() (or texture2D) is handled in Postprocess shaders.
William Claydock
 

Re: [postprocess shaders] Disable texture() interpolation?

Postby dpJudas » Tue Oct 12, 2021 3:38 pm

If it really is the shader, then you could use texelFetch together with texSize to definitely force a pixelated look.
dpJudas
 
 
 
Joined: 28 May 2016

Re: [postprocess shaders] Disable texture() interpolation?

Postby William Claydock » Tue Oct 12, 2021 4:03 pm

I figured it out.

coord = vec2(floor(coord.x * texSize.x) + 0.5, floor(coord.y * texSize.y) + 0.5) / texSize;

Adding 0.5 to the coordinates after the calculation seemed to fix it, so this is technically solved now. I'll try to see if i can use texelfetch instead (if that's a more stable solution, or something). I think texture() should return the texture interpolated according to the player's settings however.

void main() {
ivec2 texSize = textureSize(InputTexture, 0);
vec2 coord = TexCoord;
coord -= 0.5;
coord *= 1.5;
coord += 0.5;
coord = vec2(floor(coord.x * texSize.x) + 0.5, floor(coord.y * texSize.y) + 0.5) / texSize;
FragColor = texture(InputTexture, coord);
}

Thank you for the help.
William Claydock
 

Re: [postprocess shaders] Disable texture() interpolation?

Postby dpJudas » Tue Oct 12, 2021 6:19 pm

You're welcome.

Positioning the coordinate to be exactly at the center of a texel (like you're doing) will in most cases create effectively the same result as calling texelFetch. It might even be faster on some GPUs (though I'd generally assume the speed is about the same). The main difference is that when you use texelFetch() the value be exactly what is stored in the texture, while texture() could still have some floating point rounding precision loss. This won't matter for what you're doing though.
dpJudas
 
 
 
Joined: 28 May 2016


Return to Scripting

Who is online

Users browsing this forum: No registered users and 0 guests