45class InvalidationController;
72static constexpr char gSphereSkSL[] =
73 "uniform shader child;"
75 "uniform half3x3 rot_matrix;"
76 "uniform half2 child_scale;"
77 "uniform half side_select;"
82 "half3 to_sphere(half3 EYE) {"
83 "half eye_z2 = EYE.z*EYE.z;"
85 "half a = dot(EYE, EYE),"
88 "t = (-b + side_select*sqrt(b*b - 4*a*c))/(2*a);"
90 "return half3(0, 0, -EYE.z) + EYE*t;"
93 "half4 main(float2 xy) {"
94 "half3 EYE = half3(xy, -5.5),"
98 "half kRPI = 1/3.1415927;"
101 "0.5 + kRPI * 0.5 * atan(RN.x, RN.z),"
102 "0.5 + kRPI * asin(RN.y)"
105 "return apply_light(EYE, N, child.eval(UV*child_scale));"
123static constexpr char gBasicLightSkSL[] =
124 "uniform half l_coeff_ambient;"
126 "half4 apply_light(half3 EYE, half3 N, half4 c) {"
127 "c.rgb *= l_coeff_ambient;"
132static constexpr char gFancyLightSkSL[] =
133 "uniform half3 l_vec;"
134 "uniform half3 l_color;"
135 "uniform half l_coeff_ambient;"
136 "uniform half l_coeff_diffuse;"
137 "uniform half l_coeff_specular;"
138 "uniform half l_specular_exp;"
140 "half4 apply_light(half3 EYE, half3 N, half4 c) {"
141 "half3 LR = reflect(-l_vec*side_select, N);"
142 "half s_base = max(dot(normalize(EYE), LR), 0),"
144 "a = l_coeff_ambient,"
145 "d = l_coeff_diffuse * max(dot(l_vec, N), 0),"
146 "s = l_coeff_specular * saturate(pow(s_base, l_specular_exp));"
148 "c.rgb = (a + d*l_color)*c.rgb + s*l_color*c.a;"
181 , fChildSize(child_size) {}
183 enum class RenderSide {
203 if (!fContentShader || this->hasChildrenInval()) {
204 const auto& child = this->children()[0];
215 return fContentShader;
219 const auto has_fancy_light =
220 fLightVec.
length() > 0 && (fDiffuseLight > 0 || fSpecularLight > 0);
223 ? sphere_fancylight_effect()
224 : sphere_basiclight_effect());
226 builder.child (
"child") = this->contentShader();
227 builder.uniform(
"child_scale") = fChildSize;
228 builder.uniform(
"side_select") = selector;
229 builder.uniform(
"rot_matrix") = std::array<float,9>{
230 fRot.
rc(0,0), fRot.
rc(0,1), fRot.
rc(0,2),
231 fRot.
rc(1,0), fRot.
rc(1,1), fRot.
rc(1,2),
232 fRot.
rc(2,0), fRot.
rc(2,1), fRot.
rc(2,2),
235 builder.uniform(
"l_coeff_ambient") = fAmbientLight;
237 if (has_fancy_light) {
238 builder.uniform(
"l_vec") = fLightVec * -selector;
239 builder.uniform(
"l_color") = fLightColor;
240 builder.uniform(
"l_coeff_diffuse") = fDiffuseLight;
241 builder.uniform(
"l_coeff_specular") = fSpecularLight;
242 builder.uniform(
"l_specular_exp") = fSpecularExp;
248 return builder.makeShader(&lm);
252 fSphereShader.
reset();
253 if (fSide != RenderSide::kOutside) {
254 fSphereShader = this->buildEffectShader(1);
256 if (fSide != RenderSide::kInside) {
257 auto outside = this->buildEffectShader(-1);
258 fSphereShader = fSphereShader
260 std::move(fSphereShader),
262 :
std::move(outside);
267 fCenter.
fY - fRadius,
268 fCenter.
fX + fRadius,
269 fCenter.
fY + fRadius);
272 void onRender(
SkCanvas* canvas,
const RenderContext* ctx)
const override {
281 canvas->
drawCircle(fCenter, fRadius, sphere_paint);
284 const RenderNode* onNodeAt(
const SkPoint&)
const override {
return nullptr; }
296 RenderSide fSide = RenderSide::kFull;
298 SkV3 fLightVec = {0,0,1},
299 fLightColor = {1,1,1};
300 float fAmbientLight = 1,
308class SphereAdapter final :
public DiscardableAdapterBase<SphereAdapter, SphereNode> {
311 const AnimationBuilder* abuilder,
327 kLightIntensity_Index = 10,
328 kLightColor_Index = 11,
329 kLightHeight_Index = 12,
330 kLightDirection_Index = 13,
335 kSpecular_Index = 18,
336 kRoughness_Index = 19,
339 EffectBinder(jprops, *abuilder,
this)
340 .bind( kOffset_Index, fOffset )
341 .bind( kRadius_Index, fRadius )
342 .bind( kRotX_Index, fRotX )
343 .bind( kRotY_Index, fRotY )
344 .bind( kRotZ_Index, fRotZ )
345 .bind(kRotOrder_Index, fRotOrder)
346 .bind( kRender_Index, fRender )
348 .bind(kLightIntensity_Index, fLightIntensity)
349 .bind( kLightColor_Index, fLightColor )
350 .bind( kLightHeight_Index, fLightHeight )
351 .bind(kLightDirection_Index, fLightDirection)
352 .bind( kAmbient_Index, fAmbient )
353 .bind( kDiffuse_Index, fDiffuse )
354 .bind( kSpecular_Index, fSpecular )
355 .bind( kRoughness_Index, fRoughness );
359 void onSync()
override {
362 case 1:
return SphereNode::RenderSide::kFull;
363 case 2:
return SphereNode::RenderSide::kOutside;
365 default:
return SphereNode::RenderSide::kInside;
377 case 1:
return rx * ry * rz;
378 case 2:
return rx * rz * ry;
379 case 3:
return ry * rx * rz;
380 case 4:
return ry * rz * rx;
381 case 5:
return rz * rx * ry;
383 default:
return rz * ry * rx;
388 const auto light_vec = [](
float height,
float direction) {
391 x = std::cos(direction) * r,
392 y = std::sin(direction) * r;
397 const auto& sph = this->node();
399 sph->setCenter({fOffset.x, fOffset.y});
400 sph->setRadius(fRadius);
401 sph->setSide(
side(fRender));
402 sph->setRotation(rotation(fRotOrder, fRotX, fRotY, fRotZ));
404 sph->setAmbientLight (
SkTPin(fAmbient * 0.01f, 0.0f, 2.0f));
406 const auto intensity =
SkTPin(fLightIntensity * 0.01f, 0.0f, 10.0f);
407 sph->setDiffuseLight (
SkTPin(fDiffuse * 0.01f, 0.0f, 1.0f) * intensity);
408 sph->setSpecularLight(
SkTPin(fSpecular* 0.01f, 0.0f, 1.0f) * intensity);
410 sph->setLightVec(light_vec(
411 SkTPin(fLightHeight * 0.01f, -1.0f, 1.0f),
415 const auto lc =
static_cast<SkColor4f>(fLightColor);
416 sph->setLightColor({lc.fR, lc.fG, lc.fB});
418 sph->setSpecularExp(1/
SkTPin(fRoughness, 0.001f, 0.5f));
429 ColorValue fLightColor;
438 using INHERITED = DiscardableAdapterBase<SphereAdapter, SphereNode>;
445 auto sphere = sk_make_sp<SphereNode>(std::move(layer), fLayerSize);
@ kSrcOver
r = s + (1-sa)*d
static int side(double x)
#define INHERITED(method,...)
sk_sp< T > sk_ref_sp(T *obj)
#define SG_ATTRIBUTE(attr_name, attr_type, attr_container)
#define SkDegreesToRadians(degrees)
#define SkScalarRoundToInt(x)
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
SkScalar rc(int r, int c) const
static SkM44 Rotate(SkV3 axis, SkScalar radians)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
static const SkMatrix & I()
void setAntiAlias(bool aa)
void setShader(sk_sp< SkShader > shader)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, SkFilterMode mode, const SkMatrix *localMatrix, const SkRect *tileRect) const
static Result MakeForShader(SkString sksl, const Options &)
void reset(T *ptr=nullptr)
void attachDiscardableAdapter(sk_sp< T > adapter) const
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
static constexpr SkRect MakeSize(const SkSize &size)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)