Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkNormalSource_DEFINED
      9 #define SkNormalSource_DEFINED
     10 
     11 #include "SkFlattenable.h"
     12 #include "SkShader.h"
     13 
     14 class SkMatrix;
     15 struct SkPoint3;
     16 
     17 #if SK_SUPPORT_GPU
     18 class GrFragmentProcessor;
     19 #endif
     20 
     21 /** Abstract class that generates or reads in normals for use by SkLightingShader.
     22 */
     23 class SK_API SkNormalSource : public SkFlattenable {
     24 public:
     25     virtual ~SkNormalSource() override;
     26 
     27 #if SK_SUPPORT_GPU
     28     /** Returns a fragment processor that takes no input and outputs a normal (already rotated)
     29         as its output color. To be used as a child fragment processor.
     30     */
     31     virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(const SkShader::AsFPArgs&) const = 0;
     32 #endif
     33 
     34     class Provider {
     35     public:
     36         virtual ~Provider() {}
     37 
     38         /** Called for each span of the object being drawn on the CPU. Your subclass should set
     39             the appropriate normals that correspond to the specified device coordinates.
     40         */
     41         virtual void fillScanLine(int x, int y, SkPoint3 output[], int count) const = 0;
     42     };
     43 
     44     /** Returns an instance of 'Provider' that provides normals for the CPU pipeline. The
     45         necessary data will be initialized in place at 'storage'.
     46     */
     47     virtual Provider* asProvider(const SkShader::ContextRec&, SkArenaAlloc*) const = 0;
     48 
     49     /** Returns a normal source that provides normals sourced from the the normal map argument.
     50 
     51         @param  map  a shader that outputs the normal map
     52         @param  ctm  the current canvas' total matrix, used to rotate normals when necessary.
     53 
     54         nullptr will be returned if 'map' is null
     55 
     56         The normal map is currently assumed to be an 8888 image where the normal at a texel
     57         is retrieved by:
     58             N.x = R-127;
     59             N.y = G-127;
     60             N.z = B-127;
     61             N.normalize();
     62         The +Z axis is thus encoded in RGB as (127, 127, 255) while the -Z axis is
     63         (127, 127, 0).
     64     */
     65     static sk_sp<SkNormalSource> MakeFromNormalMap(sk_sp<SkShader> map, const SkMatrix& ctm);
     66 
     67     /** Returns a normal source that provides straight-up normals only <0, 0, 1>.
     68     */
     69     static sk_sp<SkNormalSource> MakeFlat();
     70 
     71     /** This enum specifies the shape of the bevel. All bevels output <0, 0, 1> as the surface
     72      *  normal for any point more than 'width' away from any edge.
     73      *
     74      *  Mathematical details:
     75      *  For the purpose of describing the shape of the bevel, we define 'w' to be the given width of
     76      *  the bevel, and 'h' to be the given height. We will assume the shape is rotated such that the
     77      *  point being shaded as well as the closest point in the shape's edge to that point are in the
     78      *  x-axis, and the shape is translated so that the aforementioned point in the edge is at
     79      *  coordinates (w, 0, 0) and the end of the bevel is at (0, 0, h).
     80      *
     81      */
     82     enum class BevelType {
     83         /* This bevel simulates a surface that is slanted from the shape's edges inwards, linearly.
     84          *
     85          * Mathematical details:
     86          * This bevel follows a straight line from (w, 0, 0) to (0, 0, h).
     87          */
     88         kLinear,
     89         /* This bevel simulates a surface that rounds off at the shape's edges, smoothly becoming
     90          * perpendicular to the x-y plane.
     91          *
     92          * Mathematical details:
     93          * This bevel follows the only quadratic bezier curve whose start point is at (w, 0, 0),
     94          * control point is at (w, 0, h), and end point is at (0, 0, h).
     95          */
     96         kRoundedOut,
     97         /* This bevel simulates a surface that sharply becomes perpendicular to the x-y plane when
     98          * at 'width' units from the nearest edge, and then rounds off towards the shape's
     99          * edge, smoothly becoming parallel to the x-y plane.
    100          *
    101          * Mathematical details:
    102          * This bevel follows the only quadratic bezier curve whose start point is at (w, 0, 0),
    103          * control point is at (0, 0, 0), and end point is at (0, 0, h).
    104          */
    105         kRoundedIn
    106     };
    107 
    108     /** Returns a normal source that generates a bevel for the shape being drawn. Currently this is
    109         not implemented on CPU rendering. On GPU this currently only works for anti-aliased circles
    110         and rectangles.
    111 
    112         @param  type   the type of bevel to add.
    113         @param  width  the width of the bevel, in source space. Must be positive.
    114         @param  height the height of the plateau, in source space. Can be positive, negative,
    115                        or zero. A negative height means the simulated bevels slope downwards.
    116     */
    117     static sk_sp<SkNormalSource> MakeBevel(BevelType, SkScalar width, SkScalar height);
    118 
    119     SK_DEFINE_FLATTENABLE_TYPE(SkNormalSource)
    120     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
    121 };
    122 
    123 #endif
    124