253 lines
7.1 KiB
C++
253 lines
7.1 KiB
C++
#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(Mat3F const& transformation) 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(Mat3F const& transformation = Mat3F::identity());
|
|
|
|
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;
|
|
};
|
|
|
|
}
|