1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-23 06:44:38 +01:00

Fixed OpenGL palette drawing

Added palettes to the texture atlas and now correctly use them to generate
images. Transparency semi supported but the colours are not quite
correct.
This commit is contained in:
duncanspumpkin
2016-09-18 15:40:27 +01:00
parent 8ffe9cdcf6
commit 5f7a6fb369
11 changed files with 140 additions and 6 deletions

View File

@@ -10,6 +10,8 @@ flat in int fTexColourAtlas;
in vec2 fTexColourCoords;
flat in int fTexMaskAtlas;
in vec2 fTexMaskCoords;
flat in int fTexPaletteAtlas;
flat in vec4 fTexPaletteBounds;
flat in int fMask;
in vec2 fPosition;
@@ -25,7 +27,38 @@ void main()
discard;
}
vec4 texel = uPalette[texture(uTexture, vec3(fTexColourCoords, float(fTexColourAtlas))).r];
vec4 texel;
// If remap palette used
if ((fFlags & (1 << 1)) != 0)
{
// z is the size of each x pixel in the atlas
float x = fTexPaletteBounds.x + texture(uTexture, vec3(fTexColourCoords, float(fTexColourAtlas))).r * fTexPaletteBounds.z;
texel = uPalette[texture(uTexture, vec3(x, fTexPaletteBounds.y, float(fTexPaletteAtlas))).r];
} // If transparent or special transparent
else if ((fFlags & ((1 << 2) | (1 << 3))) != 0)
{
float line = texture(uTexture,vec3(fTexColourCoords, float(fTexColourAtlas))).r;
if (line == 0.0)
{
discard;
}
float alpha = 0.5;
if ((fFlags & (1 << 2)) != 0)
{
alpha = 0.5 + (line - 1.0) / 10.0;
}
// z is the size of each x pixel in the atlas
float x = fTexPaletteBounds.x + fTexPaletteBounds.z * 50.0;
oColour = vec4(uPalette[texture(uTexture, vec3(x, fTexPaletteBounds.y, float(fTexPaletteAtlas))).r].rgb, alpha);
return;
}
else
{
texel = uPalette[texture(uTexture, vec3(fTexColourCoords, float(fTexColourAtlas))).r];
}
vec4 mask = uPalette[texture(uTexture, vec3(fTexMaskCoords, float(fTexMaskAtlas))).r];
if (fMask != 0)

View File

@@ -7,6 +7,8 @@ in int ivTexColourAtlas;
in vec4 ivTexColourBounds;
in int ivTexMaskAtlas;
in vec4 ivTexMaskBounds;
in int ivTexPaletteAtlas;
in vec4 ivTexPaletteBounds;
in int ivFlags;
in vec4 ivColour;
in ivec4 ivBounds;
@@ -23,6 +25,8 @@ flat out int fTexColourAtlas;
out vec2 fTexColourCoords;
flat out int fTexMaskAtlas;
out vec2 fTexMaskCoords;
flat out int fTexPaletteAtlas;
flat out vec4 fTexPaletteBounds;
flat out int fMask;
void main()
@@ -64,6 +68,8 @@ void main()
fMask = ivMask;
fTexColourAtlas = ivTexColourAtlas;
fTexMaskAtlas = ivTexMaskAtlas;
fTexPaletteAtlas = ivTexPaletteAtlas;
fTexPaletteBounds = ivTexPaletteBounds;
gl_Position = vec4(pos, 0.0, 1.0);
}

View File

@@ -195,6 +195,7 @@ void FASTCALL gfx_draw_sprite_raw_masked(rct_drawpixelinfo *dpi, int x, int y, i
void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo * dpi, int image, int x, int y, uint8 colour);
void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour);
uint8* FASTCALL gfx_draw_sprite_get_palette(int image_id, uint32 tertiary_colour);
void FASTCALL gfx_draw_sprite_palette_set_software(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer);
void FASTCALL gfx_draw_sprite_raw_masked_software(rct_drawpixelinfo *dpi, int x, int y, int maskImage, int colourImage);

View File

@@ -40,6 +40,7 @@ struct DrawImageCommand {
sint32 clip[4];
CachedTextureInfo texMask;
CachedTextureInfo texColour;
CachedTextureInfo texPalette;
sint32 bounds[4];
bool mask;
};

View File

