[whatwg] I believe source rectangles for HTML5 Canvas drawImage are specified incorrectly
Kevin Gadd
kevin.gadd at gmail.com
Mon Dec 10 13:17:07 PST 2012
I can't speak for the most common approach in HTML5 games, but using a
temporary surface for drawing sprites is definitely not a common
approach in non-canvas games. I've never seen it proposed before this
thread for canvas dev, either, but I'm not an expert there. This is at
least an area where someone who has a passing familiarity with
graphics programming is not going to have their expectations met.
One reason spritemaps get used is to reduce overhead when deploying
game content. In that case, copying the individual images out is not a
problem and it's no big deal that canvas is specified this way.
Another reason is that in Direct3D and OpenGL, historically state
changes have come at a significant cost, so putting all of your
individual images into a single texture allows you to draw lots of
objects with no state changes. While state changes are dramatically
cheaper on modern hardware, they still aren't free. Of course, this
doesn't necessarily apply to canvas backends, but that's part of why
people do it. If, like me, you're building browser games that use
WebGL where available and use canvas for fallback, it is basically
impossible to convert your texture atlases/spritemaps into individual
images because texture coordinates (and as a result, the canvas source
rectangles used in fallback) can map to any part of the texture.
Re: the efficiency of clips, I don't think you can state that it's
'much more expensive' unless you've tested it. The kind of clip he
describes is absurdly fast on 3D hardware and built into both the
Direct3D and OpenGL specs:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb147354%28v=vs.85%29.aspx
http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml
It should be possible to apply a similar technique to software canvas
implementations, but I won't claim to know whether that's done. Canvas
clipping in general is certainly more complicated, but what he
described is not. I agree that using clips is a reasonable way to
express that kind of rendering operation (especially since it
simplifies the javascript you have to write) and it allows both of
these use cases - spritemaps and subregion updates - to coexist.
It's also not a safe assumption that subregion updates are common in
games. Certainly any game using Direct3D, OpenGL or WebGL is unlikely
to be doing subregion updates since typically your entire framebuffer
is discarded by the GPU (or at least not reliable) after you
swapbuffers/present. Doing partial updates requires extra effort to
set up offscreen render targets and make copies of pixel data. I
wouldn't be shocked if there are canvas-based games out there doing
subregion updates, but I can't think of more than one or two that I've
ever seen.
If we're talking about optimizing for one use case over another, there
should be data to support that it is the only important use case.
Arguably, it should be possible to provide reasonable performance for
both use cases here...
-kg
On Mon, Dec 10, 2012 at 1:04 PM, Rik Cabanier <cabanier at gmail.com> wrote:
>
>
> On Mon, Dec 10, 2012 at 11:03 AM, Justin Novosad <junov at chromium.org> wrote:
>>
>> On Mon, Dec 10, 2012 at 1:24 PM, Ian Hickson <ian at hixie.ch> wrote:
>>
>> >
>> > The reason to prefer the current behaviour is if you want to just update
>> > a
>> > small part of an image. For example, if you draw a bit photo, then draw
>> > text over it, then want to remove the text by just drawing the photo
>> > over
>> > where the text was but not redrawing the whole thing. If we clamped to
>> > source rectangle, we'd get artefacts in this case that couldn't be
>> > worked
>> > around (unlike the problems with scaling sprites, which can be worked
>> > around, albeit in a suboptimal fashion).
>> >
>> >
>> I disagree. There is an efficient workaround for updating a subregion of
>> an
>> image without getting filtering artifacts around the edges : use clipping
>> to limit the update region
>
>
> How is that an efficient workaround?
> It involves setting a clip, calling drawimge with a larger (complete?) image
> and then removing the clip.
> This seems much more expensive for such as common operation. (ie a game that
> wants to remove an animated character)
>
>>
>> On the other hand, the workaround to prevent color bleeding when using
>> spritemap is much less efficient since it requires padding, which is
>> wasteful by definition, and in cases where the sprite can be downsized,
>> the
>> padding margins may have to be very large.
>
>
> As Ian said, copying the sprite image to a non-scaled canvas first (which
> most games probably do anyway) works around the issue.
> There is no need for padding in that case.
>
>
>
>
--
-kg
More information about the whatwg
mailing list