Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/engine/common/math/Matrix4f.java
Original file line number Diff line number Diff line change
Expand Up @@ -876,4 +876,10 @@ public Matrix4f translate(ConstraintPair translate) {
return translate(translate.x().get(), translate.y().get());
}

public float[] toArray() {
float[] arr = new float[16];
store(arr);
return arr;
}

}
51 changes: 49 additions & 2 deletions src/main/java/nomadrealms/context/game/world/map/area/Chunk.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
package nomadrealms.context.game.world.map.area;

import static engine.common.colour.Colour.toRangedVector;
import static nomadrealms.context.game.world.map.area.Tile.TILE_HORIZONTAL_SPACING;
import static nomadrealms.context.game.world.map.area.Tile.TILE_RADIUS;
import static nomadrealms.context.game.world.map.area.Tile.TILE_VERTICAL_SPACING;
import static nomadrealms.context.game.world.map.area.coordinate.ChunkCoordinate.CHUNK_SIZE;
import static nomadrealms.render.vao.shape.HexagonVao.HEIGHT;
import static nomadrealms.render.vao.shape.HexagonVao.SIDE_LENGTH;

import java.util.ArrayList;
import java.util.List;

import engine.common.math.Matrix4f;
import engine.common.math.Vector2f;
import engine.common.math.Vector3f;
import engine.common.math.Vector4f;
import engine.visuals.constraint.box.ConstraintPair;
import nomadrealms.context.game.world.map.area.coordinate.ChunkCoordinate;
import nomadrealms.context.game.world.map.area.coordinate.TileCoordinate;
import nomadrealms.context.game.world.map.generation.MapGenerationStrategy;
import nomadrealms.render.RenderingEnvironment;
import nomadrealms.render.vao.shape.InstancedHexagonVao;

/**
* A chunk is a 16x16 grid of tiles. This is the optimal size for batch rendering. Chunks are how we limit the rendering
Expand Down Expand Up @@ -49,12 +57,51 @@ public Tile tile(int x, int y) {
}

public void render(RenderingEnvironment re) {
float[] transforms = new float[CHUNK_SIZE * CHUNK_SIZE * 16];
float[] colors = new float[CHUNK_SIZE * CHUNK_SIZE * 4];
int i = 0;
Vector2f toCenter = new Vector2f(TILE_RADIUS * SIDE_LENGTH, TILE_RADIUS * HEIGHT);
ConstraintPair chunkPos = zone.pos().add(indexPosition());
for (int row = 0; row < CHUNK_SIZE; row++) {
for (int col = 0; col < CHUNK_SIZE; col++) {
tiles[row][col].render(re);
Tile tile = tiles[row][col];

// Calculation logic copied from Tile.indexPosition()
Vector2f base = new Vector2f(tile.coord().x() * TILE_HORIZONTAL_SPACING, tile.coord().y() * TILE_VERTICAL_SPACING);
Vector2f columnOffset = new Vector2f(0, (tile.coord().x() % 2 == 0) ? 0 : TILE_RADIUS * HEIGHT);
ConstraintPair indexPosition = new ConstraintPair(toCenter.add(base).add(columnOffset));

ConstraintPair position = chunkPos.add(indexPosition);
Vector2f screenPosition = position.sub(re.camera.position()).vector();
Matrix4f transform = new Matrix4f(screenPosition.x(), screenPosition.y(), TILE_RADIUS * 2 * SIDE_LENGTH * 0.98f,
TILE_RADIUS * 2 * SIDE_LENGTH * 0.98f, re.glContext).rotate(0, new Vector3f(0, 0, 1));
System.arraycopy(transform.toArray(), 0, transforms, i * 16, 16);
Vector4f color = toRangedVector(tile.color());
colors[i * 4] = color.x();
colors[i * 4 + 1] = color.y();
colors[i * 4 + 2] = color.z();
colors[i * 4 + 3] = color.w();
i++;
}
}
InstancedHexagonVao.colorVBO().data(colors).updateData();
InstancedHexagonVao.transformVBO().data(transforms).updateData();
re.instancedShaderProgram.use(re.glContext);
InstancedHexagonVao.instance().drawInstanced(re.glContext, CHUNK_SIZE * CHUNK_SIZE);

for (int row = 0; row < CHUNK_SIZE; row++) {
for (int col = 0; col < CHUNK_SIZE; col++) {
Tile tile = tiles[row][col];
// Calculation logic copied from Tile.indexPosition()
Vector2f base = new Vector2f(tile.coord().x() * TILE_HORIZONTAL_SPACING, tile.coord().y() * TILE_VERTICAL_SPACING);
Vector2f columnOffset = new Vector2f(0, (tile.coord().x() % 2 == 0) ? 0 : TILE_RADIUS * HEIGHT);
ConstraintPair indexPosition = new ConstraintPair(toCenter.add(base).add(columnOffset));

ConstraintPair position = chunkPos.add(indexPosition);
Vector2f screenPosition = position.sub(re.camera.position()).vector();
tile.renderContent(re, screenPosition);
}
}
// TODO: instanced rendering - render all tiles in a chunk together
}

private ConstraintPair indexPosition() {
Expand Down
16 changes: 12 additions & 4 deletions src/main/java/nomadrealms/context/game/world/map/area/Tile.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public abstract class Tile implements Target, HasTooltip {

protected int color = rgb(126, 200, 80);

public int color() {
return color;
}

/**
* No-arg constructor for serialization.
*/
Expand Down Expand Up @@ -85,13 +89,20 @@ public void render(RenderingEnvironment re) {
ConstraintPair position = chunk.pos().add(indexPosition());
Vector2f screenPosition = position.sub(re.camera.position()).vector();
render(re, screenPosition, 1);
}

