Alpha masked sprite.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m44s

This commit is contained in:
2024-11-22 07:46:48 -05:00
parent bcca6285af
commit fb5ca55fda
6 changed files with 143 additions and 17 deletions

View File

@@ -53,7 +53,7 @@ JGL::J2D::End();
```
## Requirements
An OpenGL 2.1 or newer accelerator that supports the `GL_ARB_framebuffer_object` extension or
An OpenGL 2.1 or newer accelerator with at-least two texture mappers that supports the `GL_ARB_framebuffer_object` extension or
an implementation that can provide those features through alternative means (common on ArmSoC and Risc-V).
## Compatability

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -224,6 +224,26 @@ namespace JGL::J2D {
float originX = 0, float originY = 0,float scaleX = 1, float scaleY = 1,
const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a sprite to the screen by passing a G̶L̶u̶i̶n̶t̶ JGL Texture that represents a handle to a loaded texture.
/// @param texture A texture instance to be displayed.
/// @param alpha_mask A texture which determines how much of the sprite you can see. Grayscale image exported as "8bpc RGBA".
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param origin The center point around which the image should have all transformations applied to it.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param rad_rotation A float representing the rotation of the sprite where 0 is no rotation and 1 is the maximum rotation (would look the same as 0).
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
/// @see class Texture
void DrawSprite(const Texture& texture, const Texture& alpha_mask, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, const Texture* alpha_mask, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture& texture, const Texture& alpha_mask, float positionX, float positionY, float rad_rotation = 0, float originX = 0, float originY = 0,
float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, const Texture* alpha_mask, float positionX, float positionY, float rad_rotation = 0, float originX = 0, float originY = 0,
float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a piece of a sprite to the screen, similar to DrawSprite.
/// @param texture A texture instance to be displayed.
/// @param position The point at which to draw the sprite (from the top-left down).

View File

@@ -98,9 +98,8 @@ Gizmo c({350, 300});
Gizmo d({450, 250});
Texture* image;
Texture* image2;
Texture* image_mask;
RenderTarget* j2d_render_target;
RenderTarget* image2_render_target;
class JGLDemoWindow : public ReWindow::RWindow
{
@@ -119,14 +118,10 @@ public:
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
image = new Texture("assets/sprites/Re3D.png", TextureFilteringMode::BILINEAR);
image_mask = new Texture("assets/sprites/alpha_mask_2.png");
j2d_render_target = new RenderTarget({540, 540}, {0,0,0,0}, false, MSAA_SAMPLE_RATE::MSAA_NONE);
image2 = image;
image2_render_target = new RenderTarget(image2);
J2D::Begin(image2_render_target);
J2D::DrawString(Colors::Red, "TEST", 0, 16, 1, 16, FreeSans);
J2D::FillRect(Colors::Blue, {0,0}, {4,4});
J2D::End();
//Texture::MultiplyByAlphaMask(*image, *image_mask);
}
Vector3 textAngle = {0,0,0};
@@ -184,7 +179,7 @@ public:
J2D::Begin(j2d_render_target, true);
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
J2D::DrawSprite(image2, {300, 400}, sprite_radians * 0.10f, {0.5,0.5}, {1, 1}, Colors::White);
J2D::DrawSprite(image, {300, 400}, sprite_radians * 0.10f, {0.5,0.5}, {1, 1}, Colors::White);
J2D::DrawMirrorSprite(image, {400, 300}, Direction::Horizontal | Direction::Vertical, sprite_radians, {0.5,0.5}, {1, 1}, Colors::White);
J2D::DrawPartialSprite(image, {225, 300}, image->GetDimensions() * 0.25, image->GetDimensions() * 0.75, sprite_radians, {0.5, 0.5}, {1,1}, Colors::White);
J2D::FillRect(Colors::Pinks::HotPink, {68, 120}, {32, 32});
@@ -228,8 +223,10 @@ public:
J2D::Begin();
J2D::DrawPartialRenderTarget(j2d_render_target, {0, 0}, {0,0}, {512, 512});
//J2D::DrawSprite(j2d_render_target, {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White);
J2D::DrawSprite(image2_render_target, {300, 500}, 0, {0.5, 0.5}, {1,1}, Colors::White);
J2D::DrawSprite(image, image_mask, {0, 0}, 0.25, {0.5, 0.5}, {1,1});
//J2D::DrawSprite(, {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White);
//J2D::DrawSprite( {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White);
J2D::End();
}

View File

@@ -101,8 +101,10 @@ namespace JGL {
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureUnit);
activeTextureUnit = activeTextureUnit - GL_TEXTURE0;
if (activeTextureUnit != 0)
if (activeTextureUnit != 0) {
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
}
if (glIsEnabled(GL_DEPTH_TEST))
wasDepthTestEnabled = true,
@@ -173,6 +175,10 @@ namespace JGL {
if (!wasBlendEnabled)
glDisable(GL_BLEND);
//Select whatever texture mapper was selected before.
glActiveTexture(GL_TEXTURE0 + activeTextureUnit);
glClientActiveTexture(GL_TEXTURE0 + activeTextureUnit);
if (wasTexture2DEnabled)
glEnable(GL_TEXTURE_2D);
@@ -182,9 +188,6 @@ namespace JGL {
if (wasColorArrayEnabled)
glEnableClientState(GL_COLOR_ARRAY);
//Select whatever texture_handle unit was selected before.
glActiveTexture(GL_TEXTURE0 + activeTextureUnit);
//Put the draw color back how it was before.
glColor4fv(oldColor);
@@ -442,7 +445,113 @@ namespace JGL {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void J2D::DrawPartialRenderTarget(const JGL::RenderTarget & rt, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size,
void J2D::DrawSprite(const Texture& texture, const Texture &alpha_mask, const Vector2& position, float rad_rotation,
const Vector2& origin, const Vector2& scale,const Color4& color, JGL::Direction inversion) {
if (!inJ2D)
Logger::Error("Drawing J2D element before J2D begin.");
if (texture.GetDimensions() != alpha_mask.GetDimensions())
Logger::Warning("The alpha mask and the texture are not the same size.");
const Vector2 size = texture.GetDimensions();
std::array<Vector2, 4> textureCoordinates{};
if (texture.GetFlags() & INVERT_Y)
textureCoordinates = {Vector2(0, 1), Vector2(0, 0), Vector2(1, 0), Vector2(1, 1)};
else
textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0)};
// TODO: Kind of a mess, refactor to be more sensible later.
// Factors in scaling and origin correctly.
// i.e. to render at 2x size, from the center, at coords XY, use {2, 2} scale, and {0.5, 0.5} offset.
const Vector2 offset = origin * size;
Vector2 pos2 = position;
Vector2 scaled_size = scale * size;
Vector2 size2 = scaled_size;
float cos_theta = std::cos(rad_rotation);
float sin_theta = std::sin(rad_rotation);
std::array<Vector2, 4> vertices =
{
pos2, // Top-left vertex
{pos2.x, pos2.y + size2.y}, // Bottom-left
{pos2.x + size2.x, pos2.y + size2.y}, // Bottom-right
{pos2.x + size2.x, pos2.y} // Top-right
};
//Rotate the vertices about the origin by float rad_rotation.
if (rad_rotation != 0)
for (auto& v: vertices)
v = {(v.x - pos2.x - offset.x * scale.x) * cos_theta - (v.y - pos2.y - offset.y * scale.y) * sin_theta +
pos2.x + offset.x * scale.x,
(v.x - pos2.x - offset.x * scale.x) * sin_theta + (v.y - pos2.y - offset.y * scale.y) * cos_theta +
pos2.y + offset.y * scale.y
};
if (inversion == Direction::Vertical)
std::swap(textureCoordinates[0], textureCoordinates[1]),
std::swap(textureCoordinates[3], textureCoordinates[2]);
if (inversion == Direction::Horizontal)
std::swap(textureCoordinates[0], textureCoordinates[3]),
std::swap(textureCoordinates[1], textureCoordinates[2]);
glColor4ubv(color.ptr());
// Texture 0.
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
// Texture 1.
glActiveTexture(GL_TEXTURE1);
glClientActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, alpha_mask.GetGLTextureHandle());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
// Draw.
glDrawArrays(GL_QUADS, 0, 4);
// Reset Texture 1.
glBindTexture(GL_TEXTURE_2D, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_TEXTURE_2D);
// Reset Texture 0.
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glColor4fv(baseColor);
}
void J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, const Vector2& position, float rad_rotation,
const Vector2& origin, const Vector2& scale,const Color4& color, Direction inversion) {
DrawSprite(*texture, *alpha_mask, position, rad_rotation, origin, scale, color, inversion);
}
void J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, float positionX, float positionY, float rad_rotation,
float originX, float originY,float scaleX, float scaleY,const Color4& color, Direction inversion) {
DrawSprite(texture, alpha_mask, {positionX, positionY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
}
void J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, float positionX, float positionY, float rad_rotation,
float originX, float originY,float scaleX, float scaleY,const Color4& color, Direction inversion) {
DrawSprite(*texture, *alpha_mask, {positionX, positionY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
}
void J2D::DrawPartialRenderTarget(const JGL::RenderTarget& rt, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size,
float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color, JGL::Direction inversion) {
//Correct for the render-target being upside-down.