0

correct (though chunk-local only) per-face lighting

This commit is contained in:
Aaron Griffith
2010-09-27 19:04:35 -04:00
parent a15390cc47
commit db62ad94ee
2 changed files with 68 additions and 9 deletions

View File

@@ -14,7 +14,7 @@
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
import numpy
from PIL import Image, ImageDraw
from PIL import Image, ImageDraw, ImageEnhance
from itertools import izip, count
import os.path
import hashlib
@@ -37,6 +37,13 @@ image
# use that as the mask. Then take the image and use im.convert("RGB") to strip
# the image from its alpha channel, and use that as the source to paste()
def get_lighting_coefficient(skylight, blocklight):
"""Takes a raw blocklight and skylight, and returns a value
between 0.0 (fully lit) and 1.0 (fully black) that can be used as
an alpha value for a blend with a black source image. It mimics
Minecraft lighting calculations."""
return 1.0 - pow(0.8, 15 - max(blocklight, skylight))
def get_lvldata(filename):
"""Takes a filename and returns the Level struct, which contains all the
level info"""
@@ -317,11 +324,38 @@ class ChunkRenderer(object):
# Draw the actual block on the image. For cave images,
# tint the block with a color proportional to its depth
if cave:
# no lighting for cave -- depth is probably more useful
img.paste(Image.blend(t[0],depth_colors[z],0.3), (imgx, imgy), t[1])
else:
light_coeff = pow(0.95, 15 - max(blocklight[x,y,z], skylight[x,y,z]))
img.paste(Image.blend(t[0], black_color, 1.0 - light_coeff), (imgx, imgy), t[1])
#img.paste(t[0], (imgx, imgy), t[1])
if blockid in transparent_blocks:
# transparent means draw the whole
# block shaded with the current
# block's light
black_coeff = get_lighting_coefficient(skylight[x,y,z], blocklight[x,y,z])
img.paste(Image.blend(t[0], black_color, black_coeff), (imgx, imgy), t[1])
else:
# draw each face lit appropriately,
# but first just draw the block
img.paste(t[0], (imgx, imgy), t[1])
# top face
if z != 127 and (blocks[x,y,z+1] in transparent_blocks):
black_coeff = get_lighting_coefficient(skylight[x,y,z+1], blocklight[x,y,z+1])
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[0]).enhance(black_coeff))
# left face
black_coeff = 0.0
if x != 0:
black_coeff = get_lighting_coefficient(skylight[x-1,y,z], blocklight[x-1,y,z])
if x == 0 or (blocks[x-1,y,z] in transparent_blocks):
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
# right face
black_coeff = 0.0
if y != 15:
black_coeff = get_lighting_coefficient(skylight[x,y+1,z], blocklight[x,y+1,z])
if y == 15 or (blocks[x,y+1,z] in transparent_blocks):
img.paste((0,0,0), (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))
# Draw edge lines
if blockid not in transparent_blocks:
@@ -338,6 +372,32 @@ class ChunkRenderer(object):
return img
# Render 3 blending masks for lighting
# first is top (+Z), second is left (-X), third is right (+Y)
def generate_facemasks():
white = Image.new("L", (24,24), 255)
top = Image.new("L", (24,24), 0)
left = Image.new("L", (24,24), 0)
whole = Image.new("L", (24,24), 0)
toppart = textures.transform_image(white)
leftpart = textures.transform_image_side(white)
top.paste(toppart, (0,0))
left.paste(leftpart, (0,6))
right = left.transpose(Image.FLIP_LEFT_RIGHT)
# Manually touch up 6 pixels that leave a gap, like in
# textures._build_block()
for x,y in [(13,23), (17,21), (21,19)]:
right.putpixel((x,y), 255)
for x,y in [(3,4), (7,2), (11,0)]:
top.putpixel((x,y), 255)
return (top, left, right)
facemasks = generate_facemasks()
black_color = Image.new("RGB", (24,24), (0,0,0))
# Render 128 different color images for color coded depth blending in cave mode
def generate_depthcolors():
@@ -358,5 +418,4 @@ def generate_depthcolors():
g -= 7
return depth_colors
black_color = Image.new("RGB", (24,24), (0,0,0))
depth_colors = generate_depthcolors()

View File

@@ -106,7 +106,7 @@ def _split_terrain(terrain):
# This maps terainids to 16x16 images
terrain_images = _split_terrain(_get_terrain_image())
def _transform_image(img):
def transform_image(img):
"""Takes a PIL image and rotates it left 45 degrees and shrinks the y axis
by a factor of 2. Returns the resulting image, which will be 24x12 pixels
@@ -134,7 +134,7 @@ def _transform_image(img):
newimg = img.transform((24,12), Image.AFFINE, transform)
return newimg
def _transform_image_side(img):
def transform_image_side(img):
"""Takes an image and shears it for the left side of the cube (reflect for
the right side)"""
@@ -158,13 +158,13 @@ def _build_block(top, side, texID=None):
"""
img = Image.new("RGBA", (24,24), (38,92,255,0))
top = _transform_image(top)
top = transform_image(top)
if not side:
img.paste(top, (0,0), top)
return img
side = _transform_image_side(side)
side = transform_image_side(side)
otherside = side.transpose(Image.FLIP_LEFT_RIGHT)