From 90c9ae22e8c509f131acacb99bfcb5f04e67c4ea Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Mon, 25 Jul 2022 16:37:28 +0200 Subject: [PATCH] Added better model shading, and visually stretched bullets for fancier appearance. --- .../aos2_client/model/ClientPlayer.java | 11 ++++++++ .../aos2_client/model/OtherPlayer.java | 23 +++++++++++++--- .../aos2_client/render/GameRenderer.java | 26 ++++++++++++------- .../aos2_client/render/ModelRenderer.java | 11 +++++--- .../aos2_client/render/gui/GUIRenderer.java | 3 +++ .../render/model/ModelRenderable.java | 6 +++++ .../main/resources/shader/model/fragment.glsl | 11 +++----- .../main/resources/shader/model/vertex.glsl | 13 ++++++++-- 8 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 client/src/main/java/nl/andrewl/aos2_client/render/model/ModelRenderable.java diff --git a/client/src/main/java/nl/andrewl/aos2_client/model/ClientPlayer.java b/client/src/main/java/nl/andrewl/aos2_client/model/ClientPlayer.java index 40dd04e..e3ed59c 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/model/ClientPlayer.java +++ b/client/src/main/java/nl/andrewl/aos2_client/model/ClientPlayer.java @@ -3,6 +3,7 @@ package nl.andrewl.aos2_client.model; import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.item.Inventory; +import org.joml.Matrix3f; import org.joml.Matrix4f; import java.util.ArrayList; @@ -14,6 +15,9 @@ public class ClientPlayer extends Player { private final Matrix4f heldItemTransform = new Matrix4f(); private final float[] heldItemTransformData = new float[16]; + private final Matrix3f heldItemNormalTransform = new Matrix3f(); + private final float[] heldItemNormalTransformData = new float[9]; + public ClientPlayer(int id, String username) { super(id, username); this.health = 1; @@ -45,9 +49,16 @@ public class ClientPlayer extends Player { .rotate(-cam.getOrientation().y + (float) Math.PI / 2, Camera.RIGHT) .translate(-0.35f, -0.4f, 0.5f); heldItemTransform.get(heldItemTransformData); + + heldItemTransform.normal(heldItemNormalTransform); + heldItemNormalTransform.get(heldItemNormalTransformData); } public float[] getHeldItemTransformData() { return heldItemTransformData; } + + public float[] getHeldItemNormalTransformData() { + return heldItemNormalTransformData; + } } diff --git a/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java b/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java index 5d67717..f155773 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java +++ b/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java @@ -3,6 +3,7 @@ package nl.andrewl.aos2_client.model; import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.item.ItemTypes; +import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; @@ -22,14 +23,15 @@ public class OtherPlayer extends Player { */ private byte selectedBlockValue; - /** - * The transformation used to render this player in the world. - */ private final Matrix4f modelTransform = new Matrix4f(); private final float[] modelTransformData = new float[16]; + private final Matrix3f normalTransform = new Matrix3f(); + private final float[] normalTransformData = new float[9]; private final Matrix4f heldItemTransform = new Matrix4f(); private final float[] heldItemTransformData = new float[16]; + private final Matrix3f heldItemNormalTransform = new Matrix3f(); + private final float[] heldItemNormalTransformData = new float[9]; public OtherPlayer(int id, String username) { super(id, username); @@ -61,17 +63,32 @@ public class OtherPlayer extends Player { .translate(position) .rotate(orientation.x, Camera.UP); modelTransform.get(modelTransformData); + + modelTransform.normal(normalTransform); + normalTransform.get(normalTransformData); + heldItemTransform.set(modelTransform) .translate(0.5f, 1.1f, -0.5f) .rotate((float) Math.PI, Camera.UP); heldItemTransform.get(heldItemTransformData); + + heldItemTransform.normal(heldItemNormalTransform); + heldItemNormalTransform.get(heldItemNormalTransformData); } public float[] getModelTransformData() { return modelTransformData; } + public float[] getNormalTransformData() { + return normalTransformData; + } + public float[] getHeldItemTransformData() { return heldItemTransformData; } + + public float[] getHeldItemNormalTransformData() { + return heldItemNormalTransformData; + } } diff --git a/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java b/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java index 1b1a5c4..812860e 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java +++ b/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java @@ -3,6 +3,7 @@ package nl.andrewl.aos2_client.render; import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Client; import nl.andrewl.aos2_client.config.ClientConfig; +import nl.andrewl.aos2_client.model.ClientPlayer; import nl.andrewl.aos2_client.render.chunk.ChunkRenderer; import nl.andrewl.aos2_client.render.gui.GUIRenderer; import nl.andrewl.aos2_client.render.gui.GUITexture; @@ -11,10 +12,12 @@ import nl.andrewl.aos_core.model.item.BlockItemStack; import nl.andrewl.aos_core.model.item.Gun; import nl.andrewl.aos_core.model.item.GunItemStack; import nl.andrewl.aos_core.model.item.ItemTypes; +import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; import org.lwjgl.glfw.*; import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GLUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -184,9 +187,11 @@ public class GameRenderer { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); chunkRenderer.draw(camera, client.getWorld().getChunkMeshesToDraw()); + ClientPlayer myPlayer = client.getMyPlayer(); + // Draw models. Use one texture at a time for efficiency. modelRenderer.start(camera.getViewTransformData()); - client.getMyPlayer().updateHeldItemTransform(camera); + myPlayer.updateHeldItemTransform(camera); playerModel.bind(); for (var player : client.getPlayers().values()) { @@ -195,17 +200,17 @@ public class GameRenderer { } else { modelRenderer.setAspectColor(new Vector3f(0.3f, 0.3f, 0.3f)); } - modelRenderer.render(playerModel, player.getModelTransformData()); + modelRenderer.render(playerModel, player.getModelTransformData(), player.getNormalTransformData()); } playerModel.unbind(); rifleModel.bind(); - if (client.getMyPlayer().getInventory().getSelectedItemStack().getType().getId() == ItemTypes.RIFLE.getId()) { - modelRenderer.render(rifleModel, client.getMyPlayer().getHeldItemTransformData()); + if (myPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.RIFLE.getId()) { + modelRenderer.render(rifleModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData()); } for (var player : client.getPlayers().values()) { if (player.getHeldItemId() == ItemTypes.RIFLE.getId()) { - modelRenderer.render(rifleModel, player.getHeldItemTransformData()); + modelRenderer.render(rifleModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData()); } } rifleModel.unbind(); @@ -214,23 +219,26 @@ public class GameRenderer { if (client.getMyPlayer().getInventory().getSelectedItemStack().getType().getId() == ItemTypes.BLOCK.getId()) { BlockItemStack stack = (BlockItemStack) client.getMyPlayer().getInventory().getSelectedItemStack(); modelRenderer.setAspectColor(client.getWorld().getPalette().getColor(stack.getSelectedValue())); - modelRenderer.render(blockModel, client.getMyPlayer().getHeldItemTransformData()); + modelRenderer.render(blockModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData()); } modelRenderer.setAspectColor(new Vector3f(0.5f, 0.5f, 0.5f)); for (var player : client.getPlayers().values()) { if (player.getHeldItemId() == ItemTypes.BLOCK.getId()) { - modelRenderer.render(blockModel, player.getHeldItemTransformData()); + modelRenderer.render(blockModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData()); } } blockModel.unbind(); bulletModel.bind(); Matrix4f projectileTransform = new Matrix4f(); + Matrix3f projectileNormalTransform = new Matrix3f(); for (var projectile : client.getProjectiles().values()) { projectileTransform.identity() .translate(projectile.getPosition()) - .rotateTowards(projectile.getVelocity(), Camera.UP); - modelRenderer.render(bulletModel, projectileTransform); + .rotateTowards(projectile.getVelocity(), Camera.UP) + .scale(1, 1, projectile.getVelocity().length() / 5); + projectileTransform.normal(projectileNormalTransform); + modelRenderer.render(bulletModel, projectileTransform, projectileNormalTransform); } bulletModel.unbind(); diff --git a/client/src/main/java/nl/andrewl/aos2_client/render/ModelRenderer.java b/client/src/main/java/nl/andrewl/aos2_client/render/ModelRenderer.java index 1454e6e..6c728ab 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/render/ModelRenderer.java +++ b/client/src/main/java/nl/andrewl/aos2_client/render/ModelRenderer.java @@ -1,6 +1,7 @@ package nl.andrewl.aos2_client.render; import nl.andrewl.aos2_client.render.model.Model; +import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; @@ -14,6 +15,7 @@ public class ModelRenderer { private final int projectionUniform; private final int viewUniform; private final int modelUniform; + private final int normalUniform; private final int textureSamplerUniform; private final int colorUniform; @@ -22,10 +24,11 @@ public class ModelRenderer { .withShader("shader/model/vertex.glsl", GL_VERTEX_SHADER) .withShader("shader/model/fragment.glsl", GL_FRAGMENT_SHADER) .build(); -// System.out.println(glGetProgramInfoLog(shaderProgram.getId())); // Enable for debugging! + System.out.println(glGetProgramInfoLog(shaderProgram.getId())); // Enable for debugging! projectionUniform = shaderProgram.getUniform("projectionTransform"); viewUniform = shaderProgram.getUniform("viewTransform"); modelUniform = shaderProgram.getUniform("modelTransform"); + normalUniform = shaderProgram.getUniform("normalTransform"); colorUniform = shaderProgram.getUniform("aspectColor"); textureSamplerUniform = shaderProgram.getUniform("textureSampler"); } @@ -46,13 +49,15 @@ public class ModelRenderer { glUniform3f(colorUniform, color.x, color.y, color.z); } - public void render(Model model, Matrix4f modelTransform) { + public void render(Model model, Matrix4f modelTransform, Matrix3f normalTransform) { glUniformMatrix4fv(modelUniform, false, modelTransform.get(new float[16])); + glUniformMatrix3fv(normalUniform, false, normalTransform.get(new float[16])); model.draw(); } - public void render(Model model, float[] transformData) { + public void render(Model model, float[] transformData, float[] normalData) { glUniformMatrix4fv(modelUniform, false, transformData); + glUniformMatrix3fv(normalUniform, false, normalData); model.draw(); } diff --git a/client/src/main/java/nl/andrewl/aos2_client/render/gui/GUIRenderer.java b/client/src/main/java/nl/andrewl/aos2_client/render/gui/GUIRenderer.java index 0a85037..6dba8df 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/render/gui/GUIRenderer.java +++ b/client/src/main/java/nl/andrewl/aos2_client/render/gui/GUIRenderer.java @@ -19,6 +19,7 @@ public class GUIRenderer { private final int vertexCount; private final ShaderProgram shaderProgram; private final int transformUniformLocation; + private final int textureSamplerUniform; private final Matrix4f transformMatrix; private final float[] transformMatrixData; @@ -47,6 +48,7 @@ public class GUIRenderer { .withShader("shader/gui/fragment.glsl", GL_FRAGMENT_SHADER) .build(); transformUniformLocation = shaderProgram.getUniform("transform"); + textureSamplerUniform = shaderProgram.getUniform("guiTexture"); shaderProgram.bindAttribute(0, "position"); this.transformMatrix = new Matrix4f(); this.transformMatrixData = new float[16]; @@ -67,6 +69,7 @@ public class GUIRenderer { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); + glUniform1i(textureSamplerUniform, 0); } public void draw(String name, float scaleX, float scaleY, float x, float y) { diff --git a/client/src/main/java/nl/andrewl/aos2_client/render/model/ModelRenderable.java b/client/src/main/java/nl/andrewl/aos2_client/render/model/ModelRenderable.java new file mode 100644 index 0000000..8b7afb9 --- /dev/null +++ b/client/src/main/java/nl/andrewl/aos2_client/render/model/ModelRenderable.java @@ -0,0 +1,6 @@ +package nl.andrewl.aos2_client.render.model; + +public interface ModelRenderable { + float[] getModelTransformData(); + float[] getNormalTransformData(); +} diff --git a/client/src/main/resources/shader/model/fragment.glsl b/client/src/main/resources/shader/model/fragment.glsl index de9da2a..40c1fab 100644 --- a/client/src/main/resources/shader/model/fragment.glsl +++ b/client/src/main/resources/shader/model/fragment.glsl @@ -1,7 +1,7 @@ #version 460 core in vec2 textureCoords; -in vec3 vertexNormal; +in vec3 vertexColor; out vec4 fragmentColor; @@ -14,12 +14,7 @@ void main() { if (baseColor == templateColor) { baseColor = vec4(aspectColor, 1.0); } - vec3 lightDirection = normalize(vec3(0.5, -1.0, -0.5));// TODO: Add this via a uniform. - vec3 lightColor = vec3(1.0, 1.0, 0.9); // TODO: Add this via a uniform. - vec3 ambientComponent = vec3(0.1, 0.1, 0.1); - vec3 diffuseComponent = max(dot(vertexNormal * -1, lightDirection), 0.0) * lightColor; - // TODO: Add shading based on light. - // fragmentColor = vec4((ambientComponent + diffuseComponent), 1.0) * baseColor; - fragmentColor = baseColor; + + fragmentColor = vec4(vertexColor * vec3(baseColor), 1.0); } \ No newline at end of file diff --git a/client/src/main/resources/shader/model/vertex.glsl b/client/src/main/resources/shader/model/vertex.glsl index 9dad643..75e6cbd 100644 --- a/client/src/main/resources/shader/model/vertex.glsl +++ b/client/src/main/resources/shader/model/vertex.glsl @@ -7,12 +7,21 @@ layout (location = 2) in vec2 textureCoordsIn; uniform mat4 projectionTransform; uniform mat4 viewTransform; uniform mat4 modelTransform; +uniform mat3 normalTransform; out vec2 textureCoords; -out vec3 vertexNormal; +out vec3 vertexColor; void main() { gl_Position = projectionTransform * viewTransform * modelTransform * vec4(vertexPositionIn, 1.0); - vertexNormal = vec3(modelTransform * vec4(vertexNormalIn, 1.0)); + vec3 vertexNormal = normalize(normalTransform * vertexNormalIn); + textureCoords = textureCoordsIn; + + vec3 lightDirection = normalize(vec3(0.5, -1.0, -0.5));// TODO: Add this via a uniform. + vec3 lightColor = vec3(1.0, 1.0, 0.9); // TODO: Add this via a uniform. + + float ambientComponent = 0.1; + float diffuseComponent = max(dot(-vertexNormal, lightDirection), 0.0); + vertexColor = (ambientComponent + diffuseComponent) * lightColor; } \ No newline at end of file