diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java
index 4030249..807fcda 100644
--- a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java
+++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapeParts.java
@@ -153,6 +153,6 @@ public class ShapeParts {
height,
inner
);
- }
+ }
}
diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapePrototype.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapePrototype.java
new file mode 100644
index 0000000..f2cc631
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/ShapePrototype.java
@@ -0,0 +1,248 @@
+/*
+ * Progressia
+ * Copyright (C) 2020-2021 Wind Corporation and contributors
+ *
+ * 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.progressia.client.graphics.model;
+
+import java.nio.ShortBuffer;
+import java.util.Objects;
+
+import glm.mat._3.Mat3;
+import glm.mat._4.Mat4;
+import glm.vec._2.Vec2;
+import glm.vec._3.Vec3;
+import glm.vec._4.Vec4;
+import ru.windcorp.progressia.client.graphics.Colors;
+import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram.VertexBuilder;
+import ru.windcorp.progressia.client.graphics.texture.Texture;
+import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
+import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram.WRPVertexBuilder;
+import ru.windcorp.progressia.common.util.StashingStack;
+import ru.windcorp.progressia.common.util.VectorUtil;
+
+public class ShapePrototype {
+
+ private final ShapeRenderProgram program;
+
+ private Texture texture;
+
+ private final Vec3[] positions;
+ private final Vec4[] colorMultipliers;
+ private final Vec2[] textureCoords;
+ private final Vec3[] forcedNormals;
+
+ private ShortBuffer indices;
+ private ShortBuffer flippedIndices = null;
+
+ protected static final int TRANSFORM_STACK_SIZE = 64;
+ private final StashingStack transformStack = new StashingStack<>(
+ TRANSFORM_STACK_SIZE,
+ Mat4::new
+ );
+
+ public ShapePrototype(
+ ShapeRenderProgram program,
+ Texture texture,
+ Vec3[] positions,
+ Vec4[] colorMultipliers,
+ Vec2[] textureCoords,
+ Vec3[] forcedNormals,
+ ShortBuffer indices
+ ) {
+ this.program = Objects.requireNonNull(program, "program");
+ this.texture = texture;
+ this.indices = Objects.requireNonNull(indices, "indices");
+
+ Objects.requireNonNull(positions, "positions");
+ Objects.requireNonNull(colorMultipliers, "colorMultipliers");
+ Objects.requireNonNull(textureCoords, "textureCoords");
+
+ if (forcedNormals != null && !(program instanceof WorldRenderProgram)) {
+ throw new IllegalArgumentException("Cannot force normals on non-WorldRenderPrograms cuz javahorse stupiddd");
+ }
+
+ if (forcedNormals == null) {
+ forcedNormals = new Vec3[positions.length];
+ }
+
+ this.positions = positions;
+ this.colorMultipliers = colorMultipliers;
+ this.textureCoords = textureCoords;
+ this.forcedNormals = forcedNormals;
+
+ if (positions.length != colorMultipliers.length) {
+ throw new IllegalArgumentException("positions.length (" + positions.length + ") != colorMultipliers.length (" + colorMultipliers + ")");
+ }
+
+ if (positions.length != textureCoords.length) {
+ throw new IllegalArgumentException("positions.length (" + positions.length + ") != textureCoords.length (" + textureCoords + ")");
+ }
+
+ if (positions.length != forcedNormals.length) {
+ throw new IllegalArgumentException("positions.length (" + positions.length + ") != forcedNormals.length (" + forcedNormals + ")");
+ }
+
+ transformStack.push().identity();
+ }
+
+ public ShapePart build() {
+ VertexBuilder builder = program.getVertexBuilder();
+
+ Vec3 transformedPosition = new Vec3();
+
+ for (int i = 0; i < positions.length; ++i) {
+
+ transformedPosition.set(positions[i]);
+ if (transformStack.getSize() > 1) {
+ VectorUtil.applyMat4(transformedPosition, transformStack.getHead());
+ }
+
+ if (forcedNormals[i] != null && builder instanceof WRPVertexBuilder) {
+ ((WRPVertexBuilder) builder).addVertex(
+ transformedPosition, colorMultipliers[i], textureCoords[i], forcedNormals[i]
+ );
+ } else {
+ builder.addVertex(transformedPosition, colorMultipliers[i], textureCoords[i]);
+ }
+ }
+
+ return new ShapePart(texture, builder.assemble(), indices);
+ }
+
+ public ShapePrototype apply(Mat4 transform) {
+ for (Vec3 vector : positions) {
+ VectorUtil.applyMat4(vector, transform);
+ }
+ return this;
+ }
+
+ public ShapePrototype apply(Mat3 transform) {
+ for (Vec3 vector : positions) {
+ transform.mul(vector);
+ }
+ return this;
+ }
+
+ public Mat4 push() {
+ Mat4 previous = transformStack.getHead();
+ return transformStack.push().set(previous);
+ }
+
+ public ShapePrototype pop() {
+ transformStack.pop();
+ return this;
+ }
+
+ public ShapePrototype setTexture(Texture texture) {
+ this.texture = texture;
+ return this;
+ }
+
+ public ShapePrototype deleteTexture() {
+ this.texture = null;
+ return this;
+ }
+
+ public ShapePrototype resetColorMultiplier() {
+ for (Vec4 color : colorMultipliers) {
+ color.set(Colors.WHITE);
+ }
+ return this;
+ }
+
+ public ShapePrototype addColorMultiplier(Vec4 color) {
+ for (Vec4 c : colorMultipliers) {
+ c.mul(color);
+ }
+ return this;
+ }
+
+ public ShapePrototype flip() {
+ ShortBuffer tmp = indices;
+ indices = flippedIndices;
+ flippedIndices = tmp;
+
+ if (indices == null) {
+ int length = flippedIndices.limit();
+ indices = ShortBuffer.allocate(length);
+ for (int i = 0; i < length; ++i) {
+ indices.put(i, flippedIndices.get(length - i - 1));
+ }
+ }
+
+ return this;
+ }
+
+ public ShapePrototype makeDoubleSided() {
+ int length = indices.limit();
+ ShortBuffer newIndices = ShortBuffer.allocate(length * 2);
+
+ for (int i = 0; i < length; ++i) {
+ newIndices.put(i, indices.get(i));
+ }
+ for (int i = 0; i < length; ++i) {
+ newIndices.put(i + length, indices.get(length - i - 1));
+ }
+
+ indices = flippedIndices = newIndices;
+
+ return this;
+ }
+
+ public static ShapePrototype unitSquare(Texture texture, Vec4 color, ShapeRenderProgram program) {
+ return new ShapePrototype(
+ program,
+ texture,
+ new Vec3[] {
+ new Vec3(0, 0, 0),
+ new Vec3(0, 1, 0),
+ new Vec3(1, 0, 0),
+ new Vec3(1, 1, 0)
+ },
+ new Vec4[] {
+ new Vec4(color),
+ new Vec4(color),
+ new Vec4(color),
+ new Vec4(color)
+ },
+ new Vec2[] {
+ new Vec2(0, 0),
+ new Vec2(0, 1),
+ new Vec2(1, 0),
+ new Vec2(1, 1)
+ },
+ null,
+ ShortBuffer.wrap(new short[] {3, 1, 0, 2, 3, 0})
+ );
+ }
+
+ public static ShapePrototype unitSquare(Texture texture, Vec4 color) {
+ return unitSquare(texture, color, WorldRenderProgram.getDefault());
+ }
+
+ public static ShapePrototype unitSquare(Texture texture) {
+ return unitSquare(texture, Colors.WHITE, WorldRenderProgram.getDefault());
+ }
+
+ public static ShapePrototype unitSquare(Vec4 color) {
+ return unitSquare(null, color, WorldRenderProgram.getDefault());
+ }
+
+ public static ShapePrototype unitSquare() {
+ return unitSquare(null, Colors.WHITE, WorldRenderProgram.getDefault());
+ }
+
+}
diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java
index e027cef..c2444d2 100644
--- a/src/main/java/ru/windcorp/progressia/test/TestContent.java
+++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java
@@ -65,6 +65,8 @@ import ru.windcorp.progressia.server.world.tile.*;
import ru.windcorp.progressia.test.Flowers.FlowerVariant;
import ru.windcorp.progressia.test.Rocks.RockType;
import ru.windcorp.progressia.test.gen.TestGravityModel;
+import ru.windcorp.progressia.test.trees.BlockRenderLeavesHazel;
+import ru.windcorp.progressia.test.trees.BlockRenderLeavesPine;
public class TestContent {
@@ -131,7 +133,7 @@ public class TestContent {
register(new BlockLogic("Test:Log"));
register(new BlockData("Test:TemporaryLeaves"));
- register(new BlockRenderTransparentCube("Test:TemporaryLeaves", getBlockTexture("TemporaryLeaves")));
+ register(new BlockRenderLeavesHazel("Test:TemporaryLeaves", getBlockTexture("LeavesHazel")));
// Sic, using Glass logic for leaves because Test
register(new TestBlockLogicGlass("Test:TemporaryLeaves"));
@@ -142,6 +144,11 @@ public class TestContent {
register(new BlockData("Test:Tux"));
register(new TestBlockRenderTux("Test:Tux"));
register(new BlockLogic("Test:Tux"));
+
+ register(new BlockData("Test:LeavesPine"));
+ register(new BlockRenderLeavesPine("Test:LeavesPine", getBlockTexture("LeavesPine")));
+ // Sic, using Glass logic for leaves because Test
+ register(new TestBlockLogicGlass("Test:LeavesPine"));
BlockDataRegistry.getInstance().values().forEach(PLACEABLE_BLOCKS::add);
PLACEABLE_BLOCKS.removeIf(b -> placeableBlacklist.contains(b.getId()));
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java
index b559582..84328bd 100644
--- a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java
+++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestBushFeature.java
@@ -38,10 +38,12 @@ public class TestBushFeature extends MultiblockVegetationFeature {
Vec3i center = context.getLocation().add_(0, 0, 1);
- context.setBlock(center, trunk);
- context.setBlock(center.add_(0, 0, 1), leaves);
+ if (size > 0.8) {
+ context.setBlock(center, trunk);
+ context.setBlock(center.add_(0, 0, 1), leaves);
+ }
- iterateBlob(center, stretch(size, 1.3, 2.5), stretch(size, 0.6, 1.5), 0.7, 2, p -> {
+ iterateBlob(center, stretch(size, 0.5, 2.5), stretch(size, 0.6, 1.5), 0.7, 2, p -> {
setLeaves(context, p, leaves);
});
}
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java
index 611ec07..72becc1 100644
--- a/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java
+++ b/src/main/java/ru/windcorp/progressia/test/gen/feature/TestTreeFeature.java
@@ -24,33 +24,44 @@ import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
public class TestTreeFeature extends MultiblockVegetationFeature {
-
+
private final BlockData trunk = BlockDataRegistry.getInstance().get("Test:Log");
- private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
+ private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:LeavesPine");
public TestTreeFeature(String id, SurfaceFloatField selector) {
- super(id, selector, 10 * 10);
+ super(id, selector, 7 * 7);
}
-
+
@Override
protected void grow(SurfaceBlockContext context, double selectorValue) {
-
+
Vec3i start = context.getLocation().add_(0, 0, 1);
Vec3i center = start.add_(0);
double size = selectorValue * randomDouble(context, 0.8, 1.2);
-
- int height = (int) stretch(size, 3, 7);
+ double volume = stretch(size, 2.5, 1);
+
+ int height = (int) stretch(size, 8, 12);
for (; center.z < start.z + height; ++center.z) {
context.setBlock(center, trunk);
}
-
- double branchHorDistance = 0;
+ --center.z;
+
+ iterateBlob(center, 1.5 * volume, 1.75, 0.5, 3, p -> {
+ setLeaves(context, p, leaves);
+ });
+
+ int branchCount = 1 + context.getRandom().nextInt(2) + (int) (stretch(size, 0, 4));
+
+ for (int i = 0; i < branchCount; ++i) {
- do {
- double branchSize = 0.5 + randomDouble(context, 1, 2) * size;
double branchHorAngle = randomDouble(context, 0, 2 * Math.PI);
- int branchVertOffset = (int) randomDouble(context, -2, 0);
+ double branchHorDistance = randomDouble(context, 0.7, 1.5) * volume;
+
+ int branchVertOffset = (int) randomDouble(context, -height / 3.0, -height / 1.5);
+
+ double branchSize = randomDouble(context, 1, 2) * volume;
+ double branchHeight = 1.5;
Vec3i branchCenter = center.add_(
(int) (Math.sin(branchHorAngle) * branchHorDistance),
@@ -58,12 +69,12 @@ public class TestTreeFeature extends MultiblockVegetationFeature {
branchVertOffset
);
- iterateBlob(branchCenter, 1 * branchSize, 2.3 * branchSize, 0.5, 3, p -> {
+ iterateBlob(branchCenter, branchSize, branchHeight, 0.5, 3, p -> {
setLeaves(context, p, leaves);
});
- branchHorDistance = randomDouble(context, 0.7, 1.5);
- } while (context.getRandom().nextInt(8) > 1);
+ }
+
}
}
diff --git a/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesHazel.java b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesHazel.java
new file mode 100644
index 0000000..9626b16
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesHazel.java
@@ -0,0 +1,99 @@
+/*
+ * Progressia
+ * Copyright (C) 2020-2021 Wind Corporation and contributors
+ *
+ * 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.progressia.test.trees;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Random;
+import java.util.function.Consumer;
+
+import glm.vec._3.i.Vec3i;
+import ru.windcorp.progressia.client.graphics.backend.Usage;
+import ru.windcorp.progressia.client.graphics.model.Renderable;
+import ru.windcorp.progressia.client.graphics.model.Shape;
+import ru.windcorp.progressia.client.graphics.model.ShapePart;
+import ru.windcorp.progressia.client.graphics.model.ShapePrototype;
+import ru.windcorp.progressia.client.graphics.texture.Texture;
+import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
+import ru.windcorp.progressia.client.world.block.BlockRender;
+import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSimple.BlockOptimizedSimple;
+import ru.windcorp.progressia.common.world.DefaultChunkData;
+
+public class BlockRenderLeavesHazel extends BlockRender implements BlockOptimizedSimple {
+
+ private final Texture texture;
+
+ public BlockRenderLeavesHazel(String id, Texture texture) {
+ super(id);
+ this.texture = texture;
+ }
+
+ @Override
+ public void getShapeParts(DefaultChunkData chunk, Vec3i bic, Consumer output) {
+ ShapePrototype sp = ShapePrototype.unitSquare(texture).makeDoubleSided();
+ sp.push().translate(bic.x, bic.y, bic.z);
+
+ Random random = new Random(chunk.getX() ^ bic.x);
+ random.setSeed(random.nextLong() ^ chunk.getY() ^ bic.y);
+ random.setSeed(random.nextLong() ^ chunk.getZ() ^ bic.z);
+
+ final float angle = (float) (Math.PI / 4);
+
+ sp.push().translate(0, 0, random.nextFloat() * 0.5f)
+ .rotateZ(random.nextFloat() * Math.PI)
+ .rotateX(-0.3f + random.nextFloat() * 0.6)
+ .scale(1.3f);
+
+ sp.push().translate(0, 0, -0.5f).rotateX(angle).translate(-0.5f, -0.5f, 0);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.push().translate(0, 0, -0.5f).rotateX(-angle).translate(-0.5f, -0.5f, 0);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.push().translate(0, 0, -0.5f).rotateY(angle).translate(-0.5f, -0.5f, 0);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.push().translate(0, 0, -0.5f).rotateY(-angle).translate(-0.5f, -0.5f, 0);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.pop();
+ }
+
+ @Override
+ public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) {
+ Collection parts = new ArrayList<>(6);
+
+ getShapeParts(chunk, blockInChunk, parts::add);
+
+ return new Shape(
+ Usage.STATIC,
+ WorldRenderProgram.getDefault(),
+ parts.toArray(new ShapePart[parts.size()])
+ );
+ }
+
+ @Override
+ public boolean needsOwnRenderable() {
+ return false;
+ }
+
+}
diff --git a/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesPine.java b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesPine.java
new file mode 100644
index 0000000..32f98b5
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/test/trees/BlockRenderLeavesPine.java
@@ -0,0 +1,106 @@
+/*
+ * Progressia
+ * Copyright (C) 2020-2021 Wind Corporation and contributors
+ *
+ * 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.progressia.test.trees;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Random;
+import java.util.function.Consumer;
+
+import glm.vec._3.i.Vec3i;
+import ru.windcorp.progressia.client.graphics.Colors;
+import ru.windcorp.progressia.client.graphics.backend.Usage;
+import ru.windcorp.progressia.client.graphics.model.Renderable;
+import ru.windcorp.progressia.client.graphics.model.Shape;
+import ru.windcorp.progressia.client.graphics.model.ShapePart;
+import ru.windcorp.progressia.client.graphics.model.ShapePrototype;
+import ru.windcorp.progressia.client.graphics.texture.Texture;
+import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
+import ru.windcorp.progressia.client.world.block.BlockRender;
+import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSimple.BlockOptimizedSimple;
+import ru.windcorp.progressia.common.world.DefaultChunkData;
+
+public class BlockRenderLeavesPine extends BlockRender implements BlockOptimizedSimple {
+
+ private final Texture texture;
+
+ public BlockRenderLeavesPine(String id, Texture texture) {
+ super(id);
+ this.texture = texture;
+ }
+
+ @Override
+ public void getShapeParts(DefaultChunkData chunk, Vec3i bic, Consumer output) {
+ Random random = new Random(chunk.getX() ^ bic.x);
+ random.setSeed(random.nextLong() ^ chunk.getY() ^ bic.y);
+ random.setSeed(random.nextLong() ^ chunk.getZ() ^ bic.z);
+
+ ShapePrototype sp = ShapePrototype.unitSquare(texture).makeDoubleSided();
+ sp.push().translate(
+ bic.x + random.nextFloat() * 0.3f - 0.15f,
+ bic.y + random.nextFloat() * 0.3f - 0.15f,
+ bic.z
+ );
+
+ final float angle = 0.5f;
+
+ for (float offset : new float[] { -0.25f, -0.75f }) {
+ sp.push().translate(0, 0, offset + random.nextFloat() * 0.5f)
+ .rotateZ(-0.3f + random.nextFloat() * 0.6)
+ .rotateX(-0.3f + random.nextFloat() * 0.6);
+
+ sp.push().translate(0, 0, -0.3f).rotateX(angle).translate(-0.5f, -0.5f, 0.5f);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.push().translate(0, 0, -0.3f).rotateX(-angle).translate(-0.5f, -0.5f, 0.5f);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.push().translate(0, 0, -0.3f).rotateY(angle).translate(-0.5f, -0.5f, 0.5f);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.push().translate(0, 0, -0.3f).rotateY(-angle).translate(-0.5f, -0.5f, 0.5f);
+ output.accept(sp.build());
+ sp.pop();
+
+ sp.pop();
+ sp.addColorMultiplier(Colors.GRAY_A);
+ }
+ }
+
+ @Override
+ public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) {
+ Collection parts = new ArrayList<>(6);
+
+ getShapeParts(chunk, blockInChunk, parts::add);
+
+ return new Shape(
+ Usage.STATIC,
+ WorldRenderProgram.getDefault(),
+ parts.toArray(new ShapePart[parts.size()])
+ );
+ }
+
+ @Override
+ public boolean needsOwnRenderable() {
+ return false;
+ }
+
+}
diff --git a/src/main/resources/assets/textures/blocks/LeavesHazel.png b/src/main/resources/assets/textures/blocks/LeavesHazel.png
new file mode 100644
index 0000000..ec12d2d
Binary files /dev/null and b/src/main/resources/assets/textures/blocks/LeavesHazel.png differ
diff --git a/src/main/resources/assets/textures/blocks/LeavesPine.png b/src/main/resources/assets/textures/blocks/LeavesPine.png
new file mode 100644
index 0000000..f01e127
Binary files /dev/null and b/src/main/resources/assets/textures/blocks/LeavesPine.png differ
diff --git a/src/main/resources/assets/textures/blocks/LogSide.png b/src/main/resources/assets/textures/blocks/LogSide.png
index c4d7ca1..0f9506f 100644
Binary files a/src/main/resources/assets/textures/blocks/LogSide.png and b/src/main/resources/assets/textures/blocks/LogSide.png differ
diff --git a/src/main/resources/assets/textures/blocks/LogTop.png b/src/main/resources/assets/textures/blocks/LogTop.png
index fb61de5..99adc89 100644
Binary files a/src/main/resources/assets/textures/blocks/LogTop.png and b/src/main/resources/assets/textures/blocks/LogTop.png differ