plutoengine/engine-core/plutospritesheet/src/main/java/org/plutoengine/graphics/Renderer2D.java

245 lines
5.7 KiB
Java
Executable File

package org.plutoengine.graphics;
import org.joml.Matrix3x2f;
import org.joml.Matrix3x2fc;
import org.joml.Vector4f;
import org.lwjgl.opengl.GL33;
import org.plutoengine.graphics.gl.DrawMode;
import org.plutoengine.graphics.gl.vao.QuadPresets;
import org.plutoengine.graphics.gl.vao.VertexArray;
import org.plutoengine.graphics.texture.texture2d.Texture2D;
import org.plutoengine.util.color.IRGBA;
import java.util.Stack;
/**
* A builder-like renderer for 2D rectangles. Note that the internal state is
* not monitored for performance reasons and outside events may affect active
* instances, such as changing the active shader or texture. In order to restore
* the internal state to the default.
*
* @author 493msi
*/
public class Renderer2D
{
public static VertexArray standardQuad;
public static VertexArray centeredQuad;
private static IShader2D defaultShader;
public static final Renderer2D INSTANCE = new Renderer2D();
protected Matrix3x2f transformation = new Matrix3x2f();
protected IShader2D customShader;
protected VertexArray activeVA;
protected Texture2D activeTexture;
protected boolean modifiedTransformation = false;
private static final Stack<IShader2D> customShaderStack = new Stack<>();
public static void load(IShader2D defaultShaderIn)
{
standardQuad = QuadPresets.basicNoNeg();
centeredQuad = QuadPresets.halvedSize();
defaultShader = defaultShaderIn;
}
public static void unload()
{
if (standardQuad != null)
{
standardQuad.close();
}
if (centeredQuad != null)
{
centeredQuad.close();
}
}
/**
* Pushes a custom {@link IShader2D shader} to be used in place of the
* default one.
*/
public static void pushCustomShader(IShader2D shader)
{
customShaderStack.push(shader);
}
/**
* Removes the top {@link IShader2D shader} from the custom shader stack.
*/
public static IShader2D popCustomShader()
{
return customShaderStack.pop();
}
/**
* Checks if the renderer is currently supplied with a custom
* {@link IShader2D shader}.
*/
public static boolean hasCustomShader()
{
return !customShaderStack.empty();
}
public static Renderer2D draw(VertexArray va, IShader2D shader)
{
GL33.glEnable(GL33.GL_BLEND);
INSTANCE.customShader = shader;
INSTANCE.customShader.start();
INSTANCE.customShader.loadRecolor(1, 1, 1, 1);
INSTANCE.identity();
INSTANCE.switchVertexArray(va);
INSTANCE.activeTexture = null;
return INSTANCE;
}
public static Renderer2D draw(VertexArray va)
{
return draw(va, hasCustomShader() ? customShaderStack.peek() : defaultShader);
}
public static Renderer2D draw()
{
return draw(standardQuad);
}
public Renderer2D identity()
{
this.transformation.identity();
return this;
}
public Renderer2D switchVertexArray(VertexArray va)
{
va.bind();
va.enableAllAttributes();
this.activeVA = va;
return this;
}
public Renderer2D rotate(float rotation)
{
this.transformation.rotate(rotation);
return this;
}
public Renderer2D at(float x, float y, float width, float height)
{
this.identity();
this.transformation.translate(x, y);
this.transformation.scale(width, height);
this.modifiedTransformation = true;
return this;
}
public Renderer2D translate(float x, float y)
{
this.transformation.translate(x, y);
this.modifiedTransformation = true;
return this;
}
public Renderer2D scale(float width, float height)
{
this.transformation.scale(width, height);
this.modifiedTransformation = true;
return this;
}
public Renderer2D transformation(Matrix3x2fc transformationMatrix)
{
this.transformation.set(transformationMatrix);
this.modifiedTransformation = true;
return this;
}
private Renderer2D writeTransformation()
{
this.customShader.loadTransformationMatrix(this.transformation);
this.modifiedTransformation = false;
return this;
}
public Renderer2D texturef(Texture2D texture, float u, float v, float width, float height)
{
if (this.activeTexture != texture)
{
this.activeTexture = texture;
texture.bind();
}
this.customShader.loadUV(u, 1 - v - height, width, height);
return this;
}
public Renderer2D texture(Texture2D texture, int u, int v, int width, int height)
{
return this.texturef(texture, u / (float) texture.getWidth(), v / (float) texture.getHeight(), width / (float) texture.getWidth(), height / (float) texture.getHeight());
}
public Renderer2D texture(Texture2D texture)
{
return this.texturef(texture, 0.0f, 0.0f, 1.0f, 1.0f);
}
public Renderer2D recolor(float r, float g, float b, float a)
{
this.customShader.loadRecolor(r, g, b, a);
return this;
}
public Renderer2D recolor(IRGBA rgba)
{
this.customShader.loadRecolor(rgba.red(), rgba.green(), rgba.blue(), rgba.alpha());
return this;
}
public Renderer2D recolor(Vector4f recolor)
{
this.customShader.loadRecolor(recolor);
return this;
}
public void flush()
{
if (this.modifiedTransformation)
{
this.writeTransformation();
this.modifiedTransformation = false;
}
this.activeVA.draw(DrawMode.TRIANGLES);
}
}