osb/source/application/StarRenderer_opengl20.hpp
2023-07-01 03:58:02 +10:00

214 lines
6.0 KiB
C++

#ifndef STAR_RENDERER_OPENGL_HPP
#define STAR_RENDERER_OPENGL_HPP
#include "StarTextureAtlas.hpp"
#include "StarRenderer.hpp"
#include "GL/glew.h"
namespace Star {
STAR_CLASS(OpenGl20Renderer);
// OpenGL 2.0 implementation of Renderer. OpenGL context must be created and
// active during construction, destruction, and all method calls.
class OpenGl20Renderer : public Renderer {
public:
OpenGl20Renderer();
~OpenGl20Renderer();
String rendererId() const override;
Vec2U screenSize() const 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, Image 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;
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 GlRenderVertex {
Vec2F screenCoordinate;
Vec2F textureCoordinate;
float textureIndex;
Vec4B color;
float param1;
};
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;
};
struct EffectParameter {
GLint parameterUniform = -1;
VariantTypeIndex parameterType;
Maybe<RenderEffectParameter> parameterValue;
};
struct EffectTexture {
GLint textureUniform = -1;
unsigned textureUnit;
TextureAddressing textureAddressing = TextureAddressing::Clamp;
TextureFiltering textureFiltering = TextureFiltering::Linear;
GLint textureSizeUniform = -1;
RefPtr<GlLoneTexture> textureValue;
};
struct Effect {
GLuint program;
Json config;
StringMap<EffectParameter> parameters;
StringMap<EffectTexture> textures;
};
static bool logGlErrorSummary(String prefix);
static void uploadTextureImage(PixelFormat pixelFormat, Vec2U size, uint8_t const* data);
static RefPtr<GlLoneTexture> createGlTexture(Image const& texture, TextureAddressing addressing, TextureFiltering filtering);
shared_ptr<GlRenderBuffer> createGlRenderBuffer();
void flushImmediatePrimitives();
void renderGlBuffer(GlRenderBuffer const& renderBuffer, Mat3F const& transformation);
void setupGlUniforms(GLuint program);
Vec2U m_screenSize;
GLuint m_program = 0;
GLint m_positionAttribute = -1;
GLint m_texCoordAttribute = -1;
GLint m_texIndexAttribute = -1;
GLint m_colorAttribute = -1;
GLint m_param1Attribute = -1;
List<GLint> m_textureUniforms = {};
List<GLint> m_textureSizeUniforms = {};
GLint m_screenSizeUniform = -1;
GLint m_vertexTransformUniform = -1;
StringMap<Effect> m_effects;
Effect* m_currentEffect;
RefPtr<GlTexture> m_whiteTexture;
Maybe<RectI> m_scissorRect;
bool m_limitTextureGroupSize;
bool m_useMultiTexturing;
List<shared_ptr<GlTextureGroup>> m_liveTextureGroups;
List<RenderPrimitive> m_immediatePrimitives;
shared_ptr<GlRenderBuffer> m_immediateRenderBuffer;
};
}
#endif