From 495d0df36b7f852d35283823b66e335f1815d396 Mon Sep 17 00:00:00 2001 From: Guerra24 Date: Sun, 29 Nov 2015 15:43:50 -0600 Subject: [PATCH] New Particle System. --- assets/shaders/FragmentParticle.glsl | 10 ++ assets/shaders/VertexParticle.glsl | 10 ++ .../voxel/client/core/VoxelVariables.java | 3 +- .../voxel/client/core/states/GameSPState.java | 18 ++- .../client/core/states/InPauseState.java | 8 +- .../client/graphics/ParticleRenderer.java | 81 ++++++++++ .../graphics/shaders/ParticleShader.java | 34 ++++ .../voxel/client/particle/Particle.java | 49 ++++++ .../voxel/client/particle/ParticleMaster.java | 57 +++++++ .../voxel/client/particle/ParticlePoint.java | 15 ++ .../voxel/client/particle/ParticleSystem.java | 151 ++++++++++++++++++ .../voxel/client/resources/GameResources.java | 13 +- .../guerra24/voxel/client/world/IWorld.java | 2 +- .../voxel/client/world/InfinityWorld.java | 19 ++- .../voxel/client/world/chunks/Chunk.java | 10 ++ .../voxel/client/world/entities/Player.java | 4 +- 16 files changed, 461 insertions(+), 23 deletions(-) create mode 100644 src/main/java/net/guerra24/voxel/client/graphics/ParticleRenderer.java create mode 100644 src/main/java/net/guerra24/voxel/client/graphics/shaders/ParticleShader.java create mode 100644 src/main/java/net/guerra24/voxel/client/particle/Particle.java create mode 100644 src/main/java/net/guerra24/voxel/client/particle/ParticleMaster.java create mode 100644 src/main/java/net/guerra24/voxel/client/particle/ParticlePoint.java create mode 100644 src/main/java/net/guerra24/voxel/client/particle/ParticleSystem.java diff --git a/assets/shaders/FragmentParticle.glsl b/assets/shaders/FragmentParticle.glsl index c7feeb358..0e3000967 100644 --- a/assets/shaders/FragmentParticle.glsl +++ b/assets/shaders/FragmentParticle.glsl @@ -24,5 +24,15 @@ #version 330 core +in vec3 pass_Position; + +out vec4 [4] out_Color; + void main(void){ + + out_Color[0] = vec4(1.0); + out_Color[1] = vec4(pass_Position.xyz,0); + out_Color[2] = vec4(0,1,0,0); + out_Color[3] = vec4(0.0,0.0,0.0,0); + } \ No newline at end of file diff --git a/assets/shaders/VertexParticle.glsl b/assets/shaders/VertexParticle.glsl index c7feeb358..ed2732c2f 100644 --- a/assets/shaders/VertexParticle.glsl +++ b/assets/shaders/VertexParticle.glsl @@ -24,5 +24,15 @@ #version 330 core +in vec2 position; + +out vec3 pass_Position; + +uniform mat4 projectionMatrix; +uniform mat4 modelViewMatrix; + void main(void){ + vec4 pos = modelViewMatrix * vec4(position, 0.0, 1.0); + gl_Position = projectionMatrix * pos; + pass_Position = pos.xyz; } \ No newline at end of file diff --git a/src/main/java/net/guerra24/voxel/client/core/VoxelVariables.java b/src/main/java/net/guerra24/voxel/client/core/VoxelVariables.java index 3cb2835a8..e7ef3a734 100644 --- a/src/main/java/net/guerra24/voxel/client/core/VoxelVariables.java +++ b/src/main/java/net/guerra24/voxel/client/core/VoxelVariables.java @@ -44,7 +44,7 @@ public class VoxelVariables { public static final String version = "0.0.9"; public static final String apiVersion = "0.0.4"; public static final String state = "ALPHA"; - public static final int build = 126; + public static final int build = 127; public static int FOV = 90; public static int WIDTH = 1280; public static int HEIGHT = 720; @@ -78,6 +78,7 @@ public class VoxelVariables { public static final int CHUNK_HEIGHT = 16; public static final int DIM_0 = 0; public static final int DIM_1 = 1; + public static final float GRAVITY = -10; /** * Graphics Settings */ diff --git a/src/main/java/net/guerra24/voxel/client/core/states/GameSPState.java b/src/main/java/net/guerra24/voxel/client/core/states/GameSPState.java index 576570ea0..d081e7dc7 100644 --- a/src/main/java/net/guerra24/voxel/client/core/states/GameSPState.java +++ b/src/main/java/net/guerra24/voxel/client/core/states/GameSPState.java @@ -3,13 +3,14 @@ import net.guerra24.voxel.client.api.API; import net.guerra24.voxel.client.core.GlobalStates; import net.guerra24.voxel.client.core.GlobalStates.GameState; +import net.guerra24.voxel.client.core.State; +import net.guerra24.voxel.client.core.Voxel; +import net.guerra24.voxel.client.core.VoxelVariables; import net.guerra24.voxel.client.graphics.opengl.Display; +import net.guerra24.voxel.client.particle.ParticleMaster; import net.guerra24.voxel.client.resources.GameResources; import net.guerra24.voxel.client.resources.GuiResources; import net.guerra24.voxel.client.world.WorldsHandler; -import net.guerra24.voxel.client.core.State; -import net.guerra24.voxel.client.core.Voxel; -import net.guerra24.voxel.client.core.VoxelVariables; /** * Single Player GameState @@ -27,10 +28,11 @@ public void update(Voxel voxel, GlobalStates states, float delta) { API api = voxel.getApi(); Display display = voxel.getDisplay(); - worlds.getActiveWorld().updateChunksGeneration(gm, api); + worlds.getActiveWorld().updateChunksGeneration(gm, api, delta); gm.getPhysics().getMobManager().update(delta, gm, gi, worlds.getActiveWorld(), api); gm.update(gm.getSkyboxRenderer().update(delta)); gm.getRenderer().getWaterRenderer().update(delta); + ParticleMaster.getInstance().update(delta); if (!display.isDisplayFocused() && !VoxelVariables.debug) { gm.getCamera().unlockMouse(); @@ -56,16 +58,18 @@ public void render(Voxel voxel, GlobalStates states, float delta) { worlds.getActiveWorld().updateChunksShadow(gm); gm.getMasterShadowRenderer().end(); } - gm.getPostProcessing().getPost_fbo().begin(); + gm.getDeferredShadingRenderer().getPost_fbo().begin(); gm.getRenderer().prepare(); gm.getRenderer().begin(gm); worlds.getActiveWorld().updateChunksRender(gm); gm.getRenderer().end(gm); gm.getSkyboxRenderer().render(VoxelVariables.RED, VoxelVariables.GREEN, VoxelVariables.BLUE, delta, gm); gm.getRenderer().renderEntity(gm.getPhysics().getMobManager().getMobs(), gm); - gm.getPostProcessing().getPost_fbo().end(); + ParticleMaster.getInstance().render(gm.getCamera()); + gm.getDeferredShadingRenderer().getPost_fbo().end(); + gm.getRenderer().prepare(); - gm.getPostProcessing().render(gm); + gm.getDeferredShadingRenderer().render(gm); } } diff --git a/src/main/java/net/guerra24/voxel/client/core/states/InPauseState.java b/src/main/java/net/guerra24/voxel/client/core/states/InPauseState.java index 311c07f15..b0d21e741 100644 --- a/src/main/java/net/guerra24/voxel/client/core/states/InPauseState.java +++ b/src/main/java/net/guerra24/voxel/client/core/states/InPauseState.java @@ -6,6 +6,7 @@ import net.guerra24.voxel.client.core.Voxel; import net.guerra24.voxel.client.core.VoxelVariables; import net.guerra24.voxel.client.menu.PauseMenu; +import net.guerra24.voxel.client.particle.ParticleMaster; import net.guerra24.voxel.client.resources.GameResources; import net.guerra24.voxel.client.world.WorldsHandler; import net.guerra24.voxel.universal.util.vector.Vector3f; @@ -60,16 +61,17 @@ public void render(Voxel voxel, GlobalStates states, float delta) { worlds.getActiveWorld().updateChunksShadow(gm); gm.getMasterShadowRenderer().end(); } - gm.getPostProcessing().getPost_fbo().begin(); + gm.getDeferredShadingRenderer().getPost_fbo().begin(); gm.getRenderer().prepare(); gm.getRenderer().begin(gm); worlds.getActiveWorld().updateChunksRender(gm); gm.getRenderer().end(gm); gm.getSkyboxRenderer().render(VoxelVariables.RED, VoxelVariables.GREEN, VoxelVariables.BLUE, delta, gm); gm.getRenderer().renderEntity(gm.getPhysics().getMobManager().getMobs(), gm); - gm.getPostProcessing().getPost_fbo().end(); + ParticleMaster.getInstance().render(gm.getCamera()); + gm.getDeferredShadingRenderer().getPost_fbo().end(); gm.getRenderer().prepare(); - gm.getPostProcessing().render(gm); + gm.getDeferredShadingRenderer().render(gm); gm.getGuiRenderer().renderGui(gm.guis4); } diff --git a/src/main/java/net/guerra24/voxel/client/graphics/ParticleRenderer.java b/src/main/java/net/guerra24/voxel/client/graphics/ParticleRenderer.java new file mode 100644 index 000000000..b898012b6 --- /dev/null +++ b/src/main/java/net/guerra24/voxel/client/graphics/ParticleRenderer.java @@ -0,0 +1,81 @@ +package net.guerra24.voxel.client.graphics; + +import static org.lwjgl.opengl.GL11.GL_TRIANGLE_STRIP; +import static org.lwjgl.opengl.GL11.glDepthMask; +import static org.lwjgl.opengl.GL11.glDrawArrays; +import static org.lwjgl.opengl.GL20.glDisableVertexAttribArray; +import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray; +import static org.lwjgl.opengl.GL30.glBindVertexArray; + +import java.util.Queue; + +import net.guerra24.voxel.client.graphics.shaders.ParticleShader; +import net.guerra24.voxel.client.particle.Particle; +import net.guerra24.voxel.client.resources.Loader; +import net.guerra24.voxel.client.resources.models.RawModel; +import net.guerra24.voxel.client.util.Maths; +import net.guerra24.voxel.client.world.entities.Camera; +import net.guerra24.voxel.universal.util.vector.Matrix4f; +import net.guerra24.voxel.universal.util.vector.Vector3f; + +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 RawModel quad; + private ParticleShader shader; + + public ParticleRenderer(Loader loader, Matrix4f projectionMatrix) { + quad = loader.loadToVAO(VERTICES, 2); + shader = new ParticleShader(); + shader.start(); + shader.loadProjectionMatrix(projectionMatrix); + } + + public void render(Queue particles, Camera camera) { + Matrix4f viewMatrix = Maths.createViewMatrix(camera); + prepare(); + for (Particle particle : particles) { + updateModelViewMatrix(particle.getPosition(), particle.getRotation(), particle.getScale(), viewMatrix); + glDrawArrays(GL_TRIANGLE_STRIP, 0, quad.getVertexCount()); + } + finishRendering(); + } + + private void updateModelViewMatrix(Vector3f position, float rotation, float scale, Matrix4f viewMatrix) { + Matrix4f modelMatrix = new Matrix4f(); + Matrix4f.translate(position, modelMatrix, 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; + Matrix4f.rotate((float) Math.toRadians(rotation), new Vector3f(0, 0, 1), modelMatrix, modelMatrix); + Matrix4f.scale(new Vector3f(scale, scale, scale), modelMatrix, modelMatrix); + Matrix4f modelViewMatrix = Matrix4f.mul(viewMatrix, modelMatrix, null); + shader.loadModelViewMatrix(modelViewMatrix); + } + + private void prepare() { + shader.start(); + glBindVertexArray(quad.getVaoID()); + glEnableVertexAttribArray(0); + glDepthMask(false); + } + + private void finishRendering() { + glDepthMask(true); + glDisableVertexAttribArray(0); + glBindVertexArray(0); + shader.stop(); + } + + public void cleanUp() { + shader.cleanUp(); + } + +} diff --git a/src/main/java/net/guerra24/voxel/client/graphics/shaders/ParticleShader.java b/src/main/java/net/guerra24/voxel/client/graphics/shaders/ParticleShader.java new file mode 100644 index 000000000..9bbf322fe --- /dev/null +++ b/src/main/java/net/guerra24/voxel/client/graphics/shaders/ParticleShader.java @@ -0,0 +1,34 @@ +package net.guerra24.voxel.client.graphics.shaders; + +import net.guerra24.voxel.client.core.VoxelVariables; +import net.guerra24.voxel.universal.util.vector.Matrix4f; + +public class ParticleShader extends ShaderProgram { + + private int location_modelViewMatrix; + private int location_projectionMatrix; + + public ParticleShader() { + super(VoxelVariables.VERTEX_FILE_PARTICLE, VoxelVariables.FRAGMENT_FILE_PARTICLE); + } + + @Override + protected void getAllUniformLocations() { + location_modelViewMatrix = super.getUniformLocation("modelViewMatrix"); + location_projectionMatrix = super.getUniformLocation("projectionMatrix"); + } + + @Override + protected void bindAttributes() { + super.bindAttribute(0, "position"); + } + + public void loadModelViewMatrix(Matrix4f modelView) { + super.loadMatrix(location_modelViewMatrix, modelView); + } + + public void loadProjectionMatrix(Matrix4f projectionMatrix) { + super.loadMatrix(location_projectionMatrix, projectionMatrix); + } + +} diff --git a/src/main/java/net/guerra24/voxel/client/particle/Particle.java b/src/main/java/net/guerra24/voxel/client/particle/Particle.java new file mode 100644 index 000000000..caf0d7db4 --- /dev/null +++ b/src/main/java/net/guerra24/voxel/client/particle/Particle.java @@ -0,0 +1,49 @@ +package net.guerra24.voxel.client.particle; + +import net.guerra24.voxel.client.core.VoxelVariables; +import net.guerra24.voxel.universal.util.vector.Vector3f; + +public class Particle { + + private Vector3f position; + private Vector3f velocity; + + private float gravityEffect; + private float lifeLeght; + private float rotation; + private float scale; + private float elapsedTime = 0; + + public Particle(Vector3f position, Vector3f velocity, float gravityEffect, float lifeLeght, float rotation, + float scale) { + this.position = position; + this.velocity = velocity; + this.gravityEffect = gravityEffect; + this.lifeLeght = lifeLeght; + this.rotation = rotation; + this.scale = scale; + ParticleMaster.getInstance().addParticle(this); + } + + public boolean update(float delta) { + velocity.y += VoxelVariables.GRAVITY * gravityEffect * delta; + Vector3f change = new Vector3f(velocity); + change.scale(delta); + Vector3f.add(change, position, position); + elapsedTime += delta; + return elapsedTime < lifeLeght; + } + + public Vector3f getPosition() { + return position; + } + + public float getRotation() { + return rotation; + } + + public float getScale() { + return scale; + } + +} diff --git a/src/main/java/net/guerra24/voxel/client/particle/ParticleMaster.java b/src/main/java/net/guerra24/voxel/client/particle/ParticleMaster.java new file mode 100644 index 000000000..824122681 --- /dev/null +++ b/src/main/java/net/guerra24/voxel/client/particle/ParticleMaster.java @@ -0,0 +1,57 @@ +package net.guerra24.voxel.client.particle; + +import java.util.Iterator; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import net.guerra24.voxel.client.graphics.ParticleRenderer; +import net.guerra24.voxel.client.resources.Loader; +import net.guerra24.voxel.client.world.entities.Camera; +import net.guerra24.voxel.universal.util.vector.Matrix4f; + +public class ParticleMaster { + + private static ParticleMaster instance = null; + + public static ParticleMaster getInstance() { + if (instance == null) { + instance = new ParticleMaster(); + } + return instance; + } + + private Queue particles; + private ParticleRenderer renderer; + + private ParticleMaster() { + } + + public void init(Loader loader, Matrix4f projectionMatrix) { + particles = new ConcurrentLinkedQueue(); + renderer = new ParticleRenderer(loader, projectionMatrix); + } + + public void update(float delta) { + Iterator iterator = particles.iterator(); + while (iterator.hasNext()) { + Particle p = iterator.next(); + boolean stillAlive = p.update(delta); + if (!stillAlive) + iterator.remove(); + } + + } + + public void render(Camera camera) { + renderer.render(particles, camera); + } + + public void cleanUp() { + renderer.cleanUp(); + } + + public void addParticle(Particle particle) { + particles.add(particle); + } + +} diff --git a/src/main/java/net/guerra24/voxel/client/particle/ParticlePoint.java b/src/main/java/net/guerra24/voxel/client/particle/ParticlePoint.java new file mode 100644 index 000000000..d5e456da8 --- /dev/null +++ b/src/main/java/net/guerra24/voxel/client/particle/ParticlePoint.java @@ -0,0 +1,15 @@ +package net.guerra24.voxel.client.particle; + +import net.guerra24.voxel.universal.util.vector.Vector3f; + +public class ParticlePoint { + private Vector3f pos; + + public ParticlePoint(Vector3f pos) { + this.pos = pos; + } + + public Vector3f getPos() { + return pos; + } +} diff --git a/src/main/java/net/guerra24/voxel/client/particle/ParticleSystem.java b/src/main/java/net/guerra24/voxel/client/particle/ParticleSystem.java new file mode 100644 index 000000000..b5390b4a2 --- /dev/null +++ b/src/main/java/net/guerra24/voxel/client/particle/ParticleSystem.java @@ -0,0 +1,151 @@ +package net.guerra24.voxel.client.particle; + +import java.util.Random; + +import net.guerra24.voxel.universal.util.vector.Matrix4f; +import net.guerra24.voxel.universal.util.vector.Vector3f; +import net.guerra24.voxel.universal.util.vector.Vector4f; + +public class ParticleSystem { + + private float pps, averageSpeed, gravityComplient, averageLifeLength, averageScale; + + private float speedError, lifeError, scaleError = 0; + private boolean randomRotation = false; + private Vector3f direction; + private float directionDeviation = 0; + + private Random random = new Random(); + + public ParticleSystem(float pps, float speed, float gravityComplient, float lifeLength, float scale) { + this.pps = pps; + this.averageSpeed = speed; + this.gravityComplient = gravityComplient; + this.averageLifeLength = lifeLength; + this.averageScale = scale; + } + + /** + * @param direction + * - The average direction in which particles are emitted. + * @param deviation + * - A value between 0 and 1 indicating how far from the chosen + * direction particles can deviate. + */ + public void setDirection(Vector3f direction, float deviation) { + this.direction = new Vector3f(direction); + this.directionDeviation = (float) (deviation * Math.PI); + } + + public void randomizeRotation() { + randomRotation = true; + } + + /** + * @param error + * - A number between 0 and 1, where 0 means no error margin. + */ + public void setSpeedError(float error) { + this.speedError = error * averageSpeed; + } + + /** + * @param error + * - A number between 0 and 1, where 0 means no error margin. + */ + public void setLifeError(float error) { + this.lifeError = error * averageLifeLength; + } + + /** + * @param error + * - A number between 0 and 1, where 0 means no error margin. + */ + public void setScaleError(float error) { + this.scaleError = error * averageScale; + } + + public void generateParticles(Vector3f systemCenter, float delta) { + float particlesToCreate = pps * delta; + int count = (int) Math.floor(particlesToCreate); + float partialParticle = particlesToCreate % 1; + for (int i = 0; i < count; i++) { + emitParticle(systemCenter); + } + if (Math.random() < partialParticle) { + emitParticle(systemCenter); + } + } + + public void generateParticles(ParticlePoint particlePoint, float delta) { + float particlesToCreate = pps * delta; + int count = (int) Math.floor(particlesToCreate); + float partialParticle = particlesToCreate % 1; + for (int i = 0; i < count; i++) { + emitParticle(particlePoint.getPos()); + } + if (Math.random() < partialParticle) { + emitParticle(particlePoint.getPos()); + } + } + + private void emitParticle(Vector3f center) { + Vector3f velocity = null; + if (direction != null) { + velocity = generateRandomUnitVectorWithinCone(direction, directionDeviation); + } else { + velocity = generateRandomUnitVector(); + } + velocity.normalise(); + velocity.scale(generateValue(averageSpeed, speedError)); + float scale = generateValue(averageScale, scaleError); + float lifeLength = generateValue(averageLifeLength, lifeError); + new Particle(new Vector3f(center), velocity, gravityComplient, lifeLength, generateRotation(), scale); + } + + private float generateValue(float average, float errorMargin) { + float offset = (random.nextFloat() - 0.5f) * 2f * errorMargin; + return average + offset; + } + + private float generateRotation() { + if (randomRotation) { + return random.nextFloat() * 360f; + } else { + return 0; + } + } + + private static Vector3f generateRandomUnitVectorWithinCone(Vector3f coneDirection, float angle) { + float cosAngle = (float) Math.cos(angle); + Random random = new Random(); + float theta = (float) (random.nextFloat() * 2f * Math.PI); + float z = cosAngle + (random.nextFloat() * (1 - cosAngle)); + float rootOneMinusZSquared = (float) Math.sqrt(1 - z * z); + float x = (float) (rootOneMinusZSquared * Math.cos(theta)); + float y = (float) (rootOneMinusZSquared * Math.sin(theta)); + + Vector4f direction = new Vector4f(x, y, z, 1); + if (coneDirection.x != 0 || coneDirection.y != 0 || (coneDirection.z != 1 && coneDirection.z != -1)) { + Vector3f rotateAxis = Vector3f.cross(coneDirection, new Vector3f(0, 0, 1), null); + rotateAxis.normalise(); + float rotateAngle = (float) Math.acos(Vector3f.dot(coneDirection, new Vector3f(0, 0, 1))); + Matrix4f rotationMatrix = new Matrix4f(); + rotationMatrix.rotate(-rotateAngle, rotateAxis); + Matrix4f.transform(rotationMatrix, direction, direction); + } else if (coneDirection.z == -1) { + direction.z *= -1; + } + return new Vector3f(direction); + } + + private Vector3f generateRandomUnitVector() { + float theta = (float) (random.nextFloat() * 2f * Math.PI); + float z = (random.nextFloat() * 2) - 1; + float rootOneMinusZSquared = (float) Math.sqrt(1 - z * z); + float x = (float) (rootOneMinusZSquared * Math.cos(theta)); + float y = (float) (rootOneMinusZSquared * Math.sin(theta)); + return new Vector3f(x, y, z); + } + +} \ No newline at end of file diff --git a/src/main/java/net/guerra24/voxel/client/resources/GameResources.java b/src/main/java/net/guerra24/voxel/client/resources/GameResources.java index 59bbe5091..91fbe0769 100644 --- a/src/main/java/net/guerra24/voxel/client/resources/GameResources.java +++ b/src/main/java/net/guerra24/voxel/client/resources/GameResources.java @@ -40,6 +40,7 @@ import net.guerra24.voxel.client.graphics.SkyboxRenderer; import net.guerra24.voxel.client.graphics.TextMasterRenderer; import net.guerra24.voxel.client.menu.Menu; +import net.guerra24.voxel.client.particle.ParticleMaster; import net.guerra24.voxel.client.resources.models.GuiTexture; import net.guerra24.voxel.client.sound.LibraryLWJGLOpenAL; import net.guerra24.voxel.client.sound.soundsystem.SoundSystem; @@ -80,7 +81,7 @@ public class GameResources { private TextMasterRenderer textMasterRenderer; private TextHandler textHandler; private GlobalStates globalStates; - private DeferredShadingRenderer postProcessing; + private DeferredShadingRenderer deferredShadingRenderer; private MasterShadowRenderer masterShadowRenderer; private OcclusionRenderer occlusionRenderer; private SoundSystem soundSystem; @@ -119,8 +120,9 @@ public void init() { guiRenderer = new GuiRenderer(loader); occlusionRenderer = new OcclusionRenderer(renderer.getProjectionMatrix()); skyboxRenderer = new SkyboxRenderer(loader, renderer.getProjectionMatrix()); - postProcessing = new DeferredShadingRenderer(loader, this); + deferredShadingRenderer = new DeferredShadingRenderer(loader, this); masterShadowRenderer = new MasterShadowRenderer(); + ParticleMaster.getInstance().init(loader, renderer.getProjectionMatrix()); physics = new Physics(this); frustum = new Frustum(); textMasterRenderer = new TextMasterRenderer(loader); @@ -178,7 +180,8 @@ public void cleanUp() { textMasterRenderer.cleanUp(); masterShadowRenderer.cleanUp(); occlusionRenderer.cleanUp(); - postProcessing.cleanUp(); + ParticleMaster.getInstance().cleanUp(); + deferredShadingRenderer.cleanUp(); guiRenderer.cleanUp(); renderer.cleanUp(); loader.cleanUp(); @@ -229,8 +232,8 @@ public SoundSystem getSoundSystem() { return soundSystem; } - public DeferredShadingRenderer getPostProcessing() { - return postProcessing; + public DeferredShadingRenderer getDeferredShadingRenderer() { + return deferredShadingRenderer; } public Frustum getFrustum() { diff --git a/src/main/java/net/guerra24/voxel/client/world/IWorld.java b/src/main/java/net/guerra24/voxel/client/world/IWorld.java index 218283616..e17011ff8 100644 --- a/src/main/java/net/guerra24/voxel/client/world/IWorld.java +++ b/src/main/java/net/guerra24/voxel/client/world/IWorld.java @@ -15,7 +15,7 @@ public interface IWorld { public void createDimension(GameResources gm, API api); - public void updateChunksGeneration(GameResources gm, API api); + public void updateChunksGeneration(GameResources gm, API api, float delta); public void updateChunksRender(GameResources gm); diff --git a/src/main/java/net/guerra24/voxel/client/world/InfinityWorld.java b/src/main/java/net/guerra24/voxel/client/world/InfinityWorld.java index d19fb246b..61768ab9b 100644 --- a/src/main/java/net/guerra24/voxel/client/world/InfinityWorld.java +++ b/src/main/java/net/guerra24/voxel/client/world/InfinityWorld.java @@ -40,6 +40,8 @@ import net.guerra24.voxel.client.api.API; import net.guerra24.voxel.client.core.VoxelVariables; +import net.guerra24.voxel.client.particle.ParticlePoint; +import net.guerra24.voxel.client.particle.ParticleSystem; import net.guerra24.voxel.client.resources.GameResources; import net.guerra24.voxel.client.util.Logger; import net.guerra24.voxel.client.world.chunks.Chunk; @@ -71,9 +73,10 @@ public class InfinityWorld implements IWorld { private int tempRadius = 0; private int seedi; private ChunkGenerator chunkGenerator; - //private WorldService service; + // private WorldService service; private String codeName = "Infinity"; private Queue lightNodes; + private ParticleSystem particleSystem; @Override public void startWorld(String name, Random seed, int chunkDim, API api, GameResources gm) { @@ -91,12 +94,17 @@ public void startWorld(String name, Random seed, int chunkDim, API api, GameReso @Override public void init(GameResources gm) { + particleSystem = new ParticleSystem(20, 1, -0.01f, 4, 0.2f); + particleSystem.setDirection(new Vector3f(0, 1, 0), 0.1f); + particleSystem.setLifeError(0.8f); + particleSystem.setScaleError(0.2f); + particleSystem.setSpeedError(0.2f); seedi = seed.nextInt(); noise = new SimplexNoise(128, 0.3f, seedi); lightNodes = new LinkedList<>(); chunks = new HashMap(); chunkGenerator = new ChunkGenerator(); - //service = new WorldService(); + // service = new WorldService(); gm.getPhysics().getMobManager().getPlayer().setPosition(gm.getCamera().getPosition()); } @@ -128,7 +136,7 @@ public void createDimension(GameResources gm, API api) { } @Override - public void updateChunksGeneration(GameResources gm, API api) { + public void updateChunksGeneration(GameResources gm, API api, float delta) { if (gm.getCamera().getPosition().x < 0) xPlayChunk = (int) ((gm.getCamera().getPosition().x - 16) / 16); if (gm.getCamera().getPosition().y < 0) @@ -162,6 +170,9 @@ public void updateChunksGeneration(GameResources gm, API api) { } } else { Chunk chunk = getChunk(chunkDim, xx, yy, zz); + for (ParticlePoint particlePoint : chunk.getParticlePoints()) { + particleSystem.generateParticles(particlePoint, delta); + } if (!chunk.created) chunk.createBasicTerrain(this); if (!chunk.decorated) { @@ -523,7 +534,7 @@ public void clearDimension(GameResources gm) { } } } - //service.es.shutdown(); + // service.es.shutdown(); chunks.clear(); } diff --git a/src/main/java/net/guerra24/voxel/client/world/chunks/Chunk.java b/src/main/java/net/guerra24/voxel/client/world/chunks/Chunk.java index 49c5574b6..50005a29e 100644 --- a/src/main/java/net/guerra24/voxel/client/world/chunks/Chunk.java +++ b/src/main/java/net/guerra24/voxel/client/world/chunks/Chunk.java @@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import net.guerra24.voxel.client.core.VoxelVariables; +import net.guerra24.voxel.client.particle.ParticlePoint; import net.guerra24.voxel.client.resources.GameResources; import net.guerra24.voxel.client.util.Logger; import net.guerra24.voxel.client.util.Maths; @@ -52,6 +53,7 @@ public class Chunk { public byte[][][] lightMap; private transient Queue blocksMesh; private transient Queue blocksMeshtemp; + private transient Queue particlePoints; private transient int sizeX, sizeY, sizeZ; private transient boolean readyToRender = true; public transient boolean needsRebuild = true, updated = false, updating = false, empty = true, genQuery = false, @@ -106,6 +108,7 @@ public void init(IWorld world) { public void load() { blocksMesh = new ConcurrentLinkedQueue(); blocksMeshtemp = new ConcurrentLinkedQueue(); + particlePoints = new ConcurrentLinkedQueue(); sizeX = VoxelVariables.CHUNK_SIZE; sizeY = VoxelVariables.CHUNK_HEIGHT; sizeZ = VoxelVariables.CHUNK_SIZE; @@ -136,6 +139,7 @@ public void update(IWorld world) { blocksMeshtemp.addAll(blocksMesh); readyToRender = false; blocksMesh.clear(); + particlePoints.clear(); rebuildChunkSection(blocksMesh, world); calculateLight(blocksMesh, world); readyToRender = true; @@ -196,6 +200,8 @@ public void rebuildChunkSection(Queue cubes, IWorld world) { if (Block.getBlock(blocks[x][y][z]) == Block.Torch) { cubes.add(Block.getBlock(blocks[x][y][z]) .getSingleModel(new Vector3f(x + cx * sizeX, y + cy * sizeY, z + cz * sizeZ))); + particlePoints.add(new ParticlePoint(new Vector3f((x + cx * sizeX) + 0.5f, + (y + cy * sizeY) + 0.8f, (z + cz * sizeZ) - 0.5f))); } else if (Block.getBlock(blocks[x][y][z]).usesSingleModel()) { cubes.add(Block.getBlock(blocks[x][y][z]) .getSingleModel(new Vector3f(x + cx * sizeX, y + cy * sizeY, z + cz * sizeZ))); @@ -295,6 +301,10 @@ public void setTorchLight(int x, int y, int z, int val) { lightMap[x & 0xF][y & 0xF][z & 0xF] = (byte) ((lightMap[x & 0xF][y & 0xF][z & 0xF] & 0xF0) | val); } + public Queue getParticlePoints() { + return particlePoints; + } + private boolean cullFaceWest(int x, int y, int z, IWorld world) { if (x > (cx * sizeX) + 1 && x < (cx * sizeX) + 16) { if (getLocalBlock(x - 1, y, z) != Block.Air.getId() && getLocalBlock(x - 1, y, z) != Block.Water.getId() diff --git a/src/main/java/net/guerra24/voxel/client/world/entities/Player.java b/src/main/java/net/guerra24/voxel/client/world/entities/Player.java index 9d2705911..914051db5 100644 --- a/src/main/java/net/guerra24/voxel/client/world/entities/Player.java +++ b/src/main/java/net/guerra24/voxel/client/world/entities/Player.java @@ -25,6 +25,7 @@ package net.guerra24.voxel.client.world.entities; import net.guerra24.voxel.client.api.API; +import net.guerra24.voxel.client.core.VoxelVariables; import net.guerra24.voxel.client.resources.GameResources; import net.guerra24.voxel.client.resources.GuiResources; import net.guerra24.voxel.client.resources.models.TexturedModel; @@ -35,7 +36,6 @@ import net.guerra24.voxel.universal.util.vector.Vector3f; public class Player extends Entity implements IEntity { - private final float GRAVITY = -10; private final float JUMP_POWER = 4; private boolean isInWater = false; private float upwardsSpeed = 0; @@ -65,7 +65,7 @@ public void update(float delta, GameResources gm, GuiResources gi, IWorld world, isInWater = true; isInAir = false; } else { - upwardsSpeed += GRAVITY * delta; + upwardsSpeed += VoxelVariables.GRAVITY * delta; isInAir = true; isInWater = false; }