OpenGL: Improve Shaders

This commit is contained in:
LRFLEW 2017-10-19 15:46:49 -05:00 committed by Michał Janiszewski
parent f105237a2e
commit 6bf2e0157b
25 changed files with 515 additions and 963 deletions

View File

@ -470,9 +470,8 @@
F76C887D1EC5324E00FA49E2 /* CursorData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C858A1EC4E82600FA49E2 /* CursorData.cpp */; };
F76C887E1EC5324E00FA49E2 /* CursorRepository.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C858B1EC4E82600FA49E2 /* CursorRepository.cpp */; };
F76C887F1EC5324E00FA49E2 /* CopyFramebufferShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C85911EC4E82600FA49E2 /* CopyFramebufferShader.cpp */; };
F76C88801EC5324E00FA49E2 /* DrawImageShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C85941EC4E82600FA49E2 /* DrawImageShader.cpp */; };
F76C88801EC5324E00FA49E2 /* DrawRectShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C85941EC4E82600FA49E2 /* DrawRectShader.cpp */; };
F76C88811EC5324E00FA49E2 /* DrawLineShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C85961EC4E82600FA49E2 /* DrawLineShader.cpp */; };
F76C88821EC5324E00FA49E2 /* FillRectShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C85981EC4E82600FA49E2 /* FillRectShader.cpp */; };
F76C88831EC5324E00FA49E2 /* OpenGLAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C859B1EC4E82600FA49E2 /* OpenGLAPI.cpp */; };
F76C88841EC5324E00FA49E2 /* OpenGLDrawingEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C859D1EC4E82600FA49E2 /* OpenGLDrawingEngine.cpp */; };
F76C88851EC5324E00FA49E2 /* OpenGLFramebuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C859E1EC4E82600FA49E2 /* OpenGLFramebuffer.cpp */; };
@ -1392,12 +1391,10 @@
F76C85911EC4E82600FA49E2 /* CopyFramebufferShader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CopyFramebufferShader.cpp; sourceTree = "<group>"; };
F76C85921EC4E82600FA49E2 /* CopyFramebufferShader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CopyFramebufferShader.h; sourceTree = "<group>"; };
F76C85931EC4E82600FA49E2 /* DrawCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DrawCommands.h; sourceTree = "<group>"; };
F76C85941EC4E82600FA49E2 /* DrawImageShader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DrawImageShader.cpp; sourceTree = "<group>"; };
F76C85951EC4E82600FA49E2 /* DrawImageShader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DrawImageShader.h; sourceTree = "<group>"; };
F76C85941EC4E82600FA49E2 /* DrawRectShader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DrawRectShader.cpp; sourceTree = "<group>"; };
F76C85951EC4E82600FA49E2 /* DrawRectShader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DrawRectShader.h; sourceTree = "<group>"; };
F76C85961EC4E82600FA49E2 /* DrawLineShader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DrawLineShader.cpp; sourceTree = "<group>"; };
F76C85971EC4E82600FA49E2 /* DrawLineShader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DrawLineShader.h; sourceTree = "<group>"; };
F76C85981EC4E82600FA49E2 /* FillRectShader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FillRectShader.cpp; sourceTree = "<group>"; };
F76C85991EC4E82600FA49E2 /* FillRectShader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FillRectShader.h; sourceTree = "<group>"; };
F76C859A1EC4E82600FA49E2 /* GLSLTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLSLTypes.h; sourceTree = "<group>"; };
F76C859B1EC4E82600FA49E2 /* OpenGLAPI.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OpenGLAPI.cpp; sourceTree = "<group>"; };
F76C859C1EC4E82600FA49E2 /* OpenGLAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenGLAPI.h; sourceTree = "<group>"; };
@ -2669,12 +2666,10 @@
F76C85911EC4E82600FA49E2 /* CopyFramebufferShader.cpp */,
F76C85921EC4E82600FA49E2 /* CopyFramebufferShader.h */,
F76C85931EC4E82600FA49E2 /* DrawCommands.h */,
F76C85941EC4E82600FA49E2 /* DrawImageShader.cpp */,
F76C85951EC4E82600FA49E2 /* DrawImageShader.h */,
F76C85961EC4E82600FA49E2 /* DrawLineShader.cpp */,
F76C85971EC4E82600FA49E2 /* DrawLineShader.h */,
F76C85981EC4E82600FA49E2 /* FillRectShader.cpp */,
F76C85991EC4E82600FA49E2 /* FillRectShader.h */,
F76C85941EC4E82600FA49E2 /* DrawRectShader.cpp */,
F76C85951EC4E82600FA49E2 /* DrawRectShader.h */,
F76C859A1EC4E82600FA49E2 /* GLSLTypes.h */,
F76C859B1EC4E82600FA49E2 /* OpenGLAPI.cpp */,
F76C859C1EC4E82600FA49E2 /* OpenGLAPI.h */,
@ -3232,7 +3227,7 @@
4C93F18F1F8B747A00A9330D /* PirateShip.cpp in Sources */,
C654DF381F69C0430040F43D /* StaffFirePrompt.cpp in Sources */,
C651A8D91F30204300443BCA /* Text.cpp in Sources */,
F76C88801EC5324E00FA49E2 /* DrawImageShader.cpp in Sources */,
F76C88801EC5324E00FA49E2 /* DrawRectShader.cpp in Sources */,
C685E51D1F8907850090598F /* Research.cpp in Sources */,
C64644FB1F3FA4120026AC2D /* EditorScenarioOptions.cpp in Sources */,
F775F5371EE3724F001F00E7 /* DummyAudioContext.cpp in Sources */,
@ -3263,7 +3258,6 @@
4CFE4E801F90A3F1005243C2 /* Peep.cpp in Sources */,
C654DF3A1F69C0430040F43D /* TitleEditor.cpp in Sources */,
C666EE6F1F37ACB10061AA04 /* DebugPaint.cpp in Sources */,
F76C88821EC5324E00FA49E2 /* FillRectShader.cpp in Sources */,
F76C88831EC5324E00FA49E2 /* OpenGLAPI.cpp in Sources */,
4C93F1521F8B744400A9330D /* Steeplechase.cpp in Sources */,
4C93F1BD1F8E185600A9330D /* NewsItem.cpp in Sources */,

View File

@ -3,7 +3,6 @@
uniform vec4 uPalette[256];
uniform usampler2D uTexture;
in vec2 fPosition;
in vec2 fTextureCoordinate;
out vec4 oColour;

View File

@ -1,42 +1,12 @@
#version 150
uniform ivec2 uScreenSize;
uniform ivec4 uBounds;
uniform ivec4 uTextureCoordinates;
in vec4 vPosition;
in vec2 vTextureCoordinate;
in uint vIndex;
out vec2 fPosition;
out vec2 fTextureCoordinate;
void main()
{
vec2 pos;
switch (vIndex) {
case 0u:
pos = uBounds.xy;
fTextureCoordinate = uTextureCoordinates.xy;
break;
case 1u:
pos = uBounds.zy;
fTextureCoordinate = uTextureCoordinates.zy;
break;
case 2u:
pos = uBounds.xw;
fTextureCoordinate = uTextureCoordinates.xw;
break;
case 3u:
pos = uBounds.zw;
fTextureCoordinate = uTextureCoordinates.zw;
break;
}
fPosition = pos;
// Transform screen coordinates to viewport
pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0;
pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0;
pos.y *= -1;
gl_Position = vec4(pos, 0.0, 1.0);
fTextureCoordinate = vTextureCoordinate;
gl_Position = vPosition;
}

View File

