Implement blend masking, fix block_foliage model hack.
parent
32f4a9414c
commit
dad2f216fa
|
@ -5,6 +5,7 @@ layout (location = 1) out vec4 gNormal;
|
|||
layout (location = 2) out vec4 gSpecular;
|
||||
|
||||
in vec2 texCoords;
|
||||
in vec2 blendMaskCoords;
|
||||
in vec3 blend;
|
||||
in vec3 fragPos;
|
||||
in vec3 normal;
|
||||
|
@ -14,10 +15,20 @@ uniform float time;
|
|||
uniform sampler2D tex;
|
||||
|
||||
void main() {
|
||||
vec4 spec = texture(tex, texCoords) * vec4(blend, 1);
|
||||
if (spec.a < 0.1) discard;
|
||||
gSpecular = spec;
|
||||
float blendMaskMult = -1;
|
||||
if (blendMaskCoords.x >= 0 && blendMaskCoords.y >= 0) blendMaskMult = texture(tex, blendMaskCoords).r;
|
||||
|
||||
vec4 spec = texture(tex, texCoords);
|
||||
vec3 blendCol = blend;
|
||||
if (blendMaskMult >= 0) {
|
||||
blendCol = (vec3(1, 1, 1) * (1 - blendMaskMult)) + (blendCol * blendMaskMult);
|
||||
}
|
||||
|
||||
spec = vec4(spec.xyz * blendCol, spec.w);
|
||||
|
||||
if (spec.a < 0.1) discard;
|
||||
|
||||
gSpecular = spec;
|
||||
gPosition = vec4(fragPos, 1);
|
||||
gNormal = vec4(normal, 1);
|
||||
}
|
|
@ -5,9 +5,10 @@
|
|||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec2 aTexCoords;
|
||||
layout (location = 2) in vec3 aBlend;
|
||||
layout (location = 3) in float aNormal;
|
||||
layout (location = 4) in float aShaderMod;
|
||||
layout (location = 5) in vec3 aModValues;
|
||||
layout (location = 3) in vec2 aBlendMaskCoords;
|
||||
layout (location = 4) in float aNormal;
|
||||
layout (location = 5) in float aShaderMod;
|
||||
layout (location = 6) in vec3 aModValues;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 projection;
|
||||
|
@ -18,6 +19,7 @@ uniform sampler2D swayTex;
|
|||
uniform float time;
|
||||
|
||||
out vec2 texCoords;
|
||||
out vec2 blendMaskCoords;
|
||||
out vec3 blend;
|
||||
out vec3 fragPos;
|
||||
out vec3 normal;
|
||||
|
@ -90,6 +92,7 @@ void main() {
|
|||
|
||||
fragPos = (view * worldPos).xyz;
|
||||
texCoords = aTexCoords;
|
||||
blendMaskCoords = aBlendMaskCoords;
|
||||
blend = aBlend;
|
||||
normal = nml.xyz;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct BlockModel {
|
|||
{glm::vec3{0, 1, 0}, glm::vec3{}, glm::vec2{0, 0}, glm::vec2{}}};
|
||||
indices = {0, 1, 2, 2, 3, 0};
|
||||
accessInd = std::max(0, std::min(static_cast<int>(textureRefs.size() - 1), 2));
|
||||
MeshPart leftMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd]);
|
||||
MeshPart leftMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd], nullptr);
|
||||
blockModel.parts[static_cast<int>(Dir::LEFT)].push_back(leftMeshPart);
|
||||
|
||||
//Right Face
|
||||
|
@ -52,7 +52,7 @@ struct BlockModel {
|
|||
{glm::vec3{1, 1, 0}, glm::vec3{}, glm::vec2{0, 0}, glm::vec2{}}};
|
||||
indices = {0, 1, 2, 2, 3, 0};
|
||||
accessInd = std::max(0, std::min(static_cast<int>(textureRefs.size() - 1), 3));
|
||||
MeshPart rightMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd]);
|
||||
MeshPart rightMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd], nullptr);
|
||||
blockModel.parts[static_cast<int>(Dir::RIGHT)].push_back(rightMeshPart);
|
||||
|
||||
//Top Face
|
||||
|
@ -63,7 +63,7 @@ struct BlockModel {
|
|||
{glm::vec3{1, 1, 0}, glm::vec3{}, glm::vec2{1, 0}, glm::vec2{}}};
|
||||
indices = {0, 1, 2, 2, 3, 0};
|
||||
accessInd = std::max(0, std::min(static_cast<int>(textureRefs.size() - 1), 0));
|
||||
MeshPart topMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd]);
|
||||
MeshPart topMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd], nullptr);
|
||||
blockModel.parts[static_cast<int>(Dir::TOP)].push_back(topMeshPart);
|
||||
|
||||
//Bottom Face
|
||||
|
@ -74,7 +74,7 @@ struct BlockModel {
|
|||
{glm::vec3{0, 0, 1}, glm::vec3{}, glm::vec2{0, 1}, glm::vec2{}}};
|
||||
indices = {0, 1, 2, 2, 3, 0};
|
||||
accessInd = std::max(0, std::min(static_cast<int>(textureRefs.size() - 1), 1));
|
||||
MeshPart bottomMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd]);
|
||||
MeshPart bottomMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd], nullptr);
|
||||
blockModel.parts[static_cast<int>(Dir::BOTTOM)].push_back(bottomMeshPart);
|
||||
|
||||
//Front Face
|
||||
|
@ -85,7 +85,7 @@ struct BlockModel {
|
|||
{glm::vec3{0, 1, 1}, glm::vec3{}, glm::vec2{0, 0}, glm::vec2{}}};
|
||||
indices = {0, 1, 2, 2, 3, 0};
|
||||
accessInd = std::max(0, std::min(static_cast<int>(textureRefs.size() - 1), 4));
|
||||
MeshPart frontMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd]);
|
||||
MeshPart frontMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd], nullptr);
|
||||
blockModel.parts[static_cast<int>(Dir::FRONT)].push_back(frontMeshPart);
|
||||
|
||||
//Back Face
|
||||
|
@ -96,7 +96,7 @@ struct BlockModel {
|
|||
{glm::vec3{1, 0, 0}, glm::vec3{}, glm::vec2{1, 1}, glm::vec2{}}};
|
||||
indices = {0, 1, 2, 2, 3, 0};
|
||||
accessInd = std::max(0, std::min(static_cast<int>(textureRefs.size() - 1), 5));
|
||||
MeshPart backMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd]);
|
||||
MeshPart backMeshPart(vertices, indices, textureRefs[accessInd], biomeTints[accessInd], nullptr);
|
||||
blockModel.parts[static_cast<int>(Dir::BACK)].push_back(backMeshPart);
|
||||
|
||||
return blockModel;
|
||||
|
|
|
@ -11,5 +11,7 @@ struct BlockModelVertex {
|
|||
glm::vec3 pos;
|
||||
glm::vec3 nml;
|
||||
glm::vec2 tex;
|
||||
glm::vec2 blendMask;
|
||||
glm::vec2 texUVs;
|
||||
glm::vec2 blendMaskUVs;
|
||||
};
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
//
|
||||
|
||||
#include "MeshPart.h"
|
||||
#include "../../util/Util.h"
|
||||
|
||||
MeshPart::MeshPart(const std::vector<BlockModelVertex>& vertices, const std::vector<unsigned int>& indices, std::shared_ptr<AtlasRef> texture, bool biomeTint) :
|
||||
MeshPart::MeshPart(const std::vector<BlockModelVertex>& vertices, const std::vector<unsigned int>& indices,
|
||||
std::shared_ptr<AtlasRef> texture, unsigned int blendInd, std::shared_ptr<AtlasRef> blendMask) :
|
||||
vertices(vertices),
|
||||
indices(indices),
|
||||
texture(texture),
|
||||
biomeTint(biomeTint) {
|
||||
blendInd(blendInd),
|
||||
blendMask(blendMask) {
|
||||
|
||||
//We assume these vertex structs do not have normals, and generate them here from the triangle information.
|
||||
//To do this, we have to assume that each group of 3 indices is a triangle (which it would be hard for it to not be)
|
||||
|
@ -43,6 +46,23 @@ MeshPart::MeshPart(const std::vector<BlockModelVertex>& vertices, const std::vec
|
|||
//Generate solid coordinates for the defs positions
|
||||
vertex.tex.x = uv.x + ((uv.z - uv.x) * vertex.tex.x);
|
||||
vertex.tex.y = uv.y + ((uv.w - uv.y) * vertex.tex.y);
|
||||
|
||||
if (blendMask) {
|
||||
std::cout << Util::floatVecToString({vertex.blendMask.x, vertex.blendMask.y, 0}) << std::endl;
|
||||
auto bUV = blendMask->uv;
|
||||
|
||||
//Store the old positions in blendMaskUVs
|
||||
vertex.blendMaskUVs.x = vertex.blendMask.x;
|
||||
vertex.blendMaskUVs.y = vertex.blendMask.y;
|
||||
//Generate solid coordinates for the defs positions
|
||||
vertex.blendMask.x = bUV.x + ((bUV.z - bUV.x) * vertex.blendMask.x);
|
||||
vertex.blendMask.y = bUV.y + ((bUV.w - bUV.y) * vertex.blendMask.y);
|
||||
}
|
||||
else {
|
||||
// Negative One denotes full blend on fragment shader.
|
||||
vertex.blendMask.x = -1;
|
||||
vertex.blendMask.y = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,17 +18,18 @@
|
|||
#include "BlockModelVertex.h"
|
||||
|
||||
struct MeshPart {
|
||||
MeshPart(const std::vector<BlockModelVertex>& vertices, const std::vector<unsigned int>& indices, std::shared_ptr<AtlasRef> texture, bool biomeTint);
|
||||
MeshPart(const std::vector<BlockModelVertex>& vertices, const std::vector<unsigned int>& indices,
|
||||
std::shared_ptr<AtlasRef> texture, unsigned int blendInd, std::shared_ptr<AtlasRef> blendMask);
|
||||
|
||||
std::vector<BlockModelVertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
std::shared_ptr<AtlasRef> texture;
|
||||
unsigned int blendInd = 0;
|
||||
std::shared_ptr<AtlasRef> blendMask;
|
||||
|
||||
ShaderMod shaderMod = ShaderMod::NONE;
|
||||
float modValue = 0;
|
||||
|
||||
bool biomeTint = false;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ void ChunkMesh::create(const std::vector<ChunkVertex>& vertices, const std::vect
|
|||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(position));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(texCoords));
|
||||
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendColor));
|
||||
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendMaskCoords));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(normal));
|
||||
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(shaderMod));
|
||||
createVertexAttrib(idx , 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(modValues));
|
||||
|
|
|
@ -11,6 +11,7 @@ struct ChunkVertex {
|
|||
glm::vec3 position;
|
||||
glm::vec2 texCoords;
|
||||
glm::vec3 blendColor;
|
||||
glm::vec2 blendMaskCoords;
|
||||
float normal;
|
||||
float shaderMod;
|
||||
glm::vec3 modValues;
|
||||
|
|
|
@ -33,7 +33,7 @@ MeshGenerator::MeshGenerator(MeshDetails* meshDetails, LocalDefs& defs, std::sha
|
|||
glm::vec3 check;
|
||||
|
||||
for (unsigned short i = 0; i < 4096; i++) {
|
||||
BlockModel& model = atlas.blockFromId(chunk->getBlock(i)).farModel;
|
||||
BlockModel& model = atlas.blockFromId(chunk->getBlock(i)).model;
|
||||
glm::vec3 biomeTint = defs.biomes.biomeFromId(chunk->getBiome(i)).biomeTint;
|
||||
|
||||
if (model.visible) {
|
||||
|
@ -120,7 +120,8 @@ void MeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart
|
|||
meshDetails->vertices.push_back({
|
||||
vertex.pos + offset,
|
||||
vertex.tex,
|
||||
((mp.biomeTint) ? tint : glm::vec3{1, 1, 1}),
|
||||
(mp.blendInd ? tint : glm::vec3 {1, 1, 1}),
|
||||
(mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}),
|
||||
Util::packFloat(vertex.nml),
|
||||
static_cast<float>(mp.shaderMod),
|
||||
modData
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace RegisterBlocks {
|
|||
glm::vec3 pos(points[offset], points[offset + 1], points[offset + 2]);
|
||||
glm::vec2 tex(points[offset + 3], points[offset + 4]);
|
||||
|
||||
vertices.push_back({pos, {0, 0, 0}, tex, {0, 0}});
|
||||
vertices.push_back(BlockModelVertex {pos, {}, tex, tex, {}, {}});
|
||||
}
|
||||
|
||||
int ind = 0;
|
||||
|
@ -121,22 +121,47 @@ namespace RegisterBlocks {
|
|||
int tex = std::max(static_cast<int>(meshPartTable.get_or<float>("tex", 1)), 1);
|
||||
auto texture = textures[std::min(tex - 1, (int) textures.size() - 1)];
|
||||
|
||||
//TODO: Make this a proper texture modifier, dont do jank bullshit
|
||||
bool biometint = false;
|
||||
if (strncmp(texture.data(), "biometint(", 10) == 0) {
|
||||
biometint = true;
|
||||
texture = texture.substr(10, texture.length() - 11);
|
||||
bool blendInd = false;
|
||||
std::string blendMask = "";
|
||||
|
||||
if (strncmp(texture.data(), "tint(", 5) == 0 && texture.find_last_of(')') != std::string::npos) {
|
||||
// Biome tinting time
|
||||
texture.erase(std::remove(texture.begin(), texture.end(), ' '), texture.end());
|
||||
|
||||
std::string::size_type paramsBegin = texture.find_first_of('(');
|
||||
std::string::size_type paramsEnd = texture.find_last_of(')');
|
||||
|
||||
std::string paramsString = texture.substr(paramsBegin + 1, paramsEnd - paramsBegin - 1);
|
||||
|
||||
std::vector<std::string> params;
|
||||
std::string::size_type pos = 0;
|
||||
while ((pos = paramsString.find(',')) != std::string::npos) {
|
||||
params.push_back(paramsString.substr(0, pos));
|
||||
paramsString.erase(0, pos + 1);
|
||||
}
|
||||
params.push_back(paramsString);
|
||||
|
||||
if (params.size() < 2) throw "Invalid biome tint values. Must have at least 2 params.";
|
||||
|
||||
texture = params[1];
|
||||
blendInd = atoi(params[0].data()) + 1; //TODO: support multiple blend colors
|
||||
blendMask = (params.size() >= 3 ? params[2] : "");
|
||||
}
|
||||
|
||||
// Add texture refs to blockModel if the textures table is provided
|
||||
std::shared_ptr<AtlasRef> textureRef = nullptr;
|
||||
std::shared_ptr<AtlasRef> textureRef = nullptr, blendMaskRef = nullptr;
|
||||
if (atlas) {
|
||||
textureRef = (*atlas)[texture];
|
||||
model.textureRefs.insert(textureRef);
|
||||
|
||||
if (blendInd && !blendMask.empty()) {
|
||||
blendMaskRef = (*atlas)[blendMask];
|
||||
model.textureRefs.insert(blendMaskRef);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the meshpart object
|
||||
MeshPart meshPart(std::move(vertices), std::move(indices), textureRef, biometint);
|
||||
MeshPart meshPart(std::move(vertices), std::move(indices), textureRef, blendInd, blendMaskRef);
|
||||
|
||||
// Add the shader mod, if it exists
|
||||
sol::optional<sol::table> shaderModTable = meshPartTable.get<sol::optional<sol::table>>("shader_mod");
|
||||
|
@ -191,8 +216,8 @@ namespace RegisterBlocks {
|
|||
std::vector<bool> biomeTints;
|
||||
for (auto i = 0; i < lowdef_textures.size(); i++) {
|
||||
std::string texture = lowdef_textures[i];
|
||||
if (strncmp(texture.data(), "biometint(", 10) == 0) {
|
||||
texture = texture.substr(10, texture.length() - 11);
|
||||
if (strncmp(texture.data(), "tint(", 5) == 0) {
|
||||
texture = texture.substr(8, texture.length() - 8);
|
||||
biomeTints.emplace_back(true);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -62,47 +62,10 @@ zepha.register_blockmodel("base:block_foliage", {
|
|||
1, 1, 0, 0, 0,
|
||||
1, 0, 0, 0, 1
|
||||
}
|
||||
}, {
|
||||
-- Hovered faces for biome tinting begin here
|
||||
face = "left",
|
||||
tex = 4,
|
||||
points = {
|
||||
-0.003, 0, 0, 0, 1,
|
||||
-0.003, 0, 1, 1, 1,
|
||||
-0.003, 1, 1, 1, 0,
|
||||
-0.003, 1, 0, 0, 0
|
||||
}
|
||||
}, {
|
||||
face = "right",
|
||||
tex = 4,
|
||||
points = {
|
||||
1.003, 1, 1, 0, 0,
|
||||
1.003, 0, 1, 0, 1,
|
||||
1.003, 0, 0, 1, 1,
|
||||
1.003, 1, 0, 1, 0
|
||||
}
|
||||
}, {
|
||||
face = "front",
|
||||
tex = 4,
|
||||
points = {
|
||||
0, 0, 1.003, 0, 1,
|
||||
1, 0, 1.003, 1, 1,
|
||||
1, 1, 1.003, 1, 0,
|
||||
0, 1, 1.003, 0, 0
|
||||
}
|
||||
}, {
|
||||
face = "back",
|
||||
tex = 4,
|
||||
points = {
|
||||
0, 0, -0.003, 1, 1,
|
||||
0, 1, -0.003, 1, 0,
|
||||
1, 1, -0.003, 0, 0,
|
||||
1, 0, -0.003, 0, 1
|
||||
}
|
||||
}, {
|
||||
--Floats begin here
|
||||
face = "front",
|
||||
tex = 5,
|
||||
tex = 4,
|
||||
points = {
|
||||
0, 1, 1, 0, 0,
|
||||
0.005, 0.2, 1.2, 0, 1,
|
||||
|
@ -115,7 +78,7 @@ zepha.register_blockmodel("base:block_foliage", {
|
|||
}
|
||||
}, {
|
||||
face = "back",
|
||||
tex = 5,
|
||||
tex = 4,
|
||||
points = {
|
||||
1.005, 0.2, -0.2, 0, 1,
|
||||
0.005, 0.2, -0.2, 1, 1,
|
||||
|
@ -128,7 +91,7 @@ zepha.register_blockmodel("base:block_foliage", {
|
|||
}
|
||||
}, {
|
||||
face = "right",
|
||||
tex = 5,
|
||||
tex = 4,
|
||||
points = {
|
||||
1.2, 0.2, 1.005, 0, 1,
|
||||
1.2, 0.2, 0.005, 1, 1,
|
||||
|
@ -141,7 +104,7 @@ zepha.register_blockmodel("base:block_foliage", {
|
|||
}
|
||||
}, {
|
||||
face = "left",
|
||||
tex = 5,
|
||||
tex = 4,
|
||||
points = {
|
||||
0, 1, 0, 0, 0,
|
||||
-0.2, 0.2, 0.005, 0, 1,
|
||||
|
|
|
@ -2,16 +2,15 @@ zepha.register_block("zeus:default:grass", {
|
|||
name = "Grass",
|
||||
model = "base:block_foliage",
|
||||
textures = {
|
||||
"biometint(zeus:default:grass_top)",
|
||||
"tint(0, zeus:default:grass_top)",
|
||||
"zeus:default:dirt",
|
||||
"zeus:default:grass_side_under",
|
||||
"biometint(zeus:default:grass_side)",
|
||||
"biometint(zeus:default:grass_floating)",
|
||||
"tint(0, zeus:default:grass_side_under, zeus:default:grass_side_under_mask)",
|
||||
"tint(0, zeus:default:grass_floating)",
|
||||
},
|
||||
lowdef_textures = {
|
||||
"zeus:default:grass_top",
|
||||
"tint(0, zeus:default:grass_top)",
|
||||
"zeus:default:dirt",
|
||||
"zeus:default:grass_side_ld"
|
||||
"tint(0, zeus:default:grass_side_ld, zeus:default:grass_side_ld_mask)"
|
||||
},
|
||||
toughness = {
|
||||
hand = 3,
|
||||
|
@ -29,20 +28,15 @@ zepha.register_block("zeus:default:grass_slab", {
|
|||
name = "Grass Slab",
|
||||
model = "base:block_slab_foliage",
|
||||
textures = {
|
||||
"biometint(zeus:default:grass_top)",
|
||||
"tint(0, zeus:default:grass_top)",
|
||||
"zeus:default:dirt",
|
||||
"biometint(zeus:default:grass_top)",
|
||||
"biometint(zeus:default:grass_top)",
|
||||
"biometint(zeus:default:grass_top)",
|
||||
"biometint(zeus:default:grass_top)",
|
||||
"biometint(zeus:default:grass_floating)",
|
||||
"tint(0, zeus:default:grass_top)",
|
||||
"tint(0, zeus:default:grass_top)",
|
||||
"tint(0, zeus:default:grass_top)",
|
||||
"tint(0, zeus:default:grass_top)",
|
||||
"tint(0, zeus:default:grass_floating)",
|
||||
},
|
||||
culls = false,
|
||||
## lowdef_textures = {
|
||||
## "zeus:default:grass_top",
|
||||
## "zeus:default:dirt",
|
||||
## "zeus:default:grass_side_ld"
|
||||
## },
|
||||
toughness = {
|
||||
hand = 3,
|
||||
shovel = 1,
|
||||
|
|
|
@ -5,7 +5,7 @@ for i = 1, 5, 1 {
|
|||
name = "Tall Grass",
|
||||
model = "base:cross_plant",
|
||||
textures = {
|
||||
"biometint(zeus:default:tallgrass_"..i..")"
|
||||
"tint(0, zeus:default:tallgrass_"..i..")"
|
||||
},
|
||||
lowdef_render = false,
|
||||
selection_box = {
|
||||
|
|
|
@ -8,7 +8,7 @@ zepha.register_entity("zeus:default:test", {
|
|||
## walk = {0, 300}
|
||||
## })
|
||||
## self.object.anims:set_anim("walk"):play()
|
||||
self.object.scale = 1/4
|
||||
## self.object.scale = 1/4
|
||||
},
|
||||
on_update = fn(self, delta) {
|
||||
self.object.pos = vector.add(vector.multiply(v(0.6 * math.sin(math.rad(self.object.yaw)), 0,
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 761 B After Width: | Height: | Size: 824 B |
Binary file not shown.
After Width: | Height: | Size: 208 B |
Binary file not shown.
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 876 B |
Binary file not shown.
After Width: | Height: | Size: 205 B |
Loading…
Reference in New Issue