From 7dee1eb95fccd3ac0b9106a3479774c74639919c Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Mon, 3 Aug 2020 21:44:36 +0300 Subject: [PATCH] Re-written flat render pipeline to support transforms FlatRender now supports arbitrary transforms GLSL 1.40 is now used in shaders --- .../optica/client/graphics/Colors.java | 2 +- .../client/graphics/backend/InputHandler.java | 18 +- .../backend/shaders/CombinedShader.java | 2 +- .../graphics/flat/AssembledFlatLayer.java | 61 +---- .../flat/AssembledFlatRenderHelper.java | 35 +++ .../flat/DefaultFlatRenderHelper.java | 68 ++++++ .../graphics/flat/FlatRenderHelper.java | 65 +----- .../graphics/flat/FlatRenderProgram.java | 54 +++-- .../client/graphics/flat/LayerTestUI.java | 46 ++-- .../optica/client/graphics/flat/Mask.java | 18 +- .../client/graphics/flat/MaskStack.java | 46 ++++ .../client/graphics/flat/RenderTarget.java | 213 ++++++++++++------ .../client/graphics/flat/TransformedMask.java | 158 +++++++++++++ .../client/graphics/input/WheelEvent.java | 18 ++ .../graphics/input/WheelScrollEvent.java | 73 ++++-- .../client/graphics/model/LambdaModel.java | 125 ++++++++++ .../graphics/model/ShapeRenderHelper.java | 2 +- .../client/graphics/world/LayerWorld.java | 3 + .../optica/common/util/StashingStack.java | 20 ++ .../assets/shaders/Flat.fragment.glsl | 31 ++- .../resources/assets/shaders/Flat.vertex.glsl | 2 +- .../assets/shaders/FlatDefault.fragment.glsl | 2 +- .../assets/shaders/FlatDefault.vertex.glsl | 2 +- .../assets/shaders/Shape.fragment.glsl | 2 +- .../assets/shaders/Shape.vertex.glsl | 2 +- .../assets/shaders/World.fragment.glsl | 2 +- .../assets/shaders/World.vertex.glsl | 2 +- .../assets/shaders/WorldDefault.fragment.glsl | 2 +- .../assets/shaders/WorldDefault.vertex.glsl | 2 +- .../assets/textures/compass_icon.png | Bin 0 -> 1289 bytes .../assets/textures/compass_icon_arrow.png | Bin 0 -> 236 bytes 31 files changed, 812 insertions(+), 264 deletions(-) create mode 100644 src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatRenderHelper.java create mode 100644 src/main/java/ru/windcorp/optica/client/graphics/flat/DefaultFlatRenderHelper.java create mode 100644 src/main/java/ru/windcorp/optica/client/graphics/flat/MaskStack.java create mode 100644 src/main/java/ru/windcorp/optica/client/graphics/flat/TransformedMask.java create mode 100644 src/main/java/ru/windcorp/optica/client/graphics/model/LambdaModel.java create mode 100644 src/main/resources/assets/textures/compass_icon.png create mode 100644 src/main/resources/assets/textures/compass_icon_arrow.png diff --git a/src/main/java/ru/windcorp/optica/client/graphics/Colors.java b/src/main/java/ru/windcorp/optica/client/graphics/Colors.java index f0927a5..369c7a3 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/Colors.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/Colors.java @@ -33,6 +33,6 @@ public class Colors { DEBUG_CYAN = 0x00FFFF, DEBUG_MAGENTA = 0xFF00FF, - DEBUG_YELLOW = 0x00FFFF; + DEBUG_YELLOW = 0xFFFF00; } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/backend/InputHandler.java b/src/main/java/ru/windcorp/optica/client/graphics/backend/InputHandler.java index 38e835a..e040df3 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/backend/InputHandler.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/backend/InputHandler.java @@ -26,18 +26,19 @@ public class InputHandler { private static final EventBus INPUT_EVENT_BUS = new EventBus("Input"); - // ScrollEvent Start + // ScrollEvent private static class ModifiableWheelScrollEvent extends WheelScrollEvent { public void initialize(double xoffset, double yoffset) { - this.xoffset = xoffset; - this.yoffset = yoffset; + this.xOffset = xoffset; + this.yOffset = yoffset; } } - private static final ModifiableWheelScrollEvent THE_SCROLL_EVENT = new ModifiableWheelScrollEvent(); + private static final ModifiableWheelScrollEvent THE_SCROLL_EVENT = + new ModifiableWheelScrollEvent(); static void handleMouseWheel( long window, @@ -49,7 +50,7 @@ public class InputHandler { dispatch(THE_SCROLL_EVENT); } - // KeyEvent Start + // KeyEvent private static class ModifiableKeyEvent extends KeyEvent { @@ -62,7 +63,8 @@ public class InputHandler { } - private static final ModifiableKeyEvent THE_KEY_EVENT = new ModifiableKeyEvent(); + private static final ModifiableKeyEvent THE_KEY_EVENT = + new ModifiableKeyEvent(); static void handleKeyInput( long window, @@ -76,7 +78,7 @@ public class InputHandler { dispatch(THE_KEY_EVENT); } - // CursorEvent Start + // CursorMoveEvent private static class ModifiableCursorMoveEvent extends CursorMoveEvent { @@ -111,6 +113,8 @@ public class InputHandler { CURSOR_POSITION.set(x, y); } + // Misc + public static double getCursorX() { return CURSOR_POSITION.x; } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/backend/shaders/CombinedShader.java b/src/main/java/ru/windcorp/optica/client/graphics/backend/shaders/CombinedShader.java index dcd9571..61ccfb8 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/backend/shaders/CombinedShader.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/backend/shaders/CombinedShader.java @@ -44,7 +44,7 @@ public class CombinedShader extends Shader { } private static String combine(String[] resources) { - StringBuilder accumulator = new StringBuilder("#version 120\n"); + StringBuilder accumulator = new StringBuilder("#version 140\n"); for (String resourceName : resources) { Resource resource = getShaderResource(resourceName); diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatLayer.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatLayer.java index 8085306..f246ee7 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatLayer.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatLayer.java @@ -18,16 +18,16 @@ package ru.windcorp.optica.client.graphics.flat; import ru.windcorp.optica.client.graphics.Layer; -import ru.windcorp.optica.client.graphics.model.WorldRenderable; public abstract class AssembledFlatLayer extends Layer { - private final FlatRenderHelper helper = new FlatRenderHelper(); + private final AssembledFlatRenderHelper helper = + new AssembledFlatRenderHelper(); private final RenderTarget target = new RenderTarget(); private boolean needsReassembly = true; - private Clip[] clips = null; + private RenderTarget.Clip[] clips = null; public AssembledFlatLayer(String name) { super(name); @@ -57,64 +57,11 @@ public abstract class AssembledFlatLayer extends Layer { doReassemble(); } - for (Clip clip : clips) { + for (RenderTarget.Clip clip : clips) { clip.render(helper); } helper.reset(); } - public static class Clip { - - private final Mask mask = new Mask(); - private final WorldRenderable renderable; - - public Clip( - int startX, int startY, - int endX, int endY, - WorldRenderable renderable - ) { - mask.set(startX, startY, endX, endY); - this.renderable = renderable; - } - - public Clip( - Mask mask, - WorldRenderable renderable - ) { - this( - mask.getStartX(), mask.getStartY(), - mask.getEndX(), mask.getEndY(), - renderable - ); - } - - public int getStartX() { - return mask.getStartX(); - } - - public int getStartY() { - return mask.getStartY(); - } - - public int getEndX() { - return mask.getEndX(); - } - - public int getEndY() { - return mask.getEndY(); - } - - public WorldRenderable getRenderable() { - return renderable; - } - - public void render(FlatRenderHelper helper) { - helper.pushMask(getStartX(), getStartY(), getEndX(), getEndY()); - renderable.render(helper); - helper.popTransform(); - } - - } - } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatRenderHelper.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatRenderHelper.java new file mode 100644 index 0000000..9763644 --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatRenderHelper.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Optica + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ +package ru.windcorp.optica.client.graphics.flat; + +import java.nio.FloatBuffer; + +public class AssembledFlatRenderHelper extends FlatRenderHelper { + + private FloatBuffer masks; + + @Override + protected FloatBuffer getMasks() { + return masks; + } + + public void setMasks(FloatBuffer masks) { + this.masks = masks; + } + +} diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/DefaultFlatRenderHelper.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/DefaultFlatRenderHelper.java new file mode 100644 index 0000000..4749b77 --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/DefaultFlatRenderHelper.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Optica + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ +package ru.windcorp.optica.client.graphics.flat; + +import java.nio.FloatBuffer; + +import glm.mat._4.Mat4; + +public class DefaultFlatRenderHelper extends FlatRenderHelper { + + private final TransformedMask transformer = new TransformedMask(); + + protected final MaskStack maskStack = new MaskStack(); + + protected final boolean[] hasMask = new boolean[TRANSFORM_STACK_SIZE]; + + public void pushMask(Mask mask, Mat4 transform) { + pushMask(transformer.set(mask, transform), transform); + } + + public void pushMask(TransformedMask mask, Mat4 transform) { + hasMask[transformStack.getSize()] = true; + pushTransform().mul(transform); + maskStack.pushMask(mask); + } + + @Override + public Mat4 pushTransform() { + hasMask[transformStack.getSize()] = false; + return super.pushTransform(); + } + + @Override + public void popTransform() { + super.popTransform(); + + if (hasMask[transformStack.getSize()]) { + maskStack.popMask(); + } + } + + @Override + public void reset() { + super.reset(); + maskStack.clear(); + } + + @Override + protected FloatBuffer getMasks() { + return maskStack.getBuffer(); + } + +} diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderHelper.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderHelper.java index aa2aae0..45f9cc5 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderHelper.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderHelper.java @@ -17,69 +17,28 @@ *******************************************************************************/ package ru.windcorp.optica.client.graphics.flat; +import java.nio.FloatBuffer; + +import glm.mat._4.Mat4; import ru.windcorp.optica.client.graphics.backend.GraphicsInterface; import ru.windcorp.optica.client.graphics.model.ShapeRenderHelper; -public class FlatRenderHelper extends ShapeRenderHelper { +public abstract class FlatRenderHelper extends ShapeRenderHelper { - private static final float MAX_DEPTH = 1 << 16; + protected static final float MAX_DEPTH = 1 << 16; - private final Mask mask = new Mask(); + protected final Mat4 finalTransform = new Mat4(); - { - setupScreenTransform(); - } + protected abstract FloatBuffer getMasks(); - public FlatRenderHelper pushMask( - int startX, int startY, - int endX, int endY - ) { - mask.set(startX, startY, endX, endY); - pushTransform().translate(startX, startY, 0); - return this; - } - - public FlatRenderHelper pushMask(Mask mask) { - return pushMask( - mask.getStartX(), mask.getStartY(), - mask.getEndX(), mask.getEndY() - ); - } - - public int getStartX() { - return mask.getStartX(); - } - - public int getStartY() { - return mask.getStartY(); - } - - public int getEndX() { - return mask.getEndX(); - } - - public int getEndY() { - return mask.getEndY(); - } - - public boolean isRenderable() { - return !mask.isEmpty(); - } - @Override - public void reset() { - super.reset(); - - setupScreenTransform(); - mask.set(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - private void setupScreenTransform() { + public Mat4 getFinalTransform() { float width = GraphicsInterface.getFramebufferWidth(); float height = GraphicsInterface.getFramebufferHeight(); - - getTransform().translate(-1, +1, 0) - .scale(2 / width, -2 / height, 1 / MAX_DEPTH); + + return finalTransform.identity().translate(-1, +1, 0) + .scale(2 / width, -2 / height, 1 / MAX_DEPTH) + .mul(getTransform()); } } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderProgram.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderProgram.java index 6fdd152..4a41b67 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderProgram.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderProgram.java @@ -19,10 +19,12 @@ package ru.windcorp.optica.client.graphics.flat; import static org.lwjgl.opengl.GL11.*; +import java.nio.FloatBuffer; + import com.google.common.collect.ObjectArrays; -import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.Uniform2Int; -import ru.windcorp.optica.client.graphics.model.Face; +import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.Uniform1Int; +import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.Uniform2Float; import ru.windcorp.optica.client.graphics.model.Shape; import ru.windcorp.optica.client.graphics.model.ShapeRenderHelper; import ru.windcorp.optica.client.graphics.model.ShapeRenderProgram; @@ -42,17 +44,19 @@ public class FlatRenderProgram extends ShapeRenderProgram { return def; } + public static final int MASK_STACK_SIZE = 16; // As in Flat.fragment.glsl + private static final String FLAT_VERTEX_SHADER_RESOURCE = "Flat.vertex.glsl"; private static final String FLAT_FRAGMENT_SHADER_RESOURCE = "Flat.fragment.glsl"; private static final String - MASK_START_UNIFORM_NAME = "maskStart", - MASK_END_UNIFORM_NAME = "maskEnd"; + MASK_COUNT_UNIFORM_NAME = "maskCount", + MASKS_UNIFORM_NAME = "masks"; - private final Uniform2Int maskStartUniform; - private final Uniform2Int maskEndUniform; + private final Uniform1Int maskCountUniform; + private final Uniform2Float masksUniform; public FlatRenderProgram( String[] vertexShaderResources, @@ -63,8 +67,8 @@ public class FlatRenderProgram extends ShapeRenderProgram { attachFragmentShader(fragmentShaderResources) ); - this.maskStartUniform = getUniform(MASK_START_UNIFORM_NAME).as2Int(); - this.maskEndUniform = getUniform(MASK_END_UNIFORM_NAME).as2Int(); + this.maskCountUniform = getUniform(MASK_COUNT_UNIFORM_NAME).as1Int(); + this.masksUniform = getUniform(MASKS_UNIFORM_NAME).as2Float(); } private static String[] attachVertexShader(String[] others) { @@ -77,15 +81,8 @@ public class FlatRenderProgram extends ShapeRenderProgram { @Override public void render(ShapeRenderHelper helper, Shape shape) { - if (((FlatRenderHelper) helper).isRenderable()) { - super.render(helper, shape); - } - } - - @Override - protected void renderFace(Face face) { glDisable(GL_CULL_FACE); - super.renderFace(face); + super.render(helper, shape); glEnable(GL_CULL_FACE); } @@ -94,8 +91,29 @@ public class FlatRenderProgram extends ShapeRenderProgram { super.configure(argHelper); FlatRenderHelper helper = ((FlatRenderHelper) argHelper); - maskStartUniform.set(helper.getStartX(), helper.getStartY()); - maskEndUniform.set(helper.getEndX(), helper.getEndY()); + configureMasks(helper.getMasks()); + } + + private void configureMasks(FloatBuffer masks) { + int pos = masks.position(); + int limit = masks.limit(); + int size = pos / TransformedMask.SIZE_IN_FLOATS; + + maskCountUniform.set(size); + + masks.flip(); + masksUniform.set(masks); + +// for (int i = 0; i < pos; ++i) { +// if (i % TransformedMask.SIZE_IN_FLOATS == 0) { +// System.out.print(" | "); +// } +// System.out.print(masks.get(i) + "; "); +// } +// System.out.println(); + + masks.limit(limit); + masks.position(pos); } } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/LayerTestUI.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/LayerTestUI.java index 1afc76e..16d73aa 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/flat/LayerTestUI.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/LayerTestUI.java @@ -21,14 +21,17 @@ import org.lwjgl.glfw.GLFW; import com.google.common.eventbus.Subscribe; +import glm.mat._4.Mat4; import ru.windcorp.optica.client.graphics.Colors; import ru.windcorp.optica.client.graphics.backend.GraphicsInterface; import ru.windcorp.optica.client.graphics.input.KeyEvent; +import ru.windcorp.optica.client.graphics.model.LambdaModel; import ru.windcorp.optica.client.graphics.texture.SimpleTexture; import ru.windcorp.optica.client.graphics.texture.Sprite; import ru.windcorp.optica.client.graphics.texture.Texture; import ru.windcorp.optica.client.graphics.texture.TextureManager; import ru.windcorp.optica.client.graphics.texture.TextureSettings; +import ru.windcorp.optica.client.graphics.world.LayerWorld; public class LayerTestUI extends AssembledFlatLayer { @@ -40,37 +43,46 @@ public class LayerTestUI extends AssembledFlatLayer { private boolean flag = false; - private static int width = 512 + 256; - private static final int height = 64; - private static final int border = 5; + private static final int WIDTH = 512 + 256; + private static final int HEIGHT = 80; + private static final int BORDER = 5; @Override protected void assemble(RenderTarget target) { - - final int boxColor = flag ? 0xEE8888 : 0xEEEE88; final int borderColor = flag ? 0xAA4444 : 0xAAAA44; final int boxShadowColor = flag ? 0x440000 : 0x444400; - int x = (getWidth() - width) / 2; - int y = getHeight() - height; - - y -= 2*border; + int x = (getWidth() - WIDTH) / 2; + int y = getHeight() - HEIGHT - 2*BORDER; - target.fill(x + border, y + border, width, height, boxShadowColor); - target.fill(x - 1, y - 1, width + 2, height + 2, boxShadowColor); - target.fill(x, y, width, height, borderColor); - target.fill(x + border, y + border, width - 2*border, height - 2*border, boxColor); + target.fill(x + BORDER, y + BORDER, WIDTH, HEIGHT, boxShadowColor); + target.fill(x - 1, y - 1, WIDTH + 2, HEIGHT + 2, boxShadowColor); + target.fill(x, y, WIDTH, HEIGHT, borderColor); + target.fill(x + BORDER, y + BORDER, WIDTH - 2*BORDER, HEIGHT - 2*BORDER, boxColor); final int texShadow = 2; - final int texSize = height - 4*border; + final int texSize = HEIGHT - 4*BORDER; - target.fill(x + 2*border + texShadow, y + 2*border + texShadow, texSize, texSize, Colors.BLACK); - target.drawTexture(x + 2*border, y + 2*border, texSize, texSize, qtex("compass")); + target.pushTransform(new Mat4().identity().translate(x + 2*BORDER, y + 2*BORDER, 0)); + + final Texture compassBg = qtex("compass_icon"); + final Texture compassFg = qtex("compass_icon_arrow"); + + target.drawTexture(texShadow, texShadow, texSize, texSize, Colors.BLACK, compassBg); + target.drawTexture(0, 0, texSize, texSize, compassBg); + + target.addCustomRenderer(new LambdaModel(LambdaModel.lambdaBuilder() + .addDynamicPart( + target.createRectagle(0, 0, texSize, texSize, 0xFFFFFF, compassFg), + mat -> mat.translate(texSize/2, texSize/2, 0).rotateZ(-LayerWorld.tmp_the_camera.getYaw()).translate(-texSize/2, -texSize/2, 0) + ) + )); + target.popTransform(); drawCross(target); } - + private void drawCross(RenderTarget target) { int cx = getWidth() / 2; int cy = getHeight() / 2; diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/Mask.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/Mask.java index c959b62..1295a4d 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/flat/Mask.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/Mask.java @@ -65,6 +65,14 @@ public class Mask { this.endY = endY; } + public int getWidth() { + return getEndX() - getStartX(); + } + + public int getHeight() { + return getEndY() - getStartY(); + } + public void set(int startX, int startY, int endX, int endY) { this.startX = startX; this.startY = startY; @@ -72,8 +80,14 @@ public class Mask { this.endY = endY; } - public boolean isEmpty() { - return startX >= endX || startY >= endY; + public void set(Mask copyFrom) { + set(copyFrom.startX, copyFrom.startY, copyFrom.endX, copyFrom.endY); + } + + @Override + public String toString() { + return "(" + getStartX() + "; " + getStartY() + + ") -> (" + getEndX() + "; " + getEndY() + ")"; } } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/MaskStack.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/MaskStack.java new file mode 100644 index 0000000..e0c9dcf --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/MaskStack.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Optica + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ +package ru.windcorp.optica.client.graphics.flat; + +import java.nio.FloatBuffer; + +import org.lwjgl.BufferUtils; + +public class MaskStack { + + private final FloatBuffer buffer = BufferUtils.createFloatBuffer( + FlatRenderProgram.MASK_STACK_SIZE * TransformedMask.SIZE_IN_FLOATS + ); + + public void pushMask(TransformedMask mask) { + mask.writeToBuffer(buffer); + } + + public void popMask() { + buffer.position(buffer.position() - TransformedMask.SIZE_IN_FLOATS); + } + + public void clear() { + buffer.clear(); + } + + FloatBuffer getBuffer() { + return buffer; + } + +} diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/RenderTarget.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/RenderTarget.java index fc55ca6..e087a18 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/flat/RenderTarget.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/RenderTarget.java @@ -21,7 +21,9 @@ import java.util.ArrayList; import java.util.Deque; import java.util.LinkedList; import java.util.List; +import java.util.Objects; +import glm.mat._4.Mat4; import glm.vec._3.Vec3; import ru.windcorp.optica.client.graphics.Colors; import ru.windcorp.optica.client.graphics.backend.Usage; @@ -33,10 +35,53 @@ import ru.windcorp.optica.client.graphics.texture.Texture; public class RenderTarget { - private final List assembled = new ArrayList<>(); + private static final Mat4 IDENTITY = new Mat4().identity(); - private final Deque maskStack = new LinkedList<>(); + public static class Clip { + + private final MaskStack masks = new MaskStack(); + private final Mat4 transform; + private final WorldRenderable renderable; + public Clip( + Iterable masks, + Mat4 transform, + WorldRenderable renderable + ) { + for (TransformedMask mask : masks) { + this.masks.pushMask(mask); + } + + this.transform = transform == null ? IDENTITY : transform; + this.renderable = Objects.requireNonNull(renderable, "renderable"); + } + + public Mat4 getTransform() { + return transform; + } + + public WorldRenderable getRenderable() { + return renderable; + } + + public void render(AssembledFlatRenderHelper helper) { + helper.setMasks(masks.getBuffer()); + helper.pushTransform().mul(getTransform()); + + try { + getRenderable().render(helper); + } finally { + helper.popTransform(); + helper.setMasks(null); + } + } + + } + + private final List assembled = new ArrayList<>(); + + private final Deque maskStack = new LinkedList<>(); + private final Deque transformStack = new LinkedList<>(); private final List currentClipFaces = new ArrayList<>(); private int depth = 0; @@ -45,20 +90,55 @@ public class RenderTarget { reset(); } - public void pushMaskStartEnd(int startX, int startY, int endX, int endY) { - assembleCurrentClipFromFaces(); - maskStack.push(intersect(getMask(), startX, startY, endX, endY)); + protected void assembleCurrentClipFromFaces() { + if (!currentClipFaces.isEmpty()) { + Face[] faces = currentClipFaces.toArray( + new Face[currentClipFaces.size()] + ); + currentClipFaces.clear(); + + Shape shape = new Shape( + Usage.STATIC, FlatRenderProgram.getDefault(), faces + ); + + assembled.add(new Clip( + maskStack, getTransform(), shape + )); + } } - private Mask intersect( - Mask current, - int startX, int startY, int endX, int endY - ) { - return new Mask( - Math.max(startX, current.getStartX()), - Math.max(startY, current.getStartY()), - Math.min(endX, current.getEndX()), - Math.min(endY, current.getEndY()) + public Clip[] assemble() { + assembleCurrentClipFromFaces(); + + Clip[] result = assembled.toArray( + new Clip[assembled.size()] + ); + + reset(); + + return result; + } + + private void reset() { + maskStack.clear(); + transformStack.clear(); + currentClipFaces.clear(); + assembled.clear(); + + transformStack.add(new Mat4().identity()); + depth = 0; + } + + public void pushMaskStartEnd(int startX, int startY, int endX, int endY) { + assembleCurrentClipFromFaces(); + + pushTransform(new Mat4().identity().translate(startX, startY, 0)); + + maskStack.push( + new TransformedMask( + new Mask(startX, startY, endX, endY), + getTransform() + ) ); } @@ -76,64 +156,32 @@ public class RenderTarget { public void popMask() { assembleCurrentClipFromFaces(); maskStack.pop(); + popTransform(); } - public Mask getMask() { + public TransformedMask getMask() { return maskStack.getFirst(); } - protected void assembleCurrentClipFromFaces() { - if (!currentClipFaces.isEmpty()) { - - Mask mask = getMask(); - if (mask.isEmpty()) { - currentClipFaces.clear(); - return; - } - - Face[] faces = currentClipFaces.toArray( - new Face[currentClipFaces.size()] - ); - currentClipFaces.clear(); - - Shape shape = new Shape( - Usage.STATIC, FlatRenderProgram.getDefault(), faces - ); - - assembled.add(new AssembledFlatLayer.Clip(mask, shape)); - } - } - - public AssembledFlatLayer.Clip[] assemble() { + public void pushTransform(Mat4 transform) { assembleCurrentClipFromFaces(); - - AssembledFlatLayer.Clip[] result = assembled.toArray( - new AssembledFlatLayer.Clip[assembled.size()] - ); - - reset(); - - return result; + transformStack.push(getTransform().mul(transform, transform)); } - private void reset() { - maskStack.clear(); - currentClipFaces.clear(); - assembled.clear(); - - maskStack.add(new Mask(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)); - depth = 0; + public void popTransform() { + assembleCurrentClipFromFaces(); + transformStack.pop(); + } + + public Mat4 getTransform() { + return transformStack.getFirst(); } public void addCustomRenderer(WorldRenderable renderable) { assembleCurrentClipFromFaces(); - - Mask mask = getMask(); - if (mask.isEmpty()) { - return; - } - - assembled.add(new AssembledFlatLayer.Clip(mask, renderable)); + assembled.add(new Clip( + maskStack, getTransform(), renderable + )); } protected void addFaceToCurrentClip(Face face) { @@ -144,16 +192,9 @@ public class RenderTarget { int x, int y, int width, int height, int color, Texture texture ) { - float depth = this.depth--; - - addFaceToCurrentClip(Faces.createRectangle( - FlatRenderProgram.getDefault(), - texture, - createVectorFromRGBInt(color), - new Vec3(x, y + height, depth), // Flip - new Vec3(width, 0, 0), - new Vec3(0, -height, 0) - )); + addFaceToCurrentClip( + createRectagleFace(x, y, width, height, color, texture) + ); } public void drawTexture( @@ -170,6 +211,38 @@ public class RenderTarget { drawTexture(x, y, width, height, color, null); } + public void fill(int color) { + fill( + Integer.MIN_VALUE / 2, Integer.MIN_VALUE / 2, + Integer.MAX_VALUE, Integer.MAX_VALUE, + color + ); + } + + public Face createRectagleFace( + int x, int y, int width, int height, int color, Texture texture + ) { + float depth = this.depth--; + + return Faces.createRectangle( + FlatRenderProgram.getDefault(), + texture, + createVectorFromRGBInt(color), + new Vec3(x, y + height, depth), // Flip + new Vec3(width, 0, 0), + new Vec3(0, -height, 0) + ); + } + + public Shape createRectagle( + int x, int y, int width, int height, int color, Texture texture + ) { + return new Shape( + Usage.STATIC, FlatRenderProgram.getDefault(), + createRectagleFace(x, y, width, height, color, texture) + ); + } + private static Vec3 createVectorFromRGBInt(int rgb) { int r = (rgb & 0xFF0000) >> 16; int g = (rgb & 0x00FF00) >> 8; diff --git a/src/main/java/ru/windcorp/optica/client/graphics/flat/TransformedMask.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/TransformedMask.java new file mode 100644 index 0000000..829191b --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/TransformedMask.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Optica + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ +package ru.windcorp.optica.client.graphics.flat; + +import java.nio.FloatBuffer; + +import glm.mat._4.Mat4; +import glm.vec._2.Vec2; +import glm.vec._4.Vec4; +import ru.windcorp.optica.client.graphics.backend.GraphicsInterface; + +public class TransformedMask { + + public static final int SIZE_IN_FLOATS = 2 * 3 * 2; + + private final Vec2 origin = new Vec2(); + private final Vec2 width = new Vec2(); + private final Vec2 height = new Vec2(); + + private final Vec2 counterOrigin = new Vec2(); + private final Vec2 counterWidth = new Vec2(); + private final Vec2 counterHeight = new Vec2(); + + // Temporary values, objects cached for efficiency + private Vec4 startXstartY = null; + private Vec4 startXendY = null; + private Vec4 endXstartY = null; + private Vec4 endXendY = null; + + public TransformedMask( + Vec2 origin, Vec2 width, Vec2 height, + Vec2 counterOrigin, Vec2 counterWidth, Vec2 counterHeight + ) { + set(origin, width, height, counterOrigin, counterWidth, counterHeight); + } + + public TransformedMask(Mask mask, Mat4 transform) { + set(mask, transform); + } + + public TransformedMask() { + // Do nothing + } + + public TransformedMask set( + Vec2 origin, Vec2 width, Vec2 height, + Vec2 counterOrigin, Vec2 counterWidth, Vec2 counterHeight + ) { + this.origin.set(origin.x, origin.y); + this.width.set(width.x, width.y); + this.height.set(height.x, height.y); + this.counterOrigin.set(counterOrigin.x, counterOrigin.y); + this.counterWidth.set(counterWidth.x, counterWidth.y); + this.counterHeight.set(counterHeight.x, counterHeight.y); + + return this; + } + + public TransformedMask set(Mask mask, Mat4 transform) { + applyTransform(mask, transform); + setFields(); + return this; + } + + private void applyTransform(Mask mask, Mat4 transform) { + ensureTemporaryVariablesExist(); + + int relX = mask.getWidth(); + int relY = mask.getHeight(); + + startXstartY.set( 0, 0, 0, 1); + startXendY .set( 0, relY, 0, 1); + endXstartY .set(relX, 0, 0, 1); + endXendY .set(relX, relY, 0, 1); + + transform.mul(startXstartY); + transform.mul(startXendY); + transform.mul(endXstartY); + transform.mul(endXendY); + + flipY(); + } + + private void ensureTemporaryVariablesExist() { + if (startXstartY == null) { + startXstartY = new Vec4(); + startXendY = new Vec4(); + endXstartY = new Vec4(); + endXendY = new Vec4(); + } + } + + private void flipY() { + float height = GraphicsInterface.getFramebufferHeight(); + + startXstartY.y = height - startXstartY.y; + startXendY.y = height - startXendY.y; + endXstartY.y = height - endXstartY.y; + endXendY.y = height - endXendY.y; + } + + private void setFields() { + origin.set( + startXstartY.x, + startXstartY.y + ); + + width.set( + endXstartY.x - startXstartY.x, + endXstartY.y - startXstartY.y + ); + + height.set( + startXendY.x - startXstartY.x, + startXendY.y - startXstartY.y + ); + + counterOrigin.set( + endXendY.x, + endXendY.y + ); + + counterWidth.set( + startXendY.x - endXendY.x, + startXendY.y - endXendY.y + ); + + counterHeight.set( + endXstartY.x - endXendY.x, + endXstartY.y - endXendY.y + ); + } + + public void writeToBuffer(FloatBuffer output) { + output.put(origin.x).put(origin.y); + output.put(width.x).put(width.y); + output.put(height.x).put(height.y); + output.put(counterOrigin.x).put(counterOrigin.y); + output.put(counterWidth.x).put(counterWidth.y); + output.put(counterHeight.x).put(counterHeight.y); + } + +} diff --git a/src/main/java/ru/windcorp/optica/client/graphics/input/WheelEvent.java b/src/main/java/ru/windcorp/optica/client/graphics/input/WheelEvent.java index f21b088..41c1aae 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/input/WheelEvent.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/input/WheelEvent.java @@ -1,7 +1,25 @@ +/******************************************************************************* + * Optica + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ package ru.windcorp.optica.client.graphics.input; public abstract class WheelEvent extends InputEvent { @Override public abstract WheelEvent snapshot(); + } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/input/WheelScrollEvent.java b/src/main/java/ru/windcorp/optica/client/graphics/input/WheelScrollEvent.java index f8c36b9..2b0f1b8 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/input/WheelScrollEvent.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/input/WheelScrollEvent.java @@ -1,51 +1,86 @@ +/******************************************************************************* + * Optica + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ package ru.windcorp.optica.client.graphics.input; -import glm.vec._2.d.Vec2d; - public class WheelScrollEvent extends WheelEvent { - protected double xoffset; - protected double yoffset; + protected double xOffset; + protected double yOffset; - protected WheelScrollEvent(double xoffset, double yoffset) { - this.xoffset = xoffset; - this.yoffset = yoffset; + protected WheelScrollEvent(double xOffset, double yOffset) { + this.xOffset = xOffset; + this.yOffset = yOffset; } protected WheelScrollEvent() {} - public boolean isUp() { return yoffset > 0; } + public boolean isUp() { + return yOffset > 0; + } - public boolean isDown() { return yoffset < 0; } + public boolean isDown() { + return yOffset < 0; + } - public boolean isRight() { return xoffset > 0; } + public boolean isRight() { + return xOffset > 0; + } - public boolean isLeft() { return xoffset < 0; } + public boolean isLeft() { + return xOffset < 0; + } - public boolean hasVerticalMovement() { return yoffset != 0; } + public boolean hasVerticalMovement() { + return yOffset != 0; + } - public boolean hasHorizontalMovement() { return xoffset != 0; } + public boolean hasHorizontalMovement() { + return xOffset != 0; + } - public double getX() { return xoffset; } + public double getX() { + return xOffset; + } - public double getY() { return yoffset; } + public double getY() { + return yOffset; + } @Override public WheelEvent snapshot() { - return new StaticWheelScrollEvent(xoffset, yoffset, getTime()); + return new StaticWheelScrollEvent(xOffset, yOffset, getTime()); } private class StaticWheelScrollEvent extends WheelScrollEvent { private final double time; - public StaticWheelScrollEvent(double xoffset, double yoffset, double time) { - super(xoffset, yoffset); + public StaticWheelScrollEvent( + double xOffset, double yOffset, double time + ) { + super(xOffset, yOffset); this.time = time; } @Override - public double getTime() { return time; } + public double getTime() { + return time; + } @Override public WheelEvent snapshot() { diff --git a/src/main/java/ru/windcorp/optica/client/graphics/model/LambdaModel.java b/src/main/java/ru/windcorp/optica/client/graphics/model/LambdaModel.java new file mode 100644 index 0000000..4c946dd --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/model/LambdaModel.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Optica + * Copyright (C) 2020 Wind Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *******************************************************************************/ +package ru.windcorp.optica.client.graphics.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import com.google.common.primitives.Booleans; + +import glm.mat._4.Mat4; + +public class LambdaModel extends DynamicModel { + + private static final Mat4 IDENTITY = new Mat4(); + + @FunctionalInterface + public static interface TransformGetter { + void transform(Mat4 result); + } + + private final TransformGetter[] getters; + + public LambdaModel( + WorldRenderable[] parts, + Mat4[] transforms, + boolean[] dynamic, + TransformGetter[] getters + ) { + super(parts, transforms, dynamic); + this.getters = getters; + } + + public LambdaModel(Builder builder) { + this( + builder.getParts(), builder.getTransforms(), + builder.getDynamics(), builder.getGetters() + ); + } + + @Override + protected void getDynamicTransform(int shapeIndex, Mat4 result) { + getters[shapeIndex].transform(result); + } + + public static Builder lambdaBuilder() { + return new Builder(); + } + + public static class Builder { + + private final List parts = new ArrayList<>(); + private final List transforms = new ArrayList<>(); + private final List dynamics = new ArrayList<>(); + private final List getters = new ArrayList<>(); + + protected Builder() {} + + private Builder addPart( + WorldRenderable part, + Mat4 transform, + TransformGetter getter + ) { + parts.add(Objects.requireNonNull(part, "part")); + transforms.add(Objects.requireNonNull(transform, "transform")); + dynamics.add(getter != null); + getters.add(getter); + + return this; + } + + public Builder addStaticPart( + WorldRenderable part, + Mat4 transform + ) { + return addPart(part, new Mat4(transform), null); + } + + public Builder addDynamicPart( + WorldRenderable part, + TransformGetter getter + ) { + return addPart(part, new Mat4(), getter); + } + + public Builder addStaticPart( + WorldRenderable part + ) { + return addStaticPart(part, IDENTITY); + } + + private WorldRenderable[] getParts() { + return parts.toArray(new WorldRenderable[parts.size()]); + } + + private Mat4[] getTransforms() { + return transforms.toArray(new Mat4[transforms.size()]); + } + + private boolean[] getDynamics() { + return Booleans.toArray(dynamics); + } + + private TransformGetter[] getGetters() { + return getters.toArray(new TransformGetter[getters.size()]); + } + + } + +} diff --git a/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderHelper.java b/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderHelper.java index b3b2641..8c691f3 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderHelper.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderHelper.java @@ -24,7 +24,7 @@ public class ShapeRenderHelper { protected static final int TRANSFORM_STACK_SIZE = 64; - private final StashingStack transformStack = new StashingStack<>( + protected final StashingStack transformStack = new StashingStack<>( TRANSFORM_STACK_SIZE, Mat4::new ); diff --git a/src/main/java/ru/windcorp/optica/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/optica/client/graphics/world/LayerWorld.java index 59d5bad..7e42272 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/world/LayerWorld.java @@ -35,6 +35,8 @@ import ru.windcorp.optica.common.world.WorldData; public class LayerWorld extends Layer { + public static Camera tmp_the_camera; + private final Camera camera = new Camera( new Vec3(8, 8, 8), 0, 0, @@ -59,6 +61,7 @@ public class LayerWorld extends Layer { public LayerWorld() { super("World"); + tmp_the_camera = camera; } @Override diff --git a/src/main/java/ru/windcorp/optica/common/util/StashingStack.java b/src/main/java/ru/windcorp/optica/common/util/StashingStack.java index 27acbd6..e7d520e 100644 --- a/src/main/java/ru/windcorp/optica/common/util/StashingStack.java +++ b/src/main/java/ru/windcorp/optica/common/util/StashingStack.java @@ -208,6 +208,26 @@ public class StashingStack implements Iterable { return newElement; } + /** + * Returns the specified element from the stack. Indexing starts from the + * bottom of the stack. If the index is out of bounds, an + * {@link IndexOutOfBoundsException} is thrown. + * @param index index of the element to retrieve, + * [0; {@link #getSize()}) + * @return the requested element + * @throws IndexOutOfBoundsException if the index is negative or greater + * than head + */ + public T get(int index) { + if (index > head) { + throw new IndexOutOfBoundsException( + "Requested index " + index + " > head " + head + ); + } + + return (T) contents[index]; + } + /** * Removes all elements from the stack. */ diff --git a/src/main/resources/assets/shaders/Flat.fragment.glsl b/src/main/resources/assets/shaders/Flat.fragment.glsl index be26587..15da58f 100644 --- a/src/main/resources/assets/shaders/Flat.fragment.glsl +++ b/src/main/resources/assets/shaders/Flat.fragment.glsl @@ -1,13 +1,26 @@ -#version 120 +#version 140 -uniform ivec2 maskStart; -uniform ivec2 maskEnd; +uniform int maskCount; + +uniform vec2 masks[3 * 2 * 16]; + +bool isInMaskPrimitive(int primitive) { + vec2 origin = masks[3 * primitive + 0]; + vec2 width = masks[3 * primitive + 1]; + vec2 height = masks[3 * primitive + 2]; + + vec2 current = gl_FragCoord.xy - origin; + + mat2 matrix = mat2(width, height); + vec2 relative = inverse(matrix) * current; + + return relative.x >= 0 && relative.y >= 0 && relative.x + relative.y <= 1; +} void applyMask() { - if ( - gl_FragCoord.x < maskStart.x || gl_FragCoord.x >= maskEnd.x || - gl_FragCoord.y < maskStart.y || gl_FragCoord.y >= maskEnd.y - ) { - discard; + for (int i = 0; i < maskCount; ++i) { + if (!(isInMaskPrimitive(2 * i + 0) || isInMaskPrimitive(2 * i + 1))) { + discard; + } } -} \ No newline at end of file +} diff --git a/src/main/resources/assets/shaders/Flat.vertex.glsl b/src/main/resources/assets/shaders/Flat.vertex.glsl index 7a531e1..9082679 100644 --- a/src/main/resources/assets/shaders/Flat.vertex.glsl +++ b/src/main/resources/assets/shaders/Flat.vertex.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 void flatTransferToFragment() { shapeTransferToFragment(); diff --git a/src/main/resources/assets/shaders/FlatDefault.fragment.glsl b/src/main/resources/assets/shaders/FlatDefault.fragment.glsl index 507d434..267244c 100644 --- a/src/main/resources/assets/shaders/FlatDefault.fragment.glsl +++ b/src/main/resources/assets/shaders/FlatDefault.fragment.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 void main(void) { applyTexture(); diff --git a/src/main/resources/assets/shaders/FlatDefault.vertex.glsl b/src/main/resources/assets/shaders/FlatDefault.vertex.glsl index 6ebcbfe..a317ef4 100644 --- a/src/main/resources/assets/shaders/FlatDefault.vertex.glsl +++ b/src/main/resources/assets/shaders/FlatDefault.vertex.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 void main(void) { gl_Position = applyFinalTransform(vec4(inputPositions, 1.0)); diff --git a/src/main/resources/assets/shaders/Shape.fragment.glsl b/src/main/resources/assets/shaders/Shape.fragment.glsl index 4860b9f..d188922 100644 --- a/src/main/resources/assets/shaders/Shape.fragment.glsl +++ b/src/main/resources/assets/shaders/Shape.fragment.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 varying vec3 varyingColorMultiplier; varying vec2 varyingTextureCoords; diff --git a/src/main/resources/assets/shaders/Shape.vertex.glsl b/src/main/resources/assets/shaders/Shape.vertex.glsl index b5da67f..661252d 100644 --- a/src/main/resources/assets/shaders/Shape.vertex.glsl +++ b/src/main/resources/assets/shaders/Shape.vertex.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 attribute vec3 inputPositions; diff --git a/src/main/resources/assets/shaders/World.fragment.glsl b/src/main/resources/assets/shaders/World.fragment.glsl index 7ec061b..691aadf 100644 --- a/src/main/resources/assets/shaders/World.fragment.glsl +++ b/src/main/resources/assets/shaders/World.fragment.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 varying vec3 varyingNormals; diff --git a/src/main/resources/assets/shaders/World.vertex.glsl b/src/main/resources/assets/shaders/World.vertex.glsl index 229df49..435826d 100644 --- a/src/main/resources/assets/shaders/World.vertex.glsl +++ b/src/main/resources/assets/shaders/World.vertex.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 attribute vec3 inputNormals; varying vec3 varyingNormals; diff --git a/src/main/resources/assets/shaders/WorldDefault.fragment.glsl b/src/main/resources/assets/shaders/WorldDefault.fragment.glsl index 94be7fd..1e8b869 100644 --- a/src/main/resources/assets/shaders/WorldDefault.fragment.glsl +++ b/src/main/resources/assets/shaders/WorldDefault.fragment.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 void main(void) { applyTexture(); diff --git a/src/main/resources/assets/shaders/WorldDefault.vertex.glsl b/src/main/resources/assets/shaders/WorldDefault.vertex.glsl index e9b6579..00a4097 100644 --- a/src/main/resources/assets/shaders/WorldDefault.vertex.glsl +++ b/src/main/resources/assets/shaders/WorldDefault.vertex.glsl @@ -1,4 +1,4 @@ -#version 120 +#version 140 void main(void) { gl_Position = applyFinalTransform(vec4(inputPositions, 1.0)); diff --git a/src/main/resources/assets/textures/compass_icon.png b/src/main/resources/assets/textures/compass_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ef68813d99ffcda63c00e592299bed0d38de3740 GIT binary patch literal 1289 zcmV+k1@`)hP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O=0}nye@c{hw9L5=bCCmV+SQH#?Z+&p|1x%STz= zeXq2FF@(c8F;>(3-@lFi!6Al)oQCL=_XdYcE=k59n)O(FHg36&8}k^v*lBx!u*Rad z>#d)Me}-M36M`G|>D5l5j5u)w;w|uU*uHWf55G79Sy}Bo?kSCV*?rm0IHioRBl!N_ z1&~n{@vM-{maV~6`YLukGtRhNZFho4A3I#N`<-z|+i*wTHrjD#^03=iD#-ZZ;CCDi zJL}GFw`F9n+GFLH2Sv9f4&1d?V{7xeyX-ue@-#N}*vc}3;{+=0GR>m}oQiQ+T0)E1 zVu4~6YEEc{II)23#*QmzZago2;R1+GW(nv;3K;LUXoDmvpq@cK8aD|x*-B7HY=LSP zX4$atvTj<|D;%+MWq1lB7-Pnv(V6ilZ41;|PhDmcH?Dw7de#6&SFT^-1wptCPIcjT zY4jy;%okxT6x4<0hz({ltsy4mXKvX=XA3_yj?DUMaHt~yD8kwbFl?cK@obenn;;UH z!DECz8OX&tnVk+= zp)+P@c;r0EWG6T2VCz-mAt#wXT?3{K8W;m_vAk;9gF&YX-%{F%%D7 z0VK3^%}iwHq$}4oGfD7Ls6aK=E>7jH7!-6fi#Fc0dn)%eBrQ<)}+H zlsoEnqFT+%7sW0D^|!EdYHUMcgHx7>Kh)#%-p*2QTnz2!xViVaf9Td8F!rXip3WY$ zIQfe?bKFLfAEOFy+8L`}LVOR6?x37OxZT=<@e1M%G`fUR@|{pGJ-rcq+Q6jt4%UK# ze#XeLr%xSE*(zn*1&wFlT>se9)q^hzhWUf+q~9XBMI@K0e$E2@0WgO^?`XNri@$>C zQ#ww2`W=`j8}wP0q6gS;z&fBTz;t5Vvqx@yn&7%RXF;f1X}eM zFwWk!Q&_KGoVN&BQ$dlkv^v0}=!@IlfV}0002kNkl zpqslP#t1N036c=iS{vq^GoR$WC#8fjh7f{M+qRA5p7tAAYcad7erGbVxsV2lC!y ztsUmuUyx0nLER{mZ+}5*UDpP%EX&Il(hTqg0q%qO_Ndmo00000NkvXXu0mjf>8@ED literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/textures/compass_icon_arrow.png b/src/main/resources/assets/textures/compass_icon_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..01ff5d30796defb71f5f9d5426af45bc0a35d2b2 GIT binary patch literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE({VNxT1@95m1D)z$3Dl zfk96hgc&QA+Lr+Z*-JcqUD=;-FblD=y(ls)1qxMqx;TbdoL)L{BX5HN4-3DGWaOgr zTpE`*_>?V5P&%Uj?@Oj9RkwM!e2Hg^ZHUP~ zS9O!|meGMPSMQ|tcWj8@b!iFex~tH_;E;XxAM5+Qe>-k{(r11iBd@U3WCml@F0Kog a7~>wKDrn?{$~^`;g2B_(&t;ucLK6V>(ocZ^ literal 0 HcmV?d00001