@ -1,95 +0,0 @@
#version 150
const int FLAG_COLOUR = (1 << 0);
const int FLAG_REMAP = (1 << 1);
const int FLAG_TRANSPARENT = (1 << 2);
const int FLAG_TRANSPARENT_SPECIAL = (1 << 3);
uniform usampler2DArray uTexture;
flat in ivec4 fClip;
flat in int fFlags;
flat in uint fColour;
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;
out uint oColour;
void main()
{
if (fPosition.x < fClip.x || fPosition.x > fClip.z ||
fPosition.y < fClip.y || fPosition.y > fClip.w)
{
discard;
}
uint texel;
// If remap palette used
if ((fFlags & FLAG_REMAP) != 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 = texture(uTexture, vec3(x, fTexPaletteBounds.y, float(fTexPaletteAtlas))).r;
} // If transparent or special transparent
else if ((fFlags & (FLAG_TRANSPARENT | FLAG_TRANSPARENT_SPECIAL)) != 0)
{
uint line = texture(uTexture, vec3(fTexColourCoords, float(fTexColourAtlas))).r;
if (line == 0u)
{
discard;
}
/*
float alpha = 0.5;
if ((fFlags & FLAG_TRANSPARENT_SPECIAL) != 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);
oColour = texture(uTexture, vec3(x, fTexPaletteBounds.y, float(fTexPaletteAtlas))).r;
return;
}
else
{
texel = texture(uTexture, vec3(fTexColourCoords, float(fTexColourAtlas))).r;
}
if (fMask != 0)
{
uint mask = texture(uTexture, vec3(fTexMaskCoords, float(fTexMaskAtlas))).r;
if ( mask == 0u )
{
discard;
}
oColour = texel;
}
else
{
if (texel == 0u)
{
discard;
}
if ((fFlags & FLAG_COLOUR) != 0)
{
//oColour = vec4(fColour.rgb, fColour.a * texel.a);
oColour = fColour;
}
else
{
oColour = texel;
}
}
}

View File

@ -1,74 +0,0 @@
#version 150
uniform ivec2 uScreenSize;
in ivec4 ivClip;
in int ivTexColourAtlas;
in vec4 ivTexColourBounds;
in int ivTexMaskAtlas;
in vec4 ivTexMaskBounds;
in int ivTexPaletteAtlas;
in vec4 ivTexPaletteBounds;
in int ivFlags;
in uint ivColour;
in ivec4 ivBounds;
in int ivMask;
in uint vIndex;
out vec2 fPosition;
flat out ivec4 fClip;
flat out int fFlags;
flat out uint fColour;
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()
{
vec2 pos;
switch (vIndex) {
case 0u:
pos = ivBounds.xy;
fTexColourCoords = ivTexColourBounds.xy;
fTexMaskCoords = ivTexMaskBounds.xy;
break;
case 1u:
pos = ivBounds.zy;
fTexColourCoords = ivTexColourBounds.zy;
fTexMaskCoords = ivTexMaskBounds.zy;
break;
case 2u:
pos = ivBounds.xw;
fTexColourCoords = ivTexColourBounds.xw;
fTexMaskCoords = ivTexMaskBounds.xw;
break;
case 3u:
pos = ivBounds.zw;
fTexColourCoords = ivTexColourBounds.zw;
fTexMaskCoords = ivTexMaskBounds.zw;
break;
}
fPosition = pos;
// Transform screen coordinates to viewport
pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0;
pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0;
pos.y *= -1;
fClip = ivClip;
fFlags = ivFlags;
fColour = ivColour;
fMask = ivMask;
fTexColourAtlas = ivTexColourAtlas;
fTexMaskAtlas = ivTexMaskAtlas;
fTexPaletteAtlas = ivTexPaletteAtlas;
fTexPaletteBounds = ivTexPaletteBounds;
gl_Position = vec4(pos, 0.0, 1.0);
}

View File

@ -1,6 +1,5 @@
#version 150
uniform ivec4 uClip;
uniform uint uColour;
in vec2 fPosition;
@ -9,11 +8,5 @@ out uint oColour;
void main()
{
if (fPosition.x < uClip.x || fPosition.x > uClip.z ||
fPosition.y < uClip.y || fPosition.y > uClip.w)
{
discard;
}
oColour = uColour;
}

View File

@ -2,23 +2,15 @@
uniform ivec2 uScreenSize;
uniform ivec4 uBounds;
uniform ivec4 uClip;
in uint vIndex;
in mat4x2 vVertMat;
out vec2 fPosition;
void main()
{
vec2 pos;
if (vIndex == 0u)
{
pos = uBounds.xy;
}
else
{
pos = uBounds.zw;
}
vec2 pos = clamp(vVertMat * uBounds, uClip.xy, uClip.zw);
fPosition = pos;
// Transform screen coordinates to viewport

View File

@ -0,0 +1,76 @@
#version 150
const int MASK_REMAP_COUNT = 3;
const int FLAG_NO_TEXTURE = (1 << 2);
const int FLAG_MASK = (1 << 3);
const int FLAG_CROSS_HATCH = (1 << 4);
uniform usampler2DArray uTexture;
uniform usampler2DRect uPaletteTex;
flat in int fFlags;
flat in uint fColour;
in vec3 fTexColour;
in vec3 fTexMask;
flat in vec3 fPalettes;
in vec2 fPosition;
out uint oColour;
void main()
{
uint texel;
if ((fFlags & FLAG_NO_TEXTURE) == 0)
{
texel = texture(uTexture, fTexColour).r;
if (texel == 0u)
{
discard;
}
texel += fColour;
}
else
{
texel = fColour;
}
int paletteCount = fFlags & MASK_REMAP_COUNT;
if (paletteCount >= 3 && texel >= 0x2Eu && texel < 0x3Au)
{
texel = texture(uPaletteTex, vec2(texel + 0xC5u, fPalettes.z)).r;
}
else if (paletteCount >= 2 && texel >= 0xCAu && texel < 0xD6u)
{
texel = texture(uPaletteTex, vec2(texel + 0x29u, fPalettes.y)).r;
}
else if (paletteCount >= 1)
{
texel = texture(uPaletteTex, vec2(texel, fPalettes.x)).r;
}
if (texel == 0u)
{
discard;
}
if ((fFlags & FLAG_CROSS_HATCH) != 0)
{
int posSum = int(fPosition.x) + int(fPosition.y);
if ((posSum % 2) == 0)
{
discard;
}
}
if ((fFlags & FLAG_MASK) != 0)
{
uint mask = texture(uTexture, fTexMask).r;
if ( mask == 0u )
{
discard;
}
}
oColour = texel;
}

View File

@ -0,0 +1,45 @@
#version 150
uniform ivec2 uScreenSize;
in ivec4 vClip;
in int vTexColourAtlas;
in vec4 vTexColourBounds;
in int vTexMaskAtlas;
in vec4 vTexMaskBounds;
in ivec3 vPalettes;
in int vFlags;
in uint vColour;
in ivec4 vBounds;
in mat4x2 vVertMat;
in vec2 vVertVec;
out vec2 fPosition;
flat out int fFlags;
flat out uint fColour;
out vec3 fTexColour;
out vec3 fTexMask;
flat out vec3 fPalettes;
void main()
{
// Clamp position by vClip, correcting interpolated values for the clipping
vec2 m = clamp(((vVertMat * vClip) - (vVertMat * vBounds))/(vBounds.zw - vBounds.xy) + vVertVec, 0.0, 1.0);
vec2 pos = mix(vBounds.xy, vBounds.zw, m);
fTexColour = vec3(mix(vTexColourBounds.xy, vTexColourBounds.zw, m), vTexColourAtlas);
fTexMask = vec3(mix(vTexMaskBounds.xy, vTexMaskBounds.zw, m), vTexMaskAtlas);
fPosition = pos;
// Transform screen coordinates to viewport
pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0;
pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0;
pos.y *= -1;
fFlags = vFlags;
fColour = vColour;
fPalettes = vec3(vPalettes);
gl_Position = vec4(pos, 0.0, 1.0);
}

View File

@ -1,33 +0,0 @@
#version 150
uniform ivec2 uScreenSize;
uniform ivec4 uClip;
uniform int uFlags;
uniform usampler2D uSourceFramebuffer;
uniform uint uPaletteRemap[256];
in vec2 fPosition;
out uint oColour;
void main()
{
if (fPosition.x < uClip.x || fPosition.x > uClip.z ||
fPosition.y < uClip.y || fPosition.y > uClip.w)
{
discard;
}
if ((uFlags & 1) != 0) // cross-hatch pattern
{
int posSum = int(fPosition.x) + int(fPosition.y);
if ((posSum % 2) == 0)
{
discard;
}
}
vec2 textureCoordinates = (fPosition / vec2(uScreenSize)) * vec2(1.0, -1.0) + vec2(0.0, 1.0);
uint sourceColour = texture(uSourceFramebuffer, textureCoordinates).r;
oColour = uPaletteRemap[sourceColour];
}

View File

@ -1,36 +0,0 @@
#version 150
uniform ivec2 uScreenSize;
uniform ivec4 uBounds;
in uint vIndex;
out vec2 fPosition;
void main()
{
vec2 pos;
switch (vIndex) {
case 0u:
pos = uBounds.xy;
break;
case 1u:
pos = uBounds.zy;
break;
case 2u:
pos = uBounds.xw;
break;
case 3u:
pos = uBounds.zw;
break;
}
fPosition = pos;
// Transform screen coordinates to viewport
pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0;
pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0;
pos.y *= -1;
gl_Position = vec4(pos, 0.0, 1.0);
}

View File

@ -18,6 +18,20 @@
#include "CopyFramebufferShader.h"
struct VDStruct
{
GLfloat position[2];
GLfloat texturecoordinate[2];
};
constexpr VDStruct VertexData[4] =
{
{ -1.0f, -1.0f, 0.0f, 0.0f },
{ 1.0f, -1.0f, 1.0f, 0.0f },
{ -1.0f, 1.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
};
CopyFramebufferShader::CopyFramebufferShader() : OpenGLShaderProgram("copyframebuffer")
{
GetLocations();
@ -25,16 +39,17 @@ CopyFramebufferShader::CopyFramebufferShader() : OpenGLShaderProgram("copyframeb
glGenBuffers(1, &_vbo);
glGenVertexArrays(1, &_vao);
GLuint vertices[] = { 0, 1, 2, 2, 1, 3 };
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData, GL_STATIC_DRAW);
glBindVertexArray(_vao);
glEnableVertexAttribArray(vIndex);
glVertexAttribIPointer(vIndex, 1, GL_INT, 0, nullptr);
glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, position));
glVertexAttribPointer(vTextureCoordinate, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, texturecoordinate));
glEnableVertexAttribArray(vPosition);
glEnableVertexAttribArray(vTextureCoordinate);
Use();
SetTextureCoordinates(0, 0, 1, 1);
glUniform1i(uTexture, 0);
}
@ -46,28 +61,11 @@ CopyFramebufferShader::~CopyFramebufferShader()
void CopyFramebufferShader::GetLocations()
{
uScreenSize = GetUniformLocation("uScreenSize");
uBounds = GetUniformLocation("uBounds");
uTextureCoordinates = GetUniformLocation("uTextureCoordinates");
uTexture = GetUniformLocation("uTexture");
uPalette = GetUniformLocation("uPalette");
vIndex = GetAttributeLocation("vIndex");
}
void CopyFramebufferShader::SetScreenSize(sint32 width, sint32 height)
{
glUniform2i(uScreenSize, width, height);
}
void CopyFramebufferShader::SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom)
{
glUniform4i(uBounds, left, top, right, bottom);
}
void CopyFramebufferShader::SetTextureCoordinates(sint32 left, sint32 top, sint32 right, sint32 bottom)
{
glUniform4i(uTextureCoordinates, left, top, right, bottom);
vPosition = GetAttributeLocation("vPosition");
vTextureCoordinate = GetAttributeLocation("vTextureCoordinate");
}
void CopyFramebufferShader::SetTexture(GLuint texture)
@ -82,7 +80,7 @@ void CopyFramebufferShader::SetPalette(const vec4f * glPalette) {
void CopyFramebufferShader::Draw()
{
glBindVertexArray(_vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
#endif /* DISABLE_OPENGL */

View File

@ -22,13 +22,11 @@
class CopyFramebufferShader final : public OpenGLShaderProgram
{
private:
GLuint uScreenSize;
GLuint uBounds;
GLuint uTextureCoordinates;
GLuint uTexture;
GLuint uPalette;
GLuint vIndex;
GLuint vPosition;
GLuint vTextureCoordinate;
GLuint _vbo;
GLuint _vao;
@ -37,9 +35,6 @@ public:
CopyFramebufferShader();
~CopyFramebufferShader() override;
void SetScreenSize(sint32 width, sint32 height);
void SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom);
void SetTextureCoordinates(sint32 left, sint32 top, sint32 right, sint32 bottom);
void SetTexture(GLuint texture);
void SetPalette(const vec4f * glPalette);

View File

@ -64,43 +64,33 @@ public:
}
};
struct DrawRectCommand {
uint32 flags;
GLuint sourceFramebuffer;
sint32 clip[4];
sint32 bounds[4];
GLuint paletteRemap[256];
};
struct DrawLineCommand {
struct DrawLineCommand
{
uint8 colour;
sint32 clip[4];
vec4i clip;
sint32 pos[4];
};
// Per-instance data for images
struct DrawImageCommand {
struct DrawRectCommand
{
vec4i clip;
sint32 texColourAtlas;
vec4f texColourBounds;
sint32 texMaskAtlas;
vec4f texMaskBounds;
sint32 texPaletteAtlas;
vec4f texPaletteBounds;
vec3i palettes;
sint32 flags;
uint8 colour;
uint32 colour;
vec4i bounds;
sint32 mask;
enum
{
FLAG_COLOUR = (1 << 0),
FLAG_REMAP = (1 << 1),
FLAG_TRANSPARENT = (1 << 2),
FLAG_TRANSPARENT_SPECIAL = (1 << 3),
FLAG_NO_TEXTURE = (1 << 2),
FLAG_MASK = (1 << 3),
FLAG_CROSS_HATCH = (1 << 4),
};
};
typedef CommandBatch<DrawImageCommand> ImageCommandBatch;
typedef CommandBatch<DrawLineCommand> LineCommandBatch;
typedef CommandBatch<DrawRectCommand> RectCommandBatch;

View File

@ -1,120 +0,0 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#ifndef DISABLE_OPENGL
#include "DrawImageShader.h"
DrawImageShader::DrawImageShader() : OpenGLShaderProgram("drawimage")
{
GetLocations();
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_vboInstances);
glGenVertexArrays(1, &_vao);
GLuint vertices[] = { 0, 1, 2, 2, 1, 3 };
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(_vao);
glVertexAttribIPointer(vIndex, 1, GL_INT, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glVertexAttribIPointer(vClip, 4, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, clip));
glVertexAttribIPointer(vTexColourAtlas, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texColourAtlas));
glVertexAttribPointer(vTexColourBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texColourBounds));
glVertexAttribIPointer(vTexMaskAtlas, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texMaskAtlas));
glVertexAttribPointer(vTexMaskBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texMaskBounds));
glVertexAttribIPointer(vTexPaletteAtlas, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texPaletteAtlas));
glVertexAttribPointer(vTexPaletteBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, texPaletteBounds));
glVertexAttribIPointer(vFlags, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, flags));
glVertexAttribIPointer(vColour, 1, GL_UNSIGNED_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, colour));
glVertexAttribIPointer(vBounds, 4, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, bounds));
glVertexAttribIPointer(vMask, 1, GL_INT, sizeof(DrawImageCommand), (void*) offsetof(DrawImageCommand, mask));
glEnableVertexAttribArray(vIndex);
glEnableVertexAttribArray(vClip);
glEnableVertexAttribArray(vTexColourAtlas);
glEnableVertexAttribArray(vTexColourBounds);
glEnableVertexAttribArray(vTexMaskAtlas);
glEnableVertexAttribArray(vTexMaskBounds);
glEnableVertexAttribArray(vTexPaletteAtlas);
glEnableVertexAttribArray(vTexPaletteBounds);
glEnableVertexAttribArray(vFlags);
glEnableVertexAttribArray(vColour);
glEnableVertexAttribArray(vBounds);
glEnableVertexAttribArray(vMask);
glVertexAttribDivisor(vClip, 1);
glVertexAttribDivisor(vTexColourAtlas, 1);
glVertexAttribDivisor(vTexColourBounds, 1);
glVertexAttribDivisor(vTexMaskAtlas, 1);
glVertexAttribDivisor(vTexMaskBounds, 1);
glVertexAttribDivisor(vTexPaletteAtlas, 1);
glVertexAttribDivisor(vTexPaletteBounds, 1);
glVertexAttribDivisor(vFlags, 1);
glVertexAttribDivisor(vColour, 1);
glVertexAttribDivisor(vBounds, 1);
glVertexAttribDivisor(vMask, 1);
Use();
glUniform1i(uTexture, 0);
}
DrawImageShader::~DrawImageShader()
{
glDeleteBuffers(1, &_vbo);
glDeleteBuffers(1, &_vboInstances);
glDeleteVertexArrays(1, &_vao);
}
void DrawImageShader::GetLocations()
{
uScreenSize = GetUniformLocation("uScreenSize");
uTexture = GetUniformLocation("uTexture");
vIndex = GetAttributeLocation("vIndex");
vClip = GetAttributeLocation("ivClip");
vTexColourAtlas = GetAttributeLocation("ivTexColourAtlas");
vTexColourBounds = GetAttributeLocation("ivTexColourBounds");
vTexMaskAtlas = GetAttributeLocation("ivTexMaskAtlas");
vTexMaskBounds = GetAttributeLocation("ivTexMaskBounds");
vTexPaletteAtlas = GetAttributeLocation("ivTexPaletteAtlas");
vTexPaletteBounds = GetAttributeLocation("ivTexPaletteBounds");
vFlags = GetAttributeLocation("ivFlags");
vColour = GetAttributeLocation("ivColour");
vBounds = GetAttributeLocation("ivBounds");
vMask = GetAttributeLocation("ivMask");
}
void DrawImageShader::SetScreenSize(sint32 width, sint32 height)
{
glUniform2i(uScreenSize, width, height);
}
void DrawImageShader::DrawInstances(const ImageCommandBatch& instances)
{
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glBufferData(GL_ARRAY_BUFFER, sizeof(DrawImageCommand) * instances.size(), instances.data(), GL_STREAM_DRAW);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, (GLsizei)instances.size());
}
#endif /* DISABLE_OPENGL */