@@ -40,6 +40,8 @@ DrawImageShader::DrawImageShader() : OpenGLShaderProgram("drawimage")
glVertexAttribPointer(vTexColourBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texColourBounds));
glVertexAttribIPointer(vTexMaskAtlas, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texMaskAtlas));
glVertexAttribPointer(vTexMaskBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texMaskBounds));
glVertexAttribIPointer(vTexPaletteAtlas, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texPaletteAtlas));
glVertexAttribPointer(vTexPaletteBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, texPaletteBounds));
glVertexAttribIPointer(vFlags, 1, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, flags));
glVertexAttribPointer(vColour, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, colour));
glVertexAttribIPointer(vBounds, 4, GL_INT, sizeof(DrawImageInstance), (void*) offsetof(DrawImageInstance, bounds));
@@ -51,6 +53,8 @@ DrawImageShader::DrawImageShader() : OpenGLShaderProgram("drawimage")
glEnableVertexAttribArray(vTexColourBounds);
glEnableVertexAttribArray(vTexMaskAtlas);
glEnableVertexAttribArray(vTexMaskBounds);
glEnableVertexAttribArray(vTexPaletteAtlas);
glEnableVertexAttribArray(vTexPaletteBounds);
glEnableVertexAttribArray(vFlags);
glEnableVertexAttribArray(vColour);
glEnableVertexAttribArray(vBounds);
@@ -61,6 +65,8 @@ DrawImageShader::DrawImageShader() : OpenGLShaderProgram("drawimage")
glVertexAttribDivisor(vTexColourBounds, 1);
glVertexAttribDivisor(vTexMaskAtlas, 1);
glVertexAttribDivisor(vTexMaskBounds, 1);
glVertexAttribDivisor(vTexPaletteAtlas, 1);
glVertexAttribDivisor(vTexPaletteBounds, 1);
glVertexAttribDivisor(vFlags, 1);
glVertexAttribDivisor(vColour, 1);
glVertexAttribDivisor(vBounds, 1);
@@ -91,6 +97,8 @@ void DrawImageShader::GetLocations()
vTexColourBounds = GetAttributeLocation("ivTexColourBounds");
vTexMaskAtlas = GetAttributeLocation("ivTexMaskAtlas");
vTexMaskBounds = GetAttributeLocation("ivTexMaskBounds");
vTexPaletteAtlas = GetAttributeLocation("ivTexPaletteAtlas");
vTexPaletteBounds = GetAttributeLocation("ivTexPaletteBounds");
vFlags = GetAttributeLocation("ivFlags");
vColour = GetAttributeLocation("ivColour");
vBounds = GetAttributeLocation("ivBounds");

View File

@@ -28,6 +28,8 @@ struct DrawImageInstance {
vec4f texColourBounds;
int texMaskAtlas;
vec4f texMaskBounds;
int texPaletteAtlas;
vec4f texPaletteBounds;
int flags;
vec4f colour;
vec4i bounds;
@@ -47,6 +49,8 @@ private:
GLuint vTexColourBounds;
GLuint vTexMaskAtlas;
GLuint vTexMaskBounds;
GLuint vTexPaletteAtlas;
GLuint vTexPaletteBounds;
GLuint vFlags;
GLuint vColour;
GLuint vBounds;

View File

@@ -720,6 +720,28 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
auto texture = _textureCache->GetOrLoadImageTexture(image);
command.texColour = texture;
bool special = false;
if (!(image & IMAGE_TYPE_REMAP_2_PLUS) && (image & IMAGE_TYPE_REMAP)) {
if (((image >> 19) & 0x7F) == 32) {
special = true;
}
}
if (!((image & IMAGE_TYPE_REMAP_2_PLUS) && !(image & IMAGE_TYPE_REMAP))) {
tertiaryColour = 0;
}
texture = _textureCache->GetOrLoadPaletteTexture(image, tertiaryColour, special);
command.texPalette = texture;
if (image & IMAGE_TYPE_TRANSPARENT) {
command.flags |= (1 << 3);
}
else if (image & (IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_REMAP)){
command.flags |= (1 << 1);
}
command.flags |= special << 2;
command.bounds[0] = left;
command.bounds[1] = top;
command.bounds[2] = right;
@@ -955,6 +977,15 @@ void OpenGLDrawingContext::FlushImages()
instance.colour = command.colour;
instance.bounds = {command.bounds[0], command.bounds[1], command.bounds[2], command.bounds[3]};
instance.mask = command.mask;
instance.texPaletteAtlas = command.texPalette.index;
if (instance.flags != 0) {
instance.texPaletteBounds = {
command.texPalette.normalizedBounds.x,
command.texPalette.normalizedBounds.y,
(command.texPalette.normalizedBounds.z - command.texPalette.normalizedBounds.x) / (float)(command.texPalette.bounds.z - command.texPalette.bounds.x),
(command.texPalette.normalizedBounds.w - command.texPalette.normalizedBounds.y) / (float)(command.texPalette.bounds.w - command.texPalette.bounds.y)
};
}
instances.push_back(instance);
}

