OpenGL: Add Depth Buffer and Depth Test

This commit is contained in:
LRFLEW 2017-10-19 18:49:26 -05:00 committed by Michał Janiszewski
parent 6bf2e0157b
commit 3d2d99817c
15 changed files with 146 additions and 108 deletions

View File

@ -1,12 +1,10 @@
#version 150
uniform uint uColour;
in vec2 fPosition;
flat in uint fColour;
out uint oColour;
void main()
{
oColour = uColour;
oColour = fColour;
}

View File

@ -1,22 +1,30 @@
#version 150
// Allows for about 8 million draws per frame
const float DEPTH_INCREMENT = 1.0 / float(1u << 22u);
uniform ivec2 uScreenSize;
uniform ivec4 uBounds;
uniform ivec4 uClip;
in ivec4 vBounds;
in ivec4 vClip;
in uint vColour;
in int vDepth;
in mat4x2 vVertMat;
out vec2 fPosition;
flat out uint fColour;
void main()
{
vec2 pos = clamp(vVertMat * uBounds, uClip.xy, uClip.zw);
fPosition = pos;
vec2 pos = clamp(vVertMat * vBounds, vClip.xy, vClip.zw);
// 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;
float depth = 1.0 - vDepth * DEPTH_INCREMENT;
gl_Position = vec4(pos, 0.0, 1.0);
fColour = vColour;
gl_Position = vec4(pos, depth, 1.0);
}

View File

@ -1,5 +1,8 @@
#version 150
// Allows for about 8 million draws per frame
const float DEPTH_INCREMENT = 1.0 / float(1u << 22u);
uniform ivec2 uScreenSize;
in ivec4 vClip;
@ -11,6 +14,7 @@ in ivec3 vPalettes;
in int vFlags;
in uint vColour;
in ivec4 vBounds;
in int vDepth;
in mat4x2 vVertMat;
in vec2 vVertVec;
@ -36,10 +40,11 @@ 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;
fFlags = vFlags;
fColour = vColour;
fPalettes = vec3(vPalettes);
gl_Position = vec4(pos, 0.0, 1.0);
gl_Position = vec4(pos, depth, 1.0);
}

View File

@ -73,7 +73,8 @@ void CopyFramebufferShader::SetTexture(GLuint texture)
OpenGLAPI::SetTexture(0, GL_TEXTURE_2D, texture);
}
void CopyFramebufferShader::SetPalette(const vec4f * glPalette) {
void CopyFramebufferShader::SetPalette(const vec4 * glPalette)
{
glUniform4fv(uPalette, 256, (const GLfloat *)glPalette);
}

View File

@ -36,7 +36,7 @@ public:
~CopyFramebufferShader() override;
void SetTexture(GLuint texture);
void SetPalette(const vec4f * glPalette);
void SetPalette(const vec4 * glPalette);
void Draw();

View File

@ -66,23 +66,25 @@ public:
struct DrawLineCommand
{
uint8 colour;
vec4i clip;
sint32 pos[4];
ivec4 clip;
ivec4 bounds;
GLuint colour;
GLint depth;
};
// Per-instance data for images
struct DrawRectCommand
{
vec4i clip;
sint32 texColourAtlas;
vec4f texColourBounds;
sint32 texMaskAtlas;
vec4f texMaskBounds;
vec3i palettes;
sint32 flags;
uint32 colour;
vec4i bounds;
ivec4 clip;
GLint texColourAtlas;
vec4 texColourBounds;
GLint texMaskAtlas;
vec4 texMaskBounds;
ivec3 palettes;
GLint flags;
GLuint colour;
ivec4 bounds;
GLint depth;
enum
{

View File

@ -35,6 +35,7 @@ DrawLineShader::DrawLineShader() : OpenGLShaderProgram("drawline")
GetLocations();
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_vboInstances);
glGenVertexArrays(1, &_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
@ -46,11 +47,27 @@ DrawLineShader::DrawLineShader() : OpenGLShaderProgram("drawline")
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]));
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glVertexAttribIPointer(vClip, 4, GL_INT, sizeof(DrawLineCommand), (void*) offsetof(DrawLineCommand, clip));
glVertexAttribIPointer(vBounds, 4, GL_INT, sizeof(DrawLineCommand), (void*) offsetof(DrawLineCommand, bounds));
glVertexAttribIPointer(vColour, 1, GL_UNSIGNED_INT, sizeof(DrawLineCommand), (void*) offsetof(DrawLineCommand, colour));
glVertexAttribIPointer(vDepth, 1, GL_INT, sizeof(DrawLineCommand), (void*) offsetof(DrawLineCommand, depth));
glEnableVertexAttribArray(vVertMat+0);
glEnableVertexAttribArray(vVertMat+1);
glEnableVertexAttribArray(vVertMat+2);
glEnableVertexAttribArray(vVertMat+3);
glEnableVertexAttribArray(vClip);
glEnableVertexAttribArray(vBounds);
glEnableVertexAttribArray(vColour);
glEnableVertexAttribArray(vDepth);
glVertexAttribDivisor(vClip, 1);
glVertexAttribDivisor(vBounds, 1);
glVertexAttribDivisor(vColour, 1);
glVertexAttribDivisor(vDepth, 1);
Use();
}
@ -63,9 +80,11 @@ DrawLineShader::~DrawLineShader()
void DrawLineShader::GetLocations()
{
uScreenSize = GetUniformLocation("uScreenSize");
uClip = GetUniformLocation("uClip");
uBounds = GetUniformLocation("uBounds");
uColour = GetUniformLocation("uColour");
vClip = GetAttributeLocation("vClip");
vBounds = GetAttributeLocation("vBounds");
vColour = GetAttributeLocation("vColour");
vDepth = GetAttributeLocation("vDepth");
vVertMat = GetAttributeLocation("vVertMat");
}
@ -75,27 +94,14 @@ void DrawLineShader::SetScreenSize(sint32 width, sint32 height)
glUniform2i(uScreenSize, width, height);
}
void DrawLineShader::SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom)
void DrawLineShader::DrawInstances(const LineCommandBatch& instances)
{
glUniform4i(uClip, left, top, right, bottom);
}
void DrawLineShader::SetBounds(sint32 x0, sint32 y0, sint32 x1, sint32 y1)
{
glUniform4i(uBounds, x0, y0, x1, y1);
}
void DrawLineShader::SetColour(uint8 colour)
{
glUniform1ui(uColour, colour);
}
void DrawLineShader::Draw(sint32 x0, sint32 y0, sint32 x1, sint32 y1)
{
SetBounds(x0, y0, x1, y1);
glBindVertexArray(_vao);
glDrawArrays(GL_LINES, 0, 2);
glBindBuffer(GL_ARRAY_BUFFER, _vboInstances);
glBufferData(GL_ARRAY_BUFFER, sizeof(DrawLineCommand) * instances.size(), instances.data(), GL_STREAM_DRAW);
glDrawArraysInstanced(GL_LINES, 0, 2, (GLsizei)instances.size());
}
#endif /* DISABLE_OPENGL */

