Added better model shading, and visually stretched bullets for fancier appearance.

This commit is contained in:
Andrew Lalis 2022-07-25 16:37:28 +02:00
parent 4e0e1a32fa
commit 90c9ae22e8
8 changed files with 79 additions and 25 deletions

View File

@ -3,6 +3,7 @@ package nl.andrewl.aos2_client.model;
import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.item.Inventory; import nl.andrewl.aos_core.model.item.Inventory;
import org.joml.Matrix3f;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import java.util.ArrayList; import java.util.ArrayList;
@ -14,6 +15,9 @@ public class ClientPlayer extends Player {
private final Matrix4f heldItemTransform = new Matrix4f(); private final Matrix4f heldItemTransform = new Matrix4f();
private final float[] heldItemTransformData = new float[16]; 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) { public ClientPlayer(int id, String username) {
super(id, username); super(id, username);
this.health = 1; this.health = 1;
@ -45,9 +49,16 @@ public class ClientPlayer extends Player {
.rotate(-cam.getOrientation().y + (float) Math.PI / 2, Camera.RIGHT) .rotate(-cam.getOrientation().y + (float) Math.PI / 2, Camera.RIGHT)
.translate(-0.35f, -0.4f, 0.5f); .translate(-0.35f, -0.4f, 0.5f);
heldItemTransform.get(heldItemTransformData); heldItemTransform.get(heldItemTransformData);
heldItemTransform.normal(heldItemNormalTransform);
heldItemNormalTransform.get(heldItemNormalTransformData);
} }
public float[] getHeldItemTransformData() { public float[] getHeldItemTransformData() {
return heldItemTransformData; return heldItemTransformData;
} }
public float[] getHeldItemNormalTransformData() {
return heldItemNormalTransformData;
}
} }

View File

@ -3,6 +3,7 @@ package nl.andrewl.aos2_client.model;
import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.item.ItemTypes; import nl.andrewl.aos_core.model.item.ItemTypes;
import org.joml.Matrix3f;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -22,14 +23,15 @@ public class OtherPlayer extends Player {
*/ */
private byte selectedBlockValue; private byte selectedBlockValue;
/**
* The transformation used to render this player in the world.
*/
private final Matrix4f modelTransform = new Matrix4f(); private final Matrix4f modelTransform = new Matrix4f();
private final float[] modelTransformData = new float[16]; 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 Matrix4f heldItemTransform = new Matrix4f();
private final float[] heldItemTransformData = new float[16]; 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) { public OtherPlayer(int id, String username) {
super(id, username); super(id, username);
@ -61,17 +63,32 @@ public class OtherPlayer extends Player {
.translate(position) .translate(position)
.rotate(orientation.x, Camera.UP); .rotate(orientation.x, Camera.UP);
modelTransform.get(modelTransformData); modelTransform.get(modelTransformData);
modelTransform.normal(normalTransform);
normalTransform.get(normalTransformData);
heldItemTransform.set(modelTransform) heldItemTransform.set(modelTransform)
.translate(0.5f, 1.1f, -0.5f) .translate(0.5f, 1.1f, -0.5f)
.rotate((float) Math.PI, Camera.UP); .rotate((float) Math.PI, Camera.UP);
heldItemTransform.get(heldItemTransformData); heldItemTransform.get(heldItemTransformData);
heldItemTransform.normal(heldItemNormalTransform);
heldItemNormalTransform.get(heldItemNormalTransformData);
} }
public float[] getModelTransformData() { public float[] getModelTransformData() {
return modelTransformData; return modelTransformData;
} }
public float[] getNormalTransformData() {
return normalTransformData;
}
public float[] getHeldItemTransformData() { public float[] getHeldItemTransformData() {
return heldItemTransformData; return heldItemTransformData;
} }
public float[] getHeldItemNormalTransformData() {
return heldItemNormalTransformData;
}
} }

View File

@ -3,6 +3,7 @@ package nl.andrewl.aos2_client.render;
import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.Client; import nl.andrewl.aos2_client.Client;
import nl.andrewl.aos2_client.config.ClientConfig; 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.chunk.ChunkRenderer;
import nl.andrewl.aos2_client.render.gui.GUIRenderer; import nl.andrewl.aos2_client.render.gui.GUIRenderer;
import nl.andrewl.aos2_client.render.gui.GUITexture; 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.Gun;
import nl.andrewl.aos_core.model.item.GunItemStack; import nl.andrewl.aos_core.model.item.GunItemStack;
import nl.andrewl.aos_core.model.item.ItemTypes; import nl.andrewl.aos_core.model.item.ItemTypes;
import org.joml.Matrix3f;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.lwjgl.glfw.*; import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GLUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -184,9 +187,11 @@ public class GameRenderer {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
chunkRenderer.draw(camera, client.getWorld().getChunkMeshesToDraw()); chunkRenderer.draw(camera, client.getWorld().getChunkMeshesToDraw());
ClientPlayer myPlayer = client.getMyPlayer();
// Draw models. Use one texture at a time for efficiency. // Draw models. Use one texture at a time for efficiency.
modelRenderer.start(camera.getViewTransformData()); modelRenderer.start(camera.getViewTransformData());
client.getMyPlayer().updateHeldItemTransform(camera); myPlayer.updateHeldItemTransform(camera);
playerModel.bind(); playerModel.bind();
for (var player : client.getPlayers().values()) { for (var player : client.getPlayers().values()) {
@ -195,17 +200,17 @@ public class GameRenderer {
} else { } else {
modelRenderer.setAspectColor(new Vector3f(0.3f, 0.3f, 0.3f)); modelRenderer.setAspectColor(new Vector3f(0.3f, 0.3f, 0.3f));
} }
modelRenderer.render(playerModel, player.getModelTransformData()); modelRenderer.render(playerModel, player.getModelTransformData(), player.getNormalTransformData());
} }
playerModel.unbind(); playerModel.unbind();
rifleModel.bind(); rifleModel.bind();
if (client.getMyPlayer().getInventory().getSelectedItemStack().getType().getId() == ItemTypes.RIFLE.getId()) { if (myPlayer.getInventory().getSelectedItemStack().getType().getId() == ItemTypes.RIFLE.getId()) {
modelRenderer.render(rifleModel, client.getMyPlayer().getHeldItemTransformData()); modelRenderer.render(rifleModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData());
} }
for (var player : client.getPlayers().values()) { for (var player : client.getPlayers().values()) {
if (player.getHeldItemId() == ItemTypes.RIFLE.getId()) { if (player.getHeldItemId() == ItemTypes.RIFLE.getId()) {
modelRenderer.render(rifleModel, player.getHeldItemTransformData()); modelRenderer.render(rifleModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData());
} }
} }
rifleModel.unbind(); rifleModel.unbind();
@ -214,23 +219,26 @@ public class GameRenderer {
if (client.getMyPlayer().getInventory().getSelectedItemStack().getType().getId() == ItemTypes.BLOCK.getId()) { if (client.getMyPlayer().getInventory().getSelectedItemStack().getType().getId() == ItemTypes.BLOCK.getId()) {
BlockItemStack stack = (BlockItemStack) client.getMyPlayer().getInventory().getSelectedItemStack(); BlockItemStack stack = (BlockItemStack) client.getMyPlayer().getInventory().getSelectedItemStack();
modelRenderer.setAspectColor(client.getWorld().getPalette().getColor(stack.getSelectedValue())); 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)); modelRenderer.setAspectColor(new Vector3f(0.5f, 0.5f, 0.5f));
for (var player : client.getPlayers().values()) { for (var player : client.getPlayers().values()) {
if (player.getHeldItemId() == ItemTypes.BLOCK.getId()) { if (player.getHeldItemId() == ItemTypes.BLOCK.getId()) {
modelRenderer.render(blockModel, player.getHeldItemTransformData()); modelRenderer.render(blockModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData());
} }
} }
blockModel.unbind(); blockModel.unbind();
bulletModel.bind(); bulletModel.bind();
Matrix4f projectileTransform = new Matrix4f(); Matrix4f projectileTransform = new Matrix4f();
Matrix3f projectileNormalTransform = new Matrix3f();
for (var projectile : client.getProjectiles().values()) { for (var projectile : client.getProjectiles().values()) {
projectileTransform.identity() projectileTransform.identity()
.translate(projectile.getPosition()) .translate(projectile.getPosition())
.rotateTowards(projectile.getVelocity(), Camera.UP); .rotateTowards(projectile.getVelocity(), Camera.UP)
modelRenderer.render(bulletModel, projectileTransform); .scale(1, 1, projectile.getVelocity().length() / 5);
projectileTransform.normal(projectileNormalTransform);
modelRenderer.render(bulletModel, projectileTransform, projectileNormalTransform);
} }
bulletModel.unbind(); bulletModel.unbind();

View File

@ -1,6 +1,7 @@
package nl.andrewl.aos2_client.render; package nl.andrewl.aos2_client.render;
import nl.andrewl.aos2_client.render.model.Model; import nl.andrewl.aos2_client.render.model.Model;
import org.joml.Matrix3f;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -14,6 +15,7 @@ public class ModelRenderer {
private final int projectionUniform; private final int projectionUniform;
private final int viewUniform; private final int viewUniform;
private final int modelUniform; private final int modelUniform;
private final int normalUniform;
private final int textureSamplerUniform; private final int textureSamplerUniform;
private final int colorUniform; private final int colorUniform;
@ -22,10 +24,11 @@ public class ModelRenderer {
.withShader("shader/model/vertex.glsl", GL_VERTEX_SHADER) .withShader("shader/model/vertex.glsl", GL_VERTEX_SHADER)
.withShader("shader/model/fragment.glsl", GL_FRAGMENT_SHADER) .withShader("shader/model/fragment.glsl", GL_FRAGMENT_SHADER)
.build(); .build();
// System.out.println(glGetProgramInfoLog(shaderProgram.getId())); // Enable for debugging! System.out.println(glGetProgramInfoLog(shaderProgram.getId())); // Enable for debugging!
projectionUniform = shaderProgram.getUniform("projectionTransform"); projectionUniform = shaderProgram.getUniform("projectionTransform");
viewUniform = shaderProgram.getUniform("viewTransform"); viewUniform = shaderProgram.getUniform("viewTransform");
modelUniform = shaderProgram.getUniform("modelTransform"); modelUniform = shaderProgram.getUniform("modelTransform");
normalUniform = shaderProgram.getUniform("normalTransform");
colorUniform = shaderProgram.getUniform("aspectColor"); colorUniform = shaderProgram.getUniform("aspectColor");
textureSamplerUniform = shaderProgram.getUniform("textureSampler"); textureSamplerUniform = shaderProgram.getUniform("textureSampler");
} }
@ -46,13 +49,15 @@ public class ModelRenderer {
glUniform3f(colorUniform, color.x, color.y, color.z); 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])); glUniformMatrix4fv(modelUniform, false, modelTransform.get(new float[16]));
glUniformMatrix3fv(normalUniform, false, normalTransform.get(new float[16]));
model.draw(); model.draw();
} }
public void render(Model model, float[] transformData) { public void render(Model model, float[] transformData, float[] normalData) {
glUniformMatrix4fv(modelUniform, false, transformData); glUniformMatrix4fv(modelUniform, false, transformData);
glUniformMatrix3fv(normalUniform, false, normalData);
model.draw(); model.draw();
} }

View File

@ -19,6 +19,7 @@ public class GUIRenderer {
private final int vertexCount; private final int vertexCount;
private final ShaderProgram shaderProgram; private final ShaderProgram shaderProgram;
private final int transformUniformLocation; private final int transformUniformLocation;
private final int textureSamplerUniform;
private final Matrix4f transformMatrix; private final Matrix4f transformMatrix;
private final float[] transformMatrixData; private final float[] transformMatrixData;
@ -47,6 +48,7 @@ public class GUIRenderer {
.withShader("shader/gui/fragment.glsl", GL_FRAGMENT_SHADER) .withShader("shader/gui/fragment.glsl", GL_FRAGMENT_SHADER)
.build(); .build();
transformUniformLocation = shaderProgram.getUniform("transform"); transformUniformLocation = shaderProgram.getUniform("transform");
textureSamplerUniform = shaderProgram.getUniform("guiTexture");
shaderProgram.bindAttribute(0, "position"); shaderProgram.bindAttribute(0, "position");
this.transformMatrix = new Matrix4f(); this.transformMatrix = new Matrix4f();
this.transformMatrixData = new float[16]; this.transformMatrixData = new float[16];
@ -67,6 +69,7 @@ public class GUIRenderer {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glUniform1i(textureSamplerUniform, 0);
} }
public void draw(String name, float scaleX, float scaleY, float x, float y) { public void draw(String name, float scaleX, float scaleY, float x, float y) {

View File

@ -0,0 +1,6 @@
package nl.andrewl.aos2_client.render.model;
public interface ModelRenderable {
float[] getModelTransformData();
float[] getNormalTransformData();
}

View File

@ -1,7 +1,7 @@
#version 460 core #version 460 core
in vec2 textureCoords; in vec2 textureCoords;
in vec3 vertexNormal; in vec3 vertexColor;
out vec4 fragmentColor; out vec4 fragmentColor;
@ -14,12 +14,7 @@ void main() {
if (baseColor == templateColor) { if (baseColor == templateColor) {
baseColor = vec4(aspectColor, 1.0); 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; fragmentColor = vec4(vertexColor * vec3(baseColor), 1.0);
// TODO: Add shading based on light.
// fragmentColor = vec4((ambientComponent + diffuseComponent), 1.0) * baseColor;
fragmentColor = baseColor;
} }

View File

@ -7,12 +7,21 @@ layout (location = 2) in vec2 textureCoordsIn;
uniform mat4 projectionTransform; uniform mat4 projectionTransform;
uniform mat4 viewTransform; uniform mat4 viewTransform;
uniform mat4 modelTransform; uniform mat4 modelTransform;
uniform mat3 normalTransform;
out vec2 textureCoords; out vec2 textureCoords;
out vec3 vertexNormal; out vec3 vertexColor;
void main() { void main() {
gl_Position = projectionTransform * viewTransform * modelTransform * vec4(vertexPositionIn, 1.0); gl_Position = projectionTransform * viewTransform * modelTransform * vec4(vertexPositionIn, 1.0);
vertexNormal = vec3(modelTransform * vec4(vertexNormalIn, 1.0)); vec3 vertexNormal = normalize(normalTransform * vertexNormalIn);
textureCoords = textureCoordsIn; 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;
} }