public void renderContent(RenderingEnvironment re, Vector2f screenPosition) {
if (re.showDebugInfo) {
re.textRenderer
.alignCenterHorizontal()
.alignCenterVertical()
.render(screenPosition.x(), screenPosition.y(), coord.x() + ", " + coord.y(),
0, re.font, 0.35f * TILE_RADIUS, rgb(255, 255, 255));
}
for (WorldItem item : items) {
re.textureRenderer.render(re.imageMap.get(item.item().image()), screenPosition.x() - ITEM_SIZE * 0.5f,
screenPosition.y() - ITEM_SIZE * 0.5f, ITEM_SIZE, ITEM_SIZE);
}
}

/**
Expand Down Expand Up @@ -125,10 +136,7 @@ public void render(RenderingEnvironment re, Vector2f screenPosition, float scale
new Matrix4f(screenPosition.x(), screenPosition.y(), TILE_RADIUS * 2 * SIDE_LENGTH * 0.98f,
TILE_RADIUS * 2 * SIDE_LENGTH * 0.98f, re.glContext).rotate(radians, new Vector3f(0, 0, 1)))
.use(new DrawFunction().vao(HexagonVao.instance()).glContext(re.glContext));
for (WorldItem item : items) {
re.textureRenderer.render(re.imageMap.get(item.item().image()), screenPosition.x() - ITEM_SIZE * 0.5f,
screenPosition.y() - ITEM_SIZE * 0.5f, ITEM_SIZE, ITEM_SIZE);
}
renderContent(re, screenPosition);
}

public Actor actor() {
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/nomadrealms/render/RenderingEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public class RenderingEnvironment {
public FragmentShader bloomCombinationFragmentShader;
public ShaderProgram bloomCombinationShaderProgram;

public VertexShader instancedVertexShader;
public FragmentShader instancedFragmentShader;
public ShaderProgram instancedShaderProgram;

public GameFont font;
public Map<String, Texture> imageMap = new HashMap<>();

Expand Down Expand Up @@ -111,6 +115,10 @@ private void loadShaders() {
.source(new StringLoader(getFile("/shaders/bloom_combination.glsl")).load()).load();
bloomCombinationShaderProgram = new ShaderProgram().attach(bloomVertexShader, bloomCombinationFragmentShader)
.load();

instancedVertexShader = new VertexShader().source(new StringLoader(getFile("/shaders/instancedVertex.glsl")).load()).load();
instancedFragmentShader = new FragmentShader().source(new StringLoader(getFile("/shaders/instancedFrag.glsl")).load()).load();
instancedShaderProgram = new ShaderProgram().attach(instancedVertexShader, instancedFragmentShader).load();
}

private void loadImages() {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/nomadrealms/render/vao/shape/HexagonVao.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class HexagonVao {

private HexagonVao() {
}
private static final float[] POSITIONS = {
public static final float[] POSITIONS = {
0, 0, 0,
-SIDE_LENGTH, 0, 0,
-SIDE_LENGTH * 0.5f, HEIGHT, 0,
Expand All @@ -29,7 +29,7 @@ private HexagonVao() {
-SIDE_LENGTH * 0.5f, -HEIGHT, 0,
};

private static final float[] TEXTURE_COORDINATES = {
public static final float[] TEXTURE_COORDINATES = {
0.5f, 0.5f,
0.25f, 0.5f,
0.125f, 0.25f,
Expand All @@ -39,7 +39,7 @@ private HexagonVao() {
0.125f, 0.75f,
};

private static final int[] INDICES = {
public static final int[] INDICES = {
0, 1, 2,
0, 2, 3,
0, 3, 4,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package nomadrealms.render.vao.shape;

import static nomadrealms.context.game.world.map.area.coordinate.ChunkCoordinate.CHUNK_SIZE;
import static nomadrealms.render.vao.shape.HexagonVao.INDICES;
import static nomadrealms.render.vao.shape.HexagonVao.POSITIONS;
import static nomadrealms.render.vao.shape.HexagonVao.TEXTURE_COORDINATES;

import engine.visuals.lwjgl.render.ElementBufferObject;
import engine.visuals.lwjgl.render.InstancedVertexBufferObject;
import engine.visuals.lwjgl.render.VertexArrayObject;
import engine.visuals.lwjgl.render.VertexBufferObject;

public class InstancedHexagonVao {

public static final int MAX_INSTANCES = CHUNK_SIZE * CHUNK_SIZE;

private static VertexArrayObject vao;
private static VertexBufferObject colorVBO;
private static VertexBufferObject transformVBO;

private InstancedHexagonVao() {
}

public static VertexArrayObject instance() {
if (vao == null) {
load();
}
return vao;
}

public static VertexBufferObject colorVBO() {
if (colorVBO == null) {
load();
}
return colorVBO;
}

public static VertexBufferObject transformVBO() {
if (transformVBO == null) {
load();
}
return transformVBO;
}

private static void load() {
ElementBufferObject ebo = new ElementBufferObject().indices(INDICES).load();
VertexBufferObject positionsVBO = new VertexBufferObject().index(0).data(POSITIONS).dimensions(3).load();
VertexBufferObject textureCoordinatesVBO = new VertexBufferObject().index(1).data(TEXTURE_COORDINATES).dimensions(2).load();

colorVBO = new InstancedVertexBufferObject().index(2).data(new float[4 * MAX_INSTANCES]).dimensions(4).divisor().perInstance().load();
transformVBO = new InstancedVertexBufferObject().index(3).data(new float[16 * MAX_INSTANCES]).dimensions(16).divisor().perInstance().load();

vao = new VertexArrayObject().vbos(positionsVBO, textureCoordinatesVBO, colorVBO, transformVBO).ebo(ebo).load();
}

}
9 changes: 9 additions & 0 deletions src/main/resources/shaders/instancedFrag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#version 330 core
out vec4 outColor;

in vec2 texCoord;
in vec4 fragColor;

void main() {
outColor = fragColor;
}
15 changes: 15 additions & 0 deletions src/main/resources/shaders/instancedVertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 uv;
layout(location = 2) in vec4 instanceColor;
layout(location = 3) in mat4 instanceTransform;

out vec2 texCoord;
out vec4 fragColor;

void main() {
gl_Position = instanceTransform * vec4(position, 1.0);
texCoord = uv;
fragColor = instanceColor;
}