View File

@ -19,6 +19,17 @@
#include "DrawLineShader.h"
#include "OpenGLFramebuffer.h"
struct VDStruct
{
GLfloat mat[4][2];
};
constexpr VDStruct VertexData[2] =
{
{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f },
};
DrawLineShader::DrawLineShader() : OpenGLShaderProgram("drawline")
{
GetLocations();
@ -26,13 +37,19 @@ DrawLineShader::DrawLineShader() : OpenGLShaderProgram("drawline")
glGenBuffers(1, &_vbo);
glGenVertexArrays(1, &_vao);
GLuint vertices[] = { 0, 1 };
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData, GL_STATIC_DRAW);
glBindVertexArray(_vao);
glEnableVertexAttribArray(vIndex);
glVertexAttribIPointer(vIndex, 1, GL_INT, 0, nullptr);
glVertexAttribPointer(vVertMat+0, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[0]));
glVertexAttribPointer(vVertMat+1, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[1]));
glVertexAttribPointer(vVertMat+2, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[2]));
glVertexAttribPointer(vVertMat+3, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[3]));
glEnableVertexAttribArray(vVertMat+0);
glEnableVertexAttribArray(vVertMat+1);
glEnableVertexAttribArray(vVertMat+2);
glEnableVertexAttribArray(vVertMat+3);
Use();
}
@ -50,7 +67,7 @@ void DrawLineShader::GetLocations()
uBounds = GetUniformLocation("uBounds");
uColour = GetUniformLocation("uColour");
vIndex = GetAttributeLocation("vIndex");
vVertMat = GetAttributeLocation("vVertMat");
}
void DrawLineShader::SetScreenSize(sint32 width, sint32 height)

