diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-04-08 14:22:22 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-04-08 14:22:22 +1000 |
commit | 8a8a0501590e83cbc598c7491fca0b767094466f (patch) | |
tree | 4fd806e646179fa9a7e4027cc60e19492d003ade /source/application/StarRenderer_opengl.hpp | |
parent | 4458d2e85ed7f9e373af290dbe8063a52d2824b5 (diff) |
2 features: multi-sample anti-aliasing & Lua patches for images
Diffstat (limited to 'source/application/StarRenderer_opengl.hpp')
-rw-r--r-- | source/application/StarRenderer_opengl.hpp | 252 |
1 files changed, 252 insertions, 0 deletions
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<String> const& shaders) override; + + void setEffectParameter(String const& parameterName, RenderEffectParameter const& parameter) override; + void setEffectTexture(String const& textureName, ImageView const& image) override; + + void setScissorRect(Maybe<RectI> 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<RenderPrimitive>& 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<GLuint> { + 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<GlTextureGroup>, 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<GlTextureGroup> 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<GlVertexBufferTexture> textures; + GLuint vertexBuffer = 0; + size_t vertexCount = 0; + }; + + ~GlRenderBuffer(); + + void set(List<RenderPrimitive>& primitives) override; + + RefPtr<GlTexture> whiteTexture; + ByteArray accumulationBuffer; + + HashSet<TexturePtr> usedTextures; + List<GlVertexBuffer> vertexBuffers; + + bool useMultiTexturing{true}; + }; + + struct EffectParameter { + GLint parameterUniform = -1; + VariantTypeIndex parameterType = 0; + Maybe<RenderEffectParameter> parameterValue; + }; + + struct EffectTexture { + GLint textureUniform = -1; + unsigned textureUnit = 0; + TextureAddressing textureAddressing = TextureAddressing::Clamp; + TextureFiltering textureFiltering = TextureFiltering::Linear; + GLint textureSizeUniform = -1; + RefPtr<GlLoneTexture> textureValue; + }; + + struct GlFrameBuffer : RefCounter { + GLuint id = 0; + RefPtr<GlLoneTexture> texture; + + Json config; + bool blitted = false; + unsigned multisample = 0; + + GlFrameBuffer(Json const& config); + ~GlFrameBuffer(); + }; + + class Effect { + public: + GLuint program = 0; + Json config; + StringMap<EffectParameter> parameters; + StringMap<EffectTexture> textures; + + StringMap<GLuint> attributes; + StringMap<GLuint> 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<GlLoneTexture> createGlTexture(ImageView const& image, TextureAddressing addressing, TextureFiltering filtering); + + shared_ptr<GlRenderBuffer> createGlRenderBuffer(); + + void flushImmediatePrimitives(); + + void renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F const& transformation); + + void setupGlUniforms(Effect& effect); + + RefPtr<OpenGlRenderer::GlFrameBuffer> getGlFrameBuffer(String const& id); + void blitGlFrameBuffer(RefPtr<OpenGlRenderer::GlFrameBuffer> const& frameBuffer); + void switchGlFrameBuffer(RefPtr<OpenGlRenderer::GlFrameBuffer> 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<GLint> m_textureUniforms = {}; + List<GLint> m_textureSizeUniforms = {}; + GLint m_screenSizeUniform = -1; + GLint m_vertexTransformUniform = -1; + + Json m_config; + + StringMap<Effect> m_effects; + Effect* m_currentEffect; + + StringMap<RefPtr<GlFrameBuffer>> m_frameBuffers; + RefPtr<GlFrameBuffer> m_currentFrameBuffer; + + RefPtr<GlTexture> m_whiteTexture; + + Maybe<RectI> m_scissorRect; + + bool m_limitTextureGroupSize; + bool m_useMultiTexturing; + unsigned m_multiSampling; // if non-zero, is enabled and acts as sample count + List<shared_ptr<GlTextureGroup>> m_liveTextureGroups; + + List<RenderPrimitive> m_immediatePrimitives; + shared_ptr<GlRenderBuffer> m_immediateRenderBuffer; +}; + +} |