Page 1 of 2
Pixa (was raster / shader project - insane?)
Posted: 15 Feb 2012 13:50
by andythenorth
I am considering using PIL (python image library) to procedurally generate trailers for trucks. Trailers are highly regular in shape, and drawing them to all lengths etc needed for BANDIT will be dull.
I have no experience in this, if I try to invent raster / shader from ground up, it's probably going to be bad.
Anyone interested in helping with this as an experiment?
I have two routes under consideration:
1. comping predefined blocks of pixels, e.g. trailer rear end, n * trailer middle part, trailer front end. This would build up trailers as though building with lego. This route requires component parts shaded for all 8 angles.
2. shading each face (truck trailers are quite regular), e.g floor, rear side, rear end, front side, front end. Pixels would be simply over-written where necessary. This route might be able to use transforms on the - view to generate other views procedurally.
My experience drawing graphics with code is limited to logo-style 'move cursor(delta_x, delta_y), draw(colour)'. Dunno if that's enough
Re: Raster / shader project - insane?
Posted: 15 Feb 2012 22:57
by andythenorth
Not insane. Works. More another time.
Re: Raster / shader project - insane?
Posted: 16 Feb 2012 22:18
by andythenorth
Trailer gets a floorplan drawn in false colour.
Pixel generator then sequences pixels to create trailer body.
Pixel sequence is determined by colours in floor plan + body type required.
Won't work at all for complex vehicles.
Will work well for vehicles with regular shapes (fairly certain this includes oval and cylindrical tankers as well as box shapes).
- test_input.png (2.83 KiB) Viewed 6318 times
- a_test_trailer.png (2.63 KiB) Viewed 6318 times
Code is pretty simple (this is non-optimised, non-configurable proof of concept):
Code: Select all
import Image
import ImageDraw
spritesheet = Image.open('test_input.png')
spritesheetpx = spritesheet.load()
draw = ImageDraw.Draw(spritesheet)
colours = {}
for x in range(spritesheet.size[0]):
for y in range(spritesheet.size[1]):
colour = spritesheetpx[x,y]
if colour != 255 and colour != 0 and colour != 15:
colours[colour] = ''
if spritesheetpx[x,y] == 240:
if x%2 == 0:
body_colour = 10
cc_colour = 200
else:
body_colour = 11
cc_colour = 201
draw.point([(x,y)],fill=body_colour)
draw.point([(x,y-1)],fill=cc_colour)
draw.point([(x,y-2)],fill=body_colour)
draw.point([(x,y-3)],fill=body_colour)
draw.point([(x,y-4)],fill=14)
if spritesheetpx[x,y] == 238:
if x%2 == 0:
body_colour = 11
cc_colour = 201
else:
body_colour = 12
cc_colour = 202
draw.point([(x,y)],fill=body_colour)
draw.point([(x,y-1)],fill=cc_colour)
draw.point([(x,y-2)],fill=body_colour)
draw.point([(x,y-3)],fill=body_colour)
draw.point([(x,y-4)],fill=14)
if spritesheetpx[x,y] == 209:
draw.point([(x,y)],fill=16)
draw.point([(x,y-1)],fill=17)
draw.point([(x,y-2)],fill=18)
draw.point([(x,y-3)],fill=19)
draw.point([(x,y-4)],fill=14)
spritesheet.save('a_test_trailer.png')
print colours
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 06:30
by andythenorth
Improved generator code; also a utility which will print out indexes for the palette used in a spritesheet.
Code: Select all
import Image
import ImageDraw
spritesheet = Image.open('test_input.png')
spritesheetpx = spritesheet.load()
draw = ImageDraw.Draw(spritesheet)
# global constants
body_colour = 10
cc_colour = 202
#each sequence is a tuple containing lists in format: [(x-offset,y-offset), colour]
pixel_sequences = dict (
body_outer = ([(0, 0), body_colour], [(0, 1), cc_colour], [(0, 2), body_colour], [(0, 3), body_colour], [(0, 4), 14]),
body_end = ([(0, 0), body_colour], [(0, 1), cc_colour], [(0, 2), body_colour], [(0, 3), body_colour], [(0, 4), 14]),
body_inner = ([(0, 0), 16], [(0, 1), 17], [(0, 2), 18], [(0, 3), 19], [(0, 4), 14]),
)
key_colour_mapping = {
209 : dict(seq = 'body_inner', colour_shift= 0),
238 : dict(seq = 'body_outer', colour_shift = 0),
240 : dict(seq = 'body_end', colour_shift = -1),
}
def get_pixel_sequence(x, y, key_colour):
key_map = key_colour_mapping[key_colour]
raw_sequence = pixel_sequences[key_map['seq']]
pixel_sequence = []
for i in raw_sequence:
pixel_sequence.append({
'x' : x + i[0][0],
'y' : y - i[0][1],
'colour' : i[1] + key_map['colour_shift'],
})
return pixel_sequence
colours = {} #used for debug
for x in range(spritesheet.size[0]):
for y in range(spritesheet.size[1]):
colour = spritesheetpx[x,y]
if colour != 255 and colour != 0 and colour != 15:
colours[colour] = ''
if spritesheetpx[x,y] in key_colour_mapping.keys():
seq = get_pixel_sequence(x, y, spritesheetpx[x,y])
for i in seq:
draw.point([(i['x'],i['y'])], fill=i['colour'])
spritesheet.save('a_test_trailer.png')
print colours # debug: what colours did we find in this spritesheet?
Palette Utility
Code: Select all
import Image
import ImageDraw
import ImagePalette
spritesheet = Image.open('test_input.png')
block_size = 30
palette_key = Image.new('P',(16*block_size,16*block_size))
draw = ImageDraw.Draw(palette_key)
print spritesheet.mode
palette_key.putpalette(spritesheet.palette)
x = 0
y = 0
for i in range (256):
draw.rectangle([(x,y),(x+block_size,y+block_size)],fill=i)
bg_size = draw.textsize(str(i))
text_pos = (x+(block_size/4),y+(block_size/3))
draw.rectangle([(text_pos[0]-1,text_pos[1]+1),(text_pos[0]+bg_size[0],text_pos[1]+bg_size[1]-2)],fill=255)
draw.text((x+(block_size/4),y+(block_size/3)),str(i),fill=1)
x = x+block_size
if x == 16*block_size:
x = 0
y = y + block_size
palette_key.save('palette_key.png')
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 06:59
by PikkaBird
Your ideas are intriguing to me and I wish to subscribe to your newsletter.
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 07:19
by andythenorth
I thought I'd better prove all angles work before going onto tanker bodies etc.
Here's a comp of the input (top row) and result (second row).
The magic colours in the trailer floor plan map to sequences of pixels. Each sequence contains colours and x / y offsets from starting pixel. Straight shapes offset in y direction only. I can do regular curved shapes by offsetting in x direction as well.
I'll also do loading/load sprites (for coal etc) by drawing the pattern on the floor pattern, then varying the length of the sequence.
For things like steel loads, I'm going to comp them on from pre-drawn images, using more magic pixels to set location.
- result.png (5.29 KiB) Viewed 6274 times
Zoomed (for luck):
- result_zoom.png (13.93 KiB) Viewed 6274 times
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 07:58
by FooBar
Interesting concept.
The only drawing-by-code I once did is a graph, via PHP using GD. But that appears to be more or less the same as how PIL works, so I can more or less follow what you're doing (apart from tuples and dicts, I'm only familiar with arrays, these appear overly complicated).
Now do one with cargo
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 08:53
by andythenorth
FooBar wrote:I can more or less follow what you're doing (apart from tuples and dicts, I'm only familiar with arrays
A little python-php translation then for you
List ~= array with ints as keys (0-based)
Tuple ~= array with ints as keys (0-based), but immutable (can't append, slice etc)
Dict ~= array
Now do one with cargo
Later I will.
I've no idea what this technique I'm using is called. I'm sure it exists in computer graphics lore.
It reminds of extruding a spline in CGI, but it differs quite a bit.
Also reminds me slightly of of building Doom levels in the wad editor, about 16 years ago
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 09:02
by FooBar
andythenorth wrote:A little python-php translation then for you
List ~= array with ints as keys (0-based)
Tuple ~= array with ints as keys (0-based), but immutable (can't append, slice etc)
Dict ~= array
Ah, thanks. I guess the fact that dict !== array makes that the other two actually have a use
As for what it's called? I guess it's some form of computer generated imagery.
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 20:38
by andythenorth
FooBar wrote:Now do one with cargo
Re: Raster / shader project - insane?
Posted: 17 Feb 2012 23:23
by FooBar
very cool
if you keep the purple for the cargo, you can then use that as base for recolouring.
Re: Raster / shader project - insane?
Posted: 18 Feb 2012 06:37
by andythenorth
FooBar wrote:if you keep the purple for the cargo, you can then use that as base for recolouring.
I'll just generate pngs at compile time with the cargo colours needed
Resulting grf will be a little larger than if recolour sprites were used, openttd (may) be fractionally faster due to not recolouring. Swings / roundabouts
Re: Raster / shader project - insane?
Posted: 18 Feb 2012 13:27
by andythenorth
Procedural buildings (quick test)
Re: Raster / shader project - insane?
Posted: 18 Feb 2012 13:31
by Lord Aro
Didn't Zephyris do something like that at some point?
Re: Raster / shader project - insane?
Posted: 18 Feb 2012 13:43
by andythenorth
Lord Aro wrote:Didn't Zephyris do something like that at some point?
Yes, same idea, different approach to implementation.
Re: Raster / shader project - insane?
Posted: 18 Feb 2012 13:56
by andythenorth
Re: Raster / shader project - insane?
Posted: 19 Feb 2012 08:50
by andythenorth
Generation of load colours and load states is done.
A range of body colours can be generated.
The trailer length, number of wheels etc are controlled by the input png file that defines the floorplan.
Below are a few examples of output - the generator creates more than this, but it's not necessary to prove that by posting them all here
This can (obviously) be extended to other styles of body, e.g. flatbed, open etc
Re: Raster / shader project - insane?
Posted: 20 Feb 2012 21:47
by andythenorth
Tank trailer input file + result.
The extra set of wheels in the input file is used to generate separate pngs for A trailers and B trailers - the brown pixels are painted as tyres, or masked out with blue.
- tanker_input.png (7.85 KiB) Viewed 5982 times
- tank_trailers_2.png (64.95 KiB) Viewed 5982 times
Re: Raster / shader project - insane?
Posted: 21 Feb 2012 07:19
by andythenorth
Tanker B-Train
Re: Raster / shader project - insane?
Posted: 21 Feb 2012 08:14
by FooBar
I'm quite surprised you can draw a tanker out of a single line of pixels!