View File

@ -18,18 +18,22 @@
#include "GLSLTypes.h"
#include "OpenGLShaderProgram.h"
#include "DrawCommands.h"
class DrawLineShader final : public OpenGLShaderProgram
{
private:
GLuint uScreenSize;
GLuint uClip;
GLuint uBounds;
GLuint uColour;
GLuint vClip;
GLuint vBounds;
GLuint vColour;
GLuint vDepth;
GLuint vVertMat;
GLuint _vbo;
GLuint _vboInstances;
GLuint _vao;
public:
@ -37,11 +41,7 @@ public:
~DrawLineShader() override;
void SetScreenSize(sint32 width, sint32 height);
void SetClip(sint32 left, sint32 top, sint32 right, sint32 bottom);
void SetBounds(sint32 x0, sint32 y0, sint32 x1, sint32 y1);
void SetColour(uint8 colour);
void Draw(sint32 x0, sint32 y0, sint32 x1, sint32 y1);
void DrawInstances(const LineCommandBatch& instances);
private:
void GetLocations();

View File

@ -61,6 +61,7 @@ DrawRectShader::DrawRectShader() : OpenGLShaderProgram("drawrect")
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));
glVertexAttribIPointer(vDepth, 1, GL_INT, sizeof(DrawRectCommand), (void*) offsetof(DrawRectCommand, depth));
glEnableVertexAttribArray(vVertMat+0);
glEnableVertexAttribArray(vVertMat+1);
@ -77,6 +78,7 @@ DrawRectShader::DrawRectShader() : OpenGLShaderProgram("drawrect")
glEnableVertexAttribArray(vFlags);
glEnableVertexAttribArray(vColour);
glEnableVertexAttribArray(vBounds);
glEnableVertexAttribArray(vDepth);
glVertexAttribDivisor(vClip, 1);
glVertexAttribDivisor(vTexColourAtlas, 1);
@ -87,6 +89,7 @@ DrawRectShader::DrawRectShader() : OpenGLShaderProgram("drawrect")
glVertexAttribDivisor(vFlags, 1);
glVertexAttribDivisor(vColour, 1);
glVertexAttribDivisor(vBounds, 1);
glVertexAttribDivisor(vDepth, 1);
Use();
glUniform1i(uTexture, 0);
@ -115,6 +118,7 @@ void DrawRectShader::GetLocations()
vFlags = GetAttributeLocation("vFlags");
vColour = GetAttributeLocation("vColour");
vBounds = GetAttributeLocation("vBounds");
vDepth = GetAttributeLocation("vDepth");
vVertMat = GetAttributeLocation("vVertMat");
vVertVec = GetAttributeLocation("vVertVec");

