Re: [whatwg] CSS Filter Effects for Canvas 2D Context

On Mon, Jul 16, 2012 at 2:02 PM, Ashley Gullen <ashley@scirra.com> wrote:

> I'd like to bring up this subject again especially now that first
> implementations are starting to appear.
>
> IMO the big use case here is games - the CSS filters are great for
> interesting visual effects.  However there doesn't seem to be a way to use
> them in canvas rendering, other than applying the effect to an entire
> canvas. Games typically want to apply effects to individual objects
> (meaning individual drawImage() calls), and there is no good way to do
> this.  Stacking separate canvas elements is out of the question, because it
> makes Z ordering with effects impossible.  Consider trying to overlay an
> image with no effect on top of an image with an effect.  Also consider the
> fact canvas has compositing modes like "lighter" and "destination-out", but
> CSS filters do not provide these. This makes it impossible to combine CSS
> filters and composite modes. An example is displaying an additive blended
> explosion (typical in games) on top of an image with a blur CSS filter,
> which seems to be impossible to achieve at all.
>

Forcing developers to use CSS with Canvas to get high-level *graphics*
functionality is just plain wrong. If anything, it's completely backwards.
Why do we arbitrarily restrict high-level graphics functionality such as
filters and composite modes to individual technologies like CSS and Canvas?
I'm completely unaware of the advantages of such an approach. The term "CSS
filters" is absurd.

Filters are an important high-level graphics capability that should be
available to any HTML5 technology that chooses to incorporate them. I agree
with Ashley, let's get them into Canvas.

One way to define this is to specify that drawImage(), when passed another
> canvas as a parameter, must take in to account the canvas' 'filter' CSS
> property.  So to draw an image with a blur you'd render using an
> intermediate canvas, e.g.
>
> tempcanvascontext.drawImage(myimage, 0, 0);
> tempcanvas.style.filter = "blur(10px)";
> gamecanvascontext.drawImage(tempcanvas, 0, 0); // draws with blur
>
> Another way would be just to add a 'filter' property to the 2D context,
> e.g.:
>
> gamecanvascontext.filter = "blur(10px)";
> gamecanvascontext.drawImage(myimage, 0, 0);
>
> This would also be extremely powerful if custom CSS shaders are also
> supported, allowing for user-written effects in the canvas 2D context.
>
> Effects should should apply to all drawing operations for consistency,
> including lines, paths, rectangles and patterns.
>

I like the filter attribute on the context, provided that it's part of the
state saved by save():

    gamecanvascontext.drawImage(...); // image drawn normally

    gamecanvascontext.save();

    gamecanvascontext.filter = '...';
    gamecanvascontext.drawImage(...); // image drawn w/filter

    gamecanvascontext.restore();

    gamecanvascontext.drawImage(...); // image drawn normally

The default filter could be a no-op, which would be similar in behavior to
the default clipping region (they would both do nothing).


> I have no idea if this is easy for implementers (would appreciate comments
> on that), but hopefully the CSS filter rendering can be recycled with
> drawImage().
>
> Another argument is that you should just use WebGL and write shaders for
> advanced effects.
>

It's a poor argument, IMO. We should leave 3D for WebGL, but make advanced
effects available to all interested technologies.


>  This is an option, but given that a filter effect can be applied to an
> entire canvas, it seems a waste not to enable it for individual draw calls,
> especially given the 2D context is considerably easier and quicker to code
> for.
>

Agreed.


David


>
> Ashley Gullen
> Scirra.com
>
>
> On 25 January 2012 16:26, Tab Atkins Jr. <jackalmage@gmail.com> wrote:
>
>> On Wed, Jan 25, 2012 at 6:41 AM, David Geary <david.mark.geary@gmail.com>
>> wrote:
>> > On Tue, Jan 24, 2012 at 5:22 PM, Chris Marrin <cmarrin@apple.com>
>> wrote:
>> >> Adding filter functions to canvas would require you to re-render the
>> items
>> >> for every filter change and you'd have to animate it all yourself.
>> >
>> > Sure, but you must create a superfluous canvas for each set of images
>> that
>> > you animate, and invoke an entirely different technology to apply the
>> > filter. You must  make sure that those superfluous canvases have
>> > transparent backgrounds, no borders, and have the correct Z order so
>> they
>> > appear over, and not under, the primary canvas for the application. And
>> I'm
>> > sure there are other gotchas to this hybrid approach that don't
>> immediately
>> > come to mind.
>> >
>> > I'd much rather use the filtering underlying API and control the
>> rendering
>> > and animation myself.
>>
>> Yes, it's effectively creating an ad-hoc retained-mode API out of
>> multiple <canvas> elements solely so it can apply filtering.
>>
>> (Using multiple backing canvases to sprite things is a reasonable
>> performance hack, but I don't think it should be required for basic
>> functionality.)
>>
>> ~TJ
>>
>
>

Received on Thursday, 26 July 2012 18:43:31 UTC