Illuminated.js – 2D lights and shadows rendering engine for HTML5 applications
blog.greweb.fr
blog.greweb.fr
One thing that excites me especially is that a simple game creation engine in the browser might be a great chance to excite kids about programming with a very low barrier to entry.
Still cool as a tech demo though.
Do you use a lot of sampling in the lights? I reach good fps on my macbook pro, especially on Chrome (but also on my home computer under Linux).
I hope we can use it with less sampling and less compute() calls for our games :)
Runs so slow I can barely drag the objects around. It looks great though, I mean the output is fantastic just not performant.
Now my technique of combining shadow samples together is probably not the most efficient, I draw them with source-over and an alpha which is also a wrong hacky current implementation... but maybe using the CanvasData would be less efficient (technically I need to make the average of shadow samples' grayscales) - well we never know, I haven't tried yet ;)
I would be happy to have any contribution in the library :)
You think using getImageData and putImageData is more performant that drawImage(canvas, 0, 0) ?
BTW i'm not sure it will works for combining images together with special composite operation.
http://jsperf.com/canvas-drawimage-vs-putimagedata/11
also read this about imageData caching and explanations of the different opts. loop unrolling helps a bit, forget the typed array stuff for now, it wont work anywhere for some time.
http://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipul...
But I don't use hidden canvases, just .drawImage each visible tile of terrain into the middle canvas each frame. I'll try to draw to hidden canvas, and see the difference, thanks for suggestion.
When I draw everything moving to off screen canvas, and then drawImage this off screen canvas into visible canvas, I get 48% of time in draw function, and ~35 fps.
It is indeed faster to draw everything to off screen canvas, than to on screen one (when I commented out copying off screen canvas to on screen canvas, and left only drawing sprites and tiles to off screen canvas - I got steady 60 fps, but obviously nothing is visible then :)). And copying whole canvas to the visible one is still slower, than drawing the sprites and tiles on the visible canvas in the first place.
But thanks for ideas.
My fastest code:
for (var y=y1; y>=y0; --y) {
var resultY = (0.5+
(level.topLeft.y - camera.position.y + camera.screen.height / 2 +
level.cellHeight + y * level.cellHeight-level.cellHeight)
)|0; // fast clip to int
for (var x=x1; x>=x0; --x) {
var tileImageNo = level.layers[z].cells.valueAt([x, y])-1;
if (tileImageNo==null || tileImageNo<=0) {
//nothing to do
} else {
ctxOnScreenCanvas.drawImage(
tiles[tileImageNo],
(0.5+
(level.topLeft.x - camera.position.x + camera.screen.width / 2 +
level.cellWidth + x * level.cellWidth- level.cellWidth)
)|0, // fast clip to int
resultY
);
}
}
}
I've also tried drawing to OffScreenCanvas in the loop, and then drawing that canvas to screen, but it was slower.I could try drawing to off screen canvas only when player moves out off current off screen canvas, but that will trade small delay each turn into big delay every N turns, and that's even worse. But I'll try that.
EDIT: cuting out not important code.
- You have a background layer, lets just say it's a blue background - A middle layer, lets say clouds that move as you move to the right - And a tile layer, which draws the sprites, and the tiles of the maps
For the tile layer, we can break it down into two separate groups, animated sprites, and static sprites.
The static sprites, can be drawn to the offscreen canvas, and you get the imageData from that one time, and then push that data to the screen there after. Then the animated sprites will just be drawn to the on screen canvas every time. http://imgur.com/n6RFF The stuff that should be drawn to the offscreen canvas, then grab the image data has gray around it, and the animated sprites are in the green.
So for drawing the tiles of the map we only have to loop through the tile data, one time, and after that if the imgData remains valid (a separate flag) we can just push that imgData to the screen.
This would also allow drawing section of the screens on the offscreen canvas in chunks, and storing that draw to just be pushed to the screen at appropriate times.
I don't know if I explained it very well, I could probably through together a crappy little demo if you'd like.
they use multiple canvas layers. from working a lot with canvas lately, the fastest was to draw to canvas is not to draw to it :). if you have a scrolling bg that is static, you can just use a bg image sprite and scroll it via CSS/js. anything that can be done with a sprite should probably be done with one.
even for collisions etc, you're best off doing all the logic for your shapes and manipulating a DOM element (or even a mini-canvas) than re-rendering an entire huge canvas.
http://demo.greweb.fr/illuminated.js/#{%22lights%22:[{%22ins...],%22objects%22:[{%22instance%22:%22DiscObject%22,%22center%22:{%22x%22:313.5,%22y%22:190.316650390625},%22radius%22:34},{%22instance%22:%22DiscObject%22,%22center%22:{%22x%22:175.5,%22y%22:146.316650390625},%22radius%22:38},{%22instance%22:%22PolygonObject%22,%22points%22:[{%22x%22:426.5,%22y%22:82.316650390625},{%22x%22:449.5,%22y%22:189.316650390625},{%22x%22:481.5,%22y%22:143.316650390625},{%22x%22:487.5,%22y%22:94.316650390625},{%22x%22:487.5,%22y%22:87.316650390625},{%22x%22:433.5,%22y%22:32.316650390625},{%22x%22:381.5,%22y%22:42.316650390625},{%22x%22:346.5,%22y%22:136.316650390625},{%22x%22:346.5,%22y%22:138.316650390625}]}],%22globals%22:{%22maskcolor%22:%22rgba%280,0,0,0.9%29%22}}
history.replaceState({}, title, "#"+hash);
would have fixed it.( https://github.com/gre/illuminated.js/blob/master/demo.js#L1... )
Any idea?
And also I don't have to store anything on my server, bit.ly like services are the new way of storing the information :)
Am I wrong?
http://stackoverflow.com/questions/94346/can-i-legally-incor...
ok so I'll move it to LGPL soon then ;)
Yep, This is what I want for Illuminated.js. I prefer to have benefits of the library modifications. It's a bit more restrictive coming from MIT (I used to use it for some projects) but it's not as restrictive as a "non-commercial only" license, so IMO it's quite ok, it's a minimum of thanks to the library.
Regards
Additionally, afaict, it's problematic to use on embedded, closed platforms, such as iOS.
Yeah, I need to fix that, this is link to my wrong sampling implementation.
If you use only 1 sampling you will see it is fixed.
Might I suggest instead of a solution in real time, how about a static deal that essentially generates a lightmap to overlay on top of the scene? I can think of several uses for that.
This demonstration instantly makes me think of Blizzard's Diablo II from 2000, which features an identical effect during gameplay, with a seemingly infinite number of shadow-generating obstacles and as many light sources casting shadows as there are players on the screen, and it runs perfectly smooth even on a 500mhz P3.