View File

@ -27,7 +27,7 @@ private:
GLuint uBounds;
GLuint uColour;
GLuint vIndex;
GLuint vVertMat;
GLuint _vbo;
GLuint _vao;

View File

@ -0,0 +1,138 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#ifndef DISABLE_OPENGL
#include "DrawRectShader.h"
struct VDStruct
{
GLfloat mat[4][2];
GLfloat vec[2];
};
constexpr VDStruct VertexData[4] =
{
{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f },
};
DrawRectShader::DrawRectShader() : OpenGLShaderProgram("drawrect")
{
GetLocations();
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_vboInstances);
glGenVertexArrays(1, &_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData, GL_STATIC_DRAW);
glBindVertexArray(_vao);
glVertexAttribPointer(vVertMat+0, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[0]));
glVertexAttribPointer(vVertMat+1, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[1]));
glVertexAttribPointer(vVertMat+2, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[2]));
glVertexAttribPointer(vVertMat+3, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, mat[3]));
glVertexAttribPointer(vVertVec, 2, GL_FLOAT, GL_FALSE, sizeof(VDStruct), (void*) offsetof(VDStruct, vec) );
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glVertexAttribIPointer(vClip, 4, GL_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, clip));
glVertexAttribIPointer(vTexColourAtlas, 1, GL_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, texColourAtlas));
glVertexAttribPointer(vTexColourBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, texColourBounds));
glVertexAttribIPointer(vTexMaskAtlas, 1, GL_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, texMaskAtlas));
glVertexAttribPointer(vTexMaskBounds, 4, GL_FLOAT, GL_FALSE, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, texMaskBounds));
glVertexAttribIPointer(vPalettes, 3, GL_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, palettes));
glVertexAttribIPointer(vFlags, 1, GL_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, flags));
glVertexAttribIPointer(vColour, 1, GL_UNSIGNED_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, colour));
glVertexAttribIPointer(vBounds, 4, GL_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, bounds));
glEnableVertexAttribArray(vVertMat+0);
glEnableVertexAttribArray(vVertMat+1);
glEnableVertexAttribArray(vVertMat+2);
glEnableVertexAttribArray(vVertMat+3);
glEnableVertexAttribArray(vVertVec);
glEnableVertexAttribArray(vClip);
glEnableVertexAttribArray(vTexColourAtlas);
glEnableVertexAttribArray(vTexColourBounds);
glEnableVertexAttribArray(vTexMaskAtlas);
glEnableVertexAttribArray(vTexMaskBounds);
glEnableVertexAttribArray(vPalettes);
glEnableVertexAttribArray(vFlags);
glEnableVertexAttribArray(vColour);
glEnableVertexAttribArray(vBounds);
glVertexAttribDivisor(vClip, 1);
glVertexAttribDivisor(vTexColourAtlas, 1);
glVertexAttribDivisor(vTexColourBounds, 1);
glVertexAttribDivisor(vTexMaskAtlas, 1);
glVertexAttribDivisor(vTexMaskBounds, 1);
glVertexAttribDivisor(vPalettes, 1);
glVertexAttribDivisor(vFlags, 1);
glVertexAttribDivisor(vColour, 1);
glVertexAttribDivisor(vBounds, 1);
Use();
glUniform1i(uTexture, 0);
glUniform1i(uPaletteTex, 1);
}
DrawRectShader::~DrawRectShader()
{
glDeleteBuffers(1, &_vbo);
glDeleteBuffers(1, &_vboInstances);
glDeleteVertexArrays(1, &_vao);
}
void DrawRectShader::GetLocations()
{
uScreenSize = GetUniformLocation("uScreenSize");
uTexture = GetUniformLocation("uTexture");
uPaletteTex = GetUniformLocation("uPaletteTex");
vClip = GetAttributeLocation("vClip");
vTexColourAtlas = GetAttributeLocation("vTexColourAtlas");
vTexColourBounds = GetAttributeLocation("vTexColourBounds");
vTexMaskAtlas = GetAttributeLocation("vTexMaskAtlas");
vTexMaskBounds = GetAttributeLocation("vTexMaskBounds");
vPalettes = GetAttributeLocation("vPalettes");
vFlags = GetAttributeLocation("vFlags");
vColour = GetAttributeLocation("vColour");
vBounds = GetAttributeLocation("vBounds");
vVertMat = GetAttributeLocation("vVertMat");
vVertVec = GetAttributeLocation("vVertVec");
}
void DrawRectShader::SetScreenSize(sint32 width, sint32 height)
{
glUniform2i(uScreenSize, width, height);
}
void DrawRectShader::DrawInstances(const RectCommandBatch& instances)
{
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glBufferData(GL_ARRAY_BUFFER, sizeof(DrawRectCommand) * instances.size(), instances.data(), GL_STREAM_DRAW);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, (GLsizei)instances.size());
}
#endif /* DISABLE_OPENGL */

