ParticleRenderer.java 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package eu.tankernn.gameEngine.particles;
  2. import java.nio.FloatBuffer;
  3. import java.util.List;
  4. import java.util.Map;
  5. import org.lwjgl.BufferUtils;
  6. import org.lwjgl.opengl.GL11;
  7. import org.lwjgl.opengl.GL15;
  8. import org.lwjgl.opengl.GL20;
  9. import org.lwjgl.opengl.GL30;
  10. import org.lwjgl.opengl.GL31;
  11. import org.lwjgl.util.vector.Matrix4f;
  12. import org.lwjgl.util.vector.Vector3f;
  13. import eu.tankernn.gameEngine.entities.Camera;
  14. import eu.tankernn.gameEngine.loader.Loader;
  15. import eu.tankernn.gameEngine.renderEngine.Vao;
  16. import eu.tankernn.gameEngine.renderEngine.Vbo;
  17. public class ParticleRenderer {
  18. private static final float[] VERTICES = {-0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f};
  19. private static final int MAX_INSTANCES = 10000;
  20. private static final int INSTANCE_DATA_LENGTH = 21;
  21. private static final FloatBuffer buffer = BufferUtils.createFloatBuffer(MAX_INSTANCES * INSTANCE_DATA_LENGTH);
  22. private Vao quad;
  23. private ParticleShader shader;
  24. private Vbo vbo;
  25. private int pointer = 0;
  26. protected ParticleRenderer(Loader loader, Matrix4f projectionMatrix) {
  27. this.vbo = Vbo.create(GL15.GL_ARRAY_BUFFER, GL15.GL_STREAM_DRAW, INSTANCE_DATA_LENGTH * MAX_INSTANCES);
  28. quad = loader.loadToVAO(VERTICES, 2);
  29. for (int i = 0; i < 5; i++)
  30. quad.addInstacedAttribute(vbo, i + 1, 4, INSTANCE_DATA_LENGTH, i * 4);
  31. quad.addInstacedAttribute(vbo, 6, 1, INSTANCE_DATA_LENGTH, 20);
  32. shader = new ParticleShader();
  33. shader.start();
  34. shader.projectionMatrix.loadMatrix(projectionMatrix);
  35. shader.stop();
  36. }
  37. protected void render(Map<ParticleTexture, List<Particle>> particles, Camera camera) {
  38. Matrix4f viewMatrix = camera.getViewMatrix();
  39. prepare();
  40. for (ParticleTexture texture: particles.keySet()) {
  41. bindTexture(texture);
  42. List<Particle> particleList = particles.get(texture);
  43. pointer = 0;
  44. float[] vboData = new float[particleList.size() * INSTANCE_DATA_LENGTH];
  45. for (Particle p: particleList) {
  46. updateModelViewMatrix(p.getPosition(), p.getRotation(), p.getScale(), viewMatrix, vboData);
  47. updateTexCoordInfo(p, vboData);
  48. }
  49. vbo.updateData(vboData, buffer);
  50. GL31.glDrawArraysInstanced(GL11.GL_TRIANGLE_STRIP, 0, quad.getIndexCount(), particleList.size());
  51. }
  52. finishRendering();
  53. }
  54. protected void cleanUp() {
  55. shader.cleanUp();
  56. }
  57. private void updateTexCoordInfo(Particle particle, float[] data) {
  58. data[pointer++] = particle.getTexOffset1().x;
  59. data[pointer++] = particle.getTexOffset1().y;
  60. data[pointer++] = particle.getTexOffset2().x;
  61. data[pointer++] = particle.getTexOffset2().y;
  62. data[pointer++] = particle.getBlend();
  63. }
  64. private void bindTexture(ParticleTexture texture) {
  65. int blendType = texture.usesAdditiveBlending() ? GL11.GL_ONE : GL11.GL_ONE_MINUS_SRC_ALPHA;
  66. GL11.glBlendFunc(GL11.GL_SRC_ALPHA, blendType);
  67. texture.getTexture().bindToUnit(0);
  68. shader.numberOfRows.loadFloat(texture.getNumberOfRows());
  69. }
  70. private void updateModelViewMatrix(Vector3f position, float rotation, float scale, Matrix4f viewMatrix, float[] vboData) {
  71. Matrix4f modelMatrix = new Matrix4f();
  72. Matrix4f.translate(position, modelMatrix, modelMatrix);
  73. //Sets rotation of model matrix to transpose of rotation of view matrix
  74. modelMatrix.m00 = viewMatrix.m00;
  75. modelMatrix.m01 = viewMatrix.m10;
  76. modelMatrix.m02 = viewMatrix.m20;
  77. modelMatrix.m10 = viewMatrix.m01;
  78. modelMatrix.m11 = viewMatrix.m11;
  79. modelMatrix.m12 = viewMatrix.m21;
  80. modelMatrix.m20 = viewMatrix.m02;
  81. modelMatrix.m21 = viewMatrix.m12;
  82. modelMatrix.m22 = viewMatrix.m22;
  83. Matrix4f.rotate((float) Math.toRadians(rotation), new Vector3f(0, 0, 1), modelMatrix, modelMatrix);
  84. Matrix4f.scale(new Vector3f(scale, scale, scale), modelMatrix, modelMatrix);
  85. Matrix4f modelViewMatrix = Matrix4f.mul(viewMatrix, modelMatrix, null);
  86. storeMatrixData(modelViewMatrix, vboData);
  87. }
  88. private void storeMatrixData(Matrix4f matrix, float[] vboData) {
  89. vboData[pointer++] = matrix.m00;
  90. vboData[pointer++] = matrix.m01;
  91. vboData[pointer++] = matrix.m02;
  92. vboData[pointer++] = matrix.m03;
  93. vboData[pointer++] = matrix.m10;
  94. vboData[pointer++] = matrix.m11;
  95. vboData[pointer++] = matrix.m12;
  96. vboData[pointer++] = matrix.m13;
  97. vboData[pointer++] = matrix.m20;
  98. vboData[pointer++] = matrix.m21;
  99. vboData[pointer++] = matrix.m22;
  100. vboData[pointer++] = matrix.m23;
  101. vboData[pointer++] = matrix.m30;
  102. vboData[pointer++] = matrix.m31;
  103. vboData[pointer++] = matrix.m32;
  104. vboData[pointer++] = matrix.m33;
  105. }
  106. private void prepare() {
  107. shader.start();
  108. GL30.glBindVertexArray(quad.id);
  109. for (int i = 0; i < 7; i++)
  110. GL20.glEnableVertexAttribArray(i);
  111. GL11.glEnable(GL11.GL_BLEND);
  112. GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
  113. GL11.glDepthMask(false);
  114. }
  115. private void finishRendering() {
  116. GL11.glDepthMask(true);
  117. GL11.glDisable(GL11.GL_BLEND);
  118. for (int i = 0; i < 7; i++)
  119. GL20.glDisableVertexAttribArray(i);
  120. GL30.glBindVertexArray(0);
  121. shader.stop();
  122. }
  123. }