diff --git a/src/main/java/ru/windcorp/optica/client/ClientProxy.java b/src/main/java/ru/windcorp/optica/client/ClientProxy.java index 4df867b..3cd9a2c 100644 --- a/src/main/java/ru/windcorp/optica/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/optica/client/ClientProxy.java @@ -21,6 +21,8 @@ import ru.windcorp.optica.Proxy; import ru.windcorp.optica.client.graphics.GUI; import ru.windcorp.optica.client.graphics.backend.GraphicsBackend; import ru.windcorp.optica.client.graphics.backend.RenderTaskQueue; +import ru.windcorp.optica.client.graphics.flat.FlatRenderProgram; +import ru.windcorp.optica.client.graphics.flat.LayerTestUI; import ru.windcorp.optica.client.graphics.world.LayerWorld; import ru.windcorp.optica.client.graphics.world.WorldRenderProgram; @@ -30,6 +32,7 @@ public class ClientProxy implements Proxy { public void initialize() { GraphicsBackend.initialize(); try { + RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init); RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); } catch (InterruptedException e) { // TODO Auto-generated catch block @@ -37,6 +40,7 @@ public class ClientProxy implements Proxy { } GUI.addBottomLayer(new LayerWorld()); + GUI.addTopLayer(new LayerTestUI()); } } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/Colors.java b/src/main/java/ru/windcorp/optica/client/graphics/Colors.java new file mode 100644 index 0000000..e189ead --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/Colors.java @@ -0,0 +1,21 @@ +package ru.windcorp.optica.client.graphics; + +public class Colors { + + public static final int + WHITE = 0xFFFFFF, + BLACK = 0x000000, + + GRAY_4 = 0x444444, + GRAY = 0x888888, + GRAY_A = 0xAAAAAA, + + DEBUG_RED = 0xFF0000, + DEBUG_GREEN = 0x00FF00, + DEBUG_BLUE = 0x0000FF, + + DEBUG_CYAN = 0x00FFFF, + DEBUG_MAGENTA = 0xFF00FF, + DEBUG_YELLOW = 0x00FFFF; + +} diff --git a/src/main/java/ru/windcorp/optica/client/graphics/Layer.java b/src/main/java/ru/windcorp/optica/client/graphics/Layer.java index fcdfaf6..bb04456 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/Layer.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/Layer.java @@ -17,6 +17,8 @@ *******************************************************************************/ package ru.windcorp.optica.client.graphics; +import ru.windcorp.optica.client.graphics.backend.GraphicsInterface; + public abstract class Layer { private final String name; @@ -43,5 +45,13 @@ public abstract class Layer { protected abstract void initialize(); protected abstract void doRender(); + + protected float getWidth() { + return GraphicsInterface.getFramebufferWidth(); + } + + protected float getHeight() { + return GraphicsInterface.getFramebufferHeight(); + } } 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 new file mode 100644 index 0000000..6982724 --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/AssembledFlatLayer.java @@ -0,0 +1,103 @@ +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 RenderTarget target = new RenderTarget(); + + private boolean needsReassembly = true; + private Clip[] clips = null; + + public AssembledFlatLayer(String name) { + super(name); + } + + @Override + protected void initialize() { + // TODO Auto-generated method stub + + } + + public void markForReassembly() { + needsReassembly = true; + } + + private void doReassemble() { + assemble(target); + clips = target.assemble(); + needsReassembly = false; + } + + protected abstract void assemble(RenderTarget target); + + @Override + protected void doRender() { + if (needsReassembly) { + doReassemble(); + } + + for (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/FlatGraphics.java b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatGraphics.java new file mode 100644 index 0000000..182306c --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatGraphics.java @@ -0,0 +1,7 @@ +package ru.windcorp.optica.client.graphics.flat; + +public class FlatGraphics { + + + +} 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 new file mode 100644 index 0000000..f30cc4a --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderHelper.java @@ -0,0 +1,65 @@ +package ru.windcorp.optica.client.graphics.flat; + +import ru.windcorp.optica.client.graphics.backend.GraphicsInterface; +import ru.windcorp.optica.client.graphics.model.ShapeRenderHelper; + +public class FlatRenderHelper extends ShapeRenderHelper { + + private final Mask mask = new Mask(); + + { + setupScreenTransform(); + } + + 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() { + float width = GraphicsInterface.getFramebufferWidth(); + float height = GraphicsInterface.getFramebufferHeight(); + + getTransform().translate(-1, +1, 0).scale(2 / width, -2 / height, 1); + } + +} 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 new file mode 100644 index 0000000..2748d6a --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/FlatRenderProgram.java @@ -0,0 +1,84 @@ +package ru.windcorp.optica.client.graphics.flat; + +import static org.lwjgl.opengl.GL11.*; + +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.model.Shape; +import ru.windcorp.optica.client.graphics.model.ShapeRenderHelper; +import ru.windcorp.optica.client.graphics.model.ShapeRenderProgram; + +public class FlatRenderProgram extends ShapeRenderProgram { + + private static FlatRenderProgram def = null; + + public static void init() { + def = new FlatRenderProgram( + new String[] {"FlatDefault.vertex.glsl"}, + new String[] {"FlatDefault.fragment.glsl"} + ); + } + + public static FlatRenderProgram getDefault() { + return def; + } + + 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"; + + private final Uniform2Int maskStartUniform; + private final Uniform2Int maskEndUniform; + + public FlatRenderProgram( + String[] vertexShaderResources, + String[] fragmentShaderResources + ) { + super( + attachVertexShader(vertexShaderResources), + attachFragmentShader(fragmentShaderResources) + ); + + this.maskStartUniform = getUniform(MASK_START_UNIFORM_NAME).as2Int(); + this.maskEndUniform = getUniform(MASK_END_UNIFORM_NAME).as2Int(); + } + + private static String[] attachVertexShader(String[] others) { + return ObjectArrays.concat(FLAT_VERTEX_SHADER_RESOURCE, others); + } + + private static String[] attachFragmentShader(String[] others) { + return ObjectArrays.concat(FLAT_FRAGMENT_SHADER_RESOURCE, others); + } + + @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); + glEnable(GL_CULL_FACE); + } + + @Override + protected void configure(ShapeRenderHelper argHelper) { + super.configure(argHelper); + FlatRenderHelper helper = ((FlatRenderHelper) argHelper); + + maskStartUniform.set(helper.getStartX(), helper.getStartY()); + maskEndUniform.set(helper.getEndX(), helper.getEndY()); + } + +} 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 new file mode 100644 index 0000000..5108330 --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/LayerTestUI.java @@ -0,0 +1,76 @@ +package ru.windcorp.optica.client.graphics.flat; + +import org.lwjgl.glfw.GLFW; + +import com.google.common.eventbus.Subscribe; + +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.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; + +public class LayerTestUI extends AssembledFlatLayer { + + public LayerTestUI() { + super("TestUI"); + + GraphicsInterface.subscribeToInputEvents(this); + } + + private boolean flag = false; + + @Override + protected void assemble(RenderTarget target) { + final float width = 512 + 256; + final float height = 64; + final float border = 5; + + final int boxColor = flag ? 0xEE8888 : 0xEEEE88; + final int borderColor = flag ? 0xAA4444 : 0xAAAA44; + final int boxShadowColor = flag ? 0x440000 : 0x444400; + + float x = (getWidth() - width) / 2; + float y = getHeight() - height; + + y -= 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); + + final float texShadow = 2; + final float 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")); + } + + @Subscribe + public void onKeyEvent(KeyEvent event) { + if (event.isRepeat() || event.getKey() != GLFW.GLFW_KEY_LEFT_CONTROL) { + return; + } + + flag = event.isPress(); + markForReassembly(); + } + + /* + * TMP texture loader + */ + + private static final TextureSettings TEXTURE_SETTINGS = + new TextureSettings(false); + + private static Texture qtex(String name) { + return new SimpleTexture(new Sprite( + TextureManager.load(name, TEXTURE_SETTINGS) + )); + } + +} 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 new file mode 100644 index 0000000..bcbc379 --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/Mask.java @@ -0,0 +1,62 @@ +package ru.windcorp.optica.client.graphics.flat; + +public class Mask { + + private int startX; + private int startY; + private int endX; + private int endY; + + public Mask(int startX, int startY, int endX, int endY) { + this.startX = startX; + this.startY = startY; + this.endX = endX; + this.endY = endY; + } + + public Mask() {} + + public int getStartX() { + return startX; + } + + public void setStartX(int startX) { + this.startX = startX; + } + + public int getStartY() { + return startY; + } + + public void setStartY(int startY) { + this.startY = startY; + } + + public int getEndX() { + return endX; + } + + public void setEndX(int endX) { + this.endX = endX; + } + + public int getEndY() { + return endY; + } + + public void setEndY(int endY) { + this.endY = endY; + } + + public void set(int startX, int startY, int endX, int endY) { + this.startX = startX; + this.startY = startY; + this.endX = endX; + this.endY = endY; + } + + public boolean isEmpty() { + return startX >= endX || startY >= endY; + } + +} 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 new file mode 100644 index 0000000..4a0ee3b --- /dev/null +++ b/src/main/java/ru/windcorp/optica/client/graphics/flat/RenderTarget.java @@ -0,0 +1,166 @@ +package ru.windcorp.optica.client.graphics.flat; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +import glm.vec._3.Vec3; +import ru.windcorp.optica.client.graphics.Colors; +import ru.windcorp.optica.client.graphics.backend.Usage; +import ru.windcorp.optica.client.graphics.model.Face; +import ru.windcorp.optica.client.graphics.model.Faces; +import ru.windcorp.optica.client.graphics.model.Shape; +import ru.windcorp.optica.client.graphics.model.WorldRenderable; +import ru.windcorp.optica.client.graphics.texture.Texture; + +public class RenderTarget { + + private static final int MAX_DEPTH = 1 << 16; + + private final List assembled = new ArrayList<>(); + + private final Deque maskStack = new LinkedList<>(); + + private final List currentClipFaces = new ArrayList<>(); + + private int depth = 0; + + public RenderTarget() { + reset(); + } + + public void pushMaskStartEnd(int startX, int startY, int endX, int endY) { + assembleCurrentClipFromFaces(); + maskStack.push(intersect(getMask(), startX, startY, endX, endY)); + } + + 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 void pushMask(Mask mask) { + pushMaskStartEnd( + mask.getStartX(), mask.getStartY(), + mask.getEndX(), mask.getEndY() + ); + } + + public void pushMaskStartSize(int x, int y, int width, int height) { + pushMaskStartEnd(x, y, x + width, y + height); + } + + public void popMask() { + assembleCurrentClipFromFaces(); + maskStack.pop(); + } + + public Mask 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() { + assembleCurrentClipFromFaces(); + + AssembledFlatLayer.Clip[] result = assembled.toArray( + new AssembledFlatLayer.Clip[assembled.size()] + ); + + reset(); + + return result; + } + + 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 addCustomRenderer(WorldRenderable renderable) { + assembleCurrentClipFromFaces(); + + Mask mask = getMask(); + if (mask.isEmpty()) { + return; + } + + assembled.add(new AssembledFlatLayer.Clip(mask, renderable)); + } + + protected void addFaceToCurrentClip(Face face) { + currentClipFaces.add(face); + } + + public void drawTexture( + float x, float y, float width, float height, + int color, Texture texture + ) { + float depth = this.depth-- / (float) MAX_DEPTH; + + addFaceToCurrentClip(Faces.createRectangle( + FlatRenderProgram.getDefault(), + texture, + createVectorFromRGBInt(color), + new Vec3(x, y + height, depth), // Flip + new Vec3(width, 0, depth), + new Vec3(0, -height, depth) + )); + } + + public void drawTexture( + float x, float y, float width, float height, + Texture texture + ) { + drawTexture(x, y, width, height, Colors.WHITE, texture); + } + + public void fill( + float x, float y, float width, float height, + int color + ) { + drawTexture(x, y, width, height, color, null); + } + + private static Vec3 createVectorFromRGBInt(int rgb) { + int r = (rgb & 0xFF0000) >> 16; + int g = (rgb & 0x00FF00) >> 8; + int b = (rgb & 0x0000FF); + + return new Vec3(r / 256f, g / 256f, b / 256f); + } + +} diff --git a/src/main/java/ru/windcorp/optica/client/graphics/model/Face.java b/src/main/java/ru/windcorp/optica/client/graphics/model/Face.java index 353eb75..f0ae15f 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/model/Face.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/model/Face.java @@ -237,7 +237,7 @@ public class Face { } public void setTexture(Texture texture) { - this.texture = Objects.requireNonNull(texture, "texture"); + this.texture = texture; } } diff --git a/src/main/java/ru/windcorp/optica/client/graphics/model/Model.java b/src/main/java/ru/windcorp/optica/client/graphics/model/Model.java index c2864c1..8055b45 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/model/Model.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/model/Model.java @@ -36,10 +36,10 @@ public abstract class Model implements WorldRenderable { Mat4 transform = getTransform(i); try { - helper.pushWorldTransform().mul(transform); + helper.pushTransform().mul(transform); part.render(helper); } finally { - helper.popWorldTransform(); + helper.popTransform(); } } } 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 f01f716..b3b2641 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 @@ -32,21 +32,21 @@ public class ShapeRenderHelper { transformStack.push().identity(); } - public Mat4 pushWorldTransform() { + public Mat4 pushTransform() { Mat4 previous = transformStack.getHead(); return transformStack.push().set(previous); } - public void popWorldTransform() { + public void popTransform() { transformStack.removeHead(); } - public Mat4 getWorldTransform() { + public Mat4 getTransform() { return transformStack.getHead(); } public Mat4 getFinalTransform() { - return getWorldTransform(); + return getTransform(); } public void reset() { diff --git a/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderProgram.java b/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderProgram.java index c695f70..2c35f64 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderProgram.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/model/ShapeRenderProgram.java @@ -35,6 +35,7 @@ import ru.windcorp.optica.client.graphics.backend.shaders.Program; import ru.windcorp.optica.client.graphics.backend.shaders.attributes.*; import ru.windcorp.optica.client.graphics.backend.shaders.uniforms.*; import ru.windcorp.optica.client.graphics.texture.Sprite; +import ru.windcorp.optica.client.graphics.texture.Texture; public class ShapeRenderProgram extends Program { @@ -53,6 +54,7 @@ public class ShapeRenderProgram extends Program { POSITIONS_ATTRIBUTE_NAME = "inputPositions", COLOR_MULTIPLER_ATTRIBUTE_NAME = "inputColorMultiplier", TEXTURE_COORDS_ATTRIBUTE_NAME = "inputTextureCoords", + USE_TEXTURE_UNIFORM_NAME = "useTexture", TEXTURE_SLOT_UNIFORM_NAME = "textureSlot", TEXTURE_START_UNIFORM_NAME = "textureStart", TEXTURE_SIZE_UNIFORM_NAME = "textureSize"; @@ -61,6 +63,7 @@ public class ShapeRenderProgram extends Program { private final AttributeVertexArray positionsAttribute; private final AttributeVertexArray colorsAttribute; private final AttributeVertexArray textureCoordsAttribute; + private final Uniform1Int useTextureUniform; private final Uniform1Int textureSlotUniform; private final Uniform2Float textureStartUniform; private final Uniform2Float textureSizeUniform; @@ -90,6 +93,9 @@ public class ShapeRenderProgram extends Program { this.textureCoordsAttribute = getAttribute(TEXTURE_COORDS_ATTRIBUTE_NAME).asVertexArray(); + this.useTextureUniform = getUniform(USE_TEXTURE_UNIFORM_NAME) + .as1Int(); + this.textureSlotUniform = getUniform(TEXTURE_SLOT_UNIFORM_NAME) .as1Int(); @@ -174,13 +180,20 @@ public class ShapeRenderProgram extends Program { } protected void renderFace(Face face) { - Sprite sprite = face.getTexture().getSprite(); + Texture texture = face.getTexture(); - sprite.getPrimitive().bind(0); - textureSlotUniform.set(0); - - textureStartUniform.set(sprite.getStart()); - textureSizeUniform.set(sprite.getSize()); + if (texture != null) { + Sprite sprite = texture.getSprite(); + + sprite.getPrimitive().bind(0); + textureSlotUniform.set(0); + useTextureUniform.set(1); + + textureStartUniform.set(sprite.getStart()); + textureSizeUniform.set(sprite.getSize()); + } else { + useTextureUniform.set(0); + } GL11.glDrawElements( GL11.GL_TRIANGLES, diff --git a/src/main/java/ru/windcorp/optica/client/graphics/texture/Sprite.java b/src/main/java/ru/windcorp/optica/client/graphics/texture/Sprite.java index 24f53df..fd39285 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/texture/Sprite.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/texture/Sprite.java @@ -24,7 +24,6 @@ import glm.vec._2.Vec2; public class Sprite { private static final Vec2 ORIGIN = new Vec2(0, 0); - private static final Vec2 FULL_PRIMITIVE = new Vec2(1, 1); private final TexturePrimitive primitive; @@ -38,7 +37,10 @@ public class Sprite { } public Sprite(TexturePrimitive primitive) { - this(primitive, ORIGIN, FULL_PRIMITIVE); + this(primitive, ORIGIN, new Vec2( + primitive.getWidth() / (float) primitive.getBufferWidth(), + primitive.getHeight() / (float) primitive.getBufferHeight() + )); } public TexturePrimitive getPrimitive() { diff --git a/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderHelper.java b/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderHelper.java index 5caefd9..6bc6657 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderHelper.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderHelper.java @@ -48,7 +48,7 @@ public class WorldRenderHelper extends ShapeRenderHelper { @Override public Mat4 getFinalTransform() { - return finalTransform.set(getViewTransform()).mul(getWorldTransform()); + return finalTransform.set(getViewTransform()).mul(getTransform()); } @Override diff --git a/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderProgram.java b/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderProgram.java index baac644..a865437 100644 --- a/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderProgram.java +++ b/src/main/java/ru/windcorp/optica/client/graphics/world/WorldRenderProgram.java @@ -96,7 +96,7 @@ public class WorldRenderProgram extends ShapeRenderProgram { @Override protected void configure(ShapeRenderHelper helper) { super.configure(helper); - worldTransformUniform.set(helper.getWorldTransform()); + worldTransformUniform.set(helper.getTransform()); } @Override diff --git a/src/main/java/ru/windcorp/optica/client/world/ChunkRender.java b/src/main/java/ru/windcorp/optica/client/world/ChunkRender.java index 53cfe27..753b6c2 100644 --- a/src/main/java/ru/windcorp/optica/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/optica/client/world/ChunkRender.java @@ -75,7 +75,7 @@ public class ChunkRender { buildModel(); } - renderer.pushWorldTransform().translate( + renderer.pushTransform().translate( data.getX() * ChunkData.BLOCKS_PER_CHUNK, data.getY() * ChunkData.BLOCKS_PER_CHUNK, data.getZ() * ChunkData.BLOCKS_PER_CHUNK @@ -83,7 +83,7 @@ public class ChunkRender { model.render(renderer); - renderer.popWorldTransform(); + renderer.popTransform(); } private void buildModel() { diff --git a/src/main/java/ru/windcorp/optica/client/world/WorldRender.java b/src/main/java/ru/windcorp/optica/client/world/WorldRender.java index 67301c9..b037e7b 100644 --- a/src/main/java/ru/windcorp/optica/client/world/WorldRender.java +++ b/src/main/java/ru/windcorp/optica/client/world/WorldRender.java @@ -56,7 +56,7 @@ public class WorldRender { } public void render(ShapeRenderHelper renderer) { - renderer.pushWorldTransform().rotateX(-Math.PI / 2); + renderer.pushTransform().rotateX(-Math.PI / 2); for (ChunkRender chunk : getChunks()) { chunk.render(renderer); diff --git a/src/main/resources/assets/shaders/Flat.fragment.glsl b/src/main/resources/assets/shaders/Flat.fragment.glsl new file mode 100644 index 0000000..be26587 --- /dev/null +++ b/src/main/resources/assets/shaders/Flat.fragment.glsl @@ -0,0 +1,13 @@ +#version 120 + +uniform ivec2 maskStart; +uniform ivec2 maskEnd; + +void applyMask() { + if ( + gl_FragCoord.x < maskStart.x || gl_FragCoord.x >= maskEnd.x || + gl_FragCoord.y < maskStart.y || gl_FragCoord.y >= maskEnd.y + ) { + 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 new file mode 100644 index 0000000..7a531e1 --- /dev/null +++ b/src/main/resources/assets/shaders/Flat.vertex.glsl @@ -0,0 +1,5 @@ +#version 120 + +void flatTransferToFragment() { + shapeTransferToFragment(); +} \ No newline at end of file diff --git a/src/main/resources/assets/shaders/FlatDefault.fragment.glsl b/src/main/resources/assets/shaders/FlatDefault.fragment.glsl new file mode 100644 index 0000000..507d434 --- /dev/null +++ b/src/main/resources/assets/shaders/FlatDefault.fragment.glsl @@ -0,0 +1,8 @@ +#version 120 + +void main(void) { + applyTexture(); + applyColorMultiplier(); + applyAlpha(); + applyMask(); +} \ No newline at end of file diff --git a/src/main/resources/assets/shaders/FlatDefault.vertex.glsl b/src/main/resources/assets/shaders/FlatDefault.vertex.glsl new file mode 100644 index 0000000..6ebcbfe --- /dev/null +++ b/src/main/resources/assets/shaders/FlatDefault.vertex.glsl @@ -0,0 +1,6 @@ +#version 120 + +void main(void) { + gl_Position = applyFinalTransform(vec4(inputPositions, 1.0)); + flatTransferToFragment(); +} \ No newline at end of file diff --git a/src/main/resources/assets/shaders/Shape.fragment.glsl b/src/main/resources/assets/shaders/Shape.fragment.glsl index d5e69b5..4860b9f 100644 --- a/src/main/resources/assets/shaders/Shape.fragment.glsl +++ b/src/main/resources/assets/shaders/Shape.fragment.glsl @@ -7,14 +7,20 @@ uniform sampler2D textureSlot; uniform vec2 textureStart; uniform vec2 textureSize; +uniform bool useTexture; + void applyTexture() { - gl_FragColor = texture2D( - textureSlot, - vec2( - varyingTextureCoords[0] * textureSize[0] + textureStart[0], - varyingTextureCoords[1] * textureSize[1] + textureStart[1] - ) - ); + if (!useTexture) { + gl_FragColor = vec4(1, 1, 1, 1); + } else { + gl_FragColor = texture2D( + textureSlot, + vec2( + varyingTextureCoords[0] * textureSize[0] + textureStart[0], + varyingTextureCoords[1] * textureSize[1] + textureStart[1] + ) + ); + } } void multiply(inout vec4 vector, float scalar) { diff --git a/src/main/resources/assets/textures/windcorp.png b/src/main/resources/assets/textures/windcorp.png new file mode 100644 index 0000000..2a1b697 Binary files /dev/null and b/src/main/resources/assets/textures/windcorp.png differ