skia2/gm/lighting.cpp

195 lines
7.8 KiB
C++
Raw Normal View History

/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/effects/SkImageFilters.h"
#include "tools/ToolUtils.h"
#include "tools/timer/TimeUtils.h"
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
#define WIDTH 660
Implement approx-match support in image filter saveLayer() offscreen. Currently, the GPU-side image filter implementation creates exact-match textures for the offscreen backing stores for saveLayer(). This is because several filters have GPU implementations which depend on the texture coordinates being 0..1. The fix is three-fold: 1) Store the actual requested size in the SkGpuDevice, so that when wrapping it in an SkBitmap for passing to filterImage(), we can give it the original size. 2) Fix the filters (SkMagnifierImageFilter, SkLightingImageFilter, SkMatrixConvolutionImageFilter, SkMatrixImageFilter) whose GPU implementation depends on 0..1 texture coordinates. 3) Remove the exception for GPU-side image filters in SkCanvas::internalSaveLayer(). For the lighting filters, there were two bugs which were cancelling each other out: the sobel filter matrix was being computed upside down, but then we'd negate the resulting normal. This worked fine in the exact-match case, but in the approx-match case we'd sample garbage along the edge pixels. Also, we never implemented the edge pixels according to spec in the GPU case. It requires a different fragment shader for each edge of the nine-patch, which meant we couldn't use asFragmentProcessor(), and had to implement the drawing via a filterImageGPU() override. In order to avoid polluting the public API, I inserted a new base class, SkLightingImageFilterInternal above Sk[Diffuse|Specular]LightingImageFilter to handle the implementation. For the SkMatrixConvolutionImageFilter, it seems the GLSL clamp() function occasionally returns values outside the clamped range, resulting in access of garbage texels even in GL_NEAREST. The fix here is to clamp to a rect inset by half a texel. There was also a bug in the unpremultiply step when fConvolveAlpha is false. For SkMatrixImageFilter, the fix was to make the generic draw path be more careful about when to use texture domain. If the bitmap already has a texture, use texture domain if the srcRect is smaller than the entire texture (not the entire bitmap). N.B.: this change will cause some minor pixel diffs in the GPU results of the following GMs (and possibly more): matriximagefilter, matrixconvolution, imagefiltersscaled, lighting, imagemagnifier, filterfastbounds, complexclip_aa_Layer_invert, complexclip_aa_layer, complexclip_bw_layer_invert, complexclip_bw_layer. BUG=skia:3532 Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9 Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641 Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
#define HEIGHT 660
namespace skiagm {
class ImageLightingGM : public GM {
public:
ImageLightingGM()
: fAzimuth(SkIntToScalar(kStartAzimuth)) {
this->setBGColor(0xFF000000);
}
protected:
SkString onShortName() override {
return SkString("lighting");
}
SkISize onISize() override {
return SkISize::Make(WIDTH, HEIGHT);
}
void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
canvas->save();
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
canvas->clipIRect(fBitmap.bounds());
canvas->drawImage(fBitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
canvas->restore();
}
void onOnceBeforeDraw() override {
fBitmap = ToolUtils::create_string_bitmap(100, 100, 0xFFFFFFFF, 20, 70, 96, "e");
}
void onDraw(SkCanvas* canvas) override {
canvas->clear(0xFF101010);
SkPaint checkPaint;
checkPaint.setColor(0xFF202020);
for (int y = 0; y < HEIGHT; y += 16) {
for (int x = 0; x < WIDTH; x += 16) {
canvas->save();
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), checkPaint);
canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), checkPaint);
canvas->restore();
}
}
SkScalar sinAzimuth = SkScalarSin(SkDegreesToRadians(fAzimuth)),
cosAzimuth = SkScalarCos(SkDegreesToRadians(fAzimuth));
SkPoint3 spotTarget = SkPoint3::Make(SkIntToScalar(40), SkIntToScalar(40), 0);
SkPoint3 spotLocation = SkPoint3::Make(spotTarget.fX + 70.7214f * cosAzimuth,
spotTarget.fY + 70.7214f * sinAzimuth,
spotTarget.fZ + SkIntToScalar(20));
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
SkScalar spotExponent1 = SK_Scalar1;
SkScalar spotExponent10 = SkIntToScalar(10);
SkScalar cutoffAngleSmall = SkIntToScalar(15);
SkScalar cutoffAngleNone = SkIntToScalar(180);
SkPoint3 pointLocation = SkPoint3::Make(spotTarget.fX + 50 * cosAzimuth,
spotTarget.fY + 50 * sinAzimuth,
SkIntToScalar(10));
SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5));
SkPoint3 distantDirection = SkPoint3::Make(cosAzimuth * SkScalarCos(elevationRad),
sinAzimuth * SkScalarCos(elevationRad),
SkScalarSin(elevationRad));
SkScalar kd = SkIntToScalar(2);
SkScalar ks = SkIntToScalar(1);
SkScalar shininess = SkIntToScalar(8);
SkScalar surfaceScale = SkIntToScalar(1);
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
SkScalar surfaceScaleSmall = 0.1f;
SkColor greenYellow = SkColorSetARGB(255, 173, 255, 47);
SkPaint paint;
SkIRect cropRect = SkIRect::MakeXYWH(20, 10, 60, 65);
SkIRect fullSizeCropRect = SkIRect::MakeXYWH(0, 0, 100, 100);
sk_sp<SkImageFilter> noopCropped(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
int y = 0;
Implement approx-match support in image filter saveLayer() offscreen. Currently, the GPU-side image filter implementation creates exact-match textures for the offscreen backing stores for saveLayer(). This is because several filters have GPU implementations which depend on the texture coordinates being 0..1. The fix is three-fold: 1) Store the actual requested size in the SkGpuDevice, so that when wrapping it in an SkBitmap for passing to filterImage(), we can give it the original size. 2) Fix the filters (SkMagnifierImageFilter, SkLightingImageFilter, SkMatrixConvolutionImageFilter, SkMatrixImageFilter) whose GPU implementation depends on 0..1 texture coordinates. 3) Remove the exception for GPU-side image filters in SkCanvas::internalSaveLayer(). For the lighting filters, there were two bugs which were cancelling each other out: the sobel filter matrix was being computed upside down, but then we'd negate the resulting normal. This worked fine in the exact-match case, but in the approx-match case we'd sample garbage along the edge pixels. Also, we never implemented the edge pixels according to spec in the GPU case. It requires a different fragment shader for each edge of the nine-patch, which meant we couldn't use asFragmentProcessor(), and had to implement the drawing via a filterImageGPU() override. In order to avoid polluting the public API, I inserted a new base class, SkLightingImageFilterInternal above Sk[Diffuse|Specular]LightingImageFilter to handle the implementation. For the SkMatrixConvolutionImageFilter, it seems the GLSL clamp() function occasionally returns values outside the clamped range, resulting in access of garbage texels even in GL_NEAREST. The fix here is to clamp to a rect inset by half a texel. There was also a bug in the unpremultiply step when fConvolveAlpha is false. For SkMatrixImageFilter, the fix was to make the generic draw path be more careful about when to use texture domain. If the bitmap already has a texture, use texture domain if the srcRect is smaller than the entire texture (not the entire bitmap). N.B.: this change will cause some minor pixel diffs in the GPU results of the following GMs (and possibly more): matriximagefilter, matrixconvolution, imagefiltersscaled, lighting, imagemagnifier, filterfastbounds, complexclip_aa_Layer_invert, complexclip_aa_layer, complexclip_bw_layer_invert, complexclip_bw_layer. BUG=skia:3532 Committed: https://skia.googlesource.com/skia/+/b97dafefe63ea0a1bbce8e8b209f4920983fb8b9 Committed: https://skia.googlesource.com/skia/+/f5f8518fe0bbd2703e4ffc1b11ad7b4312ff7641 Committed: https://skia.googlesource.com/skia/+/46112cf2a7c7307f1c9eebb5f881cbda15aa460c Review URL: https://codereview.chromium.org/1034733002
2015-04-02 11:54:56 +00:00
for (int i = 0; i < 3; i++) {
const SkIRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : nullptr;
sk_sp<SkImageFilter> input = (i == 2) ? noopCropped : nullptr;
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
// Basic point, distant and spot lights with diffuse lighting
paint.setImageFilter(SkImageFilters::PointLitDiffuse(
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
pointLocation, SK_ColorWHITE, surfaceScale, kd, input, cr));
drawClippedBitmap(canvas, paint, 0, y);
paint.setImageFilter(SkImageFilters::DistantLitDiffuse(
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
distantDirection, SK_ColorWHITE, surfaceScale, kd, input, cr));
drawClippedBitmap(canvas, paint, 110, y);
paint.setImageFilter(SkImageFilters::SpotLitDiffuse(
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE,
surfaceScale, kd, input, cr));
drawClippedBitmap(canvas, paint, 220, y);
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
// Spot light with no angle cutoff
paint.setImageFilter(SkImageFilters::SpotLitDiffuse(
spotLocation, spotTarget, spotExponent10, cutoffAngleNone, SK_ColorWHITE,
surfaceScale, kd, input, cr));
drawClippedBitmap(canvas, paint, 330, y);
// Spot light with falloff exponent
paint.setImageFilter(SkImageFilters::SpotLitDiffuse(
spotLocation, spotTarget, spotExponent1, cutoffAngleNone, SK_ColorWHITE,
surfaceScaleSmall, kd, input, cr));
drawClippedBitmap(canvas, paint, 440, y);
// Large constant to show oversaturation
paint.setImageFilter(SkImageFilters::DistantLitDiffuse(
distantDirection, greenYellow, surfaceScale, 4.f * kd, input, cr));
drawClippedBitmap(canvas, paint, 550, y);
y += 110;
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
// Basic point, distant and spot lights with specular lighting
paint.setImageFilter(SkImageFilters::PointLitSpecular(
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
pointLocation, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr));
drawClippedBitmap(canvas, paint, 0, y);
paint.setImageFilter(SkImageFilters::DistantLitSpecular(
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
distantDirection, SK_ColorWHITE, surfaceScale, ks, shininess, input, cr));
drawClippedBitmap(canvas, paint, 110, y);
paint.setImageFilter(SkImageFilters::SpotLitSpecular(
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
spotLocation, spotTarget, spotExponent1, cutoffAngleSmall, SK_ColorWHITE,
surfaceScale, ks, shininess, input, cr));
drawClippedBitmap(canvas, paint, 220, y);
Fix lighting image filters 1. Removes clamping of spotlight's specular exponent, which is not the specified behavior of feSpotLight in SVG. (note: we never clamped a specular lighting effect's specular exponent/shininess parameter, although SVG 1.1 does clamp that; that is the client's responsibility). 2. Fixes a bug in the GPU implementation of scale factor for spot lights. 3. Saturate computed lighting color after multiplying with color scale, instead of just saturating the color scale (allows high intensity lights to saturate to white which is more reasonable approximation of an HDR effect stored in an LDR color). Note: fixes 1 and 2 were originally addressed in https://bugs.chromium.org/p/chromium/issues/detail?id=472849 but the change was reverted for layout failure reasons and it was never relanded after rebasing. Note2: most of the layout test rebaselines necessary for chrome are minor and related to fix 2. The exception is svg/dynamic-updates/SVGFESpecularLightingElement-dom-kernelUnitLength-attr.html which is the result of fix 3. It took a little digging, but I believe that fix 3 actually makes that generated SVG more correct (it's original expected image was "wrong"). In that test, it has a specular constant of 4 (which is a multiplier) and a shininess of 1 (which makes it practically a "diffuse" specular). So basically we are multiplying the greenYellow color by 4 for most of the image that has a normal pointing out of the screen. Firefox renders a similarly yellow oversaturated appearance instead of clamping to the base greenYellow. Reading the feSpecularLighting spec, there is no saturation that is specified where it had been performed before this change. Instead, all that is mentioned is that the results of a given filter have to be pinned to the color channel range (e.g. the last step). Bug: skia:11007, skia:11057, skia:11153 Change-Id: I82e4a6f1742fecea59816fda75eb931c2a51d3e1 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355496 Reviewed-by: Fredrik Söderquist <fs@opera.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Tyler Denniston <tdenniston@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-01-21 23:43:58 +00:00
// Spot light with no angle cutoff
paint.setImageFilter(SkImageFilters::SpotLitSpecular(
spotLocation, spotTarget, spotExponent10, cutoffAngleNone, SK_ColorWHITE,
surfaceScale, ks, shininess, input, cr));
drawClippedBitmap(canvas, paint, 330, y);
// Spot light with falloff exponent
paint.setImageFilter(SkImageFilters::SpotLitSpecular(
spotLocation, spotTarget, spotExponent1, cutoffAngleNone, SK_ColorWHITE,
surfaceScaleSmall, ks, shininess, input, cr));
drawClippedBitmap(canvas, paint, 440, y);
// Large constant to show oversaturation
paint.setImageFilter(SkImageFilters::DistantLitSpecular(
distantDirection, greenYellow, surfaceScale, 4.f * ks, shininess, input, cr));
drawClippedBitmap(canvas, paint, 550, y);
y += 110;
}
}
bool onAnimate(double nanos) override {
constexpr SkScalar kDesiredDurationSecs = 15.0f;
fAzimuth = kStartAzimuth + TimeUtils::Scaled(1e-9 * nanos, 360.0f/kDesiredDurationSecs, 360.0f);
return true;
}
private:
static constexpr int kStartAzimuth = 225;
SkBitmap fBitmap;
SkScalar fAzimuth;
using INHERITED = GM;
};
//////////////////////////////////////////////////////////////////////////////
DEF_GM(return new ImageLightingGM;)
} // namespace skiagm