View File

@ -22,35 +22,36 @@
#include <SDL_pixels.h>
#include <vector>
class DrawImageShader final : public OpenGLShaderProgram
class DrawRectShader final : public OpenGLShaderProgram
{
private:
GLuint uScreenSize;
GLuint uTexture;
GLuint uPaletteTex;
GLuint vVertMat;
GLuint vVertVec;
GLuint vIndex;
GLuint vClip;
GLuint vTexColourAtlas;
GLuint vTexColourBounds;
GLuint vTexMaskAtlas;
GLuint vTexMaskBounds;
GLuint vTexPaletteAtlas;
GLuint vTexPaletteBounds;
GLuint vPalettes;
GLuint vFlags;
GLuint vColour;
GLuint vBounds;
GLuint vMask;
GLuint _vbo;
GLuint _vboInstances;
GLuint _vao;
public:
DrawImageShader();
~DrawImageShader() override;
DrawRectShader();
~DrawRectShader() override;
void SetScreenSize(sint32 width, sint32 height);
void DrawInstances(const ImageCommandBatch& instances);
void DrawInstances(const RectCommandBatch& instances);
private:
void GetLocations();

View File

@ -1,104 +0,0 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#ifndef DISABLE_OPENGL
#include "FillRectShader.h"
#include "OpenGLFramebuffer.h"
FillRectShader::FillRectShader() : OpenGLShaderProgram("fillrect")
{
GetLocations();
glGenBuffers(1, &_vbo);
glGenVertexArrays(1, &_vao);
GLuint vertices[] = { 0, 1, 2, 2, 1, 3 };
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(_vao);
glEnableVertexAttribArray(vIndex);
glVertexAttribIPointer(vIndex, 1, GL_INT, 0, 0);
Use();
SetFlags(0);
glUniform1i(uSourceFramebuffer, 0);
}
FillRectShader::~FillRectShader()
{
glDeleteBuffers(1, &_vbo);
glDeleteVertexArrays(1, &_vao);
}
void FillRectShader::GetLocations()
{
uScreenSize = GetUniformLocation("uScreenSize");
uClip = GetUniformLocation("uClip");
uBounds = GetUniformLocation("uBounds");
uFlags = GetUniformLocation("uFlags");
uSourceFramebuffer = GetUniformLocation("uSourceFramebuffer");
uPaletteRemap = GetUniformLocation("uPaletteRemap");
vIndex = GetAttributeLocation("vIndex");
}
void FillRectShader::SetScreenSize(sint32 width, sint32 height)
{
glUniform2i(uScreenSize, width, height);
}
void FillRectShader::SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom)
{
glUniform4i(uClip, left, top, right, bottom);
}
void FillRectShader::SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom)
{
glUniform4i(uBounds, left, top, right, bottom);
}
void FillRectShader::SetFlags(uint32 flags)
{
glUniform1i(uFlags, flags);
}
void FillRectShader::SetSourceFramebuffer(GLuint texture)
{
_sourceFramebuffer = texture;
OpenGLAPI::SetTexture(0, GL_TEXTURE_2D, texture);
}
void FillRectShader::SetPaletteRemap(const GLuint * paletteRemap)
{
glUniform1uiv(uPaletteRemap, 256, paletteRemap);
}
void FillRectShader::Draw(sint32 left, sint32 top, sint32 right, sint32 bottom)
{
SetBounds(left, top, right, bottom);
glBindVertexArray(_vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
GLuint FillRectShader::GetSourceFramebuffer() const
{
return _sourceFramebuffer;
}
#endif /* DISABLE_OPENGL */

View File

@ -1,58 +0,0 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include "GLSLTypes.h"
#include "OpenGLShaderProgram.h"
class OpenGLFramebuffer;
class FillRectShader final : public OpenGLShaderProgram
{
private:
GLuint uScreenSize;
GLuint uClip;
GLuint uBounds;
GLuint uFlags;
GLuint uSourceFramebuffer;
GLuint uPaletteRemap;
GLuint vIndex;
GLuint _vbo;
GLuint _vao;
GLuint _sourceFramebuffer = 0;
public:
FillRectShader();
~FillRectShader() override;
void SetScreenSize(sint32 width, sint32 height);
void SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom);
void SetBounds(sint32 left, sint32 top, sint32 right, sint32 bottom);
void SetFlags(uint32 flags);
void SetSourceFramebuffer(GLuint texture);
void SetPaletteRemap(const GLuint * filterMap);
void Draw(sint32 left, sint32 top, sint32 right, sint32 bottom);
GLuint GetSourceFramebuffer() const;
private:
void GetLocations();
};

View File

@ -32,6 +32,13 @@ struct vec2f
union { float y; float t; float g; };
};
struct vec3i
{
union { sint32 x; sint32 s; sint32 r; };
union { sint32 y; sint32 t; sint32 g; };
union { sint32 z; sint32 p; sint32 b; };
};
struct vec3f
{
union { float x; float s; float r; };

View File

@ -41,9 +41,8 @@
#include "OpenGLAPI.h"
#include "OpenGLFramebuffer.h"
#include "CopyFramebufferShader.h"
#include "DrawImageShader.h"
#include "DrawLineShader.h"
#include "FillRectShader.h"
#include "DrawRectShader.h"
#include "SwapFramebuffer.h"
#include "TextureCache.h"
#include "DrawCommands.h"
@ -68,9 +67,8 @@ private:
OpenGLDrawingEngine * _engine = nullptr;
rct_drawpixelinfo * _dpi = nullptr;
DrawImageShader * _drawImageShader = nullptr;
DrawLineShader * _drawLineShader = nullptr;
FillRectShader * _fillRectShader = nullptr;
DrawRectShader * _drawRectShader = nullptr;
TextureCache * _textureCache = nullptr;
@ -82,9 +80,8 @@ private:
sint32 _clipBottom = 0;
struct {
RectCommandBatch rectangles;
LineCommandBatch lines;
ImageCommandBatch images;
RectCommandBatch rects;
} _commandBuffers;
public:
@ -109,9 +106,8 @@ public:
void FlushCommandBuffers();
void FlushRectangles();
void FlushLines();
void FlushImages();
void FlushRectangles();
void SetDPI(rct_drawpixelinfo * dpi);
};
@ -383,9 +379,6 @@ private:
_swapFramebuffer = new SwapFramebuffer(_width, _height);
_copyFramebufferShader->Use();
_copyFramebufferShader->SetScreenSize(_width, _height);
_copyFramebufferShader->SetBounds(0, 0, _width, _height);
_copyFramebufferShader->SetTextureCoordinates(0, 1, 1, 0);
}
void Display()
@ -406,9 +399,8 @@ OpenGLDrawingContext::OpenGLDrawingContext(OpenGLDrawingEngine * engine)
OpenGLDrawingContext::~OpenGLDrawingContext()
{
delete _drawImageShader;
delete _drawLineShader;
delete _fillRectShader;
delete _drawRectShader;
delete _textureCache;
}
@ -421,82 +413,67 @@ IDrawingEngine * OpenGLDrawingContext::GetEngine()
void OpenGLDrawingContext::Initialise()
{
_textureCache = new TextureCache();
_drawImageShader = new DrawImageShader();
_drawRectShader = new DrawRectShader();
_drawLineShader = new DrawLineShader();
_fillRectShader = new FillRectShader();
}
void OpenGLDrawingContext::Resize(sint32 width, sint32 height)
{
FlushCommandBuffers();
_drawImageShader->Use();
_drawImageShader->SetScreenSize(width, height);
_drawRectShader->Use();
_drawRectShader->SetScreenSize(width, height);
_drawLineShader->Use();
_drawLineShader->SetScreenSize(width, height);
_fillRectShader->Use();
_fillRectShader->SetScreenSize(width, height);
}
void OpenGLDrawingContext::ResetPalette()
{
//FlushCommandBuffers();
_textureCache->SetPalette(_engine->Palette);
}
void OpenGLDrawingContext::Clear(uint8 paletteIndex)
{
FillRect(paletteIndex, _clipLeft - _offsetX, _clipTop - _offsetY, _clipRight, _clipBottom);
FillRect(paletteIndex, _clipLeft - _offsetX, _clipTop - _offsetY, _clipRight - _offsetX, _clipBottom - _offsetY);
}
void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom)
{
// Must be rendered in order, depends on already rendered contents
FlushCommandBuffers();
left += _offsetX;
top += _offsetY;
right += _offsetX;
bottom += _offsetY;
DrawRectCommand& command = _commandBuffers.rectangles.allocate();
DrawRectCommand& command = _commandBuffers.rects.allocate();
command.sourceFramebuffer = _fillRectShader->GetSourceFramebuffer();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = 0;
command.texColourBounds = { 0.0f, 0.0f, 0.0f, 0.0f };
command.texMaskAtlas = 0;
command.texMaskBounds = { 0.0f, 0.0f, 0.0f, 0.0f };
command.palettes = { 0, 0, 0 };
command.colour = colour & 0xFF;
command.bounds = { left + _offsetX, top + _offsetY, right + 1, bottom + 1 };
command.flags = DrawRectCommand::FLAG_NO_TEXTURE;
if (colour & 0x1000000)
{
// cross-pattern
command.flags = 1;
command.flags = DrawRectCommand::FLAG_CROSS_HATCH;
}
else if (colour & 0x2000000)
{
assert(false);
// Should be FilterRect
}
else
{
command.flags = 0;
}
for (size_t i = 0; i < 256; i++)
{
command.paletteRemap[i] = colour & 0xFF;
}
command.clip[0] = _clipLeft;
command.clip[1] = _clipTop;
command.clip[2] = _clipRight;
command.clip[3] = _clipBottom;
command.bounds[0] = left;
command.bounds[1] = top;
command.bounds[2] = right + 1;
command.bounds[3] = bottom + 1;
}
void OpenGLDrawingContext::FilterRect(FILTER_PALETTE_ID palette, sint32 left, sint32 top, sint32 right, sint32 bottom)
{
// ignore transparency TODO
return;
/*
// Must be rendered in order, depends on already rendered contents
FlushCommandBuffers();
@ -524,15 +501,13 @@ void OpenGLDrawingContext::FilterRect(FILTER_PALETTE_ID palette, sint32 left, si
// END FILTER
command.clip[0] = _clipLeft;
command.clip[1] = _clipTop;
command.clip[2] = _clipRight;
command.clip[3] = _clipBottom;
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.bounds[0] = left;
command.bounds[1] = top;
command.bounds[2] = right + 1;
command.bounds[3] = bottom + 1;
*/
}
void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2)
@ -546,10 +521,7 @@ void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32
command.colour = colour & 0xFF;
command.clip[0] = _clipLeft;
command.clip[1] = _clipTop;
command.clip[2] = _clipRight;
command.clip[3] = _clipBottom;
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.pos[0] = x1;
command.pos[1] = y1;
@ -589,13 +561,8 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
uint8 zoomLevel = (1 << _dpi->zoom_level);
sint32 drawOffsetX = g1Element->x_offset;
sint32 drawOffsetY = g1Element->y_offset;
sint32 drawWidth = g1Element->width;
sint32 drawHeight = g1Element->height;
sint32 left = x + drawOffsetX;
sint32 top = y + drawOffsetY;
sint32 left = x + g1Element->x_offset;
sint32 top = y + g1Element->y_offset;
sint32 zoom_mask = 0xFFFFFFFF << _dpi->zoom_level;
if (_dpi->zoom_level && g1Element->flags & G1_FLAG_RLE_COMPRESSION){
@ -609,8 +576,8 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
left &= zoom_mask;
sint32 right = left + drawWidth;
sint32 bottom = top + drawHeight;
sint32 right = left + g1Element->width;
sint32 bottom = top + g1Element->height;
if (_dpi->zoom_level && g1Element->flags & G1_FLAG_RLE_COMPRESSION) {
bottom += top & ~zoom_mask;
@ -642,46 +609,54 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
auto texture = _textureCache->GetOrLoadImageTexture(image);
int paletteCount;
vec3i palettes{};
bool special = false;
if (!(image & IMAGE_TYPE_REMAP_2_PLUS) && (image & IMAGE_TYPE_REMAP)) {
if (((image >> 19) & 0x7F) == 32) {
if (image & IMAGE_TYPE_REMAP_2_PLUS)
{
palettes.x = TextureCache::PaletteToY((image >> 19) & 0x1F);
palettes.y = TextureCache::PaletteToY((image >> 24) & 0x1F);
if (image & IMAGE_TYPE_REMAP)
{
paletteCount = 2;
}
else
{
paletteCount = 3;
palettes.z = TextureCache::PaletteToY(tertiaryColour & 0xFF);
}
}
else if (image & IMAGE_TYPE_REMAP)
{
paletteCount = 1;
palettes.x = TextureCache::PaletteToY((image >> 19) & 0xFF);
if (palettes.x == 32)
{
special = true;
}
}
if (!((image & IMAGE_TYPE_REMAP_2_PLUS) && !(image & IMAGE_TYPE_REMAP))) {
tertiaryColour = 0;
else
{
paletteCount = 0;
}
auto texture2 = _textureCache->GetOrLoadPaletteTexture(image, tertiaryColour, special);
if (special || (image & IMAGE_TYPE_TRANSPARENT))
{
// ignore transparecy TODO
return;
}
DrawImageCommand& command = _commandBuffers.images.allocate();
DrawRectCommand& command = _commandBuffers.rects.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = texture->index;
command.texColourBounds = texture->normalizedBounds;
command.texMaskAtlas = 0;
command.texMaskBounds = { 0.0f, 0.0f, 0.0f };
command.texPaletteAtlas = texture2->index;
command.texPaletteBounds = texture2->computedBounds;
command.texMaskBounds = { 0.0f, 0.0f, 0.0f, 0.0f };
command.palettes = palettes;
command.colour = 0;
command.bounds = { left, top, right, bottom };
command.mask = 0;
command.flags = 0;
if (special)
{
command.flags |= DrawImageCommand::FLAG_TRANSPARENT_SPECIAL;
}
if (image & IMAGE_TYPE_TRANSPARENT)
{
command.flags |= DrawImageCommand::FLAG_TRANSPARENT;
}
else if (image & (IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_REMAP))
{
command.flags |= DrawImageCommand::FLAG_REMAP;
}
command.flags = paletteCount;
}
void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage)
@ -728,23 +703,23 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskIm
right += _clipLeft;
bottom += _clipTop;
DrawImageCommand& command = _commandBuffers.images.allocate();
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.texPaletteAtlas = 0;
command.texPaletteBounds = {0.0f, 0.0f, 0.0f};
command.flags = 0;
command.palettes = { 0, 0, 0 };
command.flags = DrawRectCommand::FLAG_MASK;
command.colour = 0;
command.bounds = { left, top, right, bottom };
command.mask = 1;
}
void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour)
{
assert((colour & 0xFF) > 0u);
sint32 g1Id = image & 0x7FFFF;
rct_g1_element * g1Element = gfx_get_g1_element(g1Id);
@ -774,19 +749,17 @@ void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uin
right += _offsetX;
bottom += _offsetY;
DrawImageCommand& command = _commandBuffers.images.allocate();
DrawRectCommand& command = _commandBuffers.rects.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = texture->index;
command.texColourBounds = texture->normalizedBounds;
command.texMaskAtlas = 0;
command.texMaskBounds = { 0.0f, 0.0f, 0.0f };
command.texPaletteAtlas = texture->index;
command.texPaletteBounds = texture->computedBounds;
command.flags = DrawImageCommand::FLAG_COLOUR;
command.texColourAtlas = 0;
command.texColourBounds = { 0.0f, 0.0f, 0.0f, 0.0f };
command.texMaskAtlas = texture->index;
command.texMaskBounds = texture->normalizedBounds;
command.palettes = { 0, 0, 0 };
command.flags = DrawRectCommand::FLAG_NO_TEXTURE | DrawRectCommand::FLAG_MASK;
command.colour = colour & 0xFF;
command.bounds = { left, top, right, bottom };
command.mask = 0;
}
void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette)
@ -820,43 +793,23 @@ void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * p
right += _offsetX;
bottom += _offsetY;
DrawImageCommand& command = _commandBuffers.images.allocate();
DrawRectCommand& command = _commandBuffers.rects.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = texture.index;
command.texColourBounds = texture.normalizedBounds;
command.texMaskAtlas = 0;
command.texMaskBounds = { 0.0f, 0.0f, 0.0f };
command.texPaletteAtlas = 0;
command.texPaletteBounds = { 0.0f, 0.0f, 0.0f};
command.texMaskBounds = { 0.0f, 0.0f, 0.0f, 0.0f };
command.palettes = { 0, 0, 0 };
command.flags = 0;
command.colour = 0;
command.bounds = { left, top, right, bottom };
command.mask = 0;
}
void OpenGLDrawingContext::FlushCommandBuffers()
{
FlushRectangles();
FlushLines();
FlushImages();
}
void OpenGLDrawingContext::FlushRectangles()
{
for(size_t n = 0; n < _commandBuffers.rectangles.size(); n++)
{
const auto& command = _commandBuffers.rectangles[n];
_fillRectShader->Use();
_fillRectShader->SetFlags(command.flags);
_fillRectShader->SetSourceFramebuffer(command.sourceFramebuffer);
_fillRectShader->SetClip(command.clip[0], command.clip[1], command.clip[2], command.clip[3]);
_fillRectShader->SetPaletteRemap(command.paletteRemap);
_fillRectShader->Draw(command.bounds[0], command.bounds[1], command.bounds[2], command.bounds[3]);
}
_commandBuffers.rectangles.reset();
FlushRectangles();
}
void OpenGLDrawingContext::FlushLines()
@ -867,23 +820,24 @@ void OpenGLDrawingContext::FlushLines()
_drawLineShader->Use();
_drawLineShader->SetColour(command.colour);
_drawLineShader->SetClip(command.clip[0], command.clip[1], command.clip[2], command.clip[3]);
_drawLineShader->SetClip(command.clip.x, command.clip.y, command.clip.z, command.clip.w);
_drawLineShader->Draw(command.pos[0], command.pos[1], command.pos[2], command.pos[3]);
}
_commandBuffers.lines.reset();
}
void OpenGLDrawingContext::FlushImages()
void OpenGLDrawingContext::FlushRectangles()
{
if (_commandBuffers.images.size() == 0) return;
if (_commandBuffers.rects.size() == 0) return;
OpenGLAPI::SetTexture(0, GL_TEXTURE_2D_ARRAY, _textureCache->GetAtlasesTexture());
OpenGLAPI::SetTexture(1, GL_TEXTURE_RECTANGLE, _textureCache->GetPaletteTexture());
_drawImageShader->Use();
_drawImageShader->DrawInstances(_commandBuffers.images);
_drawRectShader->Use();
_drawRectShader->DrawInstances(_commandBuffers.rects);
_commandBuffers.images.reset();
_commandBuffers.rects.reset();
}
void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi)

