163 lines
5.7 KiB
Java
163 lines
5.7 KiB
Java
package io.github.hydos.ginger.engine.render.renderers;
|
|
|
|
import java.nio.FloatBuffer;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.joml.Matrix4f;
|
|
import org.joml.Vector3f;
|
|
import org.lwjgl.BufferUtils;
|
|
import org.lwjgl.opengl.GL11;
|
|
import org.lwjgl.opengl.GL13;
|
|
import org.lwjgl.opengl.GL20;
|
|
import org.lwjgl.opengl.GL30;
|
|
import org.lwjgl.opengl.GL31;
|
|
|
|
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
|
|
import io.github.hydos.ginger.engine.math.Maths;
|
|
import io.github.hydos.ginger.engine.particle.Particle;
|
|
import io.github.hydos.ginger.engine.particle.ParticleTexture;
|
|
import io.github.hydos.ginger.engine.render.models.RawModel;
|
|
import io.github.hydos.ginger.engine.render.shaders.ParticleShader;
|
|
import io.github.hydos.ginger.engine.utils.Loader;
|
|
|
|
public class ParticleRenderer
|
|
{
|
|
private static final float[] VERTICES =
|
|
{
|
|
-0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f
|
|
};
|
|
private static final int MAX_INSTANCES = 10000;
|
|
private static final int INSTANCE_DATA_LENGTH = 21;
|
|
private static final FloatBuffer buffer = BufferUtils.createFloatBuffer(MAX_INSTANCES * INSTANCE_DATA_LENGTH);
|
|
private RawModel quad;
|
|
private ParticleShader shader;
|
|
private int vbo;
|
|
private int pointer;
|
|
|
|
public ParticleRenderer(Matrix4f projectionMatrix)
|
|
{
|
|
quad = Loader.loadToVAO(VERTICES, 2);
|
|
this.vbo = Loader.createEmptyVbo(INSTANCE_DATA_LENGTH * MAX_INSTANCES);
|
|
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 1, 4, INSTANCE_DATA_LENGTH, 0);
|
|
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 2, 4, INSTANCE_DATA_LENGTH, 4);
|
|
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 3, 4, INSTANCE_DATA_LENGTH, 8);
|
|
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 4, 4, INSTANCE_DATA_LENGTH, 12);
|
|
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 5, 4, INSTANCE_DATA_LENGTH, 16);
|
|
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 6, 1, INSTANCE_DATA_LENGTH, 20);
|
|
shader = new ParticleShader();
|
|
shader.start();
|
|
shader.loadProjectionMatrix(projectionMatrix);
|
|
shader.stop();
|
|
}
|
|
|
|
public void render(Map<ParticleTexture, List<Particle>> particles, ThirdPersonCamera camera)
|
|
{
|
|
Matrix4f viewMatrix = Maths.createViewMatrix(camera);
|
|
prepare();
|
|
for (ParticleTexture texture : particles.keySet())
|
|
{
|
|
bindTexture(texture);
|
|
List<Particle> particleList = particles.get(texture);
|
|
pointer = 0;
|
|
float[] vboData = new float[particleList.size() * INSTANCE_DATA_LENGTH];
|
|
for (Particle particle : particleList)
|
|
{
|
|
updateModelViewMatrix(particle.getPosition(), particle.getRotation(), particle.getScale().x, viewMatrix, vboData);
|
|
updateTexCoordInfo(particle, vboData);
|
|
}
|
|
Loader.updateVbo(vbo, vboData, buffer);
|
|
GL31.glDrawArraysInstanced(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount(), particleList.size());
|
|
}
|
|
finishRendering();
|
|
}
|
|
|
|
public void cleanUp()
|
|
{ shader.cleanUp(); }
|
|
|
|
private void updateTexCoordInfo(Particle particle, float[] data)
|
|
{
|
|
data[pointer++] = particle.getTexOffset1().x;
|
|
data[pointer++] = particle.getTexOffset1().y;
|
|
data[pointer++] = particle.getTexOffset2().x;
|
|
data[pointer++] = particle.getTexOffset2().y;
|
|
data[pointer++] = particle.getBlend();
|
|
}
|
|
|
|
private void bindTexture(ParticleTexture texture)
|
|
{
|
|
GL13.glActiveTexture(GL13.GL_TEXTURE0);
|
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureID());
|
|
shader.loadNumberOfRows(texture.getNumberOfRows());
|
|
}
|
|
|
|
private void updateModelViewMatrix(Vector3f position, float rotation, float scale, Matrix4f viewMatrix, float[] vboData)
|
|
{
|
|
Matrix4f modelMatrix = new Matrix4f();
|
|
modelMatrix.translate(position, modelMatrix);
|
|
modelMatrix.m00(viewMatrix.m00());
|
|
modelMatrix.m01(viewMatrix.m10());
|
|
modelMatrix.m02(viewMatrix.m20());
|
|
modelMatrix.m10(viewMatrix.m01());
|
|
modelMatrix.m11(viewMatrix.m11());
|
|
modelMatrix.m12(viewMatrix.m21());
|
|
modelMatrix.m20(viewMatrix.m02());
|
|
modelMatrix.m21(viewMatrix.m12());
|
|
modelMatrix.m22(viewMatrix.m22());
|
|
modelMatrix.rotate((float) Math.toRadians(rotation), new Vector3f(0, 0, 1), modelMatrix);
|
|
modelMatrix.scale(new Vector3f(scale, scale, scale), modelMatrix);
|
|
Matrix4f modelViewMatrix = new Matrix4f();
|
|
modelViewMatrix.mul(viewMatrix, modelMatrix);
|
|
storeMatrixData(modelViewMatrix, vboData);
|
|
}
|
|
|
|
private void storeMatrixData(Matrix4f matrix, float[] vboData)
|
|
{
|
|
vboData[pointer++] = matrix.m00();
|
|
vboData[pointer++] = matrix.m01();
|
|
vboData[pointer++] = matrix.m02();
|
|
vboData[pointer++] = matrix.m03();
|
|
vboData[pointer++] = matrix.m10();
|
|
vboData[pointer++] = matrix.m11();
|
|
vboData[pointer++] = matrix.m12();
|
|
vboData[pointer++] = matrix.m13();
|
|
vboData[pointer++] = matrix.m20();
|
|
vboData[pointer++] = matrix.m21();
|
|
vboData[pointer++] = matrix.m22();
|
|
vboData[pointer++] = matrix.m23();
|
|
vboData[pointer++] = matrix.m30();
|
|
vboData[pointer++] = matrix.m31();
|
|
vboData[pointer++] = matrix.m32();
|
|
vboData[pointer++] = matrix.m33();
|
|
}
|
|
|
|
private void prepare()
|
|
{
|
|
shader.start();
|
|
GL30.glBindVertexArray(quad.getVaoID());
|
|
GL20.glEnableVertexAttribArray(0);
|
|
GL20.glEnableVertexAttribArray(1);
|
|
GL20.glEnableVertexAttribArray(2);
|
|
GL20.glEnableVertexAttribArray(3);
|
|
GL20.glEnableVertexAttribArray(4);
|
|
GL20.glEnableVertexAttribArray(5);
|
|
GL20.glEnableVertexAttribArray(6);
|
|
GL11.glEnable(GL11.GL_BLEND);
|
|
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);//TODO: add all particle effects into 1 texture to fix overlapping
|
|
}
|
|
|
|
private void finishRendering()
|
|
{
|
|
shader.stop();
|
|
GL30.glBindVertexArray(0);
|
|
GL11.glDisable(GL11.GL_BLEND);
|
|
GL20.glDisableVertexAttribArray(0);
|
|
GL20.glDisableVertexAttribArray(1);
|
|
GL20.glDisableVertexAttribArray(2);
|
|
GL20.glDisableVertexAttribArray(3);
|
|
GL20.glDisableVertexAttribArray(4);
|
|
GL20.glDisableVertexAttribArray(5);
|
|
GL20.glDisableVertexAttribArray(6);
|
|
}
|
|
}
|