@@ -18,12 +18,10 @@ <h2> Skottie </h2>
1818< canvas id =sk_onboarding width =500 height =500 > </ canvas >
1919< canvas id =sk_animated_gif width =500 height =500
2020 title ='This is an animated gif being animated in Skottie '> </ canvas >
21- < canvas id =sk_webfont width =500 height =500
22- title ='This shows loading of a custom font (e.g. WebFont) '> </ canvas >
2321
2422< h2 > RT Shader </ h2 >
2523< canvas id =rtshader width =300 height =300 > </ canvas >
26-
24+ < canvas id = rtshader2 width = 300 height = 300 > </ canvas >
2725
2826< h2 > Particles </ h2 >
2927< canvas id =particles width =500 height =500 > </ canvas >
@@ -48,7 +46,6 @@ <h2> 3D perspective transformations </h2>
4846 var confettiJSON = null ;
4947 var onboardingJSON = null ;
5048 var multiFrameJSON = null ;
51- var webfontJSON = null ;
5249 var fullBounds = { fLeft : 0 , fTop : 0 , fRight : 500 , fBottom : 500 } ;
5350
5451 var robotoData = null ;
@@ -57,9 +54,10 @@ <h2> 3D perspective transformations </h2>
5754 var bonesImageData = null ;
5855 var flightAnimGif = null ;
5956 var skpData = null ;
60- CanvasKitInit ( {
57+ const ckLoaded = CanvasKitInit ( {
6158 locateFile : ( file ) => '/node_modules/canvaskit/bin/' + file ,
62- } ) . ready ( ) . then ( ( CK ) => {
59+ } ) . ready ( ) ;
60+ ckLoaded . then ( ( CK ) => {
6361 CanvasKit = CK ;
6462 // Set bounds to fix the 4:3 resolution of the legos
6563 SkottieExample ( CanvasKit , 'sk_legos' , legoJSON ,
@@ -71,10 +69,6 @@ <h2> 3D perspective transformations </h2>
7169 SkottieExample ( CanvasKit , 'sk_animated_gif' , multiFrameJSON , fullBounds , {
7270 'image_0.png' : flightAnimGif ,
7371 } ) ;
74- SkottieExample ( CanvasKit , 'sk_webfont' , webfontJSON , fullBounds , {
75- 'Roboto-Regular' : robotoData ,
76- } ) ;
77-
7872 ParticlesAPI1 ( CanvasKit ) ;
7973
8074 ParagraphAPI1 ( CanvasKit , robotoData ) ;
@@ -132,12 +126,9 @@ <h2> 3D perspective transformations </h2>
132126 } ) ;
133127 } ) ;
134128
135- fetch ( './Roboto-Regular.woff ' ) . then ( ( resp ) => {
129+ fetch ( './Roboto-Regular.ttf ' ) . then ( ( resp ) => {
136130 resp . arrayBuffer ( ) . then ( ( buffer ) => {
137131 robotoData = buffer ;
138- SkottieExample ( CanvasKit , 'sk_webfont' , webfontJSON , fullBounds , {
139- 'Roboto-Regular' : robotoData ,
140- } ) ;
141132 ParagraphAPI1 ( CanvasKit , robotoData ) ;
142133 } ) ;
143134 } ) ;
@@ -147,6 +138,9 @@ <h2> 3D perspective transformations </h2>
147138 SkpExample ( CanvasKit , skpData ) ;
148139 } ) ;
149140
141+ const loadDog = fetch ( 'https://storage.googleapis.com/skia-cdn/misc/dog.jpg' ) . then ( ( response ) => response . arrayBuffer ( ) ) ;
142+ const loadMandrill = fetch ( 'https://storage.googleapis.com/skia-cdn/misc/mandrill_256.png' ) . then ( ( response ) => response . arrayBuffer ( ) ) ;
143+
150144 function SkottieExample ( CanvasKit , id , jsonStr , bounds , assets ) {
151145 if ( ! CanvasKit || ! jsonStr ) {
152146 return ;
@@ -370,19 +364,28 @@ <h2> 3D perspective transformations </h2>
370364 return surface ;
371365 }
372366
367+ const spiralSkSL = `
368+ uniform float rad_scale;
369+ uniform float2 in_center;
370+ uniform float4 in_colors0;
371+ uniform float4 in_colors1;
372+
373+ void main(float2 p, inout half4 color) {
374+ float2 pp = p - in_center;
375+ float radius = sqrt(dot(pp, pp));
376+ radius = sqrt(radius);
377+ float angle = atan(pp.y / pp.x);
378+ float t = (angle + 3.1415926/2) / (3.1415926);
379+ t += radius * rad_scale;
380+ t = fract(t);
381+ color = half4(mix(in_colors0, in_colors1, t));
382+ }` ;
383+
373384 function RTShaderAPI1 ( CanvasKit ) {
374- return ; // TODO(kjlubick): Fix this example.
375385 if ( ! CanvasKit ) {
376386 return ;
377387 }
378- const prog = `
379388
380- uniform half4 gColor;
381-
382- void main(float2 p, inout half4 color) {
383- color = half4(half2(p)*(1.0/255), gColor.b, 1);
384- }
385- ` ;
386389 const surface = CanvasKit . MakeCanvasSurface ( 'rtshader' ) ;
387390 if ( ! surface ) {
388391 console . error ( 'Could not make surface' ) ;
@@ -391,20 +394,135 @@ <h2> 3D perspective transformations </h2>
391394
392395 const canvas = surface . getCanvas ( ) ;
393396
394- const effect = CanvasKit . _SkRuntimeEffect . Make ( prog ) ;
395- const rot = CanvasKit . SkMatrix . rotated ( 90 , 128 , 128 ) ;
396- const shader = effect . makeShader ( [ 1 , 0 , 0 , 1 ] , true , rot ) ;
397-
397+ const effect = CanvasKit . SkRuntimeEffect . Make ( spiralSkSL ) ;
398+ const shader = effect . makeShader ( [
399+ 0.5 ,
400+ 150 , 150 ,
401+ 0 , 1 , 0 , 1 ,
402+ 1 , 0 , 0 , 1 ] , true ) ;
398403 const paint = new CanvasKit . SkPaint ( ) ;
399404 paint . setShader ( shader ) ;
400- canvas . drawRect ( CanvasKit . LTRBRect ( 0 , 0 , 256 , 256 ) , paint ) ;
405+ canvas . drawRect ( CanvasKit . LTRBRect ( 0 , 0 , 300 , 300 ) , paint ) ;
401406
402407 surface . flush ( ) ;
403408 shader . delete ( ) ;
404409 paint . delete ( ) ;
405410 effect . delete ( ) ;
406411 }
407412
413+ // RTShader2 demo
414+ Promise . all ( [ ckLoaded , loadDog , loadMandrill ] ) . then ( ( values ) => {
415+ const [ CanvasKit , dogData , mandrillData ] = values ;
416+ const dogImg = CanvasKit . MakeImageFromEncoded ( dogData ) ;
417+ if ( ! dogImg ) {
418+ console . error ( 'could not decode dog' ) ;
419+ return ;
420+ }
421+ const mandrillImg = CanvasKit . MakeImageFromEncoded ( mandrillData ) ;
422+ if ( ! mandrillImg ) {
423+ console . error ( 'could not decode mandrill' ) ;
424+ return ;
425+ }
426+ const quadrantSize = 150 ;
427+
428+ const dogShader = dogImg . makeShader ( CanvasKit . TileMode . Clamp , CanvasKit . TileMode . Clamp ,
429+ CanvasKit . SkMatrix . scaled ( quadrantSize / dogImg . width ( ) ,
430+ quadrantSize / dogImg . height ( ) ) ) ;
431+ const mandrillShader = mandrillImg . makeShader ( CanvasKit . TileMode . Clamp , CanvasKit . TileMode . Clamp ,
432+ CanvasKit . SkMatrix . scaled (
433+ quadrantSize / mandrillImg . width ( ) ,
434+ quadrantSize / mandrillImg . height ( ) ) ) ;
435+
436+ const surface = CanvasKit . MakeCanvasSurface ( 'rtshader2' ) ;
437+ if ( ! surface ) {
438+ console . error ( 'Could not make surface' ) ;
439+ return ;
440+ }
441+
442+ const prog = `
443+ in fragmentProcessor before_map;
444+ in fragmentProcessor after_map;
445+ in fragmentProcessor threshold_map;
446+
447+ uniform float cutoff;
448+ uniform float slope;
449+
450+ float smooth_cutoff(float x) {
451+ x = x * slope + (0.5 - slope * cutoff);
452+ return clamp(x, 0, 1);
453+ }
454+
455+ void main(float2 xy, inout half4 color) {
456+ half4 before = sample(before_map, xy);
457+ half4 after = sample(after_map, xy);
458+
459+ float m = smooth_cutoff(sample(threshold_map, xy).r);
460+ color = mix(before, after, half(m));
461+ }` ;
462+
463+ const canvas = surface . getCanvas ( ) ;
464+
465+ const thresholdEffect = CanvasKit . SkRuntimeEffect . Make ( prog ) ;
466+ const spiralEffect = CanvasKit . SkRuntimeEffect . Make ( spiralSkSL ) ;
467+
468+ const draw = ( x , y , shader ) => {
469+ const paint = new CanvasKit . SkPaint ( ) ;
470+ paint . setShader ( shader ) ;
471+ canvas . save ( ) ;
472+ canvas . translate ( x , y ) ;
473+ canvas . drawRect ( CanvasKit . LTRBRect ( 0 , 0 , quadrantSize , quadrantSize ) , paint ) ;
474+ canvas . restore ( ) ;
475+ paint . delete ( ) ;
476+ } ;
477+
478+ const offscreenSurface = CanvasKit . MakeSurface ( quadrantSize , quadrantSize ) ;
479+ const getBlurrySpiralShader = ( rad_scale ) => {
480+ const oCanvas = offscreenSurface . getCanvas ( ) ;
481+
482+ const spiralShader = spiralEffect . makeShader ( [
483+ rad_scale ,
484+ quadrantSize / 2 , quadrantSize / 2 ,
485+ 1 , 1 , 1 , 1 ,
486+ 0 , 0 , 0 , 1 ] , true ) ;
487+
488+ return spiralShader ;
489+ // TODO(kjlubick): The raster backend does not like atan or fract, so we can't
490+ // draw the shader into the offscreen canvas and mess with it. When we can, that
491+ // would be cool to show off.
492+
493+ const blur = CanvasKit . SkImageFilter . MakeBlur ( 0.1 , 0.1 , CanvasKit . TileMode . Clamp , null ) ;
494+
495+ const paint = new CanvasKit . SkPaint ( ) ;
496+ paint . setShader ( spiralShader ) ;
497+ paint . setImageFilter ( blur ) ;
498+ oCanvas . drawRect ( CanvasKit . LTRBRect ( 0 , 0 , quadrantSize , quadrantSize ) , paint ) ;
499+
500+ paint . delete ( ) ;
501+ blur . delete ( ) ;
502+ spiralShader . delete ( ) ;
503+ return offscreenSurface . makeImageSnapshot ( )
504+ . makeShader ( CanvasKit . TileMode . Clamp , CanvasKit . TileMode . Clamp ) ;
505+
506+ } ;
507+
508+ const drawFrame = ( ) => {
509+ surface . requestAnimationFrame ( drawFrame ) ;
510+ const thresholdShader = getBlurrySpiralShader ( Math . sin ( Date . now ( ) / 5000 ) / 2 ) ;
511+
512+ const blendShader = thresholdEffect . makeShaderWithChildren (
513+ [ 0.5 , 10 ] ,
514+ true , [ dogShader , mandrillShader , thresholdShader ] ) ;
515+ draw ( 0 , 0 , blendShader ) ;
516+ draw ( quadrantSize , 0 , thresholdShader ) ;
517+ draw ( 0 , quadrantSize , dogShader ) ;
518+ draw ( quadrantSize , quadrantSize , mandrillShader ) ;
519+
520+ blendShader . delete ( ) ;
521+ } ;
522+
523+ surface . requestAnimationFrame ( drawFrame ) ;
524+ } ) ;
525+
408526 function SkpExample ( CanvasKit , skpData ) {
409527 if ( ! skpData || ! CanvasKit ) {
410528 return ;
0 commit comments