View File

@ -28,11 +28,6 @@ TextureCache::~TextureCache()
FreeTextures();
}
void TextureCache::SetPalette(const SDL_Color * palette)
{
Memory::CopyArray(_palette, palette, 256);
}
void TextureCache::InvalidateImage(uint32 image)
{
auto kvp = _imageTextureMap.find(image);
@ -59,42 +54,6 @@ const CachedTextureInfo* TextureCache::GetOrLoadImageTexture(uint32 image)
return &(cacheItr.first->second);
}
const CachedTextureInfo* TextureCache::GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special)
{
if ((image & (IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_TRANSPARENT)) == 0)
{
static CachedTextureInfo invalidEntry{ 0 };
return &invalidEntry;
}
uint32 uniquePaletteId = image & (IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_TRANSPARENT);
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);
auto cacheItr = _paletteTextureMap.insert(std::make_pair(uniquePaletteId, cacheInfo));
return &(cacheItr.first->second);
}
CachedTextureInfo TextureCache::GetOrLoadGlyphTexture(uint32 image, uint8 * palette)
{
GlyphId glyphId;
@ -113,9 +72,9 @@ CachedTextureInfo TextureCache::GetOrLoadGlyphTexture(uint32 image, uint8 * pale
return cacheInfo;
}
void TextureCache::CreateAtlasesTexture()
void TextureCache::CreateTextures()
{
if (!_atlasesTextureInitialised)
if (!_initialized)
{
// Determine width and height to use for texture atlases
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_atlasesTextureDimensions);
@ -127,26 +86,50 @@ void TextureCache::CreateAtlasesTexture()
glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &_atlasesTextureIndicesLimit);
if (_atlasesTextureDimensions < _atlasesTextureIndicesLimit) _atlasesTextureIndicesLimit = _atlasesTextureDimensions;
AllocateAtlasesTexture();
glGenTextures(1, &_atlasesTexture);
glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
_atlasesTextureInitialised = true;
glGenTextures(1, &_paletteTexture);
glBindTexture(GL_TEXTURE_RECTANGLE, _paletteTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GeneratePaletteTexture();
_initialized = true;
_atlasesTextureIndices = 0;
}
}
void TextureCache::AllocateAtlasesTexture()
void TextureCache::GeneratePaletteTexture()
{
// Create an array texture to hold all of the atlases
glGenTextures(1, &_atlasesTexture);
glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
rct_drawpixelinfo dpi = CreateDPI(256, PALETTE_TO_G1_OFFSET_COUNT + 5);
// Init no-op palette
for (int i=0; i < 256; ++i)
{
dpi.bits[i] = i;
}
for (int i=0; i < PALETTE_TO_G1_OFFSET_COUNT; ++i)
{
GLint y = PaletteToY(i);
uint16 image = palette_to_g1_offset[i];
const rct_g1_element &element = g1Elements[image];
gfx_draw_sprite_software(&dpi, image, -element.x_offset, y - element.y_offset, 0);
}
glBindTexture(GL_TEXTURE_RECTANGLE, _paletteTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_R8UI, 256, PALETTE_TO_G1_OFFSET_COUNT + 5, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, dpi.bits);
DeleteDPI(dpi);
}
void TextureCache::EnlargeAtlasesTexture(GLuint newEntries)
{
CreateAtlasesTexture();
CreateTextures();
GLuint newIndices = _atlasesTextureIndices + newEntries;
@ -157,9 +140,7 @@ void TextureCache::EnlargeAtlasesTexture(GLuint newEntries)
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, oldPixels.data());
}
// Delete old texture, allocate a new one, then define the new format on the newly created texture
glDeleteTextures(1, &_atlasesTexture);
AllocateAtlasesTexture();
glBindTexture(GL_TEXTURE_2D_ARRAY, _atlasesTexture);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R8UI, _atlasesTextureDimensions, _atlasesTextureDimensions, newIndices, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, nullptr);
// Restore old data
@ -170,12 +151,12 @@ void TextureCache::EnlargeAtlasesTexture(GLuint newEntries)
CachedTextureInfo TextureCache::LoadImageTexture(uint32 image)
{
rct_drawpixelinfo * dpi = GetImageAsDPI(image, 0);
rct_drawpixelinfo dpi = GetImageAsDPI(image, 0);
auto cacheInfo = AllocateImage(dpi->width, dpi->height);
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);
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);
DeleteDPI(dpi);
@ -190,61 +171,23 @@ CachedTextureInfo TextureCache::LoadImageTexture(uint32 image)
return cacheInfo;
}
CachedTextureInfo TextureCache::LoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special)
CachedTextureInfo TextureCache::LoadGlyphTexture(uint32 image, uint8 * palette)
{
rct_drawpixelinfo dpi;
dpi.bits = gfx_draw_sprite_get_palette(image, tertiaryColour);
dpi.width = 256;
dpi.height = special ? 5 : 1;
rct_drawpixelinfo dpi = GetGlyphAsDPI(image, palette);
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);
cacheInfo.computedBounds =
{
cacheInfo.normalizedBounds.x,
cacheInfo.normalizedBounds.y,
(cacheInfo.normalizedBounds.z - cacheInfo.normalizedBounds.x) / (float)(cacheInfo.bounds.z - cacheInfo.bounds.x),
(cacheInfo.normalizedBounds.w - cacheInfo.normalizedBounds.y) / (float)(cacheInfo.bounds.w - cacheInfo.bounds.y)
};
return cacheInfo;
}
CachedTextureInfo TextureCache::LoadGlyphTexture(uint32 image, uint8 * palette)
{
rct_drawpixelinfo * dpi = GetGlyphAsDPI(image, palette);
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);
DeleteDPI(dpi);
return cacheInfo;
}
void * TextureCache::GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight)
{
rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF);
sint32 width = g1Element->width;
sint32 height = g1Element->height;
rct_drawpixelinfo * dpi = CreateDPI(width, height);
gfx_draw_sprite_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour);
void * pixels32 = ConvertDPIto32bpp(dpi);
DeleteDPI(dpi);
*outWidth = width;
*outHeight = height;
return pixels32;
}
CachedTextureInfo TextureCache::AllocateImage(sint32 imageWidth, sint32 imageHeight)
{
CreateAtlasesTexture();
CreateTextures();
// Find an atlas that fits this image
for (Atlas& atlas : _atlases)
@ -278,73 +221,28 @@ CachedTextureInfo TextureCache::AllocateImage(sint32 imageWidth, sint32 imageHei
return _atlases.back().Allocate(imageWidth, imageHeight);
}
rct_drawpixelinfo * TextureCache::GetImageAsDPI(uint32 image, uint32 tertiaryColour)
rct_drawpixelinfo TextureCache::GetImageAsDPI(uint32 image, uint32 tertiaryColour)
{
rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF);
sint32 width = g1Element->width;
sint32 height = g1Element->height;
rct_drawpixelinfo * dpi = CreateDPI(width, height);
gfx_draw_sprite_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour);
rct_drawpixelinfo dpi = CreateDPI(width, height);
gfx_draw_sprite_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour);
return dpi;
}
void * TextureCache::GetGlyphAsARGB(uint32 image, uint8 * palette, uint32 * outWidth, uint32 * outHeight)
rct_drawpixelinfo TextureCache::GetGlyphAsDPI(uint32 image, uint8 * palette)
{
rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF);
sint32 width = g1Element->width;
sint32 height = g1Element->height;
rct_drawpixelinfo * dpi = CreateDPI(width, height);
gfx_draw_sprite_palette_set_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, palette, nullptr);
void * pixels32 = ConvertDPIto32bpp(dpi);
DeleteDPI(dpi);
*outWidth = width;
*outHeight = height;
return pixels32;
}
rct_drawpixelinfo * TextureCache::GetGlyphAsDPI(uint32 image, uint8 * palette)
{
rct_g1_element * g1Element = gfx_get_g1_element(image & 0x7FFFF);
sint32 width = g1Element->width;
sint32 height = g1Element->height;
rct_drawpixelinfo * dpi = CreateDPI(width, height);
gfx_draw_sprite_palette_set_software(dpi, image, -g1Element->x_offset, -g1Element->y_offset, palette, nullptr);
rct_drawpixelinfo dpi = CreateDPI(width, height);
gfx_draw_sprite_palette_set_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, palette, nullptr);
return dpi;
}
void * TextureCache::ConvertDPIto32bpp(const rct_drawpixelinfo * dpi)
{
size_t numPixels = dpi->width * dpi->height;
uint8 * pixels32 = Memory::Allocate<uint8>(numPixels * 4);
uint8 * src = dpi->bits;
uint8 * dst = pixels32;
for (size_t i = 0; i < numPixels; i++)
{
uint8 paletteIndex = *src++;
if (paletteIndex == 0)
{
// Transparent
*dst++ = 0;
*dst++ = 0;
*dst++ = 0;
*dst++ = 0;
}
else
{
SDL_Color colour = _palette[paletteIndex];
*dst++ = colour.r;
*dst++ = colour.g;
*dst++ = colour.b;
*dst++ = colour.a;
}
}
return pixels32;
}
void TextureCache::FreeTextures()
{
// Free array texture
@ -352,27 +250,26 @@ void TextureCache::FreeTextures()
_imageTextureMap.clear();
}
rct_drawpixelinfo * TextureCache::CreateDPI(sint32 width, sint32 height)
rct_drawpixelinfo TextureCache::CreateDPI(sint32 width, sint32 height)
{
size_t numPixels = width * height;
uint8 * pixels8 = Memory::Allocate<uint8>(numPixels);
Memory::Set(pixels8, 0, numPixels);
rct_drawpixelinfo * dpi = new rct_drawpixelinfo();
dpi->bits = pixels8;
dpi->pitch = 0;
dpi->x = 0;
dpi->y = 0;
dpi->width = width;
dpi->height = height;
dpi->zoom_level = 0;
rct_drawpixelinfo dpi;
dpi.bits = pixels8;
dpi.pitch = 0;
dpi.x = 0;
dpi.y = 0;
dpi.width = width;
dpi.height = height;
dpi.zoom_level = 0;
return dpi;
}
void TextureCache::DeleteDPI(rct_drawpixelinfo* dpi)
void TextureCache::DeleteDPI(rct_drawpixelinfo dpi)
{
Memory::Free(dpi->bits);
delete dpi;
Memory::Free(dpi.bits);
}
GLuint TextureCache::GetAtlasesTexture()
@ -380,4 +277,14 @@ GLuint TextureCache::GetAtlasesTexture()
return _atlasesTexture;
}
GLuint TextureCache::GetPaletteTexture()
{
return _paletteTexture;
}
GLint TextureCache::PaletteToY(uint32 palette)
{
return palette > PALETTE_WATER ? palette + 5 : palette + 1;
}
#endif /* DISABLE_OPENGL */