View File

@ -41,6 +41,7 @@ private:
GLuint vFlags;
GLuint vColour;
GLuint vBounds;
GLuint vDepth;
GLuint _vbo;
GLuint _vboInstances;

View File

@ -17,49 +17,50 @@
#pragma once
#include <openrct2/common.h>
#include "OpenGLAPI.h"
#pragma pack(push, 1)
struct vec2i
struct ivec2
{
union { sint32 x; sint32 s; sint32 r; };
union { sint32 y; sint32 t; sint32 g; };
union { GLint x; GLint s; GLint r; };
union { GLint y; GLint t; GLint g; };
};
struct vec2f
struct vec2
{
union { float x; float s; float r; };
union { float y; float t; float g; };
union { GLfloat x; GLfloat s; GLfloat r; };
union { GLfloat y; GLfloat t; GLfloat g; };
};
struct vec3i
struct ivec3
{
union { sint32 x; sint32 s; sint32 r; };
union { sint32 y; sint32 t; sint32 g; };
union { sint32 z; sint32 p; sint32 b; };
union { GLint x; GLint s; GLint r; };
union { GLint y; GLint t; GLint g; };
union { GLint z; GLint p; GLint b; };
};
struct vec3f
{
union { float x; float s; float r; };
union { float y; float t; float g; };
union { float z; float p; float b; };
union { GLfloat x; GLfloat s; GLfloat r; };
union { GLfloat y; GLfloat t; GLfloat g; };
union { GLfloat z; GLfloat p; GLfloat b; };
};
struct vec4i
struct ivec4
{
union { sint32 x; sint32 s; sint32 r; };
union { sint32 y; sint32 t; sint32 g; };
union { sint32 z; sint32 p; sint32 b; };
union { sint32 w; sint32 q; sint32 a; };
union { GLint x; GLint s; GLint r; };
union { GLint y; GLint t; GLint g; };
union { GLint z; GLint p; GLint b; };
union { GLint w; GLint q; GLint a; };
};
struct vec4f
struct vec4
{
union { float x; float s; float r; };
union { float y; float t; float g; };
union { float z; float p; float b; };
union { float w; float q; float a; };
union { GLfloat x; GLfloat s; GLfloat r; };
union { GLfloat y; GLfloat t; GLfloat g; };
union { GLfloat z; GLfloat p; GLfloat b; };
union { GLfloat w; GLfloat q; GLfloat a; };
};
#pragma pack(pop)

View File

