Browse Source

functional smooth lighting for cube voxels

testing
totallyfake 1 year ago
parent
commit
fa250f5d1b
4 changed files with 180 additions and 43 deletions
  1. 6
    6
      include/graphics/voxelmodel.h
  2. 1
    1
      src/chunk.cpp
  3. 7
    15
      src/graphics/chunkmesh.cpp
  4. 166
    21
      src/graphics/voxelmodel.cpp

+ 6
- 6
include/graphics/voxelmodel.h View File

@@ -21,15 +21,15 @@ public:
where X stands for none and any numbers stand for array indexes
y = 1 y = 0 y = -1
x -1 0 1
z -1 0 X 1 X 5 X 9 X 10
0 X 2 X 6 X 7 X 11 X
1 3 X 4 X 8 X 12 X 13
y = -1
x -1 0 1
z -1 0 1 2 9 10 11 18 19 20
0 3 4 5 12 13 14 21 22 23
1 6 7 8 15 16 17 24 25 26
zero_weight controls how "smoothed" the lighting is. Read the function body for more info on how this works
*/
void getFaceLighting(std::vector<unsigned>& lighting, const FaceDirection& face, const std::array<unsigned, 14>& surrounding_light, const unsigned& zero_weight);
void getFaceLighting(std::vector<unsigned>& lighting, const FaceDirection& face, const std::array<unsigned, 27>& surrounding_light, const unsigned& zero_weight);
protected:
// top bottom north south east west, special
std::array<std::vector<unsigned>, 7> mGeometry;

+ 1
- 1
src/chunk.cpp View File

@@ -90,7 +90,7 @@ unsigned Chunk::getLightLevel(const glm::ivec3 &pos) {

unsigned Chunk::getLightPacked(const glm::ivec3 &pos) {
if (isVoxelSolid(pos.x, pos.y, pos.z)) {
return 0xFF000000;
return 0x00000000;
}
return 0xFFFFFFFF;
}

+ 7
- 15
src/graphics/chunkmesh.cpp View File

@@ -66,21 +66,13 @@ bool ChunkMesh::rebuildChunkGeometry() {
for (int k = 0; k < chunkSize; ++k) {
if (chunk->isVoxelSolid(i,j,k)) {
glm::ivec3 lpos(i,j,k);
std::array<unsigned, 14> surrounding_light;
surrounding_light[0] = chunk->getLightPacked(glm::ivec3(i-1,j+1,k-1));
surrounding_light[1] = chunk->getLightPacked(glm::ivec3(i+1,j+1,k-1));
surrounding_light[2] = chunk->getLightPacked(glm::ivec3(i,j+1,k));
surrounding_light[3] = chunk->getLightPacked(glm::ivec3(i-1,j+1,k+1));
surrounding_light[4] = chunk->getLightPacked(glm::ivec3(i+1,j+1,k+1));
surrounding_light[5] = chunk->getLightPacked(glm::ivec3(i,j,k-1));
surrounding_light[6] = chunk->getLightPacked(glm::ivec3(i-1,j,k));
surrounding_light[7] = chunk->getLightPacked(glm::ivec3(i+1,j,k));
surrounding_light[8] = chunk->getLightPacked(glm::ivec3(i,j,k+1));
surrounding_light[9] = chunk->getLightPacked(glm::ivec3(i-1,j-1,-1));
surrounding_light[10] = chunk->getLightPacked(glm::ivec3(i+1,j-1,k-1));
surrounding_light[11] = chunk->getLightPacked(glm::ivec3(i,j-1,k));
surrounding_light[12] = chunk->getLightPacked(glm::ivec3(i-1,j-1,k+1));
surrounding_light[13] = chunk->getLightPacked(glm::ivec3(i+1,j-1,k+1));
std::array<unsigned, 27> surrounding_light;
for (int l = 0; l < 27; ++l) {
glm::ivec3 offset((l % 3) - 1, //x component
(l / 9) - 1, //y component
((l % 9) / 3) - 1); //y component
surrounding_light[l] = chunk->getLightPacked(glm::ivec3(i,j,k) + offset);
}
//build face attrib

+ 166
- 21
src/graphics/voxelmodel.cpp View File

@@ -106,7 +106,7 @@ std::vector<unsigned>& VoxelModel::getFaceMesh(const int& face) {
return mGeometry[face];
}

void VoxelModel::getFaceLighting(std::vector<unsigned>& lighting, const FaceDirection& face, const std::array<unsigned, 14>& surrounding_light, const unsigned& zero_weight) {
void VoxelModel::getFaceLighting(std::vector<unsigned>& lighting, const FaceDirection& face, const std::array<unsigned, 27>& surrounding_light, const unsigned& zero_weight) {

auto blend = [](unsigned a, unsigned b, unsigned weight) {
unsigned aw = 7 - weight;
@@ -125,54 +125,199 @@ void VoxelModel::getFaceLighting(std::vector<unsigned>& lighting, const FaceDire
((((b) & 0xFF) * bw) / 7u), 255u);
return newLight;
};

auto average4 = [](unsigned a, unsigned b, unsigned c, unsigned d) {
unsigned avg = (((a >> 24) & 0xFF) +
((b >> 24) & 0xFF) +
((c >> 24) & 0xFF) +
((d >> 24) & 0xFF)) / 4;
avg = (avg << 8) | (((a >> 16) & 0xFF) +
((b >> 16) & 0xFF) +
((c >> 16) & 0xFF) +
((d >> 16) & 0xFF)) / 4;
avg = (avg << 8) | (((a >> 8) & 0xFF) +
((b >> 8) & 0xFF) +
((c >> 8) & 0xFF) +
((d >> 8) & 0xFF)) / 4;
avg = (avg << 8) | ((a & 0xFF) +
(b & 0xFF) +
(c & 0xFF) +
(d & 0xFF)) / 4;

return avg;
};
auto& face_vec = mGeometry.at(static_cast<unsigned>(face));
for (auto& i : face_vec) {
//TODO: Find a more elegant solution that a big switch case with if statements
//TODO: handle interpolation for verts that aren't on an edge
unsigned vx = (i >> 8) & 0xF;
unsigned vy = (i >> 4) & 0xF;
unsigned vz = i & 0xF;
switch(face) {
case FaceDirection::TOP:

//std::cout << vx << ", " << vz << "\n";
if (vx > 7) {
if (vz > 7) {
std::cout << "hit\n";
lighting.push_back(surrounding_light[4]); //4
lighting.push_back(average4(surrounding_light[22],
surrounding_light[23],
surrounding_light[25],
surrounding_light[26]));
} else {
lighting.push_back(surrounding_light[1]); //1
lighting.push_back(average4(surrounding_light[22],
surrounding_light[23],
surrounding_light[19],
surrounding_light[20]));
}
} else {
if (vz > 7) {
lighting.push_back(surrounding_light[3]); //3
lighting.push_back(average4(surrounding_light[22],
surrounding_light[21],
surrounding_light[24],
surrounding_light[25]));
} else {
lighting.push_back(surrounding_light[0]); //0
lighting.push_back(average4(surrounding_light[22],
surrounding_light[18],
surrounding_light[19],
surrounding_light[21]));
}
}
/*
lighting.push_back(blend(surrounding_light[2],
surrounding_light[4],
(vx + vy - 14u) / 2u));
*/
break;

case FaceDirection::BOTTOM:
lighting.push_back(surrounding_light[11]);
if (vx > 7) {
if (vz > 7) {
lighting.push_back(average4(surrounding_light[4],
surrounding_light[5],
surrounding_light[7],
surrounding_light[8]));
} else {
lighting.push_back(average4(surrounding_light[4],
surrounding_light[5],
surrounding_light[1],
surrounding_light[2]));
}
} else {
if (vz > 7) {
lighting.push_back(average4(surrounding_light[4],
surrounding_light[3],
surrounding_light[6],
surrounding_light[7]));
} else {
lighting.push_back(average4(surrounding_light[4],
surrounding_light[3],
surrounding_light[0],
surrounding_light[1]));
}
}
break;
case FaceDirection::NORTH:
lighting.push_back(surrounding_light[8]);
if (vx > 7) {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[16],
surrounding_light[17],
surrounding_light[25],
surrounding_light[26]));
} else {
lighting.push_back(average4(surrounding_light[16],
surrounding_light[17],
surrounding_light[7],
surrounding_light[8]));
}
} else {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[16],
surrounding_light[15],
surrounding_light[24],
surrounding_light[25]));
} else {
lighting.push_back(average4(surrounding_light[16],
surrounding_light[15],
surrounding_light[6],
surrounding_light[7]));
}
}
break;
case FaceDirection::SOUTH:
lighting.push_back(surrounding_light[5]);
if (vx > 7) {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[10],
surrounding_light[11],
surrounding_light[19],
surrounding_light[20]));
} else {
lighting.push_back(average4(surrounding_light[10],
surrounding_light[11],
surrounding_light[1],
surrounding_light[2]));
}
} else {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[10],
surrounding_light[9],
surrounding_light[18],
surrounding_light[19]));
} else {
lighting.push_back(average4(surrounding_light[10],
surrounding_light[9],
surrounding_light[0],
surrounding_light[1]));
}
}
break;
case FaceDirection::EAST:
lighting.push_back(surrounding_light[7]);
if (vz > 7) {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[14],
surrounding_light[17],
surrounding_light[23],
surrounding_light[26]));
} else {
lighting.push_back(average4(surrounding_light[14],
surrounding_light[17],
surrounding_light[5],
surrounding_light[8]));
}
} else {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[14],
surrounding_light[11],
surrounding_light[20],
surrounding_light[23]));
} else {
lighting.push_back(average4(surrounding_light[14],
surrounding_light[11],
surrounding_light[2],
surrounding_light[5]));
}
}
break;
case FaceDirection::WEST:
lighting.push_back(surrounding_light[6]);
break;
default:
lighting.push_back(0xFFFFFFFF);
if (vz > 7) {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[12],
surrounding_light[15],
surrounding_light[21],
surrounding_light[24]));
} else {
lighting.push_back(average4(surrounding_light[12],
surrounding_light[15],
surrounding_light[3],
surrounding_light[6]));
}
} else {
if (vy > 7) {
lighting.push_back(average4(surrounding_light[12],
surrounding_light[9],
surrounding_light[18],
surrounding_light[21]));
} else {
lighting.push_back(average4(surrounding_light[12],
surrounding_light[9],
surrounding_light[0],
surrounding_light[3]));
}
}
break;
}
}

Loading…
Cancel
Save