View File

@ -188,7 +188,7 @@ private:
class TextureCache final
{
private:
bool _atlasesTextureInitialised = false;
bool _initialized = false;
GLuint _atlasesTexture = 0;
GLint _atlasesTextureDimensions = 0;
@ -200,34 +200,30 @@ private:
std::unordered_map<uint32, CachedTextureInfo> _imageTextureMap;
std::unordered_map<uint32, CachedTextureInfo> _paletteTextureMap;
SDL_Color _palette[256];
GLuint _paletteTexture = 0;
public:
TextureCache() = default;
~TextureCache();
void SetPalette(const SDL_Color * palette);
void InvalidateImage(uint32 image);
const CachedTextureInfo* GetOrLoadImageTexture(uint32 image);
CachedTextureInfo GetOrLoadGlyphTexture(uint32 image, uint8 * palette);
const CachedTextureInfo* GetOrLoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special);
GLuint GetAtlasesTexture();
GLuint GetPaletteTexture();
static GLint PaletteToY(uint32 palette);
private:
void CreateAtlasesTexture();
void AllocateAtlasesTexture();
void CreateTextures();
void GeneratePaletteTexture();
void EnlargeAtlasesTexture(GLuint newEntries);
CachedTextureInfo LoadImageTexture(uint32 image);
CachedTextureInfo LoadGlyphTexture(uint32 image, uint8 * palette);
CachedTextureInfo LoadPaletteTexture(uint32 image, uint32 tertiaryColour, bool special);
CachedTextureInfo AllocateImage(sint32 imageWidth, sint32 imageHeight);
void * GetImageAsARGB(uint32 image, uint32 tertiaryColour, uint32 * outWidth, uint32 * outHeight);
rct_drawpixelinfo * GetImageAsDPI(uint32 image, uint32 tertiaryColour);
void * GetGlyphAsARGB(uint32 image, uint8 * palette, uint32 * outWidth, uint32 * outHeight);
rct_drawpixelinfo * GetGlyphAsDPI(uint32 image, uint8 * palette);
void * ConvertDPIto32bpp(const rct_drawpixelinfo * dpi);
rct_drawpixelinfo GetImageAsDPI(uint32 image, uint32 tertiaryColour);
rct_drawpixelinfo GetGlyphAsDPI(uint32 image, uint8 * palette);
void FreeTextures();
static rct_drawpixelinfo * CreateDPI(sint32 width, sint32 height);
static void DeleteDPI(rct_drawpixelinfo * dpi);
static rct_drawpixelinfo CreateDPI(sint32 width, sint32 height);
static void DeleteDPI(rct_drawpixelinfo dpi);
};