View File

@@ -52,14 +52,48 @@ void TextureCache::InvalidateImage(uint32 image)
CachedTextureInfo TextureCache::GetOrLoadImageTexture(uint32 image)
{
auto kvp = _imageTextureMap.find(image & 0x7FFFF);
image &= 0x7FFFF;
auto kvp = _imageTextureMap.find(image);
if (kvp != _imageTextureMap.end())
{
return kvp->second;
}
auto cacheInfo = LoadImageTexture(image);
_imageTextureMap[image & 0x7FFFF] = cacheInfo;
_imageTextureMap[image] = cacheInfo;
return cacheInfo;
}
CachedTextureInfo TextureCache::GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special)
{
if ((image & (IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_TRANSPARENT)) == 0)
return CachedTextureInfo{ 0 };
uint32 uniquePaletteId = 0;
if (!(image & IMAGE_TYPE_REMAP_2_PLUS)) {
uniquePaletteId = (image >> 19) & 0xFF;
if (!(image & IMAGE_TYPE_TRANSPARENT)) {
uniquePaletteId &= 0x7F;
}
}
else {
uniquePaletteId |= ((image >> 19) & 0x1F);
uniquePaletteId |= ((image >> 24) & 0x1F) << 8;
if (!(image & IMAGE_TYPE_REMAP)) {
uniquePaletteId |= tertiaryColour << 16;
}
}
auto kvp = _paletteTextureMap.find(uniquePaletteId);
if (kvp != _paletteTextureMap.end())
{
return kvp->second;
}
auto cacheInfo = LoadPaletteTexture(image, tertiaryColour, special);
_paletteTextureMap[uniquePaletteId] = cacheInfo;
return cacheInfo;
}
@@ -141,6 +175,20 @@ CachedTextureInfo TextureCache::LoadImageTexture(uint32 image)
return cacheInfo;
}
CachedTextureInfo TextureCache::LoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special)
{
rct_drawpixelinfo dpi;
dpi.bits = gfx_draw_sprite_get_palette(image, tertiaryColour);
dpi.width = 256;
dpi.height = special ? 5 : 1;
auto cacheInfo = AllocateImage(dpi.width, dpi.height);
glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, cacheInfo.bounds.x, cacheInfo.bounds.y, cacheInfo.index, dpi.width, dpi.height, 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, dpi.bits);
return cacheInfo;
}
CachedTextureInfo TextureCache::LoadGlyphTexture(uint32 image, uint8 * palette)
{
rct_drawpixelinfo * dpi = GetGlyphAsDPI(image, palette);

View File

@@ -196,6 +196,7 @@ private:
std::unordered_map<uint32, CachedTextureInfo> _imageTextureMap;
std::unordered_map<GlyphId, CachedTextureInfo, GlyphId::Hash, GlyphId::Equal> _glyphTextureMap;
std::unordered_map<uint32, CachedTextureInfo> _paletteTextureMap;
SDL_Color _palette[256];
@@ -206,7 +207,8 @@ public:
void InvalidateImage(uint32 image);
CachedTextureInfo GetOrLoadImageTexture(uint32 image);
CachedTextureInfo GetOrLoadGlyphTexture(uint32 image, uint8 * palette);
CachedTextureInfo GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special);
GLuint GetAtlasesTexture();
private:
@@ -214,6 +216,7 @@ private:
void EnlargeAtlasesTexture(GLuint newEntries);
CachedTextureInfo LoadImageTexture(uint32 image);
CachedTextureInfo LoadGlyphTexture(uint32 image, uint8 * palette);
CachedTextureInfo LoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special);
CachedTextureInfo AllocateImage(int imageWidth, int imageHeight);
void * GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight);
rct_drawpixelinfo * GetImageAsDPI(uint32 image, uint32 tertiaryColour);

View File

@@ -292,7 +292,7 @@ static void FASTCALL gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unk
return;
}
static uint8* FASTCALL gfx_draw_sprite_get_palette(int image_id, uint32 tertiary_colour) {
uint8* FASTCALL gfx_draw_sprite_get_palette(int image_id, uint32 tertiary_colour) {
int image_type = (image_id & 0xE0000000);
if (image_type == 0)
return NULL;

View File

@@ -176,7 +176,6 @@ static paint_struct * sub_9819_c(uint32 image_id, rct_xyz16 offset, rct_xyz16 bo
ps->map_x = gPaintMapPosition.x;
ps->map_y = gPaintMapPosition.y;
ps->mapElement = g_currently_drawn_item;
return ps;
}