-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Operating System
Linux
OpenRCT2 build
OpenRCT2, v0.4.14
Base game
RollerCoaster Tycoon 2
Area(s) with this issue?
No response
Describe the issue
The masked sprites are used to smooth the look of the transition between slopes in the following screenshot. The top window is software and the bottom window is OpenGL. Note the way software correctly has big solid pixels. OpenGL appears to have different colours within the same pixel, which should not be possible.
The cause is that OpenGL interpolates across the full size of the mask and colour sprites. Rather, it should just interpolate the same area across both (the minimum area of the two).
Offending code:
OpenRCT2/data/shaders/drawrect.vert
Lines 38 to 39 in d6a7697
fTexColour = vec3(mix(vTexColourBounds.xy, vTexColourBounds.zw, m), vTexColourAtlas); | |
fTexMask = vec3(mix(vTexMaskBounds.xy, vTexMaskBounds.zw, m), vTexMaskAtlas); |
OpenRCT2/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp
Lines 842 to 903 in d6a7697
void OpenGLDrawingContext::DrawSpriteRawMasked( | |
DrawPixelInfo& dpi, int32_t x, int32_t y, const ImageId maskImage, const ImageId colourImage) | |
{ | |
CalculcateClipping(dpi); | |
auto g1ElementMask = GfxGetG1Element(maskImage); | |
auto g1ElementColour = GfxGetG1Element(colourImage); | |
if (g1ElementMask == nullptr || g1ElementColour == nullptr) | |
{ | |
return; | |
} | |
const auto textureMask = _textureCache->GetOrLoadImageTexture(maskImage); | |
const auto textureColour = _textureCache->GetOrLoadImageTexture(colourImage); | |
int32_t drawOffsetX = g1ElementMask->x_offset; | |
int32_t drawOffsetY = g1ElementMask->y_offset; | |
int32_t drawWidth = std::min(g1ElementMask->width, g1ElementColour->width); | |
int32_t drawHeight = std::min(g1ElementMask->height, g1ElementColour->height); | |
int32_t left = x + drawOffsetX; | |
int32_t top = y + drawOffsetY; | |
int32_t right = left + drawWidth; | |
int32_t bottom = top + drawHeight; | |
if (left > right) | |
{ | |
std::swap(left, right); | |
} | |
if (top > bottom) | |
{ | |
std::swap(top, bottom); | |
} | |
left -= dpi.x; | |
top -= dpi.y; | |
right -= dpi.x; | |
bottom -= dpi.y; | |
left = dpi.zoom_level.ApplyInversedTo(left); | |
top = dpi.zoom_level.ApplyInversedTo(top); | |
right = dpi.zoom_level.ApplyInversedTo(right); | |
bottom = dpi.zoom_level.ApplyInversedTo(bottom); | |
left += _spriteOffset.x; | |
top += _spriteOffset.y; | |
right += _spriteOffset.x; | |
bottom += _spriteOffset.y; | |
DrawRectCommand& command = _commandBuffers.rects.allocate(); | |
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom }; | |
command.texColourAtlas = textureColour.index; | |
command.texColourBounds = textureColour.normalizedBounds; | |
command.texMaskAtlas = textureMask.index; | |
command.texMaskBounds = textureMask.normalizedBounds; | |
command.palettes = { 0, 0, 0 }; | |
command.flags = DrawRectCommand::FLAG_MASK; | |
command.colour = 0; | |
command.bounds = { left, top, right, bottom }; | |
command.depth = _drawCount++; | |
} |
Steps to reproduce
Look at a masked sprite. They appear on zoom levels 0 or lower for some terrain slope changes and surface changes.
Attachments
No response