From 8a8a0501590e83cbc598c7491fca0b767094466f Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:22:22 +1000 Subject: 2 features: multi-sample anti-aliasing & Lua patches for images --- source/application/StarRenderer_opengl.hpp | 252 +++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 source/application/StarRenderer_opengl.hpp (limited to 'source/application/StarRenderer_opengl.hpp') diff --git a/source/application/StarRenderer_opengl.hpp b/source/application/StarRenderer_opengl.hpp new file mode 100644 index 0000000..563ac96 --- /dev/null +++ b/source/application/StarRenderer_opengl.hpp @@ -0,0 +1,252 @@ +#pragma once + +#include "StarTextureAtlas.hpp" +#include "StarRenderer.hpp" + +#include "GL/glew.h" + +namespace Star { + +STAR_CLASS(OpenGlRenderer); + +constexpr size_t FrameBufferCount = 1; + +// OpenGL 2.0 implementation of Renderer. OpenGL context must be created and +// active during construction, destruction, and all method calls. +class OpenGlRenderer : public Renderer { +public: + OpenGlRenderer(); + ~OpenGlRenderer(); + + String rendererId() const override; + Vec2U screenSize() const override; + + void loadConfig(Json const& config) override; + void loadEffectConfig(String const& name, Json const& effectConfig, StringMap const& shaders) override; + + void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) override; + void setEffectTexture(String const& textureName, ImageView const& image) override; + + void setScissorRect(Maybe const& scissorRect) override; + + bool switchEffectConfig(String const& name) override; + + TexturePtr createTexture(Image const& texture, TextureAddressing addressing, TextureFiltering filtering) override; + void setSizeLimitEnabled(bool enabled) override; + void setMultiTexturingEnabled(bool enabled) override; + void setMultiSampling(unsigned multiSampling) override; + TextureGroupPtr createTextureGroup(TextureGroupSize size, TextureFiltering filtering) override; + RenderBufferPtr createRenderBuffer() override; + + List& immediatePrimitives() override; + void render(RenderPrimitive primitive) override; + void renderBuffer(RenderBufferPtr const& renderBuffer, Mat3F const& transformation) override; + + void flush() override; + + void setScreenSize(Vec2U screenSize); + + void startFrame(); + void finishFrame(); + +private: + struct GlTextureAtlasSet : public TextureAtlasSet { + public: + GlTextureAtlasSet(unsigned atlasNumCells); + + GLuint createAtlasTexture(Vec2U const& size, PixelFormat pixelFormat) override; + void destroyAtlasTexture(GLuint const& glTexture) override; + void copyAtlasPixels(GLuint const& glTexture, Vec2U const& bottomLeft, Image const& image) override; + + TextureFiltering textureFiltering; + }; + + struct GlTextureGroup : enable_shared_from_this, public TextureGroup { + GlTextureGroup(unsigned atlasNumCells); + ~GlTextureGroup(); + + TextureFiltering filtering() const override; + TexturePtr create(Image const& texture) override; + + GlTextureAtlasSet textureAtlasSet; + }; + + struct GlTexture : public Texture { + virtual GLuint glTextureId() const = 0; + virtual Vec2U glTextureSize() const = 0; + virtual Vec2U glTextureCoordinateOffset() const = 0; + }; + + struct GlGroupedTexture : public GlTexture { + ~GlGroupedTexture(); + + Vec2U size() const override; + TextureFiltering filtering() const override; + TextureAddressing addressing() const override; + + GLuint glTextureId() const override; + Vec2U glTextureSize() const override; + Vec2U glTextureCoordinateOffset() const override; + + void incrementBufferUseCount(); + void decrementBufferUseCount(); + + unsigned bufferUseCount = 0; + shared_ptr parentGroup; + GlTextureAtlasSet::TextureHandle parentAtlasTexture = nullptr; + }; + + struct GlLoneTexture : public GlTexture { + ~GlLoneTexture(); + + Vec2U size() const override; + TextureFiltering filtering() const override; + TextureAddressing addressing() const override; + + GLuint glTextureId() const override; + Vec2U glTextureSize() const override; + Vec2U glTextureCoordinateOffset() const override; + + GLuint textureId = 0; + Vec2U textureSize; + TextureAddressing textureAddressing = TextureAddressing::Clamp; + TextureFiltering textureFiltering = TextureFiltering::Nearest; + }; + + struct GlPackedVertexData { + uint32_t textureIndex : 2; + uint32_t fullbright : 1; + uint32_t rX : 1; + uint32_t rY : 1; + uint32_t unused : 27; + }; + + struct GlRenderVertex { + Vec2F pos; + Vec2F uv; + Vec4B color; + union Packed { + uint32_t packed; + GlPackedVertexData vars; + } pack; + }; + + struct GlRenderBuffer : public RenderBuffer { + struct GlVertexBufferTexture { + GLuint texture; + Vec2U size; + }; + + struct GlVertexBuffer { + List textures; + GLuint vertexBuffer = 0; + size_t vertexCount = 0; + }; + + ~GlRenderBuffer(); + + void set(List& primitives) override; + + RefPtr whiteTexture; + ByteArray accumulationBuffer; + + HashSet usedTextures; + List vertexBuffers; + + bool useMultiTexturing{true}; + }; + + struct EffectParameter { + GLint parameterUniform = -1; + VariantTypeIndex parameterType = 0; + Maybe parameterValue; + }; + + struct EffectTexture { + GLint textureUniform = -1; + unsigned textureUnit = 0; + TextureAddressing textureAddressing = TextureAddressing::Clamp; + TextureFiltering textureFiltering = TextureFiltering::Linear; + GLint textureSizeUniform = -1; + RefPtr textureValue; + }; + + struct GlFrameBuffer : RefCounter { + GLuint id = 0; + RefPtr texture; + + Json config; + bool blitted = false; + unsigned multisample = 0; + + GlFrameBuffer(Json const& config); + ~GlFrameBuffer(); + }; + + class Effect { + public: + GLuint program = 0; + Json config; + StringMap parameters; + StringMap textures; + + StringMap attributes; + StringMap uniforms; + + GLuint getAttribute(String const& name); + GLuint getUniform(String const& name); + }; + + static bool logGlErrorSummary(String prefix); + static void uploadTextureImage(PixelFormat pixelFormat, Vec2U size, uint8_t const* data); + + + static RefPtr createGlTexture(ImageView const& image, TextureAddressing addressing, TextureFiltering filtering); + + shared_ptr createGlRenderBuffer(); + + void flushImmediatePrimitives(); + + void renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F const& transformation); + + void setupGlUniforms(Effect& effect); + + RefPtr getGlFrameBuffer(String const& id); + void blitGlFrameBuffer(RefPtr const& frameBuffer); + void switchGlFrameBuffer(RefPtr const& frameBuffer); + + Vec2U m_screenSize; + + GLuint m_program = 0; + + GLint m_positionAttribute = -1; + GLint m_colorAttribute = -1; + GLint m_texCoordAttribute = -1; + GLint m_dataAttribute = -1; + List m_textureUniforms = {}; + List m_textureSizeUniforms = {}; + GLint m_screenSizeUniform = -1; + GLint m_vertexTransformUniform = -1; + + Json m_config; + + StringMap m_effects; + Effect* m_currentEffect; + + StringMap> m_frameBuffers; + RefPtr m_currentFrameBuffer; + + RefPtr m_whiteTexture; + + Maybe m_scissorRect; + + bool m_limitTextureGroupSize; + bool m_useMultiTexturing; + unsigned m_multiSampling; // if non-zero, is enabled and acts as sample count + List> m_liveTextureGroups; + + List m_immediatePrimitives; + shared_ptr m_immediateRenderBuffer; +}; + +} -- cgit v1.2.3