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 #include "SkNormalMapSource.h" 9 10 #include "SkArenaAlloc.h" 11 #include "SkLightingShader.h" 12 #include "SkMatrix.h" 13 #include "SkNormalSource.h" 14 #include "SkReadBuffer.h" 15 #include "SkWriteBuffer.h" 16 17 #if SK_SUPPORT_GPU 18 #include "GrCoordTransform.h" 19 #include "glsl/GrGLSLFragmentProcessor.h" 20 #include "glsl/GrGLSLFragmentShaderBuilder.h" 21 #include "SkGr.h" 22 23 class NormalMapFP : public GrFragmentProcessor { 24 public: 25 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> mapFP, 26 const SkMatrix& invCTM) { 27 return std::unique_ptr<GrFragmentProcessor>(new NormalMapFP(std::move(mapFP), invCTM)); 28 } 29 30 const char* name() const override { return "NormalMapFP"; } 31 32 const SkMatrix& invCTM() const { return fInvCTM; } 33 34 std::unique_ptr<GrFragmentProcessor> clone() const override { 35 return Make(this->childProcessor(0).clone(), fInvCTM); 36 } 37 38 private: 39 class GLSLNormalMapFP : public GrGLSLFragmentProcessor { 40 public: 41 GLSLNormalMapFP() : fColumnMajorInvCTM22{0.0f} {} 42 43 void emitCode(EmitArgs& args) override { 44 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 45 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 46 47 // add uniform 48 const char* xformUniName = nullptr; 49 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat2x2_GrSLType, 50 "Xform", &xformUniName); 51 52 SkString dstNormalColorName("dstNormalColor"); 53 this->emitChild(0, &dstNormalColorName, args); 54 fragBuilder->codeAppendf("float3 normal = normalize(%s.rgb - float3(0.5));", 55 dstNormalColorName.c_str()); 56 57 // If there's no x & y components, return (0, 0, +/- 1) instead to avoid division by 0 58 fragBuilder->codeAppend( "if (abs(normal.z) > 0.999) {"); 59 fragBuilder->codeAppendf(" %s = normalize(half4(0.0, 0.0, half(normal.z), 0.0));", 60 args.fOutputColor); 61 // Else, Normalizing the transformed X and Y, while keeping constant both Z and the 62 // vector's angle in the XY plane. This maintains the "slope" for the surface while 63 // appropriately rotating the normal regardless of any anisotropic scaling that occurs. 64 // Here, we call 'scaling factor' the number that must divide the transformed X and Y so 65 // that the normal's length remains equal to 1. 66 fragBuilder->codeAppend( "} else {"); 67 fragBuilder->codeAppendf(" float2 transformed = %s * normal.xy;", 68 xformUniName); 69 fragBuilder->codeAppend( " float scalingFactorSquared = " 70 "( (transformed.x * transformed.x) " 71 "+ (transformed.y * transformed.y) )" 72 "/(1.0 - (normal.z * normal.z));"); 73 fragBuilder->codeAppendf(" %s = half4(half2(transformed * " 74 "inversesqrt(scalingFactorSquared))," 75 "half(normal.z), 0.0);", 76 args.fOutputColor); 77 fragBuilder->codeAppend( "}"); 78 } 79 80 static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b) { 81 b->add32(0x0); 82 } 83 84 private: 85 void onSetData(const GrGLSLProgramDataManager& pdman, 86 const GrFragmentProcessor& proc) override { 87 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); 88 89 const SkMatrix& invCTM = normalMapFP.invCTM(); 90 fColumnMajorInvCTM22[0] = invCTM.get(SkMatrix::kMScaleX); 91 fColumnMajorInvCTM22[1] = invCTM.get(SkMatrix::kMSkewY); 92 fColumnMajorInvCTM22[2] = invCTM.get(SkMatrix::kMSkewX); 93 fColumnMajorInvCTM22[3] = invCTM.get(SkMatrix::kMScaleY); 94 pdman.setMatrix2f(fXformUni, fColumnMajorInvCTM22); 95 } 96 97 private: 98 // Upper-right 2x2 corner of the inverse of the CTM in column-major form 99 float fColumnMajorInvCTM22[4]; 100 GrGLSLProgramDataManager::UniformHandle fXformUni; 101 }; 102 103 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { 104 GLSLNormalMapFP::GenKey(*this, caps, b); 105 } 106 NormalMapFP(std::unique_ptr<GrFragmentProcessor> mapFP, const SkMatrix& invCTM) 107 : INHERITED(kMappedNormalsFP_ClassID, kNone_OptimizationFlags) 108 , fInvCTM(invCTM) { 109 this->registerChildProcessor(std::move(mapFP)); 110 } 111 112 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalMapFP; } 113 114 bool onIsEqual(const GrFragmentProcessor& proc) const override { 115 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>(); 116 return fInvCTM == normalMapFP.fInvCTM; 117 } 118 119 SkMatrix fInvCTM; 120 121 typedef GrFragmentProcessor INHERITED; 122 }; 123 124 std::unique_ptr<GrFragmentProcessor> SkNormalMapSourceImpl::asFragmentProcessor( 125 const GrFPArgs& args) const { 126 std::unique_ptr<GrFragmentProcessor> mapFP = as_SB(fMapShader)->asFragmentProcessor(args); 127 if (!mapFP) { 128 return nullptr; 129 } 130 131 return NormalMapFP::Make(std::move(mapFP), fInvCTM); 132 } 133 134 #endif // SK_SUPPORT_GPU 135 136 //////////////////////////////////////////////////////////////////////////// 137 138 SkNormalMapSourceImpl::Provider::Provider(const SkNormalMapSourceImpl& source, 139 SkShaderBase::Context* mapContext) 140 : fSource(source) 141 , fMapContext(mapContext) {} 142 143 SkNormalSource::Provider* SkNormalMapSourceImpl::asProvider(const SkShaderBase::ContextRec &rec, 144 SkArenaAlloc* alloc) const { 145 SkMatrix normTotalInv; 146 if (!this->computeNormTotalInverse(rec, &normTotalInv)) { 147 return nullptr; 148 } 149 150 // Normals really aren't colors, so to ensure we can always make the context, we ignore 151 // the rec's colorspace 152 SkColorSpace* dstColorSpace = nullptr; 153 154 // Overriding paint's alpha because we need the normal map's RGB channels to be unpremul'd 155 SkPaint overridePaint {*(rec.fPaint)}; 156 overridePaint.setAlpha(0xFF); 157 SkShaderBase::ContextRec overrideRec(overridePaint, *(rec.fMatrix), rec.fLocalMatrix, 158 rec.fDstColorType, dstColorSpace); 159 160 auto* context = as_SB(fMapShader)->makeContext(overrideRec, alloc); 161 if (!context) { 162 return nullptr; 163 } 164 165 return alloc->make<Provider>(*this, context); 166 } 167 168 bool SkNormalMapSourceImpl::computeNormTotalInverse(const SkShaderBase::ContextRec& rec, 169 SkMatrix* normTotalInverse) const { 170 SkMatrix total = SkMatrix::Concat(*rec.fMatrix, fMapShader->getLocalMatrix()); 171 if (rec.fLocalMatrix) { 172 total.preConcat(*rec.fLocalMatrix); 173 } 174 175 return total.invert(normTotalInverse); 176 } 177 178 #define BUFFER_MAX 16 179 void SkNormalMapSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[], 180 int count) const { 181 SkPMColor tmpNormalColors[BUFFER_MAX]; 182 183 do { 184 int n = SkTMin(count, BUFFER_MAX); 185 186 fMapContext->shadeSpan(x, y, tmpNormalColors, n); 187 188 for (int i = 0; i < n; i++) { 189 SkPoint3 tempNorm; 190 191 tempNorm.set(SkIntToScalar(SkGetPackedR32(tmpNormalColors[i])) - 127.0f, 192 SkIntToScalar(SkGetPackedG32(tmpNormalColors[i])) - 127.0f, 193 SkIntToScalar(SkGetPackedB32(tmpNormalColors[i])) - 127.0f); 194 195 tempNorm.normalize(); 196 197 198 if (!SkScalarNearlyEqual(SkScalarAbs(tempNorm.fZ), 1.0f)) { 199 SkVector transformed = fSource.fInvCTM.mapVector(tempNorm.fX, tempNorm.fY); 200 201 // Normalizing the transformed X and Y, while keeping constant both Z and the 202 // vector's angle in the XY plane. This maintains the "slope" for the surface while 203 // appropriately rotating the normal for any anisotropic scaling that occurs. 204 // Here, we call scaling factor the number that must divide the transformed X and Y 205 // so that the normal's length remains equal to 1. 206 SkScalar scalingFactorSquared = 207 (SkScalarSquare(transformed.fX) + SkScalarSquare(transformed.fY)) 208 / (1.0f - SkScalarSquare(tempNorm.fZ)); 209 SkScalar invScalingFactor = SkScalarInvert(SkScalarSqrt(scalingFactorSquared)); 210 211 output[i].fX = transformed.fX * invScalingFactor; 212 output[i].fY = transformed.fY * invScalingFactor; 213 output[i].fZ = tempNorm.fZ; 214 } else { 215 output[i] = {0.0f, 0.0f, tempNorm.fZ}; 216 output[i].normalize(); 217 } 218 219 SkASSERT(SkScalarNearlyEqual(output[i].length(), 1.0f)); 220 } 221 222 output += n; 223 x += n; 224 count -= n; 225 } while (count > 0); 226 } 227 228 //////////////////////////////////////////////////////////////////////////////// 229 230 sk_sp<SkFlattenable> SkNormalMapSourceImpl::CreateProc(SkReadBuffer& buf) { 231 232 sk_sp<SkShader> mapShader = buf.readFlattenable<SkShaderBase>(); 233 234 SkMatrix invCTM; 235 buf.readMatrix(&invCTM); 236 237 return sk_make_sp<SkNormalMapSourceImpl>(std::move(mapShader), invCTM); 238 } 239 240 void SkNormalMapSourceImpl::flatten(SkWriteBuffer& buf) const { 241 this->INHERITED::flatten(buf); 242 243 buf.writeFlattenable(fMapShader.get()); 244 buf.writeMatrix(fInvCTM); 245 } 246 247 //////////////////////////////////////////////////////////////////////////// 248 249 sk_sp<SkNormalSource> SkNormalSource::MakeFromNormalMap(sk_sp<SkShader> map, const SkMatrix& ctm) { 250 SkMatrix invCTM; 251 252 if (!ctm.invert(&invCTM) || !map) { 253 return nullptr; 254 } 255 256 return sk_make_sp<SkNormalMapSourceImpl>(std::move(map), invCTM); 257 } 258