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