Skip to content

Commit

Permalink
Adds sprite atlasing offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerboa-app committed Jul 30, 2024
1 parent 7bd3c6f commit e78b77b
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 190 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ tests/regression/user-macos/build
tests/regression/user-macos/include/*
include/vendored/VulkanSDK/Windows/Include
include/vendored/VulkanSDK/Windows/Include
include/vendored/VulkanSDK/Windows/lib
include/vendored/VulkanSDK/Windows/lib
docs/html
101 changes: 75 additions & 26 deletions examples/Sprite/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ int main(int argv, char ** argc)
jGLInstance->setTextProjection(glm::ortho(0.0,double(resX),0.0,double(resY)));
jGLInstance->setMSAA(1);

std::shared_ptr<jGL::Texture> jerboa = jGLInstance->createTexture
std::shared_ptr<jGL::Texture> atlas = jGLInstance->createTexture
(
std::vector<unsigned char>(LOGO32,LOGO32+sizeof(LOGO32)),
"resource/texture/atlas.png",
jGL::Texture::Type::RGBA
);

std::shared_ptr<jGL::Texture> heart = jGLInstance->createTexture
std::shared_ptr<jGL::Texture> jerboa = jGLInstance->createTexture
(
"resource/texture/HEART.png",
std::vector<unsigned char>(LOGO32,LOGO32+sizeof(LOGO32)),
jGL::Texture::Type::RGBA
);

std::shared_ptr<jGL::Texture> dice = jGLInstance->createTexture
std::shared_ptr<jGL::Texture> heart = jGLInstance->createTexture
(
"resource/texture/random.png",
"resource/texture/HEART.png",
jGL::Texture::Type::RGBA
);

Expand All @@ -57,12 +57,21 @@ int main(int argv, char ** argc)
2
);

float scale32Pixels = camera.screenToWorld(32.0f, 0.0f).x;
float ax = 0.25f;
float ay = 0.75f;
float as = scale32Pixels;

std::map<std::string, jGL::Transform> trans =
{
{"jerboa", jGL::Transform(0.1f, 0.9f, 0.0f, 0.1f)},
{"sAtlas1", jGL::Transform(ax, ay, 0.0f, scale32Pixels*0.5f)},
{"sAtlas2", jGL::Transform(ax+as, ay, 0.0f, scale32Pixels*0.5f)},
{"sAtlas3", jGL::Transform(ax, ay+as, 0.0f, scale32Pixels*0.5f)},
{"sAtlas4", jGL::Transform(ax+as, ay+as, 0.0f, scale32Pixels*0.5f)},
{"sAtlasFull", jGL::Transform(ax, ay+as+scale32Pixels, 0.0f, scale32Pixels)},
{"sJerboa", jGL::Transform(0.1f, 0.9f, 0.0f, 0.1f)},
{"sPi", jGL::Transform(0.1f, 0.1f, 0.0f, 0.1f)},
{"sHeart", jGL::Transform(0.5f, 0.5f, 0.0f, 0.1f)},
{"sDice", jGL::Transform(0.6f, 0.2f, 0.5f, 0.15f)},
{"lowest", jGL::Transform(0.5f, 0.1f, 0.0f, 0.1f)},
{"middle", jGL::Transform(0.55f, 0.15f, 0.0f, 0.1f)},
{"highest", jGL::Transform(0.6f, 0.2f, 0.0f, 0.1f)}
Expand All @@ -73,8 +82,8 @@ int main(int argv, char ** argc)
sprites->add
(
{
trans["jerboa"],
jGL::TextureOffset(0.0f, 0.0f),
trans["sJerboa"],
jGL::TextureOffset(),
jerboa
},
"sJerboa"
Expand All @@ -83,38 +92,78 @@ int main(int argv, char ** argc)
sprites->add
(
{
trans["sPi"],
jGL::TextureOffset(0.0f, 0.0f),
Pi
trans["sAtlas1"],
jGL::TextureOffset(0.0, 0.0, 16.0, 16.0),
atlas
},
"sPi"
"sAtlas1"
);

sprites->add
(
{
trans["sHeart"],
jGL::TextureOffset(0.0f, 0.0f),
heart
trans["sAtlas2"],
jGL::TextureOffset(16.0, 0.0, 16.0, 16.0),
atlas
},
"sHeart"
"sAtlas2"
);

sprites->add
(
{
trans["sAtlas3"],
jGL::TextureOffset(0.0, 16.0, 16.0, 16.0),
atlas
},
"sAtlas3"
);

sprites->add
(
{
trans["sAtlas4"],
jGL::TextureOffset(16.0, 16.0, 16.0, 16.0),
atlas
},
"sAtlas4"
);

sprites->add
(
{
trans["sDice"],
jGL::TextureOffset(0.0f, 0.0f),
dice
trans["sAtlasFull"],
jGL::TextureOffset(),
atlas
},
"sDice"
"sAtlasFull"
);

sprites->add
(
{
trans["sPi"],
jGL::TextureOffset(),
Pi
},
"sPi"
);

sprites->add
(
{
trans["sHeart"],
jGL::TextureOffset(),
heart
},
"sHeart"
);

sprites->add
(
{
trans["lowest"],
jGL::TextureOffset(0.0f, 0.0f),
jGL::TextureOffset(),
Pi
},
"lowest"
Expand All @@ -124,7 +173,7 @@ int main(int argv, char ** argc)
(
{
trans["middle"],
jGL::TextureOffset(0.0f, 0.0f),
jGL::TextureOffset(),
heart,
0.5f
},
Expand All @@ -136,8 +185,8 @@ int main(int argv, char ** argc)
(
{
trans["highest"],
jGL::TextureOffset(0.0f, 0.0f),
dice
jGL::TextureOffset(),
jerboa
},
"highest",
100000
Expand Down
Binary file added examples/Sprite/resource/texture/atlas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 31 additions & 22 deletions include/jGL/OpenGL/glSpriteRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ namespace jGL::GL
glSpriteRenderer(size_t sizeHint)
: SpriteRenderer(sizeHint)
{
offsets = std::vector<float>(sizeHint*4+padSprites*4,0.0f);
textureOffsets = std::vector<float>(sizeHint*4+padSprites*4,0.0f);
offsets = std::vector<float>(sizeHint*offsetDim+padSprites*offsetDim,0.0f);
textureRegion = std::vector<float>(sizeHint*textureRegionDim+padSprites*textureRegionDim,0.0f);
textureOptions = std::vector<float>(sizeHint*textureOptionsDim+padSprites*textureOptionsDim,0.0f);
initGL();
defaultShader = std::make_shared<glShader>(vertexShader, fragmentShader);
defaultShader->use();
Expand All @@ -28,27 +29,30 @@ namespace jGL::GL

void draw(std::shared_ptr<Shader> shader, std::multimap<RenderPriority, SpriteId> ids);
void draw(std::multimap<RenderPriority, SpriteId> ids) { draw(defaultShader, ids); }

void draw(std::shared_ptr<Shader> shader, std::vector<SpriteId> ids);
void draw(std::vector<SpriteId> ids) { draw(defaultShader, ids); }

private:

GLuint vao, a_position, a_offset, a_textureOffset;
GLuint vao, a_position, a_offset, a_textureRegion, a_textureOption;

float quad[6*4] =
{
// positions / texture coords
0.5f, 0.5f, 1.0f, 1.0f, // top right
0.5f, 0.5f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, // top left
-0.5f, -0.5f, 0.0f, 0.0f, // bottom left
0.5f, 0.5f, 1.0f, 1.0f // top right
-0.5f, -0.5f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, // top left
-0.5f, -0.5f, 0.0f, 0.0f, // bottom left
0.5f, 0.5f, 1.0f, 1.0f // top right
};

std::vector<float> offsets; // offset x, y, theta, scale
std::vector<float> textureOffsets; // tx, ty (atlas coords), texture unit, alpha
size_t offsetDim = 4;

std::vector<float> textureRegion; // tx, ty (region coords), lx, ly (region scale)
size_t textureRegionDim = 4;

std::vector<float> textureOptions; // texture unit, alpha
size_t textureOptionsDim = 2;

size_t padSprites = 8;

Expand All @@ -63,17 +67,21 @@ namespace jGL::GL
"layout(location=0) in vec4 a_position;\n"
"layout(location=1) in vec4 a_offset;\n"
"layout(location=2) in vec4 a_textureOffset;\n"
"layout(location=3) in vec2 a_textureOptions;\n"
"uniform mat4 proj;\n"
"out vec2 texCoord;\n"
"out vec4 texOffset;\n"
"flat out float alpha;\n"
"flat out int tex;\n"
"void main(){"
"vec2 pos = a_position.xy*a_offset.w;\n"
"float ct = cos(a_offset.z); float st = sin(a_offset.z);\n"
"mat2 rot = mat2(ct, -st, st, ct);\n"
"pos = rot*pos + a_offset.xy;\n"
"gl_Position = proj*vec4(pos,0.0,1.0);\n"
"texCoord = a_position.zw;\n"
"texOffset = a_textureOffset;\n"
"texCoord.x = (a_position.z * a_textureOffset.z)+a_textureOffset.x;\n"
"texCoord.y = (a_position.w * a_textureOffset.w)+a_textureOffset.y;\n"
"tex = int(a_textureOptions.x);\n"
"alpha = a_textureOptions.y;\n"
"}";

const char * fragmentShader =
Expand All @@ -84,16 +92,17 @@ namespace jGL::GL
"uniform sampler2D sampler2;\n"
"uniform sampler2D sampler3;\n"
"in vec2 texCoord;\n"
"in vec4 texOffset;\n"
"flat in float alpha;\n"
"flat in int tex;\n"
"layout(location=0) out vec4 colour;\n"
"void main(){\n"
// is this mental?
"if (texOffset.z == 0.0) {colour = texture(sampler0, texCoord);}\n"
"else if (texOffset.z == 1.0) {colour = texture(sampler1, texCoord);}\n"
"else if (texOffset.z == 2.0) {colour = texture(sampler2, texCoord);}\n"
"else if (texOffset.z == 3.0) {colour = texture(sampler3, texCoord);}\n"
"else {colour = vec4(0.0,0.0,0.0,texOffset.w);}\n"
"colour.a = colour.a*texOffset.a;\n"
"if (tex == 0) {colour = texture(sampler0, texCoord);}\n"
"else if (tex == 1) {colour = texture(sampler1, texCoord);}\n"
"else if (tex == 2) {colour = texture(sampler2, texCoord);}\n"
"else if (tex == 3) {colour = texture(sampler3, texCoord);}\n"
"else {colour = vec4(0.0,0.0,0.0,alpha);}\n"
"colour.a = colour.a*alpha;\n"
";\n"
"}";

Expand Down
31 changes: 28 additions & 3 deletions include/jGL/primitive.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@
namespace jGL
{

/**
* @brief Higher priority is drawn last.
* @typedef RenderPriority
* */
typedef uint64_t RenderPriority;

struct Primitive
{
virtual ~Primitive() = default;
};

/**
* @brief Particle with a texture, with a position, orientation, and scale, colour, and texture region.
*
*/
struct TexturedParticle : public Primitive
{
TexturedParticle() = default;
Expand All @@ -26,6 +34,10 @@ namespace jGL
glm::vec4 texCoord;
};

/**
* @brief Position, rotation, and scale.
*
*/
struct Transform : public Primitive
{

Expand All @@ -43,19 +55,32 @@ namespace jGL
double scale;
};

/**
* @brief Rectangular region of a texture.
*
* @param tx Lower left corner of region, along width.
* @param ty Lower left corner of region, along height.
* @param lx Length of region along width.
* @param ly Length of region along height.
*
* @remark Negative lx and ly will be handled as the maximum lengths in e.g.
* SpriteRenderer.
*/
struct TextureOffset : public Primitive
{

TextureOffset(float x, float y)
: tx(x), ty(y)
TextureOffset(float x, float y, float w, float h)
: tx(x), ty(y), lx(w), ly(h)
{}

TextureOffset()
: tx(0.0f), ty(0.0f)
: tx(0.0f), ty(0.0f), lx(-1.0), ly(-1.0)
{}

float tx;
float ty;
float lx;
float ly;
};

}
Expand Down
Loading

0 comments on commit e78b77b

Please sign in to comment.