memononen / nanovg

Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations.
zlib License
5.16k stars 775 forks source link

Proposal: add compositing setting to NanoVG. #65

Open starwing opened 10 years ago

starwing commented 10 years ago

Hi,

I hope NanoVG could add compositing support. it means, you can set how pixel composition with destination pixel. In HTML5 canvas, these compositing mode are used:

source-over
   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

source-in
   glBlendFunc(GL_DST_ALPHA, GL_ZERO);

source-out
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);

source-atop
   glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

destination-over
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);

destination-in
   glBlendFunc(GL_ZERO, GL_SRC_ALPHA)

destination-out
   glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

destination-atop
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA);

lighter
   glBlendFunc(GL_ONE, GL_ONE);

darker
   deprecated

copy
   glBlendFunc(GL_ONE, GL_ZERO);

xor
   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

see here

A function:

void nvgBlendMode(NVGcontext *ctx, int mode);

can be added, and add a field to NVGparams, backend can set correct mode before any drawing.

dougbinks commented 10 years ago

Quick note on implementation: this is best handled purely using the shader, with blending mode set to glBlendFunc( GL_ONE, GL_SRC_ALPHA). The shader can then take a constant parameter to calculate the required color and alpha outputs so as to get the blend mode required. This would then decrease the state changes needed.

paniq commented 10 years ago

A requirement came up today which would make purely additive blending highly desirable: for procedural textures, I need to render roughness / metallic / emissive / weight parameters into RGBA channels separately; (Not sure how I would actually write to A exclusively, now that I think about it. Any ideas?)

Although I could probably render to 4 seperate textures in a pre-step and then mix those into a single picture with an extra shader. That's probably the cleanest way to do it.

dougbinks commented 10 years ago

I think this could be done by modifying the code to take a five component colour (RGBXA) and using pure additive blending with pre-multiplied alpha, so outputing RGBX * A.

so:

RGBXd = RGBXd + RGBXs * As

if that's what you're asking for?

I don't think this is general enough to add to the library though - but it could be done with a custom shader such as in https://github.com/memononen/nanovg/issues/57.

olliwang commented 8 years ago

Finally, I implemented this feature. The composite operation works between nanovg frames. Just opened a pull request. https://github.com/memononen/nanovg/pull/298 This PR also solves my another issue: https://github.com/memononen/nanovg/issues/88