blob: 7e2dedddf95512c36aeabc0768621a5d029ea47d [file] [log] [blame]
Robert Phillipsa8cdbd72018-07-17 12:30:40 -04001
2/*
3 * Copyright 2015 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#ifndef SkLights_DEFINED
10#define SkLights_DEFINED
11
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkPoint3.h"
13#include "include/core/SkRefCnt.h"
14#include "include/private/SkTArray.h"
Robert Phillipsa8cdbd72018-07-17 12:30:40 -040015
Robert Phillipsa8cdbd72018-07-17 12:30:40 -040016class SkReadBuffer;
17class SkWriteBuffer;
18
19/** \class SkLights
20 SkLights encapsulates a set of directional, point and ambient lights for use with the
21 SkLightingShader.
22*/
Brian Osmanb1b14522019-11-18 15:28:34 -050023class SkLights : public SkRefCnt {
Robert Phillipsa8cdbd72018-07-17 12:30:40 -040024public:
25 class Light {
26 public:
27 enum LightType {
28 kDirectional_LightType,
29 kPoint_LightType
30 };
31
32 Light(const Light& other)
33 : fType(other.fType)
34 , fColor(other.fColor)
35 , fDirOrPos(other.fDirOrPos)
36 , fIntensity(other.fIntensity) {}
37
38 Light(Light&& other)
39 : fType(other.fType)
40 , fColor(other.fColor)
41 , fDirOrPos(other.fDirOrPos)
42 , fIntensity(other.fIntensity) {}
43
44 static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir) {
45 Light light(kDirectional_LightType, color, dir, 0.0f);
46 if (!light.fDirOrPos.normalize()) {
47 light.fDirOrPos.set(0.0f, 0.0f, 1.0f);
48 }
49 return light;
50 }
51
52 static Light MakePoint(const SkColor3f& color, const SkPoint3& pos, SkScalar intensity) {
53 return Light(kPoint_LightType, color, pos, intensity);
54 }
55
56 LightType type() const { return fType; }
57 const SkColor3f& color() const { return fColor; }
58 const SkVector3& dir() const {
59 SkASSERT(kDirectional_LightType == fType);
60 return fDirOrPos;
61 }
62 const SkPoint3& pos() const {
63 SkASSERT(kPoint_LightType == fType);
64 return fDirOrPos;
65 }
66 SkScalar intensity() const {
67 SkASSERT(kPoint_LightType == fType);
68 return fIntensity;
69 }
70
71 Light& operator=(const Light& other) {
72 if (this == &other) {
73 return *this;
74 }
75
76 fType = other.fType;
77 fColor = other.fColor;
78 fDirOrPos = other.fDirOrPos;
79 fIntensity = other.fIntensity;
80 return *this;
81 }
82
83 bool operator==(const Light& other) {
84 return (fType == other.fType) &&
85 (fColor == other.fColor) &&
86 (fDirOrPos == other.fDirOrPos) &&
87 (fIntensity == other.fIntensity);
88 }
89
90 bool operator!=(const Light& other) { return !(this->operator==(other)); }
91
92 private:
93 friend class SkLights;
94
95 Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos,
96 SkScalar intensity)
97 : fType(type)
98 , fColor(color)
99 , fDirOrPos(dirOrPos)
100 , fIntensity(intensity) {}
101
102 LightType fType;
103 SkColor3f fColor; // linear (unpremul) color. Range is 0..1 in each channel.
104
105 SkVector3 fDirOrPos; // For directional lights, holds the direction towards the
106 // light (+Z is out of the screen).
107 // If degenerate, it will be replaced with (0, 0, 1).
108 // For point lights, holds location of point light
109
110 SkScalar fIntensity; // For point lights, dictates the light intensity.
111 // Simply a multiplier to the final light output value.
112 };
113
114 class Builder {
115 public:
116 Builder() : fLights(new SkLights) {}
117
118 void add(const Light& light) {
119 if (fLights) {
120 fLights->fLights.push_back(light);
121 }
122 }
123
124 void add(Light&& light) {
125 if (fLights) {
126 fLights->fLights.push_back(std::move(light));
127 }
128 }
129
130 void setAmbientLightColor(const SkColor3f& color) {
131 if (fLights) {
132 fLights->fAmbientLightColor = color;
133 }
134 }
135
136 sk_sp<SkLights> finish() {
137 return std::move(fLights);
138 }
139
140 private:
141 sk_sp<SkLights> fLights;
142 };
143
144 /** Returns number of lights not including the ambient light.
145
146 @return number of lights not including the ambient light
147 */
148 int numLights() const { return fLights.count(); }
149
150 /** Returns the index-th light.
151
152 @param index the index of the desired light
153 @return the index-th light
154 */
155 const Light& light(int index) const { return fLights[index]; }
156
157 /** Returns the ambient light.
158
159 @return the ambient light
160 */
161 const SkColor3f& ambientLightColor() const {
162 return fAmbientLightColor;
163 }
164
165 /**
166 * Recreate an SkLights object that was serialized into a buffer.
167 *
168 * @param SkReadBuffer Serialized blob data.
169 * @return A new SkLights representing the serialized data, or NULL if the buffer is
170 * invalid.
171 */
172 static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf);
173
174 /**
175 * Serialize to a buffer.
176 *
177 * @param buffer the write buffer to write out to
178 */
179 void flatten(SkWriteBuffer& buf) const;
180
181private:
182 friend class SkLightingShaderImpl;
183
184 SkLights() : fAmbientLightColor(SkColor3f::Make(0.0f, 0.0f, 0.0f)) {}
185
Robert Phillipsa8cdbd72018-07-17 12:30:40 -0400186 SkTArray<Light> fLights;
187 SkColor3f fAmbientLightColor;
188
189 typedef SkRefCnt INHERITED;
190};
191
192#endif