493 lines
13 KiB
C++
493 lines
13 KiB
C++
//////////////////////////////////////////////////
|
|
//opengl2Dlib.h 1.2
|
|
//Copyright(c) 2020 Luta Vlad
|
|
//https://github.com/meemknight/gl2d
|
|
//
|
|
//
|
|
// dependences: glew, glm, stb_image, stb_trueType
|
|
//
|
|
//
|
|
// features:
|
|
//
|
|
// draw shapes with rotation color \
|
|
// texture transparency
|
|
// draw text with font and shadows
|
|
// camera
|
|
// shaders
|
|
// setVsync
|
|
// texture atlases and loading textures with \
|
|
// padding to fix visual bugs when using \
|
|
// pixel art sprite atlases
|
|
// draw to screen of frame buffer that can \
|
|
// be used as a texture
|
|
//
|
|
// a particle system that can use a custom \
|
|
// shader and apply a pixelate effect
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////
|
|
|
|
#pragma once
|
|
|
|
//enable simd functions
|
|
//set GL2D_SIMD to 0 if it doesn't work on your platform
|
|
#ifdef _WIN32
|
|
#define GL2D_SIMD 1
|
|
#else
|
|
#define GL2D_SIMD 0
|
|
#endif
|
|
|
|
|
|
|
|
#include <glad/glad.h>
|
|
#include <glm/glm.hpp>
|
|
#include <random>
|
|
#include <stb_image/stb_image.h>
|
|
#include <stb_truetype/stb_truetype.h>
|
|
|
|
namespace gl2d
|
|
{
|
|
|
|
//todo proper cmake, rename repo
|
|
|
|
void init();
|
|
|
|
void defaultErrorFunc(const char *msg);
|
|
|
|
using errorFuncType = decltype(defaultErrorFunc);
|
|
|
|
errorFuncType *setErrorFuncCallback(errorFuncType *newFunc);
|
|
|
|
struct Font;
|
|
|
|
//returns false on fail
|
|
bool setVsync(bool b);
|
|
|
|
namespace internal
|
|
{
|
|
struct ShaderProgram
|
|
{
|
|
GLuint id;
|
|
int u_sampler;
|
|
};
|
|
|
|
float positionToScreenCoordsX(const float position, float w);
|
|
float positionToScreenCoordsY(const float position, float h);
|
|
|
|
stbtt_aligned_quad fontGetGlyphQuad(const Font font, const char c);
|
|
glm::vec4 fontGetGlyphTextureCoords(const Font font, const char c);
|
|
|
|
}
|
|
|
|
///////////////////// COLOR ///////////////////
|
|
#pragma region Color
|
|
|
|
using Color4f = glm::vec4;
|
|
#define Colors_Red (gl2d::Color4f{ 1, 0, 0, 1 })
|
|
#define Colors_Green (gl2d::Color4f{ 0, 1, 0, 1 })
|
|
#define Colors_Blue (gl2d::Color4f{ 0, 0, 1, 1 })
|
|
#define Colors_Black (gl2d::Color4f{ 0, 0, 0, 1 })
|
|
#define Colors_White (gl2d::Color4f{ 1, 1, 1, 1 })
|
|
#define Colors_Yellow (gl2d::Color4f{ 1, 1, 0, 1 })
|
|
#define Colors_Magenta (gl2d::Color4f{ 1, 0, 1, 1 })
|
|
#define Colors_Turqoise (gl2d::Color4f{ 0, 1, 1, 1 })
|
|
#define Colors_Orange (gl2d::Color4f{ 1, (float)0x7F / 255.0f, 0, 1 })
|
|
#define Colors_Purple (gl2d::Color4f{ 101.0f / 255.0f, 29.0f / 255.0f, 173.0f / 255.0f, 1 })
|
|
#define Colors_Gray (gl2d::Color4f{ (float)0x7F / 255.0f, (float)0x7F / 255.0f, (float)0x7F / 255.0f, 1 })
|
|
|
|
#pragma endregion
|
|
|
|
///////////////////// MATH ////////////////////
|
|
#pragma region math
|
|
|
|
using Rect = glm::vec4;
|
|
glm::vec2 rotateAroundPoint(glm::vec2 vec, glm::vec2 point, const float degrees);
|
|
glm::vec2 scaleAroundPoint(glm::vec2 vec, glm::vec2 point, float scale);
|
|
|
|
#pragma endregion
|
|
|
|
///////////////////// Texture /////////////////////
|
|
#pragma region Texture
|
|
|
|
struct Texture
|
|
{
|
|
GLuint id = 0;
|
|
|
|
Texture() {};
|
|
Texture(const char *file) { loadFromFile(file); }
|
|
|
|
glm::ivec2 GetSize();
|
|
|
|
//Note: This function expects a buffer of bytes in GL_RGBA format
|
|
void createFromBuffer(const char *image_data, const int width, const int height);
|
|
void create1PxSquare(const char *b = 0);
|
|
void createFromFileData(const unsigned char *image_file_data, const size_t image_file_size);
|
|
void createFromFileDataWithPixelPadding(const unsigned char *image_file_data,
|
|
const size_t image_file_size, int blockSize);
|
|
|
|
void loadFromFile(const char *fileName);
|
|
void loadFromFileWithPixelPadding(const char *fileName, int blockSize);
|
|
|
|
void bind(const unsigned int sample = 0);
|
|
void unbind();
|
|
|
|
void cleanup();
|
|
};
|
|
|
|
struct TextureRegion
|
|
{
|
|
Texture texture;
|
|
glm::vec4 textureCoords;
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
///////////////////// Font /////////////////////
|
|
#pragma region Font
|
|
#define Default_Font_Characters_Range_Begin cast(char, ' ')
|
|
#define Default_Font_Characters_Range_End cast(char, '~')
|
|
#define Default_Font_Characters_Range_Size cast(isize, Default_Font_Characters_Range_End - Default_Font_Characters_Range_Begin)
|
|
|
|
typedef float Font_Size;
|
|
|
|
typedef struct Font Font;
|
|
struct Font
|
|
{
|
|
Texture texture;
|
|
glm::ivec2 size;
|
|
stbtt_packedchar *packedCharsBuffer;
|
|
int packedCharsBufferSize;
|
|
float max_height;
|
|
|
|
Font() {}
|
|
explicit Font(const char *file) { createFromFile(file); }
|
|
|
|
void createFromTTF(const unsigned char *ttf_data, const size_t ttf_data_size);
|
|
void createFromFile(const char *file);
|
|
};
|
|
|
|
#pragma endregion
|
|
|
|
///////////////////// Camera /////////////////////
|
|
#pragma region Camera
|
|
|
|
struct Camera;
|
|
Camera cameraCreateDefault();
|
|
|
|
struct Camera
|
|
{
|
|
glm::vec2 position;
|
|
//glm::vec2 offset; // Camera offset (displacement from target)
|
|
glm::vec2 target; // Camera target (rotation and zoom origin)
|
|
float rotation; // Camera rotation in degrees
|
|
float zoom; // Camera zoom (scaling), should be 1.0f by default
|
|
|
|
void setDefault() { *this = cameraCreateDefault(); }
|
|
glm::mat3 getMatrix();
|
|
|
|
void follow(glm::vec2 pos, float speed, float max, float w, float h);
|
|
|
|
glm::vec2 convertPoint(const glm::vec2 &p, float windowW, float windowH);
|
|
};
|
|
|
|
|
|
#pragma endregion
|
|
|
|
///////////////////// Renderer2d /////////////////////
|
|
#pragma region Renderer2d
|
|
|
|
typedef glm::vec2 Position2D;
|
|
typedef glm::vec4 Texture_Coords;
|
|
|
|
struct FrameBuffer
|
|
{
|
|
unsigned int fbo;
|
|
Texture texture;
|
|
|
|
void create(unsigned int w, unsigned int h);
|
|
void resize(unsigned int w, unsigned int h);
|
|
|
|
//clears resources
|
|
void cleanup();
|
|
|
|
//clears colors
|
|
void clear();
|
|
};
|
|
|
|
|
|
#define Renderer2D_Max_Buffer_Capacity 25000
|
|
#define DefaultTextureCoords (glm::vec4{ 0, 1, 1, 0 })
|
|
|
|
enum Renderer2DBufferType
|
|
{
|
|
quadPositions,
|
|
quadColors,
|
|
texturePositions,
|
|
|
|
bufferSize
|
|
};
|
|
|
|
typedef struct Renderer2D Renderer2D;
|
|
struct Renderer2D
|
|
{
|
|
Renderer2D() {};
|
|
|
|
void create();
|
|
|
|
GLuint buffers[Renderer2DBufferType::bufferSize];
|
|
GLuint vao;
|
|
|
|
//Note: Just for testing purposes
|
|
//4 elements each component
|
|
glm::vec2 spritePositions[Renderer2D_Max_Buffer_Capacity];
|
|
glm::vec4 spriteColors[Renderer2D_Max_Buffer_Capacity];
|
|
glm::vec2 texturePositions[Renderer2D_Max_Buffer_Capacity];
|
|
Texture spriteTextures[Renderer2D_Max_Buffer_Capacity];
|
|
|
|
int spritePositionsCount = 0;
|
|
int spriteColorsCount = 0;
|
|
int texturePositionsCount = 0;
|
|
int spriteTexturesCount = 0;
|
|
|
|
Texture white1pxSquareTexture;
|
|
|
|
internal::ShaderProgram currentShader;
|
|
Camera currentCamera;
|
|
|
|
//window metrics, should be up to date at all times
|
|
int windowW = 0;
|
|
int windowH = 0;
|
|
void updateWindowMetrics(int w, int h) { windowW = w; windowH = h; }
|
|
|
|
//converts pixels to screen (top left) (bottom right)
|
|
glm::vec4 toScreen(const glm::vec4 &transform);
|
|
|
|
inline void clearDrawData()
|
|
{
|
|
spritePositionsCount = 0;
|
|
spriteColorsCount = 0;
|
|
spriteTexturesCount = 0;
|
|
texturePositionsCount = 0;
|
|
}
|
|
|
|
glm::vec2 getTextSize(const char *text, const Font font, const float size = 1.5f,
|
|
const float spacing = 4, const float line_space = 3);
|
|
|
|
// The origin will be the bottom left corner since it represents the line for the text to be drawn
|
|
//Pacing and lineSpace are influenced by size
|
|
void renderText(glm::vec2 position, const char *text, const Font font, const Color4f color, const float size = 1.5f,
|
|
const float spacing = 4, const float line_space = 3, bool showInCenter = 1, const Color4f ShadowColor = { 0.1,0.1,0.1,1 }
|
|
, const Color4f LightColor = {});
|
|
|
|
//todo color overloads
|
|
void renderRectangle(const Rect transforms, const Color4f colors[4], const glm::vec2 origin, const float rotation, const Texture texture, const glm::vec4 textureCoords = DefaultTextureCoords);
|
|
inline void renderRectangle(const Rect transforms, const Color4f colors, const glm::vec2 origin, const float rotation, const Texture texture, const glm::vec4 textureCoords = DefaultTextureCoords)
|
|
{
|
|
Color4f c[4] = { colors,colors,colors,colors };
|
|
renderRectangle(transforms, c, origin, rotation, texture, textureCoords);
|
|
}
|
|
|
|
void renderRectangleAbsRotation(const Rect transforms, const Color4f colors[4], const glm::vec2 origin, const float rotation, const Texture texture, const glm::vec4 textureCoords = DefaultTextureCoords);
|
|
inline void renderRectangleAbsRotation(const Rect transforms, const Color4f colors, const glm::vec2 origin, const float rotation, const Texture texture, const glm::vec4 textureCoords = DefaultTextureCoords)
|
|
{
|
|
Color4f c[4] = { colors,colors,colors,colors };
|
|
renderRectangleAbsRotation(transforms, c, origin, rotation, texture, textureCoords);
|
|
}
|
|
|
|
void renderRectangle(const Rect transforms, const glm::vec2 origin, const float rotation, const Texture texture, const glm::vec4 textureCoords = DefaultTextureCoords);
|
|
void renderRectangleAbsRotation(const Rect transforms, const glm::vec2 origin, const float rotation, const Texture texture, const glm::vec4 textureCoords = DefaultTextureCoords);
|
|
|
|
void renderRectangle(const Rect transforms, const Color4f colors[4], const glm::vec2 origin = { 0,0 }, const float rotation = 0);
|
|
inline void renderRectangle(const Rect transforms, const Color4f colors, const glm::vec2 origin = { 0,0 }, const float rotation = 0)
|
|
{
|
|
Color4f c[4] = { colors,colors,colors,colors };
|
|
renderRectangle(transforms, c, origin, rotation);
|
|
}
|
|
|
|
void renderRectangleAbsRotation(const Rect transforms, const Color4f colors[4], const glm::vec2 origin = { 0,0 }, const float rotation = 0);
|
|
inline void renderRectangleAbsRotation(const Rect transforms, const Color4f colors, const glm::vec2 origin = { 0,0 }, const float rotation = 0)
|
|
{
|
|
Color4f c[4] = { colors,colors,colors,colors };
|
|
renderRectangleAbsRotation(transforms, c, origin, rotation);
|
|
}
|
|
|
|
void render9Patch(const Rect position, const int borderSize, const Color4f color, const glm::vec2 origin, const float rotation, const Texture texture, const Texture_Coords textureCoords, const Texture_Coords inner_texture_coords);
|
|
void render9Patch2(const Rect position, const int borderSize, const Color4f color, const glm::vec2 origin, const float rotation, const Texture texture, const Texture_Coords textureCoords, const Texture_Coords inner_texture_coords);
|
|
|
|
void clearScreen(const Color4f color = Colors_Black);
|
|
|
|
void setShaderProgram(const internal::ShaderProgram shader);
|
|
void setCamera(const Camera camera);
|
|
|
|
void resetCameraAndShader();
|
|
|
|
//draws to the screen
|
|
void flush();
|
|
void flushFBO(FrameBuffer frameBuffer);
|
|
};
|
|
|
|
//this should be called if the user changes the gl state by hand
|
|
void enableNecessaryGLFeatures();
|
|
|
|
#pragma endregion
|
|
|
|
///////////////////// TextureAtlas /////////////////////
|
|
#pragma region TextureAtlas
|
|
|
|
glm::vec4 computeTextureAtlas(int xCount, int yCount, int x, int y, bool flip = 0);
|
|
|
|
glm::vec4 computeTextureAtlasWithPadding(int mapXsize, int mapYsize, int xCount, int yCount, int x, int y, bool flip = 0);
|
|
|
|
struct TextureAtlas
|
|
{
|
|
TextureAtlas() {};
|
|
TextureAtlas(int x, int y):xCount(x), yCount(y) {};
|
|
|
|
int xCount;
|
|
int yCount;
|
|
|
|
glm::vec4 get(int x, int y, bool flip = 0)
|
|
{
|
|
return computeTextureAtlas(xCount, yCount, x, y, flip);
|
|
}
|
|
};
|
|
|
|
struct TextureAtlasPadding
|
|
{
|
|
TextureAtlasPadding() {};
|
|
//count count size size
|
|
TextureAtlasPadding(int x, int y, int xSize, int ySize):xCount(x), yCount(y)
|
|
, xSize(xSize), ySize(ySize)
|
|
{
|
|
};
|
|
|
|
int xCount;
|
|
int yCount;
|
|
int xSize;
|
|
int ySize;
|
|
|
|
glm::vec4 get(int x, int y, bool flip = 0)
|
|
{
|
|
return computeTextureAtlasWithPadding(xSize, ySize, xCount, yCount, x, y, flip);
|
|
}
|
|
};
|
|
// Get default internal texture (white texture)
|
|
#pragma endregion
|
|
|
|
///////////////////// ParticleSysyem /////////////////////
|
|
#pragma region ParticleSysyem
|
|
|
|
struct ParticleApearence
|
|
{
|
|
glm::vec2 size;
|
|
glm::vec4 color1;
|
|
glm::vec4 color2;
|
|
};
|
|
|
|
enum TRANZITION_TYPES
|
|
{
|
|
none = 0,
|
|
linear,
|
|
curbe,
|
|
abruptCurbe,
|
|
wave,
|
|
wave2,
|
|
delay,
|
|
delay2
|
|
};
|
|
|
|
|
|
struct ParticleSettings
|
|
{
|
|
ParticleSettings *deathRattle = nullptr;
|
|
ParticleSettings *subemitParticle = nullptr;
|
|
|
|
int onCreateCount = 0;
|
|
|
|
glm::vec2 subemitParticleTime = {};
|
|
|
|
glm::vec2 positionX = {};
|
|
glm::vec2 positionY = {};
|
|
|
|
glm::vec2 particleLifeTime = {}; // move
|
|
glm::vec2 directionX = {};
|
|
glm::vec2 directionY = {};
|
|
glm::vec2 dragX = {};
|
|
glm::vec2 dragY = {};
|
|
|
|
glm::vec2 rotation = {};
|
|
glm::vec2 rotationSpeed = {};
|
|
glm::vec2 rotationDrag = {};
|
|
|
|
ParticleApearence createApearence = {};
|
|
ParticleApearence createEndApearence = {};
|
|
|
|
gl2d::Texture *texturePtr = 0;
|
|
|
|
int tranzitionType = TRANZITION_TYPES::linear;
|
|
};
|
|
|
|
|
|
struct ParticleSystem
|
|
{
|
|
void initParticleSystem(int size);
|
|
void cleanup();
|
|
|
|
void emitParticleWave(ParticleSettings *ps, glm::vec2 pos);
|
|
|
|
|
|
void applyMovement(float deltaTime);
|
|
|
|
void draw(Renderer2D &r);
|
|
|
|
bool postProcessing = true;
|
|
float pixelateFactor = 2;
|
|
|
|
private:
|
|
|
|
int size = 0;
|
|
|
|
float *posX = 0;
|
|
float *posY = 0;
|
|
|
|
float *directionX = 0;
|
|
float *directionY = 0;
|
|
|
|
float *rotation = 0;
|
|
|
|
float *sizeXY = 0;
|
|
|
|
float *dragX = 0;
|
|
float *dragY = 0;
|
|
|
|
float *duration = 0;
|
|
float *durationTotal = 0;
|
|
|
|
glm::vec4 *color = 0;
|
|
|
|
float *rotationSpeed = 0;
|
|
float *rotationDrag = 0;
|
|
|
|
float *emitTime = 0;
|
|
|
|
char *tranzitionType = 0;
|
|
ParticleSettings **deathRattle = 0;
|
|
ParticleSettings **thisParticleSettings = 0;
|
|
ParticleSettings **emitParticle = 0;
|
|
|
|
gl2d::Texture **textures = 0;
|
|
|
|
std::mt19937 random{ std::random_device{}() };
|
|
|
|
gl2d::FrameBuffer fb;
|
|
|
|
float rand(glm::vec2 v);
|
|
};
|
|
|
|
|
|
#pragma endregion
|
|
|
|
|
|
|
|
|
|
}; |