1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-10 09:32:29 +01:00

OpenGL: Add single-pass transparency

This commit is contained in:
LRFLEW
2017-10-20 22:00:56 -05:00
committed by Michał Janiszewski
parent 3d2d99817c
commit d3d41ea724
15 changed files with 340 additions and 138 deletions

View File

@@ -263,6 +263,7 @@
D45A395D1CF300AF00659A24 /* libSDL2_ttf.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B71CF3006400659A24 /* libSDL2_ttf.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
D45A395E1CF300AF00659A24 /* libSDL2.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B81CF3006400659A24 /* libSDL2.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
D45A395F1CF300AF00659A24 /* libspeexdsp.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D45A38B91CF3006400659A24 /* libspeexdsp.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
D45E09171F99CF2F00854B2B /* ApplyTransparencyShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D45E09161F99CF2F00854B2B /* ApplyTransparencyShader.cpp */; };
D47304D51C4FF8250015C0EA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D47304D41C4FF8250015C0EA /* libz.tbd */; };
D48AFDB71EF78DBF0081C644 /* BenchGfxCommmands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D48AFDB61EF78DBF0081C644 /* BenchGfxCommmands.cpp */; };
D4A8B4B41DB41873007A2F29 /* libpng16.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A8B4B31DB41873007A2F29 /* libpng16.dylib */; };
@@ -1034,6 +1035,8 @@
D45A39561CF3007A00659A24 /* speex_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speex_resampler.h; sourceTree = "<group>"; };
D45A39571CF3007A00659A24 /* speexdsp_config_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speexdsp_config_types.h; sourceTree = "<group>"; };
D45A39581CF3007A00659A24 /* speexdsp_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speexdsp_types.h; sourceTree = "<group>"; };
D45E09151F99CF2F00854B2B /* ApplyTransparencyShader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ApplyTransparencyShader.h; sourceTree = "<group>"; };
D45E09161F99CF2F00854B2B /* ApplyTransparencyShader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ApplyTransparencyShader.cpp; sourceTree = "<group>"; };
D47304D41C4FF8250015C0EA /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
D4895D321C23EFDD000CD788 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = distribution/macos/Info.plist; sourceTree = SOURCE_ROOT; };
D48AFDB61EF78DBF0081C644 /* BenchGfxCommmands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BenchGfxCommmands.cpp; sourceTree = "<group>"; };
@@ -2663,6 +2666,8 @@
F76C85901EC4E82600FA49E2 /* opengl */ = {
isa = PBXGroup;
children = (
D45E09161F99CF2F00854B2B /* ApplyTransparencyShader.cpp */,
D45E09151F99CF2F00854B2B /* ApplyTransparencyShader.h */,
F76C85911EC4E82600FA49E2 /* CopyFramebufferShader.cpp */,
F76C85921EC4E82600FA49E2 /* CopyFramebufferShader.h */,
F76C85931EC4E82600FA49E2 /* DrawCommands.h */,
@@ -3287,6 +3292,7 @@
F76C88861EC5324E00FA49E2 /* OpenGLShaderProgram.cpp in Sources */,
F76C88871EC5324E00FA49E2 /* SwapFramebuffer.cpp in Sources */,
F76C88881EC5324E00FA49E2 /* TextureCache.cpp in Sources */,
D45E09171F99CF2F00854B2B /* ApplyTransparencyShader.cpp in Sources */,
4C93F1A61F8B748900A9330D /* DingySlide.cpp in Sources */,
F76C88891EC5324E00FA49E2 /* SoftwareDrawingEngine.cpp in Sources */,
4C93F1A91F8B748900A9330D /* SplashBoats.cpp in Sources */,

View File

@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
@@ -45,6 +46,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@@ -0,0 +1,26 @@
#version 150
uniform usampler2D uOpaqueTex;
uniform sampler2D uOpaqueDepth;
uniform usampler2D uTransparentTex;
uniform sampler2D uTransparentDepth;
uniform usampler2DRect uPaletteTex;
in vec2 fTextureCoordinate;
out uint oColour;
void main()
{
uint opaque = texture(uOpaqueTex, fTextureCoordinate).r;
float opaqueDepth = texture(uOpaqueDepth, fTextureCoordinate).r;
uint transparent = texture(uTransparentTex, fTextureCoordinate).r;
float transparentDepth = texture(uTransparentDepth, fTextureCoordinate).r;
if (transparentDepth > opaqueDepth)
{
transparent = 0u;
}
oColour = texture(uPaletteTex, vec2(opaque, transparent)).r;
}

View File

@@ -0,0 +1,12 @@
#version 150
in vec4 vPosition;
in vec2 vTextureCoordinate;
out vec2 fTextureCoordinate;
void main()
{
fTextureCoordinate = vTextureCoordinate;
gl_Position = vPosition;
}

View File

@@ -22,7 +22,7 @@ void main()
pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0;
pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0;
pos.y *= -1;
float depth = 1.0 - vDepth * DEPTH_INCREMENT;
float depth = 1.0 - (vDepth + 1) * DEPTH_INCREMENT;
fColour = vColour;

View File

@@ -40,7 +40,7 @@ void main()
pos.x = (pos.x * (2.0 / uScreenSize.x)) - 1.0;
pos.y = (pos.y * (2.0 / uScreenSize.y)) - 1.0;
pos.y *= -1;
float depth = 1.0 - vDepth * DEPTH_INCREMENT;
float depth = 1.0 - (vDepth + 1) * DEPTH_INCREMENT;
fFlags = vFlags;
fColour = vColour;

View File

@@ -0,0 +1,93 @@
#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 "ApplyTransparencyShader.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 },
};
ApplyTransparencyShader::ApplyTransparencyShader() : OpenGLShaderProgram("applytransparency")
{
GetLocations();
glGenBuffers(1, &_vbo);
glGenVertexArrays(1, &_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData, GL_STATIC_DRAW);
glBindVertexArray(_vao);
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();
glUniform1i(uOpaqueTex, 0);
glUniform1i(uOpaqueDepth, 1);
glUniform1i(uTransparentTex, 2);
glUniform1i(uTransparentDepth, 3);
glUniform1i(uPaletteTex, 4);
}
ApplyTransparencyShader::~ApplyTransparencyShader()
{
glDeleteBuffers(1, &_vbo);
glDeleteVertexArrays(1, &_vao);
}
void ApplyTransparencyShader::GetLocations()
{
uOpaqueTex = GetUniformLocation("uOpaqueTex");
uOpaqueDepth = GetUniformLocation("uOpaqueDepth");
uTransparentTex = GetUniformLocation("uTransparentTex");
uTransparentDepth = GetUniformLocation("uTransparentDepth");
uPaletteTex = GetUniformLocation("uPaletteTex");
vPosition = GetAttributeLocation("vPosition");
vTextureCoordinate = GetAttributeLocation("vTextureCoordinate");
}
void ApplyTransparencyShader::SetTextures(GLuint opaqueTex, GLuint opaqueDepth, GLuint transparentTex, GLuint transparentDepth, GLuint paletteTex)
{
OpenGLAPI::SetTexture(0, GL_TEXTURE_2D, opaqueTex);
OpenGLAPI::SetTexture(1, GL_TEXTURE_2D, opaqueDepth);
OpenGLAPI::SetTexture(2, GL_TEXTURE_2D, transparentTex);
OpenGLAPI::SetTexture(3, GL_TEXTURE_2D, transparentDepth);
OpenGLAPI::SetTexture(4, GL_TEXTURE_RECTANGLE, paletteTex);
}
void ApplyTransparencyShader::Draw()
{
glBindVertexArray(_vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
#endif /* DISABLE_OPENGL */

View File

@@ -0,0 +1,46 @@
#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 ApplyTransparencyShader final : public OpenGLShaderProgram
{
private:
GLuint uOpaqueTex;
GLuint uOpaqueDepth;
GLuint uTransparentTex;
GLuint uTransparentDepth;
GLuint uPaletteTex;
GLuint vPosition;
GLuint vTextureCoordinate;
GLuint _vbo;
GLuint _vao;
public:
ApplyTransparencyShader();
~ApplyTransparencyShader() override;
void SetTextures(GLuint opaqueTex, GLuint opaqueDepth, GLuint transparentTex, GLuint transparentDepth, GLuint paletteTex);
void Draw();
private:
void GetLocations();
};

View File

@@ -38,7 +38,7 @@ public:
{
return _numInstances == 0;
}
void reset()
void clear()
{
_numInstances = 0;
}
@@ -56,7 +56,7 @@ public:
}
const T* data() const
{
return &_instances.at(0);
return _instances.data();
}
const T& operator[](size_t idx) const
{

View File

@@ -49,8 +49,10 @@ OPENGL_PROC(PFNGLBINDBUFFERPROC, glBindBuffer)
OPENGL_PROC(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation)
OPENGL_PROC(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer)
OPENGL_PROC(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray)
OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer);
OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer)
OPENGL_PROC(PFNGLBUFFERDATAPROC, glBufferData)
OPENGL_PROC(PFNGLCLEARBUFFERFVPROC, glClearBufferfv)
OPENGL_PROC(PFNGLCLEARBUFFERUIVPROC, glClearBufferuiv)
OPENGL_PROC(PFNGLCOMPILESHADERPROC, glCompileShader)
OPENGL_PROC(PFNGLCREATEPROGRAMPROC, glCreateProgram)
OPENGL_PROC(PFNGLCREATESHADERPROC, glCreateShader)

View File

@@ -67,8 +67,10 @@ private:
OpenGLDrawingEngine * _engine = nullptr;
rct_drawpixelinfo * _dpi = nullptr;
DrawLineShader * _drawLineShader = nullptr;
DrawRectShader * _drawRectShader = nullptr;
ApplyTransparencyShader * _applyTransparencyShader = nullptr;
DrawLineShader * _drawLineShader = nullptr;
DrawRectShader * _drawRectShader = nullptr;
SwapFramebuffer * _swapFramebuffer = nullptr;
TextureCache * _textureCache = nullptr;
@@ -85,7 +87,9 @@ private:
{
LineCommandBatch lines;
RectCommandBatch rects;
} _commandBuffers;
RectCommandBatch transparent;
}
_commandBuffers;
public:
explicit OpenGLDrawingContext(OpenGLDrawingEngine * engine);
@@ -93,11 +97,13 @@ public:
IDrawingEngine * GetEngine() override;
TextureCache * GetTextureCache() const { return _textureCache; }
SwapFramebuffer * GetSwapFramebuffer() const { return _swapFramebuffer; }
const OpenGLFramebuffer & GetFinalFramebuffer() const { return _swapFramebuffer->GetFinalFramebuffer(); }
void Initialise();
void Resize(sint32 width, sint32 height);
void ResetPalette();
void ResetDrawCount() { _drawCount = 0; }
void StartNewDraw();
void Clear(uint8 paletteIndex) override;
void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override;
@@ -110,8 +116,8 @@ public:
void FlushCommandBuffers();
void FlushLines();
void FlushRectangles();
void FlushLines(LineCommandBatch &batch);
void FlushRectangles(RectCommandBatch &batch);
void SetDPI(rct_drawpixelinfo * dpi);
};
@@ -135,7 +141,6 @@ private:
CopyFramebufferShader * _copyFramebufferShader = nullptr;
OpenGLFramebuffer * _screenFramebuffer = nullptr;
SwapFramebuffer * _swapFramebuffer = nullptr;
public:
SDL_Color Palette[256];
@@ -155,7 +160,6 @@ public:
{
delete _copyFramebufferShader;
delete _screenFramebuffer;
delete _swapFramebuffer;
delete _drawingContext;
delete [] _bits;
@@ -230,11 +234,8 @@ public:
void BeginDraw() override
{
assert(_screenFramebuffer != nullptr);
assert(_swapFramebuffer != nullptr);
_drawingContext->ResetDrawCount();
_swapFramebuffer->Bind();
glClear(GL_DEPTH_BUFFER_BIT);
_drawingContext->StartNewDraw();
}
void EndDraw() override
@@ -245,7 +246,7 @@ public:
glDisable(GL_DEPTH_TEST);
_screenFramebuffer->Bind();
_copyFramebufferShader->Use();
_copyFramebufferShader->SetTexture(_swapFramebuffer->GetTargetFramebuffer()->GetTexture());
_copyFramebufferShader->SetTexture(_drawingContext->GetFinalFramebuffer().GetTexture());
_copyFramebufferShader->Draw();
CheckGLError();
@@ -268,9 +269,9 @@ public:
sint32 Screenshot() override
{
const OpenGLFramebuffer * framebuffer = _swapFramebuffer->GetTargetFramebuffer();
framebuffer->Bind();
framebuffer->GetPixels(_bitsDPI);
const OpenGLFramebuffer & framebuffer = _drawingContext->GetFinalFramebuffer();
framebuffer.Bind();
framebuffer.GetPixels(_bitsDPI);
sint32 result = screenshot_dump_png(&_bitsDPI);
return result;
}
@@ -307,12 +308,6 @@ public:
return &_bitsDPI;
}
GLuint SwapCopyReturningSourceTexture()
{
_swapFramebuffer->SwapCopy();
return _swapFramebuffer->GetSourceTexture();
}
private:
static OpenGLVersion GetOpenGLVersion()
{
@@ -381,11 +376,6 @@ private:
delete _screenFramebuffer;
_screenFramebuffer = new OpenGLFramebuffer(_window);
// Re-create canvas framebuffer
delete _swapFramebuffer;
_swapFramebuffer = new SwapFramebuffer(_width, _height);
_copyFramebufferShader->Use();
}
void Display()
@@ -406,8 +396,10 @@ OpenGLDrawingContext::OpenGLDrawingContext(OpenGLDrawingEngine * engine)
OpenGLDrawingContext::~OpenGLDrawingContext()
{
delete _applyTransparencyShader;
delete _drawLineShader;
delete _drawRectShader;
delete _swapFramebuffer;
delete _textureCache;
}
@@ -420,18 +412,24 @@ IDrawingEngine * OpenGLDrawingContext::GetEngine()
void OpenGLDrawingContext::Initialise()
{
_textureCache = new TextureCache();
_applyTransparencyShader = new ApplyTransparencyShader();
_drawRectShader = new DrawRectShader();
_drawLineShader = new DrawLineShader();
}
void OpenGLDrawingContext::Resize(sint32 width, sint32 height)
{
FlushCommandBuffers();
_commandBuffers.lines.clear();
_commandBuffers.rects.clear();
_drawRectShader->Use();
_drawRectShader->SetScreenSize(width, height);
_drawLineShader->Use();
_drawLineShader->SetScreenSize(width, height);
// Re-create canvas framebuffer
delete _swapFramebuffer;
_swapFramebuffer = new SwapFramebuffer(width, height);
}
void OpenGLDrawingContext::ResetPalette()
@@ -439,6 +437,12 @@ void OpenGLDrawingContext::ResetPalette()
//FlushCommandBuffers();
}
void OpenGLDrawingContext::StartNewDraw()
{
_drawCount = 0;
_swapFramebuffer->Clear();
}
void OpenGLDrawingContext::Clear(uint8 paletteIndex)
{
FillRect(paletteIndex, _clipLeft - _offsetX, _clipTop - _offsetY, _clipRight - _offsetX, _clipBottom - _offsetY);
@@ -478,44 +482,23 @@ void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint
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();
left += _offsetX;
top += _offsetY;
right += _offsetX;
bottom += _offsetY;
DrawRectCommand& command = _commandBuffers.rectangles.allocate();
// START FILTER
GLuint srcTexture = _engine->SwapCopyReturningSourceTexture();
command.flags = 0;
command.sourceFramebuffer = srcTexture;
uint16 g1Index = palette_to_g1_offset[palette];
rct_g1_element * g1Element = &g1Elements[g1Index];
uint8 * g1Bits = g1Element->offset;
for (size_t i = 0; i < 256; i++)
{
command.paletteRemap[i] = g1Bits[i];
}
// END FILTER
DrawRectCommand& command = _commandBuffers.transparent.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.bounds[0] = left;
command.bounds[1] = top;
command.bounds[2] = right + 1;
command.bounds[3] = bottom + 1;
*/
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 = TextureCache::PaletteToY(palette);
command.bounds = { left, top, right + 1, bottom + 1 };
command.flags = DrawRectCommand::FLAG_NO_TEXTURE;
command.depth = _drawCount++;
}
void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32 x2, sint32 y2)
@@ -627,11 +610,12 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
palettes.z = TextureCache::PaletteToY(tertiaryColour & 0xFF);
}
}
else if (image & IMAGE_TYPE_REMAP)
else if ((image & IMAGE_TYPE_REMAP) || (image & IMAGE_TYPE_TRANSPARENT))
{
paletteCount = 1;
palettes.x = TextureCache::PaletteToY((image >> 19) & 0xFF);
if (palettes.x == 32)
uint32 palette = (image >> 19) & 0xFF;
palettes.x = TextureCache::PaletteToY(palette);
if (palette == PALETTE_WATER)
{
special = true;
}
@@ -643,22 +627,34 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
if (special || (image & IMAGE_TYPE_TRANSPARENT))
{
// ignore transparecy TODO
return;
DrawRectCommand& command = _commandBuffers.transparent.allocate();
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.texColourAtlas = texture->index;
command.texColourBounds = texture->normalizedBounds;
command.texMaskAtlas = texture->index;
command.texMaskBounds = texture->normalizedBounds;
command.palettes = palettes;
command.colour = palettes.x - (special ? 1 : 0);
command.bounds = { left, top, right, bottom };
command.flags = special ? 0 : DrawRectCommand::FLAG_NO_TEXTURE | DrawRectCommand::FLAG_MASK;
command.depth = _drawCount++;
}
else
{
DrawRectCommand& command = _commandBuffers.rects.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, 0.0f };
command.palettes = palettes;
command.colour = 0;
command.bounds = { left, top, right, bottom };
command.flags = paletteCount;
command.depth = _drawCount++;
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, 0.0f };
command.palettes = palettes;
command.colour = 0;
command.bounds = { left, top, right, bottom };
command.flags = paletteCount;
command.depth = _drawCount++;
}
}
void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage)
@@ -814,31 +810,35 @@ void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * p
void OpenGLDrawingContext::FlushCommandBuffers()
{
glEnable(GL_DEPTH_TEST);
FlushLines();
FlushRectangles();
_swapFramebuffer->BindOpaque();
FlushLines(_commandBuffers.lines);
FlushRectangles(_commandBuffers.rects);
_swapFramebuffer->BindTransparent();
FlushRectangles(_commandBuffers.transparent);
_swapFramebuffer->ApplyTransparency(*_applyTransparencyShader, _textureCache->GetPaletteTexture());
}
void OpenGLDrawingContext::FlushLines()
void OpenGLDrawingContext::FlushLines(LineCommandBatch &batch)
{
if (_commandBuffers.lines.size() == 0) return;
if (batch.size() == 0) return;
_drawLineShader->Use();
_drawLineShader->DrawInstances(_commandBuffers.lines);
_drawLineShader->DrawInstances(batch);
_commandBuffers.lines.reset();
batch.clear();
}
void OpenGLDrawingContext::FlushRectangles()
void OpenGLDrawingContext::FlushRectangles(RectCommandBatch &batch)
{
if (_commandBuffers.rects.size() == 0) return;
if (batch.size() == 0) return;
OpenGLAPI::SetTexture(0, GL_TEXTURE_2D_ARRAY, _textureCache->GetAtlasesTexture());
OpenGLAPI::SetTexture(1, GL_TEXTURE_RECTANGLE, _textureCache->GetPaletteTexture());
_drawRectShader->Use();
_drawRectShader->DrawInstances(_commandBuffers.rects);
_drawRectShader->DrawInstances(batch);
_commandBuffers.rects.reset();
batch.clear();
}
void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi)

