Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/application/StarRenderer_opengl.hpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-04-08 14:22:22 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2024-04-08 14:22:22 +1000
commit8a8a0501590e83cbc598c7491fca0b767094466f (patch)
tree4fd806e646179fa9a7e4027cc60e19492d003ade /source/application/StarRenderer_opengl.hpp
parent4458d2e85ed7f9e373af290dbe8063a52d2824b5 (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.hpp252
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;
+};
+
+}