From c613bef8c5eab5f6db438818563f28309202adef Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 5 Sep 2020 23:26:54 +0300 Subject: [PATCH] Added face culling state stack and disabled face culling for entities --- .../client/TestEntityRenderJavapony.java | 66 ++++++++++++------- .../client/graphics/backend/FaceCulling.java | 27 ++++++++ .../graphics/backend/GraphicsBackend.java | 14 ++++ .../graphics/backend/LWJGLInitializer.java | 1 - .../graphics/flat/AssembledFlatLayer.java | 5 ++ .../graphics/flat/FlatRenderProgram.java | 4 -- .../client/graphics/model/Shapes.java | 28 +++++--- .../client/graphics/world/LayerWorld.java | 3 + .../progressia/client/world/ChunkRender.java | 6 -- .../progressia/client/world/WorldRender.java | 17 +++++ .../client/world/entity/QuadripedModel.java | 24 +++++-- 11 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java diff --git a/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java index 14ccabf..1dbf6ec 100644 --- a/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java +++ b/src/main/java/ru/windcorp/progressia/client/TestEntityRenderJavapony.java @@ -26,8 +26,10 @@ public class TestEntityRenderJavapony extends EntityRender { private final Renderable body; private final Renderable head; - private final Renderable foreLeg; - private final Renderable hindLeg; + private final Renderable leftForeLeg; + private final Renderable leftHindLeg; + private final Renderable rightForeLeg; + private final Renderable rightHindLeg; public TestEntityRenderJavapony() { super("Test", "Javapony"); @@ -39,8 +41,10 @@ public class TestEntityRenderJavapony extends EntityRender { this.body = createBody(texture); this.head = createHead(texture); - this.foreLeg = createForeLeg(texture); - this.hindLeg = createHindLeg(texture); + this.leftForeLeg = createLeg(texture, 160, 0, true); + this.rightForeLeg = createLeg(texture, 160, 0, false); + this.leftHindLeg = createLeg(texture, 0, 0, true); + this.rightHindLeg = createLeg(texture, 0, 0, false); } private static Renderable createBody(ComplexTexture texture) { @@ -75,7 +79,7 @@ public class TestEntityRenderJavapony extends EntityRender { ) ) .setOrigin(0, -8, 8) - .setWidth(16).setDepth(16).setHeight(4, 0, 16) + .setWidth(16).setDepth(16).setHeight(2, 0, 16) .create() ); @@ -243,7 +247,7 @@ public class TestEntityRenderJavapony extends EntityRender { // Left ear b.addPart(new PppBuilder( program, texture.getCuboidTextures(48, 128-80, 8) - ).setOrigin(-16 + 3, 16 - 8, 32).setSize(8).create()); + ).setOrigin(-16 + 3, +16, 32).setSize(8, -8, 8).flip().create()); // Muzzle b.addPart(new PppBuilder( @@ -255,7 +259,7 @@ public class TestEntityRenderJavapony extends EntityRender { texture.get(32, 64, 0, 0), texture.get(32, 64, 0, 0) ) - ).setOrigin(16, -8, 0).setSize(16, 4, 8).create()); + ).setOrigin(16, -8, 0).setSize(4, 16, 8).create()); // Nose b.addPart(new PppBuilder( @@ -267,23 +271,26 @@ public class TestEntityRenderJavapony extends EntityRender { texture.get(32, 64, 0, 0), texture.get(32, 64, 0, 0) ) - ).setOrigin(16, -4, 8).setSize(8, 4, 4).create()); + ).setOrigin(16, -4, 8).setSize(4, 8, 4).create()); return new StaticModel(b); } - - private static Renderable createForeLeg(ComplexTexture texture) { - return new PppBuilder( + + private static Renderable createLeg( + ComplexTexture texture, + int textureX, int textureY, + boolean isLeft + ) { + PppBuilder b = new PppBuilder( WorldRenderProgram.getDefault(), - texture.getCuboidTextures(160, 0, 16, 48, 16) - ).setOrigin(-8, -8, -48).setSize(16, 16, 48).create(); - } - - private static Renderable createHindLeg(ComplexTexture texture) { - return new PppBuilder( - WorldRenderProgram.getDefault(), - texture.getCuboidTextures(0, 0, 16, 48, 16) - ).setOrigin(-8, -8, -48).setSize(16, 16, 48).create(); + texture.getCuboidTextures(textureX, textureY, 16, 48, 16) + ) + .setOrigin(-8, isLeft ? +8 : -8, -48) + .setSize(16, isLeft ? -16 : +16, 48); + + if (isLeft) b.flip(); + + return b.create(); } private static Renderable createTail(ComplexTexture texture) { @@ -312,12 +319,21 @@ public class TestEntityRenderJavapony extends EntityRender { new QuadripedModel.Body(body), new QuadripedModel.Head( - head, new Vec3(16, 0, 20), 60, 45 + head, new Vec3(12, 0, 20), 60, 45 ), - new QuadripedModel.Leg(foreLeg, new Vec3( 6, +8.1f, -16), 0.0f), - new QuadripedModel.Leg(foreLeg, new Vec3( 6, -8.1f, -16), 2.5f), - new QuadripedModel.Leg(hindLeg, new Vec3(-36, +8.2f, -16), 2.5f), - new QuadripedModel.Leg(hindLeg, new Vec3(-36, -8.2f, -16), 0.0f), + new QuadripedModel.Leg( + leftForeLeg, new Vec3( 6, +8.1f, -16), 0.0f + ), + new QuadripedModel.Leg( + rightForeLeg, new Vec3( 6, -8.1f, -16), 2.5f + ), + new QuadripedModel.Leg( + leftHindLeg, new Vec3(-36, +8.2f, -16), 2.5f + ), + new QuadripedModel.Leg( + rightHindLeg, new Vec3(-36, -8.2f, -16), 0.0f + ), + 1 / 96f ); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java new file mode 100644 index 0000000..f289876 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/FaceCulling.java @@ -0,0 +1,27 @@ +package ru.windcorp.progressia.client.graphics.backend; + +import java.util.ArrayDeque; +import java.util.Deque; + +public class FaceCulling { + + private static final Deque STACK = new ArrayDeque<>(); + + public static void push(boolean useFaceCulling) { + GraphicsBackend.setFaceCulling(useFaceCulling); + STACK.push(Boolean.valueOf(useFaceCulling)); + } + + public static void pop() { + STACK.pop(); + + if (STACK.isEmpty()) { + GraphicsBackend.setFaceCulling(false); + } else { + GraphicsBackend.setFaceCulling(STACK.getFirst()); + } + } + + private FaceCulling() {} + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java index ba19d31..cc1df99 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/GraphicsBackend.java @@ -35,6 +35,8 @@ public class GraphicsBackend { private static long framesRendered = 0; private static double frameStart = Double.NaN; + private static boolean faceCullingEnabled = false; + private GraphicsBackend() {} public static void initialize() { @@ -109,5 +111,17 @@ public class GraphicsBackend { public static void startNextLayer() { glClear(GL_DEPTH_BUFFER_BIT); } + + public static void setFaceCulling(boolean useFaceCulling) { + if (useFaceCulling == faceCullingEnabled) return; + + if (useFaceCulling) { + glEnable(GL_CULL_FACE); + } else { + glDisable(GL_CULL_FACE); + } + + faceCullingEnabled = useFaceCulling; + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java index ea14292..17e36f6 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java @@ -81,7 +81,6 @@ class LWJGLInitializer { private static void initializeOpenGL() { GL.createCapabilities(); glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java index 0980e01..f53aab0 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/AssembledFlatLayer.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.client.graphics.flat; import ru.windcorp.progressia.client.graphics.Layer; +import ru.windcorp.progressia.client.graphics.backend.FaceCulling; public abstract class AssembledFlatLayer extends Layer { @@ -48,11 +49,15 @@ public abstract class AssembledFlatLayer extends Layer { @Override protected void doRender() { + FaceCulling.push(false); + for (RenderTarget.Clip clip : clips) { clip.render(helper); } helper.reset(); + + FaceCulling.pop(); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java index 9828518..846013f 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java @@ -17,8 +17,6 @@ *******************************************************************************/ package ru.windcorp.progressia.client.graphics.flat; -import static org.lwjgl.opengl.GL11.*; - import java.nio.FloatBuffer; import com.google.common.collect.ObjectArrays; @@ -81,9 +79,7 @@ public class FlatRenderProgram extends ShapeRenderProgram { @Override public void render(ShapeRenderHelper helper, Shape shape) { - glDisable(GL_CULL_FACE); super.render(helper, shape); - glEnable(GL_CULL_FACE); } @Override diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java index 90624ec..224ff11 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Shapes.java @@ -43,7 +43,9 @@ public class Shapes { Texture northTexture, Texture southTexture, Texture eastTexture, - Texture westTexture + Texture westTexture, + + boolean flip ) { Vec3 faceOrigin = Vectors.grab3(); @@ -55,7 +57,7 @@ public class Shapes { faceOrigin.set(origin).add(height).add(width), faceWidth.set(width).negate(), depth, - false + flip ); Face bottom = Faces.createRectangle( @@ -64,7 +66,7 @@ public class Shapes { origin, width, depth, - false + flip ); Face north = Faces.createRectangle( @@ -73,7 +75,7 @@ public class Shapes { faceOrigin.set(origin).add(depth), width, height, - false + flip ); Face south = Faces.createRectangle( @@ -82,7 +84,7 @@ public class Shapes { faceOrigin.set(origin).add(width), faceWidth.set(width).negate(), height, - false + flip ); Face east = Faces.createRectangle( @@ -91,7 +93,7 @@ public class Shapes { origin, depth, height, - false + flip ); Face west = Faces.createRectangle( @@ -100,7 +102,7 @@ public class Shapes { faceOrigin.set(origin).add(width).add(depth), faceWidth.set(depth).negate(), height, - false + flip ); Shape result = new Shape( @@ -134,6 +136,8 @@ public class Shapes { private final Texture eastTexture; private final Texture westTexture; + private boolean flip = false; + public PppBuilder( ShapeRenderProgram program, Texture top, @@ -237,13 +241,18 @@ public class Shapes { } public PppBuilder setSize(float x, float y, float z) { - return this.setWidth(x).setDepth(y).setHeight(z); + return this.setDepth(x).setWidth(y).setHeight(z); } public PppBuilder setSize(float size) { return this.setSize(size, size, size); } + public PppBuilder flip() { + this.flip = true; + return this; + } + public Shape create() { return createParallelepiped( program, @@ -255,7 +264,8 @@ public class Shapes { northTexture, southTexture, eastTexture, - westTexture + westTexture, + flip ); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java index 30e4c4f..6aa5a87 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerWorld.java @@ -24,6 +24,7 @@ import glm.vec._3.Vec3; import ru.windcorp.progressia.client.Client; import ru.windcorp.progressia.client.comms.controls.InputBasedControls; import ru.windcorp.progressia.client.graphics.Layer; +import ru.windcorp.progressia.client.graphics.backend.FaceCulling; import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent; @@ -102,7 +103,9 @@ public class LayerWorld extends Layer { } private void renderWorld() { + FaceCulling.push(true); this.client.getWorld().render(helper); + FaceCulling.pop(); } @Override diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index badcfb7..3bead82 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -92,12 +92,6 @@ public class ChunkRender { model.render(renderer); renderer.popTransform(); - - getData().forEachEntity(entityData -> { - renderer.pushTransform().translate(entityData.getPosition()); - getWorld().getEntityRenderable(entityData).render(renderer); - renderer.popTransform(); - }); } private void buildModel() { diff --git a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java index 68b5e22..26dd653 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.WeakHashMap; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.client.graphics.backend.FaceCulling; import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; @@ -67,8 +68,24 @@ public class WorldRender { for (ChunkRender chunk : getChunks()) { chunk.render(renderer); } + + renderEntities(renderer); } + private void renderEntities(ShapeRenderHelper renderer) { + FaceCulling.push(false); + + for (ChunkRender chunk : getChunks()) { + chunk.getData().forEachEntity(entity -> { + renderer.pushTransform().translate(entity.getPosition()); + getEntityRenderable(entity).render(renderer); + renderer.popTransform(); + }); + } + + FaceCulling.pop(); + } + public Renderable getEntityRenderable(EntityData entity) { return entityModels.computeIfAbsent( entity, diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java index 14e01e9..5b55665 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/QuadripedModel.java @@ -99,6 +99,11 @@ public class QuadripedModel implements Renderable { private float velocityCoeff = 0; private float velocity = 0; + /** + * Controls how quickly velocityCoeff approaches 1 + */ + private float velocityCutoff = 10; + private float walkingFrequency = 0.15f; private float walkingSwing = (float) toRadians(30); @@ -129,8 +134,8 @@ public class QuadripedModel implements Renderable { @Override public void render(ShapeRenderHelper renderer) { - evaluateAngles(); accountForVelocity(); + evaluateAngles(); renderer.pushTransform().scale(scale).rotateZ(bodyYaw); body.render(renderer, this); @@ -171,13 +176,15 @@ public class QuadripedModel implements Renderable { } private void accountForVelocity() { - // TODO switch to world time Vec3 horizontal = Vectors.grab3(); horizontal.set(entity.getVelocity()); horizontal.z = 0; - velocity = (float) (horizontal.length()); - velocityCoeff = -1 / (velocity * 1000 + 1) + 1; + velocity = horizontal.length(); + + evaluateVelocityCoeff(); + + // TODO switch to world time walkingAnimationParameter += velocity * GraphicsInterface.getFrameLength() * 1000; bodyYaw += velocityCoeff * normalizeAngle( @@ -186,6 +193,15 @@ public class QuadripedModel implements Renderable { Vectors.release(horizontal); } + private void evaluateVelocityCoeff() { + if (velocity * velocityCutoff > 1) { + velocityCoeff = 1; + } else { + velocityCoeff = velocity * velocityCutoff; + velocityCoeff *= velocityCoeff; + } + } + private static float normalizeAngle(float x) { final float half = (float) (PI); final float full = (float) (2 * PI);