@ -79,7 +79,10 @@ private:
sint32 _clipRight = 0;
sint32 _clipBottom = 0;
struct {
sint32 _drawCount = 0;
struct
{
LineCommandBatch lines;
RectCommandBatch rects;
} _commandBuffers;
@ -94,6 +97,7 @@ public:
void Initialise();
void Resize(sint32 width, sint32 height);
void ResetPalette();
void ResetDrawCount() { _drawCount = 0; }
void Clear(uint8 paletteIndex) override;
void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override;
@ -135,7 +139,7 @@ private:
public:
SDL_Color Palette[256];
vec4f GLPalette[256];
vec4 GLPalette[256];
OpenGLDrawingEngine(IUiContext * uiContext)
: _uiContext(uiContext)
@ -228,7 +232,9 @@ public:
assert(_screenFramebuffer != nullptr);
assert(_swapFramebuffer != nullptr);
_drawingContext->ResetDrawCount();
_swapFramebuffer->Bind();
glClear(GL_DEPTH_BUFFER_BIT);
}
void EndDraw() override
@ -236,6 +242,7 @@ public:
_drawingContext->FlushCommandBuffers();
// Scale up to window
glDisable(GL_DEPTH_TEST);
_screenFramebuffer->Bind();
_copyFramebufferShader->Use();
_copyFramebufferShader->SetTexture(_swapFramebuffer->GetTargetFramebuffer()->GetTexture());
@ -453,8 +460,9 @@ void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint
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.bounds = { left, top, right + 1, bottom + 1 };
command.flags = DrawRectCommand::FLAG_NO_TEXTURE;
command.depth = _drawCount++;
if (colour & 0x1000000)
{
@ -519,17 +527,10 @@ void OpenGLDrawingContext::DrawLine(uint32 colour, sint32 x1, sint32 y1, sint32
DrawLineCommand& command = _commandBuffers.lines.allocate();
command.colour = colour & 0xFF;
command.clip = { _clipLeft, _clipTop, _clipRight, _clipBottom };
command.pos[0] = x1;
command.pos[1] = y1;
command.pos[2] = x2;
command.pos[3] = y2;
// Must be rendered in order right now, because it does not yet use depth
FlushCommandBuffers();
command.bounds = { x1, y1, x2, y2 };
command.colour = colour & 0xFF;
command.depth = _drawCount++;
}
void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour)
@ -610,7 +611,7 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
auto texture = _textureCache->GetOrLoadImageTexture(image);
int paletteCount;
vec3i palettes{};
ivec3 palettes{};
bool special = false;
if (image & IMAGE_TYPE_REMAP_2_PLUS)
{
@ -657,6 +658,7 @@ void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 t
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)
@ -714,6 +716,7 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskIm
command.flags = DrawRectCommand::FLAG_MASK;
command.colour = 0;
command.bounds = { left, top, right, bottom };
command.depth = _drawCount++;
}
void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uint8 colour)
@ -760,6 +763,7 @@ void OpenGLDrawingContext::DrawSpriteSolid(uint32 image, sint32 x, sint32 y, uin
command.flags = DrawRectCommand::FLAG_NO_TEXTURE | DrawRectCommand::FLAG_MASK;
command.colour = colour & 0xFF;
command.bounds = { left, top, right, bottom };
command.depth = _drawCount++;
}
void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * palette)
@ -804,25 +808,22 @@ void OpenGLDrawingContext::DrawGlyph(uint32 image, sint32 x, sint32 y, uint8 * p
command.flags = 0;
command.colour = 0;
command.bounds = { left, top, right, bottom };
command.depth = _drawCount++;
}
void OpenGLDrawingContext::FlushCommandBuffers()
{
glEnable(GL_DEPTH_TEST);
FlushLines();
FlushRectangles();
}
void OpenGLDrawingContext::FlushLines()
{
for (size_t n = 0; n < _commandBuffers.lines.size(); n++)
{
const auto& command = _commandBuffers.lines[n];
if (_commandBuffers.lines.size() == 0) return;
_drawLineShader->Use();
_drawLineShader->SetColour(command.colour);
_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]);
}
_drawLineShader->Use();
_drawLineShader->DrawInstances(_commandBuffers.lines);
_commandBuffers.lines.reset();
}

View File

@ -27,6 +27,7 @@ OpenGLFramebuffer::OpenGLFramebuffer(SDL_Window * window)
{
_id = BACKBUFFER_ID;
_texture = 0;
_depth = 0;
SDL_GetWindowSize(window, &_width, &_height);
}
@ -41,9 +42,17 @@ 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);
glGenFramebuffers(1, &_id);
glBindFramebuffer(GL_FRAMEBUFFER, _id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depth, 0);
}
OpenGLFramebuffer::~OpenGLFramebuffer()
@ -51,6 +60,7 @@ OpenGLFramebuffer::~OpenGLFramebuffer()
if (_id != BACKBUFFER_ID)
{
glDeleteTextures(1, &_texture);
glDeleteTextures(1, &_depth);
glDeleteFramebuffers(1, &_id);
}
}

View File

@ -29,6 +29,7 @@ class OpenGLFramebuffer
private:
GLuint _id;
GLuint _texture;
GLuint _depth;
sint32 _width;
sint32 _height;

View File

@ -65,9 +65,9 @@ struct CachedTextureInfo
{
GLuint index;
GLuint slot;
vec4i bounds;
vec4f normalizedBounds;
vec4f computedBounds;
ivec4 bounds;
vec4 normalizedBounds;
vec4 computedBounds;
};
// Represents a texture atlas that images of a given maximum size can be allocated from
@ -159,12 +159,12 @@ public:
}
private:
vec4i GetSlotCoordinates(GLuint slot, sint32 actualWidth, sint32 actualHeight) const
ivec4 GetSlotCoordinates(GLuint slot, sint32 actualWidth, sint32 actualHeight) const
{
sint32 row = slot / _cols;
sint32 col = slot % _cols;
return vec4i
return ivec4
{
_imageSize * col,
_imageSize * row,
@ -173,14 +173,14 @@ private:
};
}
vec4f NormalizeCoordinates(const vec4i& coords) const
vec4 NormalizeCoordinates(const ivec4& coords) const
{
return vec4f
return vec4
{
coords.x / (float) _atlasWidth,
coords.y / (float) _atlasHeight,
coords.z / (float) _atlasWidth,
coords.w / (float) _atlasHeight
coords.w / (float) _atlasHeight,
};
}
};