Organized client code a bit more, and added GUI crosshair thing.
This commit is contained in:
parent
ab69ccbe5b
commit
91ef650457
|
@ -1,13 +1,19 @@
|
||||||
package nl.andrewl.aos2_client.render;
|
package nl.andrewl.aos2_client.render;
|
||||||
|
|
||||||
import nl.andrewl.aos2_client.Camera;
|
import nl.andrewl.aos2_client.Camera;
|
||||||
|
import nl.andrewl.aos2_client.render.chunk.ChunkRenderer;
|
||||||
|
import nl.andrewl.aos2_client.render.gui.GUIRenderer;
|
||||||
|
import nl.andrewl.aos2_client.render.gui.GUITexture;
|
||||||
import nl.andrewl.aos_core.model.World;
|
import nl.andrewl.aos_core.model.World;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
import static org.lwjgl.opengl.GL46.*;
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
@ -23,6 +29,7 @@ public class GameRenderer {
|
||||||
private static final float Z_FAR = 500f;
|
private static final float Z_FAR = 500f;
|
||||||
|
|
||||||
private final ChunkRenderer chunkRenderer;
|
private final ChunkRenderer chunkRenderer;
|
||||||
|
private final GUIRenderer guiRenderer;
|
||||||
private final Camera camera;
|
private final Camera camera;
|
||||||
private final World world;
|
private final World world;
|
||||||
|
|
||||||
|
@ -38,6 +45,7 @@ public class GameRenderer {
|
||||||
public GameRenderer(World world) {
|
public GameRenderer(World world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.chunkRenderer = new ChunkRenderer();
|
this.chunkRenderer = new ChunkRenderer();
|
||||||
|
this.guiRenderer = new GUIRenderer();
|
||||||
this.camera = new Camera();
|
this.camera = new Camera();
|
||||||
this.perspectiveTransform = new Matrix4f();
|
this.perspectiveTransform = new Matrix4f();
|
||||||
|
|
||||||
|
@ -52,6 +60,7 @@ public class GameRenderer {
|
||||||
|
|
||||||
primaryMonitorSettings = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
primaryMonitorSettings = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||||
if (primaryMonitorSettings == null) throw new IllegalStateException("Could not get information about the primary monitory.");
|
if (primaryMonitorSettings == null) throw new IllegalStateException("Could not get information about the primary monitory.");
|
||||||
|
log.debug("Primary monitor settings: Width: {}, Height: {}", primaryMonitorSettings.width(), primaryMonitorSettings.height());
|
||||||
windowHandle = glfwCreateWindow(screenWidth, screenHeight, "Ace of Shades 2", 0, 0);
|
windowHandle = glfwCreateWindow(screenWidth, screenHeight, "Ace of Shades 2", 0, 0);
|
||||||
if (windowHandle == 0) throw new RuntimeException("Failed to create GLFW window.");
|
if (windowHandle == 0) throw new RuntimeException("Failed to create GLFW window.");
|
||||||
fullscreen = false;
|
fullscreen = false;
|
||||||
|
@ -80,6 +89,16 @@ public class GameRenderer {
|
||||||
log.debug("Initialized OpenGL context.");
|
log.debug("Initialized OpenGL context.");
|
||||||
|
|
||||||
chunkRenderer.setupShaderProgram();
|
chunkRenderer.setupShaderProgram();
|
||||||
|
guiRenderer.setup();
|
||||||
|
// TODO: More organized way to load textures for GUI.
|
||||||
|
try {
|
||||||
|
var crosshairTexture = new GUITexture("gui/crosshair.png");
|
||||||
|
float size = 32;
|
||||||
|
crosshairTexture.getScale().set(size / screenWidth, size / screenHeight);
|
||||||
|
guiRenderer.addTexture(crosshairTexture);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
updatePerspective();
|
updatePerspective();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,12 +162,14 @@ public class GameRenderer {
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
chunkRenderer.draw(camera, world);
|
chunkRenderer.draw(camera, world);
|
||||||
|
guiRenderer.draw();
|
||||||
|
|
||||||
glfwSwapBuffers(windowHandle);
|
glfwSwapBuffers(windowHandle);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void freeWindow() {
|
public void freeWindow() {
|
||||||
|
guiRenderer.free();
|
||||||
chunkRenderer.free();
|
chunkRenderer.free();
|
||||||
GL.destroy();
|
GL.destroy();
|
||||||
Callbacks.glfwFreeCallbacks(windowHandle);
|
Callbacks.glfwFreeCallbacks(windowHandle);
|
||||||
|
|
|
@ -28,10 +28,18 @@ public class ShaderProgram {
|
||||||
glUseProgram(id);
|
glUseProgram(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stopUsing() {
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
||||||
|
|
||||||
public int getUniform(String name) {
|
public int getUniform(String name) {
|
||||||
return glGetUniformLocation(id, name);
|
return glGetUniformLocation(id, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void bindAttribute(int attribute, String variableName) {
|
||||||
|
glBindAttribLocation(id, attribute, variableName);
|
||||||
|
}
|
||||||
|
|
||||||
public void free() {
|
public void free() {
|
||||||
glDeleteProgram(id);
|
glDeleteProgram(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render;
|
package nl.andrewl.aos2_client.render.chunk;
|
||||||
|
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render;
|
package nl.andrewl.aos2_client.render.chunk;
|
||||||
|
|
||||||
import nl.andrewl.aos_core.model.Chunk;
|
import nl.andrewl.aos_core.model.Chunk;
|
||||||
import nl.andrewl.aos_core.model.World;
|
import nl.andrewl.aos_core.model.World;
|
||||||
|
@ -89,8 +89,15 @@ public class ChunkMesh {
|
||||||
*/
|
*/
|
||||||
public void draw() {
|
public void draw() {
|
||||||
glBindVertexArray(vaoId);
|
glBindVertexArray(vaoId);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
|
||||||
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
glDisableVertexAttribArray(1);
|
||||||
|
glDisableVertexAttribArray(2);
|
||||||
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void free() {
|
public void free() {
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render;
|
package nl.andrewl.aos2_client.render.chunk;
|
||||||
|
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render;
|
package nl.andrewl.aos2_client.render.chunk;
|
||||||
|
|
||||||
import nl.andrewl.aos_core.model.Chunk;
|
import nl.andrewl.aos_core.model.Chunk;
|
||||||
import nl.andrewl.aos_core.model.World;
|
import nl.andrewl.aos_core.model.World;
|
|
@ -1,6 +1,7 @@
|
||||||
package nl.andrewl.aos2_client.render;
|
package nl.andrewl.aos2_client.render.chunk;
|
||||||
|
|
||||||
import nl.andrewl.aos2_client.Camera;
|
import nl.andrewl.aos2_client.Camera;
|
||||||
|
import nl.andrewl.aos2_client.render.ShaderProgram;
|
||||||
import nl.andrewl.aos_core.model.Chunk;
|
import nl.andrewl.aos_core.model.Chunk;
|
||||||
import nl.andrewl.aos_core.model.World;
|
import nl.andrewl.aos_core.model.World;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
|
@ -0,0 +1,86 @@
|
||||||
|
package nl.andrewl.aos2_client.render.gui;
|
||||||
|
|
||||||
|
import nl.andrewl.aos2_client.render.ShaderProgram;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages rendering of 2D GUI components like cross-hairs, inventory stuff, etc.
|
||||||
|
*/
|
||||||
|
public class GUIRenderer {
|
||||||
|
private int vaoId;
|
||||||
|
private int vboId;
|
||||||
|
private int vertexCount;
|
||||||
|
private ShaderProgram shaderProgram;
|
||||||
|
private int transformUniformLocation;
|
||||||
|
|
||||||
|
|
||||||
|
private final List<GUITexture> guiTextures = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addTexture(GUITexture texture) {
|
||||||
|
guiTextures.add(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setup() {
|
||||||
|
vaoId = glGenVertexArrays();
|
||||||
|
vboId = glGenBuffers();
|
||||||
|
FloatBuffer buffer = BufferUtils.createFloatBuffer(8);
|
||||||
|
buffer.put(new float[]{
|
||||||
|
-1, 1,
|
||||||
|
-1, -1,
|
||||||
|
1, 1,
|
||||||
|
1, -1
|
||||||
|
});
|
||||||
|
buffer.flip();
|
||||||
|
vertexCount = buffer.limit();
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vboId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindVertexArray(vaoId);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, false, 2 * Float.BYTES, 0);
|
||||||
|
shaderProgram = new ShaderProgram.Builder()
|
||||||
|
.withShader("shader/gui/vertex.glsl", GL_VERTEX_SHADER)
|
||||||
|
.withShader("shader/gui/fragment.glsl", GL_FRAGMENT_SHADER)
|
||||||
|
.build();
|
||||||
|
transformUniformLocation = shaderProgram.getUniform("transform");
|
||||||
|
shaderProgram.bindAttribute(0, "position");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void draw() {
|
||||||
|
shaderProgram.use();
|
||||||
|
glBindVertexArray(vaoId);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
for (var texture : guiTextures) {
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
Matrix4f transform = new Matrix4f()
|
||||||
|
.translate(texture.getPosition().x, texture.getPosition().y, 0)
|
||||||
|
.scale(texture.getScale().x, texture.getScale().y, 1);
|
||||||
|
float[] transformData = new float[16];
|
||||||
|
transform.get(transformData);
|
||||||
|
glUniformMatrix4fv(transformUniformLocation, false, transformData);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture.getTextureId());
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount);
|
||||||
|
}
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void free() {
|
||||||
|
for (var tex : guiTextures) tex.free();
|
||||||
|
glDeleteBuffers(vboId);
|
||||||
|
glDeleteVertexArrays(vaoId);
|
||||||
|
shaderProgram.free();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package nl.andrewl.aos2_client.render.gui;
|
||||||
|
|
||||||
|
import nl.andrewl.aos_core.ImageUtils;
|
||||||
|
import org.joml.Vector2f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
public class GUITexture {
|
||||||
|
private final int textureId;
|
||||||
|
private final int width;
|
||||||
|
private final int height;
|
||||||
|
private final Vector2f position = new Vector2f(0, 0);
|
||||||
|
private final Vector2f scale = new Vector2f(1, 1);
|
||||||
|
|
||||||
|
public GUITexture(String location) throws IOException {
|
||||||
|
try (var in = GUITexture.class.getClassLoader().getResourceAsStream(location)) {
|
||||||
|
if (in == null) throw new IOException("Couldn't load texture image from " + location);
|
||||||
|
BufferedImage img = ImageIO.read(in);
|
||||||
|
width = img.getWidth();
|
||||||
|
height = img.getHeight();
|
||||||
|
|
||||||
|
textureId = glGenTextures();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, textureId);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
var buf = ImageUtils.decodePng(img);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTextureId() {
|
||||||
|
return textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2f getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2f getScale() {
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void free() {
|
||||||
|
glDeleteTextures(textureId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple data structure class holding information about a certain glyph in the
|
* Simple data structure class holding information about a certain glyph in the
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import nl.andrewl.aos2_client.render.ShaderProgram;
|
import nl.andrewl.aos2_client.render.ShaderProgram;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
import org.lwjgl.BufferUtils;
|
|
||||||
|
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL46.*;
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the vertex data for all the quads on which a text will be rendered.
|
* Stores the vertex data for all the quads on which a text will be rendered.
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewl.aos2_client.render.font;
|
package nl.andrewl.aos2_client.render.gui.font;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
Binary file not shown.
After Width: | Height: | Size: 218 B |
|
@ -0,0 +1,10 @@
|
||||||
|
#version 460 core
|
||||||
|
|
||||||
|
in vec2 texturePosition;
|
||||||
|
out vec4 fragmentColor;
|
||||||
|
|
||||||
|
uniform sampler2D guiTexture;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragmentColor = texture(guiTexture, texturePosition);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
#version 460 core
|
||||||
|
|
||||||
|
in vec2 position;
|
||||||
|
out vec2 texturePosition;
|
||||||
|
|
||||||
|
uniform mat4 transform;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = transform * vec4(position, 0.0, 1.0);
|
||||||
|
texturePosition = vec2(
|
||||||
|
(position.x + 1.0) / 2.0,
|
||||||
|
1 - (position.y + 1.0) / 2.0
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.andrewl.aos_core;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class ImageUtils {
|
||||||
|
public static ByteBuffer decodePng(BufferedImage image) {
|
||||||
|
int width = image.getWidth();
|
||||||
|
int height = image.getHeight();
|
||||||
|
|
||||||
|
// Load texture contents into a byte buffer
|
||||||
|
ByteBuffer buf = ByteBuffer.allocateDirect(4 * width * height );
|
||||||
|
|
||||||
|
// decode image
|
||||||
|
// ARGB format to -> RGBA
|
||||||
|
for( int h = 0; h < height; h++ )
|
||||||
|
for( int w = 0; w < width; w++ ) {
|
||||||
|
int argb = image.getRGB( w, h );
|
||||||
|
buf.put( (byte) ( 0xFF & ( argb >> 16 ) ) );
|
||||||
|
buf.put( (byte) ( 0xFF & ( argb >> 8 ) ) );
|
||||||
|
buf.put( (byte) ( 0xFF & ( argb ) ) );
|
||||||
|
buf.put( (byte) ( 0xFF & ( argb >> 24 ) ) );
|
||||||
|
}
|
||||||
|
buf.flip();
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue