I am about to create a light system for my game and I actually have it setup, but with this "blocky" lightning as seen in the image. I would like to smooth the faces so that two different tiles aren't notable.
I have looked around on the subject and the only real answer I found is to average all 4 surrounding neighbors light and create a gradient from it. The answer was found here, but with no special rules to follow because that is what I need to find out.
The light intensity of each tile is a fixed number between 100-255, where 100 is the darkest and 255 is the brightest(opacity) and each vertex gets this value.
Do I have to find out which neighbors use each tiles vertex point and go on from there? I really have no clue
The current version of my light look like this: EDIT: Now it looks like this. It has some flaws.
I tried to collect all the neighbours vertices and take the average of them(see image below). By following this method, I will receive different intensity values on each vertex.
This is a beginning of the algorithm. This function is meant to run for every tile in the light. From my current state of the algorithm I need to find the vertices on the same point. I am stuck here! :'-( I have updated the algorithm, but it's still got some visual flaws. Note how the top left and the bottom right sides are "blocky" when the others aren't. Also if you look very closely at the center, there is a hexagon shape, ~3 wide and high.
void Torch::smoothLight(int pX, int pY)
{
if (pX == 0 || pX == (mWidth - 1) || pY == 0 || pY == (mHeight - 1)) return;
// Tile we are smoothing
Tile *c = mTilesInRange[pY * mWidth + pX];
if (c == nullptr) return;
int x_min_1 = pX - 1;
int x_plus_1 = pX + 1;
int y_min_1 = pY - 1;
int y_plus_1 = pY + 1;
// Get all nearby tiles in all 8 weather directions
Tile *NW = mTilesInRange[y_min_1 * mWidth + x_min_1];
Tile *N = mTilesInRange[y_min_1 * mWidth + pX];
Tile *NE = mTilesInRange[y_min_1 * mWidth + x_plus_1];
Tile *E = mTilesInRange[pY * mWidth + x_plus_1];
Tile *SW = mTilesInRange[y_plus_1 * mWidth + x_min_1];
Tile *S = mTilesInRange[y_plus_1 * mWidth + pX];
Tile *SE = mTilesInRange[y_plus_1 * mWidth + x_plus_1];
Tile *W = mTilesInRange[pY * mWidth + x_min_1];
/*
- Loop trough all 4 vertices on the tile in the following order
0 1
2 3
- For each vertex, find the 3 other vertices that lies on the same point, example vertex 1:
0 1 <--
2 3
0 1 0 1
2 3 2 3
Original quad -> 0 1 0 1
-> 2 3 2 3
Result: 3 2
1 0
*/
for (int i = 0; i < 4; i++)
{
int intensitySum = 0;
// This is really ugly but I can't come up with a better algorithm
if (i == 0) // upper left
{
intensitySum += c->getQuad()[0].color.a; // me
intensitySum += N->getQuad()[3].color.a;
intensitySum += NW->getQuad()[2].color.a;
intensitySum += W->getQuad()[1].color.a;
int alpha = intensitySum / 4;
c->getQuad()[0].color.a = alpha;
}
else if (i == 1) // upper right
{
intensitySum += c->getQuad()[1].color.a; // me
intensitySum += N->getQuad()[2].color.a;
intensitySum += NE->getQuad()[3].color.a;
intensitySum += E->getQuad()[0].color.a;
int alpha = intensitySum / 4;
c->getQuad()[1].color.a = alpha;
}
else if (i == 2) // lower left
{
intensitySum += c->getQuad()[2].color.a; // me
intensitySum += E->getQuad()[3].color.a;
intensitySum += SE->getQuad()[0].color.a;
intensitySum += S->getQuad()[1].color.a;
int alpha = intensitySum / 4;
c->getQuad()[2].color.a = alpha;
}
else if (i == 3) // lower right
{
intensitySum += c->getQuad()[3].color.a; // me
intensitySum += S->getQuad()[0].color.a;
intensitySum += SW->getQuad()[1].color.a;
intensitySum += W->getQuad()[2].color.a;
int alpha = intensitySum / 4;
c->getQuad()[3].color.a = alpha;
}
}
}