Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering artifacts at different viewport sizes #282

Closed
zear opened this issue Jan 21, 2023 · 3 comments
Closed

Rendering artifacts at different viewport sizes #282

zear opened this issue Jan 21, 2023 · 3 comments

Comments

@zear
Copy link
Collaborator

zear commented Jan 21, 2023

Deathrace exhibits multiple issues related to rendering the 3d part of the screen in non-full resolution (i.e. manipulating the viewport size with -/+ keys):

1. Depth buffer

When the gRender_screen is scaled such that it doesn't match dimensions of gBack_screen, the depth buffer's position and size differs from the color buffer, causing visible artifacts on the screen:

sshot3

2. Blending

The viewport height passed to the shader should be the one of the renderer, not the color buffer. Otherwise, geometry behind transparent materials is sampled at the wrong y offset:

sshot1

3. Blending in map mode

When map mode is enabled, the scene is rendered thrice to a single frame. This breaks blending in GL renderer, which depends on a clear depth buffer. The result is fully opaque transparencies:

sshot2

4. External sky

Depending on the screen size, something seems to obstruct different parts of the external sky:

external_sky.mp4

Currently, I can't tell whether this is geometry, or the sky bitmap not rendering properly.

zear added a commit to zear/dethrace that referenced this issue Jan 21, 2023
When the `gRender_screen` is scaled such that it doesn't match
dimensions of `gBack_screen`, the depth buffer's position and size
differs from the color buffer, causing visible artifacts on the screen.

Update the depth buffer along the color buffer, so that they always
match, preventing any misalignment.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
zear added a commit to zear/dethrace that referenced this issue Jan 21, 2023
The viewport height passed to the shader should be the one of the
renderer, not the color buffer. Otherwise, geometry behind transparent
materials is sampled at the wrong y offset.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
zear added a commit to zear/dethrace that referenced this issue Jan 21, 2023
When map mode is enabled, the scene is rendered thrice to a single
frame. This breaks blending in GL renderer, which depends on a clear
depth buffer.

Don't wait for game loop to swap the frame buffers and manually clear
the depth buffer as soon as the scene is done rendering.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
@zear zear mentioned this issue Jan 21, 2023
@zear
Copy link
Collaborator Author

zear commented Jan 21, 2023

Parts 1-3 are now fixed in #283.

@zear
Copy link
Collaborator Author

zear commented Jan 22, 2023

Regarding part 4, it is the chunk of ExternalSky code responsible for filling in the background with uniform color around the sky pixelmap that is at fault. After a change to draw in white, everything becomes clear:

external_sky_bot_col.mp4

Now, the reason this happens is because the below code doesn't take pRender_buffer->base_x/pRender_buffer->base_y into account while calculating DRPixelmapRectangleFill offsets:

if (top_y > 0) {
top_col = ((tU8*)col_map->pixels)[0];
DRPixelmapRectangleFill(pRender_buffer, -pRender_buffer->origin_x, -pRender_buffer->origin_y, pRender_buffer->width, top_y, top_col);
}
bot_height = pRender_buffer->height - pRender_buffer->origin_y - hori_y - col_map->height;
if (bot_height > 0) {
bot_col = ((tU8*)col_map->pixels)[col_map->row_bytes * (col_map->height - 1)];
DRPixelmapRectangleFill(pRender_buffer, -pRender_buffer->origin_x, hori_y + col_map->height, pRender_buffer->width, bot_height, bot_col);
}

This can be easily fixed by respecting said offsets:

    /* Viewport offsets - added by Dethrace. */
    int off_x = 0;
    int off_y = 0;

(...)

#if defined(DETHRACE_FIX_BUGS)
    /* Take viewport offsets into account. */
    off_x = pRender_buffer->base_x;
    off_y = pRender_buffer->base_y;
#endif

    if (top_y > 0) { 
        top_col = ((tU8*)col_map->pixels)[0]; 
        DRPixelmapRectangleFill(pRender_buffer, off_x + -pRender_buffer->origin_x, off_y + -pRender_buffer->origin_y, pRender_buffer->width, top_y, top_col); 
    } 
    bot_height = pRender_buffer->height - pRender_buffer->origin_y - hori_y - col_map->height; 
    if (bot_height > 0) { 
        bot_col = ((tU8*)col_map->pixels)[col_map->row_bytes * (col_map->height - 1)]; 
        DRPixelmapRectangleFill(pRender_buffer, off_x + -pRender_buffer->origin_x, off_y + hori_y + col_map->height, pRender_buffer->width, bot_height, bot_col); 
    } 

However, the OG does not do that. I wonder why it works for them - they still keep track of base_x/base_y and update those fields in AdjustRenderScreenSize, so those values are most definitely not 0 at the time ExternalSky is called. And yet, the sky is rendered just fine.

@dethrace-labs @madebr
Should we debug this deeper, or is the above solution satisfactory for now?

@dethrace-labs
Copy link
Owner

Fixed with software renderer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants