Replaced old rendering with nanoVG based GUI rendering.
This commit is contained in:
parent
0b5bfca706
commit
3a70a4566b
|
@ -6,12 +6,9 @@ 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;
|
||||
import nl.andrewl.aos2_client.render.model.Model;
|
||||
import nl.andrewl.aos_core.model.Team;
|
||||
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;
|
||||
|
@ -53,13 +50,6 @@ public class GameRenderer {
|
|||
private Model shotgunModel;
|
||||
private Model flagModel;
|
||||
|
||||
// Standard GUI textures.
|
||||
private GUITexture crosshairTexture;
|
||||
private GUITexture clipTexture;
|
||||
private GUITexture bulletTexture;
|
||||
private GUITexture healthBarRedTexture;
|
||||
private GUITexture healthBarGreenTexture;
|
||||
|
||||
private long windowHandle;
|
||||
private int screenWidth = 800;
|
||||
private int screenHeight = 600;
|
||||
|
@ -134,16 +124,6 @@ public class GameRenderer {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
crosshairTexture = new GUITexture("gui/crosshair.png");
|
||||
clipTexture = new GUITexture("gui/clip.png");
|
||||
bulletTexture = new GUITexture("gui/bullet.png");
|
||||
healthBarRedTexture = new GUITexture("gui/health-red.png");
|
||||
healthBarGreenTexture = new GUITexture("gui/health-green.png");
|
||||
guiRenderer.addTexture("crosshair", crosshairTexture);
|
||||
guiRenderer.addTexture("clip", clipTexture);
|
||||
guiRenderer.addTexture("bullet", bulletTexture);
|
||||
guiRenderer.addTexture("health-red", healthBarRedTexture);
|
||||
guiRenderer.addTexture("health-green", healthBarGreenTexture);
|
||||
log.debug("Initialized GUI renderer.");
|
||||
|
||||
this.modelRenderer = new ModelRenderer();
|
||||
|
@ -183,10 +163,6 @@ public class GameRenderer {
|
|||
if (modelRenderer != null) modelRenderer.setPerspective(data);
|
||||
}
|
||||
|
||||
public Matrix4f getPerspectiveTransform() {
|
||||
return perspectiveTransform;
|
||||
}
|
||||
|
||||
public boolean windowShouldClose() {
|
||||
return glfwWindowShouldClose(windowHandle);
|
||||
}
|
||||
|
@ -290,45 +266,7 @@ public class GameRenderer {
|
|||
|
||||
// GUI rendering
|
||||
guiRenderer.start();
|
||||
guiRenderer.draw(crosshairTexture, crosshairTexture.getIdealScaleX(32, screenWidth), crosshairTexture.getIdealScaleY(32, screenHeight), 0, 0);
|
||||
// If we're holding a gun, draw clip and bullet graphics.
|
||||
if (client.getMyPlayer().getInventory().getSelectedItemStack().getType() instanceof Gun) {
|
||||
GunItemStack stack = (GunItemStack) client.getMyPlayer().getInventory().getSelectedItemStack();
|
||||
for (int i = 0; i < stack.getClipCount(); i++) {
|
||||
guiRenderer.draw(
|
||||
clipTexture,
|
||||
clipTexture.getIdealScaleX(64, screenWidth),
|
||||
clipTexture.getIdealScaleY(clipTexture.getIdealHeight(64), screenHeight),
|
||||
0.90f,
|
||||
-0.90f + (i * 0.15f)
|
||||
);
|
||||
}
|
||||
for (int i = 0; i < stack.getBulletCount(); i++) {
|
||||
guiRenderer.draw(
|
||||
bulletTexture,
|
||||
bulletTexture.getIdealScaleX(16, screenWidth),
|
||||
bulletTexture.getIdealScaleY(bulletTexture.getIdealHeight(16), screenHeight),
|
||||
0.80f - (i * 0.05f),
|
||||
-0.90f
|
||||
);
|
||||
}
|
||||
}
|
||||
// Render the player's health.
|
||||
guiRenderer.draw(
|
||||
healthBarRedTexture,
|
||||
healthBarRedTexture.getIdealScaleX(64, screenWidth),
|
||||
healthBarRedTexture.getIdealScaleY(16, screenHeight),
|
||||
-0.90f,
|
||||
-0.90f
|
||||
);
|
||||
guiRenderer.draw(
|
||||
healthBarGreenTexture,
|
||||
healthBarGreenTexture.getIdealScaleX(64 * client.getMyPlayer().getHealth(), screenWidth),
|
||||
healthBarGreenTexture.getIdealScaleY(16, screenHeight),
|
||||
-0.90f,
|
||||
-0.90f
|
||||
);
|
||||
guiRenderer.drawNvg(screenWidth, screenHeight);
|
||||
guiRenderer.drawNvg(screenWidth, screenHeight, myPlayer);
|
||||
guiRenderer.end();
|
||||
|
||||
glfwSwapBuffers(windowHandle);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package nl.andrewl.aos2_client.render.gui;
|
||||
|
||||
import nl.andrewl.aos_core.FileUtils;
|
||||
import nl.andrewl.aos_core.ImageUtils;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
|
@ -23,23 +24,21 @@ public class GUITexture {
|
|||
*/
|
||||
private final int height;
|
||||
|
||||
public GUITexture(String location) {
|
||||
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();
|
||||
public GUITexture(String location) throws IOException {
|
||||
this(FileUtils.readClasspathImage(location));
|
||||
}
|
||||
|
||||
textureId = glGenTextures();
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
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);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to load GUI texture.", e);
|
||||
}
|
||||
public GUITexture(BufferedImage img) {
|
||||
width = img.getWidth();
|
||||
height = img.getHeight();
|
||||
|
||||
textureId = glGenTextures();
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
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 getWidth() {
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package nl.andrewl.aos2_client.render.gui;
|
||||
|
||||
import nl.andrewl.aos2_client.model.ClientPlayer;
|
||||
import nl.andrewl.aos2_client.render.ShaderProgram;
|
||||
import nl.andrewl.aos2_client.util.ResourceUtils;
|
||||
import nl.andrewl.aos_core.FileUtils;
|
||||
import nl.andrewl.aos_core.model.item.BlockItem;
|
||||
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 org.joml.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.nanovg.NVGColor;
|
||||
|
@ -35,6 +39,7 @@ public class GuiRenderer {
|
|||
private static final NVGPaint paintB = NVGPaint.create();
|
||||
private static final NVGPaint paintC = NVGPaint.create();
|
||||
|
||||
// Simple 2d texture quad information.
|
||||
private final int vaoId;
|
||||
private final int vboId;
|
||||
private final int vertexCount;
|
||||
|
@ -85,7 +90,11 @@ public class GuiRenderer {
|
|||
}
|
||||
|
||||
public void loadTexture(String name, String resource) {
|
||||
textures.put(name, new GUITexture(resource));
|
||||
try {
|
||||
textures.put(name, new GUITexture(resource));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTexture(String name, GUITexture texture) {
|
||||
|
@ -102,10 +111,6 @@ public class GuiRenderer {
|
|||
glUniform1i(textureSamplerUniform, 0);
|
||||
}
|
||||
|
||||
public void draw(String name, float scaleX, float scaleY, float x, float y) {
|
||||
draw(textures.get(name), scaleX, scaleY, x, y);
|
||||
}
|
||||
|
||||
public void draw(GUITexture texture, float scaleX, float scaleY, float x, float y) {
|
||||
glActiveTexture(0);
|
||||
transformMatrix.identity()
|
||||
|
@ -117,13 +122,19 @@ public class GuiRenderer {
|
|||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount);
|
||||
}
|
||||
|
||||
public void drawNvg(float width, float height) {
|
||||
public void drawNvg(float width, float height, ClientPlayer player) {
|
||||
nvgBeginFrame(vgId, width, height, width / height);
|
||||
nvgSave(vgId);
|
||||
nvgFontSize(vgId, 60f);
|
||||
nvgFontFaceId(vgId, jetbrainsMonoFont);
|
||||
nvgTextAlign(vgId, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
|
||||
nvgText(vgId, 50, 50, "Hello world!");
|
||||
nvgFillColor(vgId, GuiUtils.rgba(1, 0, 0, 1, colorA));
|
||||
nvgText(vgId, 5, 5, "Hello world!");
|
||||
|
||||
drawCrosshair(width, height);
|
||||
drawHealthBar(width, height, player);
|
||||
drawHeldItemStackInfo(width, height, player);
|
||||
|
||||
nvgRestore(vgId);
|
||||
nvgEndFrame(vgId);
|
||||
}
|
||||
|
@ -145,5 +156,73 @@ public class GuiRenderer {
|
|||
shaderProgram.free();
|
||||
}
|
||||
|
||||
private void drawCrosshair(float w, float h) {
|
||||
float cx = w / 2f;
|
||||
float cy = h / 2f;
|
||||
|
||||
nvgStrokeColor(vgId, GuiUtils.rgba(1, 1, 1, 0.25f, colorA));
|
||||
nvgBeginPath(vgId);
|
||||
nvgMoveTo(vgId, cx - 10, cy);
|
||||
nvgLineTo(vgId, cx + 10, cy);
|
||||
nvgMoveTo(vgId, cx, cy - 10);
|
||||
nvgLineTo(vgId, cx, cy + 10);
|
||||
nvgStroke(vgId);
|
||||
}
|
||||
|
||||
private void drawHealthBar(float w, float h, ClientPlayer player) {
|
||||
nvgFillColor(vgId, GuiUtils.rgba(1, 0, 0, 1, colorA));
|
||||
nvgBeginPath(vgId);
|
||||
nvgRect(vgId, 20, h - 60, 100, 20);
|
||||
nvgFill(vgId);
|
||||
nvgFillColor(vgId, GuiUtils.rgba(0, 1, 0, 1, colorA));
|
||||
nvgBeginPath(vgId);
|
||||
nvgRect(vgId, 20, h - 60, 100 * player.getHealth(), 20);
|
||||
nvgFill(vgId);
|
||||
|
||||
nvgFillColor(vgId, GuiUtils.rgba(1, 1, 1, 1, colorA));
|
||||
nvgFontSize(vgId, 12f);
|
||||
nvgFontFaceId(vgId, jetbrainsMonoFont);
|
||||
nvgTextAlign(vgId, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
|
||||
nvgText(vgId, 20, h - 30, String.format("%.2f / 1.00 HP", player.getHealth()));
|
||||
}
|
||||
|
||||
private void drawHeldItemStackInfo(float w, float h, ClientPlayer player) {
|
||||
var stack = player.getInventory().getSelectedItemStack();
|
||||
if (stack instanceof GunItemStack g) {
|
||||
drawGunInfo(w, h, g);
|
||||
} else if (stack instanceof BlockItemStack b) {
|
||||
drawBlockInfo(w, h, b);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawGunInfo(float w, float h, GunItemStack stack) {
|
||||
Gun gun = (Gun) stack.getType();
|
||||
float y = h - 50;
|
||||
for (int i = 0; i < gun.getMaxClipCount(); i++) {
|
||||
float alpha = i < stack.getClipCount() ? 0.75f : 0.25f;
|
||||
nvgFillColor(vgId, GuiUtils.rgba(0.2f, 0.2f, 0.1f, alpha, colorA));
|
||||
nvgBeginPath(vgId);
|
||||
nvgRect(vgId, w - 60, y, 40, 30);
|
||||
nvgFill(vgId);
|
||||
y -= 35;
|
||||
}
|
||||
float x = w - 80;
|
||||
for (int i = 0; i < gun.getMaxBulletCount(); i++) {
|
||||
float alpha = i < stack.getBulletCount() ? 0.75f : 0.1f;
|
||||
nvgFillColor(vgId, GuiUtils.rgba(0.7f, 0.3f, 0, alpha, colorA));
|
||||
nvgBeginPath(vgId);
|
||||
nvgRect(vgId, x, h - 60, 10, 40);
|
||||
nvgFill(vgId);
|
||||
x -= 15;
|
||||
}
|
||||
}
|
||||
|
||||
private void drawBlockInfo(float w, float h, BlockItemStack stack) {
|
||||
BlockItem block = (BlockItem) stack.getType();
|
||||
nvgFillColor(vgId, GuiUtils.rgba(1, 1, 1, 0.75f, colorA));
|
||||
nvgFontSize(vgId, 12f);
|
||||
nvgFontFaceId(vgId, jetbrainsMonoFont);
|
||||
nvgTextAlign(vgId, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
|
||||
nvgText(vgId, w - 140, h - 30, String.format("%d / %d Blocks", stack.getAmount(), block.getMaxAmount()));
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 218 B |
Binary file not shown.
Before Width: | Height: | Size: 90 B |
Binary file not shown.
Before Width: | Height: | Size: 90 B |
|
@ -1,5 +1,7 @@
|
|||
package nl.andrewl.aos_core;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -21,6 +23,13 @@ public final class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static BufferedImage readClasspathImage(String resource) throws IOException {
|
||||
try (var in = FileUtils.class.getClassLoader().getResourceAsStream(resource)) {
|
||||
if (in == null) throw new IOException("Couldn't load texture image from " + resource);
|
||||
return ImageIO.read(in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a classpath resource into a directly-allocated byte buffer that
|
||||
* must be deallocated manually.
|
||||
|
|
Loading…
Reference in New Issue