View File

@@ -31,7 +31,7 @@ OpenGLFramebuffer::OpenGLFramebuffer(SDL_Window * window)
SDL_GetWindowSize(window, &_width, &_height);
}
OpenGLFramebuffer::OpenGLFramebuffer(sint32 width, sint32 height)
OpenGLFramebuffer::OpenGLFramebuffer(sint32 width, sint32 height, bool depth)
{
_width = width;
_height = height;
@@ -42,12 +42,19 @@ OpenGLFramebuffer::OpenGLFramebuffer(sint32 width, sint32 height)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glGenTextures(1, &_depth);
glBindTexture(GL_TEXTURE_2D, _depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
if (depth)
{
glGenTextures(1, &_depth);
glBindTexture(GL_TEXTURE_2D, _depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
else
{
_depth = 0;
}
glGenFramebuffers(1, &_id);
glBindFramebuffer(GL_FRAMEBUFFER, _id);

View File

@@ -35,12 +35,13 @@ private:
public:
explicit OpenGLFramebuffer(SDL_Window * window);
OpenGLFramebuffer(sint32 width, sint32 height);
OpenGLFramebuffer(sint32 width, sint32 height, bool depth = true);
~OpenGLFramebuffer();
GLuint GetWidth() const { return _width; }
GLuint GetHeight() const { return _height; }
GLuint GetTexture() const { return _texture; }
GLuint GetDepthTexture() const { return _depth; }
void Bind() const;
void BindDraw() const;

View File

@@ -21,30 +21,49 @@
#include "SwapFramebuffer.h"
SwapFramebuffer::SwapFramebuffer(sint32 width, sint32 height) :
_width(width), _height(height),
_targetFramebuffer(width, height), _sourceFramebuffer(width, height)
_opaqueFramebuffer(width, height), _transparentFramebuffer(width, height),
_finalFramebuffer(width, height, false)
{ }
GLuint SwapFramebuffer::GetSourceTexture() const
void SwapFramebuffer::BindOpaque()
{
return _sourceFramebuffer.GetTexture();
_opaqueFramebuffer.Bind();
}
void SwapFramebuffer::SwapCopy()
void SwapFramebuffer::BindTransparent()
{
// no longer performs swap, TODO rename function
// blit target's texture to source's texture
_sourceFramebuffer.BindDraw();
_targetFramebuffer.BindRead();
glBlitFramebuffer(0, 0, _width, _height,
0, 0, _width, _height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
_targetFramebuffer.Bind();
_transparentFramebuffer.Bind();
}
void SwapFramebuffer::Bind()
void SwapFramebuffer::ApplyTransparency(ApplyTransparencyShader &shader, GLuint paletteTex)
{
_targetFramebuffer.Bind();
_finalFramebuffer.Bind();
glDisable(GL_DEPTH_TEST);
shader.Use();
shader.SetTextures(
_opaqueFramebuffer.GetTexture(),
_opaqueFramebuffer.GetDepthTexture(),
_transparentFramebuffer.GetTexture(),
_transparentFramebuffer.GetDepthTexture(),
paletteTex
);
shader.Draw();
//Change binding to guaruntee no undefined behavior
_opaqueFramebuffer.Bind();
}
void SwapFramebuffer::Clear()
{
static const GLfloat depthValue[1] = { 1.0f };
static const GLuint indexValue[4] = { 0, 0, 0, 0 };
_opaqueFramebuffer.Bind();
glClearBufferfv(GL_DEPTH, 0, depthValue);
_transparentFramebuffer.Bind();
glClearBufferuiv(GL_COLOR, 0, indexValue);
glClearBufferfv(GL_DEPTH, 0, depthValue);
}
#endif /* DISABLE_OPENGL */

View File

@@ -18,6 +18,7 @@
#include <openrct2/common.h>
#include "OpenGLAPI.h"
#include "ApplyTransparencyShader.h"
class CopyFramebufferShader;
class OpenGLFramebuffer;
@@ -33,33 +34,20 @@ class OpenGLFramebuffer;
class SwapFramebuffer final
{
private:
const sint32 _width;
const sint32 _height;
OpenGLFramebuffer _targetFramebuffer;
OpenGLFramebuffer _sourceFramebuffer;
OpenGLFramebuffer _opaqueFramebuffer;
OpenGLFramebuffer _transparentFramebuffer;
OpenGLFramebuffer _finalFramebuffer;
public:
SwapFramebuffer(sint32 width, sint32 height);
/**
* Gets the current target framebuffer.
*/
const OpenGLFramebuffer * GetTargetFramebuffer() const { return &_targetFramebuffer; }
const OpenGLFramebuffer &GetOpaqueFramebuffer() const { return _opaqueFramebuffer; }
const OpenGLFramebuffer &GetTransparentFramebuffer() const { return _transparentFramebuffer; }
const OpenGLFramebuffer &GetFinalFramebuffer() const { return _finalFramebuffer; }
GLuint GetFinalTexture() const { return _finalFramebuffer.GetTexture(); }
/**
* Gets the texture ID for the source framebuffer.
*/
GLuint GetSourceTexture() const;
/**
* Swaps the target framebuffer, binds it and then draws the previous
* framebuffer resulting in the two buffers matching and ready for
* pre-processing.
*/
void SwapCopy();
/**
* Binds the current target framebuffer.
*/
void Bind();
void BindOpaque();
void BindTransparent();
void ApplyTransparency(ApplyTransparencyShader &shader, GLuint paletteTex);
void Clear();
};