pixel offset after rendering to fbo?

Started by
6 comments, last by RichPressence 7 years, 1 month ago

Hey, when I render the screen to an offscreen buffer for downsampling or storage for later it gets offset.

I noticed it when I was writing a wide radius bloom shader as the offset increased after every downsample and blur making it more and more noticeable.

im using opengl and have GL_LINEAR enabled for the offscreen buffer and the viewport size is 1024x1024 with the offscreen buffer matching that.

Shouldnt the offscreen buffer match the main exactly pixel for pixel if its not being resized or is this a side effect of using gl_linear?.

Heres the frag but it just passes through the color which gets sent to the next pass as an input.


uniform sampler2D ColorTexture;
uniform vec2 buffer_res;

vec2 texel = 1.0 / buffer_res;
vec2 texCoord = gl_TexCoord[0].xy;

void main() {
    // with this the offset pushes out from the center rather than off to the top right corner
    // but is still getting offset
    texCoord += vec2(0.5, 0.5) * texel;

    gl_FragColor.rgb = textureLod(bgl_RenderedTexture, texCoord, 0).rgb;
}

The images are crops from 1024x1024

Advertisement

AFAIK, you're fighting a losing battle trying to get pixel perfect results with GL_LINEAR in OpenGL.

DirectX9 guaranteed you could do it by rendering at the right size with a half-pixel offset, but I think with OpenGL you just have to avoid bi-linear filtering.

Note, I'm not 100% confident in that assertion, so very happy to be corrected.

Try this.

vec2 res = textureSize(bgl_RenderedTexture, 0);
texCoord = texCoord * (res / (res + 1.0)) + (0.5 / res);
Untested!

How do you set up your vertex coordinates, your texture coordinates, your modelviewprojection matrix? In any case, interpolation free rendering using GL_LINEAR is definitely possible.

Shouldnt the offscreen buffer match the main exactly pixel for pixel if its not being resized
Yep, assuming your geometry is correct. What do your vertices look like?

Note, I'm not 100% confident in that assertion, so very happy to be corrected.
OpenGL and D3D10+ should have no problem with this.
D3D9 uses a stupid coordinate system that requires a half-pixel offset to do this correctly.

If your goal is just to make a copy, why not use GL_NEAREST?


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

If your goal is just to make a copy, why not use GL_NEAREST?


L. Spiro

While GL_NEAREST might theoretically be faster, there's nothing wrong with trying to get it right with GL_LINEAR first. GL_NEAREST might hide a scaling mistake which could also show up with GL_NEAREST for some target sizes. With GL_LINEAR it will show up as slight blurriness for all target sizes.

Thanks for the replys guys. Seems I was doing a number of things poorly, one being how I was dividing my fbos down from my target res, im dividing and rounding now instead of div and flooring, they stay pretty square now at lower mips.

The other problem was with the fbo getting offset by 1 pixel towards the top right corner even if the res matched the main buffer.

Using this for the coords in my fbo frags when upsampling/downsampling stopped them getting offset.


uniform ivec2 buffer_res;
ivec2 intCoord = ivec2(gl_FragCoord.xy);
vec2 texCoord = vec2(intCoord + 0.5) / buffer_res;

Wouldn't surprise me its not completely bang on still need todo more checking I think.

If your goal is just to make a copy, why not use GL_NEAREST?


L. Spiro

Well I was doing this for a bloom shader and im heart set on making use of the linearly sampled gaussian blur trick to get some free taps which requires the use of gl_linear. But yeah for a straight full res copy I think gl_nearest would be best.

@Hodgman Yeah I originally thought the half pixel offset thing was the battle I was fighting till I found its a d3d9 thing.

before and now

This topic is closed to new replies.

Advertisement