fix literally fucking everything
This commit is contained in:
parent
0b7eb66703
commit
109d666eb8
9 changed files with 235 additions and 75 deletions
BIN
resources/images/ambient_occlusion.png
Normal file
BIN
resources/images/ambient_occlusion.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.8 KiB |
100
resources/scripts/ambient_occlusion_texture_generator.py
Normal file
100
resources/scripts/ambient_occlusion_texture_generator.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
from PIL import Image, ImageFilter
|
||||
import random
|
||||
import math
|
||||
|
||||
SQUARE_SIZE = 32
|
||||
SQUARES = 2**8
|
||||
ITERATIONS_PER_PIXEL = 1000
|
||||
COORDS = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]
|
||||
|
||||
|
||||
def random_point_on_sphere():
|
||||
theta = random.uniform(0, 2 * math.pi)
|
||||
phi = math.acos(random.uniform(-1, 1))
|
||||
x = math.sin(phi) * math.cos(theta)
|
||||
y = math.sin(phi) * math.sin(theta)
|
||||
z = math.cos(phi)
|
||||
return [x, y, z]
|
||||
|
||||
|
||||
calculated_squares = dict()
|
||||
with Image.new("RGBA", (SQUARE_SIZE*SQUARES, SQUARE_SIZE), "black") as im:
|
||||
px = im.load()
|
||||
|
||||
for square_id in range(SQUARES):
|
||||
print(f"square {square_id}: ", end="")
|
||||
square = square_id
|
||||
|
||||
# if 2 side touching tiles are obscuring, then we can assume the corner is obscuring as well
|
||||
if square & (1 << 6) > 0 and square & (1 << 4) > 0:
|
||||
square = square | (1 << 5)
|
||||
if square & (1 << 4) > 0 and square & (1 << 2) > 0:
|
||||
square = square | (1 << 3)
|
||||
if square & (1 << 2) > 0 and square & (1 << 0) > 0:
|
||||
square = square | (1 << 1)
|
||||
if square & (1 << 0) > 0 and square & (1 << 6) > 0:
|
||||
square = square | (1 << 7)
|
||||
|
||||
# check if we've already done the task in a rotated variation
|
||||
instance_found = False
|
||||
for rotation in range(4): # clockwise rotations by pi/2
|
||||
rotated_square = (square >> (rotation * 2)) | ((square & ((1 << rotation*2)-1)) << 2*(4 - rotation))
|
||||
if rotated_square in calculated_squares:
|
||||
square_id_from = calculated_squares[rotated_square]
|
||||
print(f"already calculated at {square_id_from}")
|
||||
|
||||
box_from = (SQUARE_SIZE*square_id_from, 0, SQUARE_SIZE*(square_id_from+1), SQUARE_SIZE)
|
||||
box_to = (SQUARE_SIZE*square_id, 0, SQUARE_SIZE*(square_id+1), SQUARE_SIZE)
|
||||
region = im.crop(box_from)
|
||||
if rotation == 1:
|
||||
region = region.transpose(Image.Transpose.ROTATE_270)
|
||||
if rotation == 2:
|
||||
region = region.transpose(Image.Transpose.ROTATE_180)
|
||||
if rotation == 3:
|
||||
region = region.transpose(Image.Transpose.ROTATE_90)
|
||||
im.paste(region, box_to)
|
||||
|
||||
instance_found = True
|
||||
break
|
||||
if instance_found:
|
||||
continue
|
||||
|
||||
# actually calculate the occlusion
|
||||
obscured = [i for c, i in enumerate(COORDS) if (square >> c) & 1 == 1]
|
||||
for x in range(SQUARE_SIZE):
|
||||
for y in range(SQUARE_SIZE):
|
||||
point_coord = ((x+0.5)/SQUARE_SIZE-0.5, (y+0.5)/SQUARE_SIZE-0.5, 0)
|
||||
count = 0
|
||||
for i in range(ITERATIONS_PER_PIXEL):
|
||||
point = random_point_on_sphere()
|
||||
point[0] += point_coord[0]
|
||||
point[1] += point_coord[1]
|
||||
rounded_point = (round(point[0]), round(point[1]))
|
||||
if rounded_point in obscured:
|
||||
count += 1
|
||||
result_color = 255-255*count//ITERATIONS_PER_PIXEL
|
||||
px[x+square_id*SQUARE_SIZE, y] = (result_color, result_color, result_color, 255)
|
||||
calculated_squares[square] = square_id
|
||||
|
||||
# smooth it
|
||||
box = (SQUARE_SIZE*square_id, 0, SQUARE_SIZE*(square_id+1), SQUARE_SIZE)
|
||||
region = im.crop(box)
|
||||
region = region.filter(filter=ImageFilter.GaussianBlur(2))
|
||||
im.paste(region, box)
|
||||
|
||||
print(f"calculated")
|
||||
|
||||
print(f"total squares calculated: {len(calculated_squares)}")
|
||||
|
||||
# result_side_length = int(SQUARES**0.5)
|
||||
# with Image.new("RGBA", (SQUARE_SIZE*result_side_length, SQUARE_SIZE*result_side_length), "black") as new_im:
|
||||
# for i in range(result_side_length):
|
||||
# box_from = (SQUARE_SIZE*result_side_length*i, 0, SQUARE_SIZE*result_side_length*(i+1), SQUARE_SIZE)
|
||||
# box_to = (0, SQUARE_SIZE*i, SQUARE_SIZE*result_side_length, SQUARE_SIZE*(i+1))
|
||||
# new_im.paste(im.crop(box_from), box_to)
|
||||
# new_im.show()
|
||||
# new_im.save("../images/ambient_occlusion.png")
|
||||
|
||||
im.show()
|
||||
im.save("../images/ambient_occlusion.png")
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#version 330 core
|
||||
|
||||
uniform sampler2D diffuseMap;
|
||||
uniform sampler2D occlusionMap;
|
||||
uniform vec2 textureTiling;
|
||||
|
||||
in vec2 fragTexCoord;
|
||||
|
|
@ -17,30 +18,52 @@ flat in int quadWidth;
|
|||
|
||||
out vec4 outColor;
|
||||
|
||||
// this is a shitty approximation of arcsin(x)/pi that gets the tails right and is reasonably close to the actual arcsin(x)/pi curve.
|
||||
float fakeArcsin(float x) {
|
||||
x = clamp(x, -1.0, 1.0);
|
||||
float ax = abs(x);
|
||||
float sqrtPart = sqrt(1.0 - ax);
|
||||
float result = 0.5 - sqrtPart * (0.5 - 0.06667 * ax);
|
||||
return x < 0.0 ? -result : result;
|
||||
int calculate_ao_square()
|
||||
{
|
||||
ivec2 tileCoord = ivec2(fragTileTexCoord);
|
||||
int ao_square = 0;
|
||||
|
||||
if(tileCoord.x == quadWidth - 1 && ((occlusionSides.x & uint(1 << tileCoord.y)) > uint(0))) ao_square |= 1 << 0;
|
||||
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y == quadHeight - 1 && bottomRightObscured > 0) ao_square |= 1 << 1;
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y != quadHeight - 1 && ((occlusionSides.x & uint(1 << (tileCoord.y+1))) > uint(0))) ao_square |= 1 << 1;
|
||||
if(tileCoord.x != quadWidth - 1 && tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << (tileCoord.x+1))) > uint(0))) ao_square |= 1 << 1;
|
||||
|
||||
if(tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << tileCoord.x)) > uint(0))) ao_square |= 1 << 2;
|
||||
|
||||
if(tileCoord.x == 0 && tileCoord.y == quadHeight - 1 && bottomLeftObscured > 0) ao_square |= 1 << 3;
|
||||
if(tileCoord.x == 0 && tileCoord.y != quadHeight - 1 && ((occlusionSides.y & uint(1 << (tileCoord.y+1))) > uint(0))) ao_square |= 1 << 3;
|
||||
if(tileCoord.x != 0 && tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << (tileCoord.x-1))) > uint(0))) ao_square |= 1 << 3;
|
||||
|
||||
if(tileCoord.x == 0 && ((occlusionSides.y & uint(1 << tileCoord.y)) > uint(0))) ao_square |= 1 << 4;
|
||||
|
||||
if(tileCoord.x == 0 && tileCoord.y == 0 && topRightObscured > 0) ao_square |= 1 << 5;
|
||||
if(tileCoord.x == 0 && tileCoord.y != 0 && ((occlusionSides.y & uint(1 << (tileCoord.y-1))) > uint(0))) ao_square |= 1 << 5;
|
||||
if(tileCoord.x != 0 && tileCoord.y == 0 && ((occlusionSides.z & uint(1 << (tileCoord.x-1))) > uint(0))) ao_square |= 1 << 5;
|
||||
|
||||
if(tileCoord.y == 0 && ((occlusionSides.z & uint(1 << tileCoord.x)) > uint(0))) ao_square |= 1 << 6;
|
||||
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y == 0 && topLeftObscured > 0) ao_square |= 1 << 7;
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y != 0 && ((occlusionSides.x & uint(1 << (tileCoord.y-1))) > uint(0))) ao_square |= 1 << 7;
|
||||
if(tileCoord.x != quadWidth - 1 && tileCoord.y == 0 && ((occlusionSides.z & uint(1 << (tileCoord.x+1))) > uint(0))) ao_square |= 1 << 7;
|
||||
|
||||
return ao_square;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texCoord = (floor(fragTexCoord*textureTiling) + fract(fragTileTexCoord)) / textureTiling;
|
||||
|
||||
int ao_square = calculate_ao_square();
|
||||
|
||||
outColor = texture(diffuseMap, texCoord);
|
||||
|
||||
ivec2 floorFragTileTexCoord = ivec2(fragTileTexCoord);
|
||||
|
||||
if(floorFragTileTexCoord.x < 1 && ((occlusionSides.x >> floorFragTileTexCoord.x) & uint(1)) == uint(1)) {
|
||||
outColor *= 0.5 + fakeArcsin(fragTileTexCoord.x);
|
||||
}
|
||||
outColor *= texture(occlusionMap, (vec2(ao_square, 0)+fract(fragTileTexCoord))/vec2(256, 1));
|
||||
|
||||
outColor.a = 1;
|
||||
|
||||
uint bit = uint(fragTileTexCoord * 32);
|
||||
outColor.g = (((occlusionSides.x >> bit) & uint(1)) == uint(1)) ?
|
||||
((bit % uint(2) == uint(0)) ? 1.0 : 0.8):
|
||||
((bit % uint(2) == uint(0)) ? 0.0 : 0.2);
|
||||
//uint bit = uint(fragTileTexCoord * 32);
|
||||
//outColor.g = (((uint(quadWidth) >> bit) & uint(1)) == uint(1)) ?
|
||||
// ((bit % uint(2) == uint(0)) ? 1.0 : 0.8):
|
||||
// ((bit % uint(2) == uint(0)) ? 0.0 : 0.2);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ void main() {
|
|||
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||
|
||||
// metadata 1 parsing
|
||||
int metadata1W = int(vertexMetadata1.w);
|
||||
int metadata1W = int(vertexMetadata1.x);
|
||||
topLeftObscured = (metadata1W & 0x1); // Take 0th bit.
|
||||
topRightObscured = (metadata1W & 0x2) >> 1; // Take 1st bits.
|
||||
bottomLeftObscured = (metadata1W & 0x4) >> 2; // Take 2nd bits.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue