xref: /aosp_15_r20/external/skia/site/docs/user/sksl.md (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker---
2*c8dee2aaSAndroid Build Coastguard Workertitle: 'SkSL & Runtime Effects'
3*c8dee2aaSAndroid Build Coastguard WorkerlinkTitle: 'SkSL'
4*c8dee2aaSAndroid Build Coastguard Worker---
5*c8dee2aaSAndroid Build Coastguard Worker
6*c8dee2aaSAndroid Build Coastguard Worker## Overview
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker**SkSL** is Skia's
9*c8dee2aaSAndroid Build Coastguard Worker[shading language](https://en.wikipedia.org/wiki/Shading_language).
10*c8dee2aaSAndroid Build Coastguard Worker**`SkRuntimeEffect`** is a Skia C++ object that can be used to create
11*c8dee2aaSAndroid Build Coastguard Worker`SkShader`, `SkColorFilter`, and `SkBlender` objects with behavior controlled by
12*c8dee2aaSAndroid Build Coastguard WorkerSkSL code.
13*c8dee2aaSAndroid Build Coastguard Worker
14*c8dee2aaSAndroid Build Coastguard WorkerYou can experiment with SkSL at https://shaders.skia.org/. The syntax is very
15*c8dee2aaSAndroid Build Coastguard Workersimilar to GLSL. When using SkSL effects in your Skia application, there are
16*c8dee2aaSAndroid Build Coastguard Workerimportant differences (from GLSL) to remember. Most of these differences are
17*c8dee2aaSAndroid Build Coastguard Workerbecause of one basic fact: **With GPU shading languages, you are programming a
18*c8dee2aaSAndroid Build Coastguard Workerstage of the
19*c8dee2aaSAndroid Build Coastguard Worker[GPU pipeline](https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview).
20*c8dee2aaSAndroid Build Coastguard WorkerWith SkSL, you are programming a stage of the Skia pipeline.**
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard WorkerIn particular, a GLSL fragment shader controls the entire behavior of the GPU
23*c8dee2aaSAndroid Build Coastguard Workerbetween the rasterizer and the blending hardware. That shader does all of the
24*c8dee2aaSAndroid Build Coastguard Workerwork to compute a color, and the color it generates is exactly what is fed to
25*c8dee2aaSAndroid Build Coastguard Workerthe fixed-function blending stage of the pipeline.
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard WorkerSkSL effects exist as part of the larger Skia pipeline. When you issue a canvas
28*c8dee2aaSAndroid Build Coastguard Workerdrawing operation, Skia (generally) assembles a single GPU fragment shader to do
29*c8dee2aaSAndroid Build Coastguard Workerall of the required work. This shader typically includes several pieces. For
30*c8dee2aaSAndroid Build Coastguard Workerexample, it might include:
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker- Evaluating whether a pixel falls inside or outside of the shape being drawn
33*c8dee2aaSAndroid Build Coastguard Worker  (or on the border, where it might apply antialiasing).
34*c8dee2aaSAndroid Build Coastguard Worker- Evaluating whether a pixel falls inside or outside of the clipping region
35*c8dee2aaSAndroid Build Coastguard Worker  (again, with possible antialiasing logic for border pixels).
36*c8dee2aaSAndroid Build Coastguard Worker- Logic for the `SkShader` on the `SkPaint`. The `SkShader` can actually be a
37*c8dee2aaSAndroid Build Coastguard Worker  tree of objects (due to `SkShaders::Blend` and other features described
38*c8dee2aaSAndroid Build Coastguard Worker  below).
39*c8dee2aaSAndroid Build Coastguard Worker- Similar logic for the `SkColorFilter` (which can also be a tree, due to
40*c8dee2aaSAndroid Build Coastguard Worker  `SkColorFilters::Compose`, `SkColorFilters::Blend`, and features described
41*c8dee2aaSAndroid Build Coastguard Worker  below).
42*c8dee2aaSAndroid Build Coastguard Worker- Blending code (for certain `SkBlendMode`s, or for custom blending specified
43*c8dee2aaSAndroid Build Coastguard Worker  with `SkPaint::setBlender`).
44*c8dee2aaSAndroid Build Coastguard Worker- Color space conversion code, as part of Skia's [color management](/docs/user/color).
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard WorkerEven if the `SkPaint` has a complex tree of objects in the `SkShader`,
47*c8dee2aaSAndroid Build Coastguard Worker`SkColorFilter`, or `SkBlender` fields, there is still only a _single_ GPU
48*c8dee2aaSAndroid Build Coastguard Workerfragment shader. Each node in that tree creates a single function. The clipping
49*c8dee2aaSAndroid Build Coastguard Workercode and geometry code each create a function. The blending code might create a
50*c8dee2aaSAndroid Build Coastguard Workerfunction. The overall fragment shader then calls all of these functions (which
51*c8dee2aaSAndroid Build Coastguard Workermay call other functions, e.g. in the case of an `SkShader` tree).
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker**Your SkSL effect contributes a function to the GPU's fragment shader.**
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker---
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker## Evaluating (sampling) other SkShaders
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard WorkerIn GLSL, a fragment shader can sample a texture. With runtime effects, the
60*c8dee2aaSAndroid Build Coastguard Workerobject that you bind (in C++) is an `SkShader`, represented by a `shader` in
61*c8dee2aaSAndroid Build Coastguard WorkerSkSL. To make it clear that you are operating on an object that will emit its
62*c8dee2aaSAndroid Build Coastguard Workerown shader code, you don't use `sample`. Instead, the `shader` object has a
63*c8dee2aaSAndroid Build Coastguard Worker`.eval()` method. Regardless, Skia has simple methods for creating an `SkShader`
64*c8dee2aaSAndroid Build Coastguard Workerfrom an `SkImage`, so it's easy to use images in your runtime effects:
65*c8dee2aaSAndroid Build Coastguard Worker
66*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_EvaluatingImageShader'></fiddle-embed-sk>
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard WorkerBecause the object you bind and evaluate is an `SkShader`, you can directly use
69*c8dee2aaSAndroid Build Coastguard Workerany Skia shader, without necessarily turning it into an image (texture) first.
70*c8dee2aaSAndroid Build Coastguard WorkerFor example, you can evaluate a linear gradient. In this example, there is no
71*c8dee2aaSAndroid Build Coastguard Workertexture created to hold the gradient. Skia generates a single fragment shader
72*c8dee2aaSAndroid Build Coastguard Workerthat computes the gradient color, samples from the image's texture, and then
73*c8dee2aaSAndroid Build Coastguard Workermultiplies the two together:
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_EvaluatingTwoShaders'></fiddle-embed-sk>
76*c8dee2aaSAndroid Build Coastguard Worker
77*c8dee2aaSAndroid Build Coastguard WorkerOf course, you can even invoke another runtime effect, allowing you to combine
78*c8dee2aaSAndroid Build Coastguard Workershader snippets dynamically:
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_EvaluatingNestedShaders'></fiddle-embed-sk>
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker---
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker## Coordinate Spaces
85*c8dee2aaSAndroid Build Coastguard Worker
86*c8dee2aaSAndroid Build Coastguard WorkerTo understand how coordinates work in SkSL, you first need to understand
87*c8dee2aaSAndroid Build Coastguard Worker[how they work in Skia](/docs/user/coordinates). If you're comfortable with
88*c8dee2aaSAndroid Build Coastguard WorkerSkia's coordinate spaces, then just remember that the coordinates supplied to
89*c8dee2aaSAndroid Build Coastguard Workeryour `main()` are **local** coordinates. They will be relative to the coordinate
90*c8dee2aaSAndroid Build Coastguard Workerspace of the `SkShader`. This will match the local space of the canvas and any
91*c8dee2aaSAndroid Build Coastguard Worker`localMatrix` transformations. Additionally, if the shader is invoked by
92*c8dee2aaSAndroid Build Coastguard Workeranother, that parent shader may modify them arbitrarily.
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard WorkerIn addition, the `SkShader` produced from an `SkImage` does not use normalized
95*c8dee2aaSAndroid Build Coastguard Workercoordinates (like a texture in GLSL). It uses `(0, 0)` in the upper-left corner,
96*c8dee2aaSAndroid Build Coastguard Workerand `(w, h)` in the bottom-right corner. Normally, this is exactly what you
97*c8dee2aaSAndroid Build Coastguard Workerwant. If you're evaluating an `SkImageShader` with coordinates based on the ones
98*c8dee2aaSAndroid Build Coastguard Workerpassed to you, the scale is correct. However, if you want to adjust those
99*c8dee2aaSAndroid Build Coastguard Workercoordinates (to do some kind of re-mapping of the image), remember that the
100*c8dee2aaSAndroid Build Coastguard Workercoordinates are scaled up to the dimensions of the image:
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_CoordinateSpaces'></fiddle-embed-sk>
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker---
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Worker## Color Spaces
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard WorkerApplications using Skia are usually [color managed](/docs/user/color). The color
109*c8dee2aaSAndroid Build Coastguard Workerspace of a surface (destination) determines the working color space for a draw.
110*c8dee2aaSAndroid Build Coastguard WorkerSource content (like shaders, including `SkImageShader`) also have color spaces.
111*c8dee2aaSAndroid Build Coastguard WorkerBy default, inputs to your SkSL shader will be transformed to the working color
112*c8dee2aaSAndroid Build Coastguard Workerspace. Some inputs require special care to get (or inhibit) this behavior, though.
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard WorkerFirst, let's see Skia's color management in action. Here, we're drawing a portion
115*c8dee2aaSAndroid Build Coastguard Workerof the mandrill image twice. The first time, we've drawn it normally, respecting
116*c8dee2aaSAndroid Build Coastguard Workerthe color space stored in the file (this happens to be the [sRGB](https://en.wikipedia.org/wiki/SRGB)
117*c8dee2aaSAndroid Build Coastguard Workercolor space. The second time, we've assigned the Rec. 2020 color space to the image.
118*c8dee2aaSAndroid Build Coastguard WorkerThis simply tells Skia to treat the image as if the colors stored are actually in
119*c8dee2aaSAndroid Build Coastguard Workerthat color space. Skia then transforms those values from Rec. 2020 to the
120*c8dee2aaSAndroid Build Coastguard Workerdestination surface's color space (sRGB). As a result, all of the colors look more
121*c8dee2aaSAndroid Build Coastguard Workervivid. More importantly, if the image really *were* in some other color space, or
122*c8dee2aaSAndroid Build Coastguard Workerif the destination surface were in some other color space, this automatic conversion
123*c8dee2aaSAndroid Build Coastguard Workeris desirable, because it ensures content looks consistently correct on any user's
124*c8dee2aaSAndroid Build Coastguard Workerscreen.
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_ColorSpaces'></fiddle-embed-sk>
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker### Uniforms
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard WorkerSkia and SkSL doesn't know if your `uniform` variables contain colors, so it won't
131*c8dee2aaSAndroid Build Coastguard Workerautomatically apply color conversion to them. In the below example, there are two
132*c8dee2aaSAndroid Build Coastguard Workeruniforms declared: `color` and `not_a_color`. The SkSL simply fades in one of the
133*c8dee2aaSAndroid Build Coastguard Workertwo uniform "colors" horizontally, choosing a different uniform for the top and
134*c8dee2aaSAndroid Build Coastguard Workerbottom half of the shader. The code passes the same values to both uniforms, four
135*c8dee2aaSAndroid Build Coastguard Workerfloating point values `{1,0,0,1}` that represent "red".
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard WorkerTo really see the effect of automatic uniform conversion, the fiddle draws to an
138*c8dee2aaSAndroid Build Coastguard Workeroffscreen surface in the [Rec. 2020](https://en.wikipedia.org/wiki/Rec._2020) color
139*c8dee2aaSAndroid Build Coastguard Workerspace. Rec. 2020 has a very _wide gamut_, which means that it can represent more
140*c8dee2aaSAndroid Build Coastguard Workervivid colors than the common default [sRGB](https://en.wikipedia.org/wiki/SRGB)
141*c8dee2aaSAndroid Build Coastguard Workercolor space. In particular, the purest red in sRGB is fairly dull compared to pure
142*c8dee2aaSAndroid Build Coastguard Workerred in Rec. 2020.
143*c8dee2aaSAndroid Build Coastguard Worker
144*c8dee2aaSAndroid Build Coastguard WorkerTo understand what happens in this fiddle, we'll explain the steps for the two
145*c8dee2aaSAndroid Build Coastguard Workerdifferent cases. For the top half, we use `not_a_color`. Skia and SkSL don't know
146*c8dee2aaSAndroid Build Coastguard Workerthat you intend to use this as a color, so the raw floating point values you supply
147*c8dee2aaSAndroid Build Coastguard Workerare fed directly to the SkSL shader. In other words - when the SkSL executes,
148*c8dee2aaSAndroid Build Coastguard Worker`not_a_color` will contain `{1,0,0,1}`, regardless of the surface's color space.
149*c8dee2aaSAndroid Build Coastguard WorkerThis produces the most vivid red possible in the destination's color space (which
150*c8dee2aaSAndroid Build Coastguard Workerends up looking like a very bright red in this case).
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard WorkerFor the bottom half, we have declared the uniform `color` with the special syntax
153*c8dee2aaSAndroid Build Coastguard Worker`layout(color)`. That tells SkSL that this variable will be used as a color.
154*c8dee2aaSAndroid Build Coastguard Worker`layout(color)` can only be used on uniform values that are `vec3` (i.e., RGB) or
155*c8dee2aaSAndroid Build Coastguard Worker`vec4` (i.e., RGBA). In either case, the colors you supply when providing uniform data
156*c8dee2aaSAndroid Build Coastguard Workershould be unpremultiplied sRGB colors. Those colors can include values outside of
157*c8dee2aaSAndroid Build Coastguard Workerthe range `[0,1]`, if you want to supply wide gamut colors. This is the same way
158*c8dee2aaSAndroid Build Coastguard Workerthat Skia accepts and stores colors on `SkPaint`. When the SkSL executes, Skia
159*c8dee2aaSAndroid Build Coastguard Workertransforms the uniform value to the working color space. In this case, that means
160*c8dee2aaSAndroid Build Coastguard Workerthat `color` (which starts out as sRGB red) is turned into whatever values represent
161*c8dee2aaSAndroid Build Coastguard Workerthat same color in the Rec. 2020 color space.
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard WorkerThe overall effect here is to make the correctly labeled uniform much duller, but
164*c8dee2aaSAndroid Build Coastguard Workerthat is actually what you want when working with uniform colors. By labeling uniform
165*c8dee2aaSAndroid Build Coastguard Workercolors this way, your source colors (that you place in uniforms) will represent the
166*c8dee2aaSAndroid Build Coastguard Workersame, consistent color regardless of the color space of the destination surface.
167*c8dee2aaSAndroid Build Coastguard Worker
168*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_Uniforms'></fiddle-embed-sk>
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker### Raw Image Shaders
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard WorkerAlthough most images contain colors that should be color managed, some images
173*c8dee2aaSAndroid Build Coastguard Workercontain data that isn't actually colors. This includes images storing normals,
174*c8dee2aaSAndroid Build Coastguard Workermaterial properties (e.g., roughness), heightmaps, or any other purely
175*c8dee2aaSAndroid Build Coastguard Workermathematical data that happens to be stored in an image. When using these kinds
176*c8dee2aaSAndroid Build Coastguard Workerof images in SkSL, you probably want to use a *raw* image shader, created with
177*c8dee2aaSAndroid Build Coastguard Worker`SkImage::makeRawShader`. These work like regular image shaders (including
178*c8dee2aaSAndroid Build Coastguard Workerfiltering and tiling), with a few major differences:
179*c8dee2aaSAndroid Build Coastguard Worker  - No color space transformation is ever applied (the color space of the image
180*c8dee2aaSAndroid Build Coastguard Worker    is ignored).
181*c8dee2aaSAndroid Build Coastguard Worker  - Images with an alpha type of kUnpremul are **not** automatically premultiplied.
182*c8dee2aaSAndroid Build Coastguard Worker  - Bicubic filtering is not supported. Requesting bicubic filtering when
183*c8dee2aaSAndroid Build Coastguard Worker    calling `makeRawShader` will return `nullptr`.
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard WorkerHere, we create an image holding a spherical normal map. Then we use that with
186*c8dee2aaSAndroid Build Coastguard Workera lighting shader to show what happens when rendering to a different color space.
187*c8dee2aaSAndroid Build Coastguard WorkerIf we use a regular image shader, the normals will be treated as colors, and
188*c8dee2aaSAndroid Build Coastguard Workertransformed to the working color space. This alters the normals, incorrectly.
189*c8dee2aaSAndroid Build Coastguard WorkerFor the final draw, we use a raw image shader, which returns the original
190*c8dee2aaSAndroid Build Coastguard Workernormals, ignoring the working color space.
191*c8dee2aaSAndroid Build Coastguard Worker
192*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_RawImageShaders'></fiddle-embed-sk>
193*c8dee2aaSAndroid Build Coastguard Worker
194*c8dee2aaSAndroid Build Coastguard Worker### Working In a Known Color Space
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard WorkerWithin an SkSL shader, you don't know what the working color space is. For many
197*c8dee2aaSAndroid Build Coastguard Workereffects, this is fine - evaluating image shaders, and doing simple color math
198*c8dee2aaSAndroid Build Coastguard Workeris usually going to give reasonable results (particularly if you know that
199*c8dee2aaSAndroid Build Coastguard Workerthe working color space for an application is always sRGB, for example). For
200*c8dee2aaSAndroid Build Coastguard Workercertain effects, though, it may be important to do some math in a fixed, known
201*c8dee2aaSAndroid Build Coastguard Workercolor space. The most common example is lighting -- to get physically accurate
202*c8dee2aaSAndroid Build Coastguard Workerlighting, math should be done in a _linear_ color space. To help with this,
203*c8dee2aaSAndroid Build Coastguard WorkerSkSL provides two intrinsic functions:
204*c8dee2aaSAndroid Build Coastguard Worker
205*c8dee2aaSAndroid Build Coastguard Worker```
206*c8dee2aaSAndroid Build Coastguard Workervec3 toLinearSrgb(vec3 color);
207*c8dee2aaSAndroid Build Coastguard Workervec3 fromLinearSrgb(vec3 color);
208*c8dee2aaSAndroid Build Coastguard Worker```
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard WorkerThese convert colors between the working color space and the linear sRGB color
211*c8dee2aaSAndroid Build Coastguard Workerspace. That space uses the sRGB color primaries (gamut), and a linear transfer
212*c8dee2aaSAndroid Build Coastguard Workerfunction. It represents values outside of the sRGB gamut using extended range
213*c8dee2aaSAndroid Build Coastguard Workervalues (below 0.0 and above 1.0). This corresponds to Android's
214*c8dee2aaSAndroid Build Coastguard Worker[LINEAR_EXTENDED_SRGB](https://developer.android.com/reference/android/graphics/ColorSpace.Named.html#LINEAR_EXTENDED_SRGB)
215*c8dee2aaSAndroid Build Coastguard Workeror Apple's
216*c8dee2aaSAndroid Build Coastguard Worker[extendedLinearSRGB](https://developer.apple.com/documentation/coregraphics/cgcolorspace/1690961-extendedlinearsrgb),
217*c8dee2aaSAndroid Build Coastguard Workerfor example.
218*c8dee2aaSAndroid Build Coastguard Worker
219*c8dee2aaSAndroid Build Coastguard WorkerHere's an example showing a sphere, with lighting math being done in the default
220*c8dee2aaSAndroid Build Coastguard Workerworking space (sRGB), and again with the math done in a linear space:
221*c8dee2aaSAndroid Build Coastguard Worker
222*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_LinearSRGB'></fiddle-embed-sk>
223*c8dee2aaSAndroid Build Coastguard Worker
224*c8dee2aaSAndroid Build Coastguard Worker---
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker## Premultiplied Alpha
227*c8dee2aaSAndroid Build Coastguard Worker
228*c8dee2aaSAndroid Build Coastguard WorkerWhen dealing with transparent colors, there are two (common)
229*c8dee2aaSAndroid Build Coastguard Worker[possible representations](https://en.wikipedia.org/wiki/Alpha_compositing#Straight_versus_premultiplied).
230*c8dee2aaSAndroid Build Coastguard WorkerSkia calls these _unpremultiplied_ (what Wikipedia calls _straight_), and
231*c8dee2aaSAndroid Build Coastguard Worker_premultiplied_. In the Skia pipeline, every `SkShader` returns premultiplied
232*c8dee2aaSAndroid Build Coastguard Workercolors.
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard WorkerIf you're familiar with OpenGL blending, you can think of it in terms of the
235*c8dee2aaSAndroid Build Coastguard Workerblend equation. For common alpha blending (called
236*c8dee2aaSAndroid Build Coastguard Worker[source-over](https://developer.android.com/reference/android/graphics/PorterDuff.Mode#SRC_OVER)),
237*c8dee2aaSAndroid Build Coastguard Workeryou would normally configure your blend function as
238*c8dee2aaSAndroid Build Coastguard Worker`(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)`. Skia defines source-over blending as
239*c8dee2aaSAndroid Build Coastguard Workerif the blend function were `(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)`.
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard WorkerSkia's use of premultiplied alpha implies:
242*c8dee2aaSAndroid Build Coastguard Worker
243*c8dee2aaSAndroid Build Coastguard Worker- If you start with an unpremultiplied `SkImage` (like a PNG), turn that into an
244*c8dee2aaSAndroid Build Coastguard Worker  `SkImageShader`, and evaluate that shader... the resulting colors will be
245*c8dee2aaSAndroid Build Coastguard Worker  `[R*A, G*A, B*A, A]`, **not** `[R, G, B, A]`.
246*c8dee2aaSAndroid Build Coastguard Worker- If your SkSL will return transparent colors, it must be sure to multiply the
247*c8dee2aaSAndroid Build Coastguard Worker  `RGB` by `A`.
248*c8dee2aaSAndroid Build Coastguard Worker- For more complex shaders, you must understand which of your colors are
249*c8dee2aaSAndroid Build Coastguard Worker  premultiplied vs. unpremultiplied. Many operations don't make sense if you mix
250*c8dee2aaSAndroid Build Coastguard Worker  both kinds of color together.
251*c8dee2aaSAndroid Build Coastguard Worker
252*c8dee2aaSAndroid Build Coastguard WorkerThe image below demonstrates this: properly premultiplied colors produce a smooth
253*c8dee2aaSAndroid Build Coastguard Workergradient as alpha decreases. Unpremultipled colors cause the gradient to display
254*c8dee2aaSAndroid Build Coastguard Workerincorrectly, becoming too bright and shifting hue as the alpha changes.
255*c8dee2aaSAndroid Build Coastguard Worker
256*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_PremultipliedAlpha'></fiddle-embed-sk>
257*c8dee2aaSAndroid Build Coastguard Worker
258*c8dee2aaSAndroid Build Coastguard Worker---
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Worker## Minified SkSL
261*c8dee2aaSAndroid Build Coastguard Worker
262*c8dee2aaSAndroid Build Coastguard WorkerSkia includes a minifier tool which can automatically reduce the size of your Runtime Effect
263*c8dee2aaSAndroid Build Coastguard Workeror SkMesh code. The tool eliminates whitespace and comments, shortens function and variable names,
264*c8dee2aaSAndroid Build Coastguard Workerand deletes unreferenced code.
265*c8dee2aaSAndroid Build Coastguard Worker
266*c8dee2aaSAndroid Build Coastguard WorkerAs an example, here is the previous demo in its minified form. The shader code is reduced to
267*c8dee2aaSAndroid Build Coastguard Workerapproximately half of its original size, while displaying the exact same result.
268*c8dee2aaSAndroid Build Coastguard Worker
269*c8dee2aaSAndroid Build Coastguard Worker<fiddle-embed-sk name='@SkSL_MinifiedSkSL'></fiddle-embed-sk>
270*c8dee2aaSAndroid Build Coastguard Worker
271*c8dee2aaSAndroid Build Coastguard WorkerTo enable this tool, add `skia_compile_modules = true` to your gn argument list. (At the command
272*c8dee2aaSAndroid Build Coastguard Workerline, type `gn args out/yourbuild` to access the arguments, or edit the file `out/yourbuild/args.gn`
273*c8dee2aaSAndroid Build Coastguard Workerdirectly.) Use `ninja` to compile Skia once more, and you will now have a new utility called
274*c8dee2aaSAndroid Build Coastguard Worker`sksl-minify` in the output directory.
275*c8dee2aaSAndroid Build Coastguard Worker
276*c8dee2aaSAndroid Build Coastguard WorkerWhen minifying a mesh program, you must supply `struct Varyings` and `struct Attributes` which
277*c8dee2aaSAndroid Build Coastguard Workercorrespond to the SkMeshSpecification. These structs will be eliminated from the minified program
278*c8dee2aaSAndroid Build Coastguard Workerfor convenience.
279*c8dee2aaSAndroid Build Coastguard Worker
280*c8dee2aaSAndroid Build Coastguard Worker`sksl-minify` takes the following command line arguments:
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard Worker- An output path, e.g. `MyShader.minified.sksl`
283*c8dee2aaSAndroid Build Coastguard Worker- An input path, e.g. `MyShader.sksl`
284*c8dee2aaSAndroid Build Coastguard Worker- (Optional) Pass `--stringify` to wrap the minified SkSL text in a quoted C++ string.
285*c8dee2aaSAndroid Build Coastguard Worker  By default, the output file will contain plain SkSL. The minified shader string in the example
286*c8dee2aaSAndroid Build Coastguard Worker  code above was created with --stringify.
287*c8dee2aaSAndroid Build Coastguard Worker- (Optional) Pass `--shader`, `--colorfilter`, `--blender`, `--meshfrag` or `--meshvert` to set
288*c8dee2aaSAndroid Build Coastguard Worker  the program kind. The default value is `--shader`.
289