Chromium Code Reviews| Index: src/core/SkNormalBevelSource.cpp |
| diff --git a/src/core/SkNormalBevelSource.cpp b/src/core/SkNormalBevelSource.cpp |
| index a63e434c3fb1fe7f01162735d8ac7ebbd11dc330..beb3d9b8b795414240b4cd8bf5f1c6fdadc9bc51 100644 |
| --- a/src/core/SkNormalBevelSource.cpp |
| +++ b/src/core/SkNormalBevelSource.cpp |
| @@ -19,6 +19,14 @@ |
| #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| #include "SkGr.h" |
| +/** \class NormalBevelFP |
| + * |
| + * Fragment processor for the SkNormalBevelSource. |
| + * |
|
robertphillips
2016/08/03 16:33:15
What do you think about renaming these bevelWidth,
dvonbeck
2016/08/03 21:04:20
Done. Should I do this in the user-facing API too?
|
| + * @param type type of the bevel |
| + * @param width width of the bevel in device space |
| + * @param height height of the bevel in device space |
| + */ |
| class NormalBevelFP : public GrFragmentProcessor { |
| public: |
| NormalBevelFP(SkNormalSource::BevelType type, SkScalar width, SkScalar height) |
| @@ -39,6 +47,7 @@ public: |
| void onEmitCode(EmitArgs& args) override { |
| GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| + const NormalBevelFP& fp = args.fFp.cast<NormalBevelFP>(); |
| GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; |
| const char* widthUniName = nullptr; |
| @@ -49,7 +58,14 @@ public: |
| fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, |
| kDefault_GrSLPrecision, "Height", &heightUniName); |
|
robertphillips
2016/08/03 16:33:14
Do you think the shader compilers are going to be
dvonbeck
2016/08/03 16:39:24
I assume so but I don't know. Do you think I shoul
dvonbeck
2016/08/03 21:04:19
No longer necessary.
|
| - fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 1.0, 0.0);", args.fOutputColor); |
| + fragBuilder->codeAppend( "vec3 normal;"); |
| + fragBuilder->codeAppendf("if (length(%s) >= %s) {", |
| + fragBuilder->distanceVectorName(), widthUniName); |
| + fragBuilder->codeAppend( " normal = vec3(0.0, 0.0, 1.0);"); |
| + fragBuilder->codeAppend( "} else {"); |
| + this->emitMath(fragBuilder, fp.fType, widthUniName, heightUniName); |
| + fragBuilder->codeAppend( "}"); |
| + fragBuilder->codeAppendf("%s = vec4(normal, 0.0);", args.fOutputColor); |
| } |
| static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, |
| @@ -73,6 +89,44 @@ public: |
| } |
| } |
| + void emitMath(GrGLSLFPFragmentBuilder* fb, SkNormalSource::BevelType type, |
| + const char* width, const char* height) { |
| + const char* distanceVector = fb->distanceVectorName(); |
| + |
| + // Setting t to the distance from the end of the bevel as opposed to the beginning if |
| + // the bevel is rounded out. |
| + if ( type == SkNormalSource::BevelType::kRoundedIn ) { |
| + fb->codeAppendf(" float t = %s - length(%s);", width, distanceVector); |
| + } else if (type == SkNormalSource::BevelType::kRoundedOut) { |
| + fb->codeAppendf(" float t = length(%s);", distanceVector); |
| + } |
| + |
| + switch (type) { |
| + case SkNormalSource::BevelType::kLinear: |
| + fb->codeAppendf(" normal = normalize(%s*vec3(%s, 0.0) " |
| + "+ vec3(0.0, 0.0, %s));", |
| + height, distanceVector, width); |
| + break; |
|
robertphillips
2016/08/03 16:33:15
Add a "// fall through" comment
dvonbeck
2016/08/03 21:04:20
Done.
|
| + case SkNormalSource::BevelType::kRoundedOut: |
| + case SkNormalSource::BevelType::kRoundedIn: |
| + // calculating the slope of the normal with respect to the distance vector by |
| + // setting it equal to the negative reciprocal of the derivative of the bezier |
|
robertphillips
2016/08/03 16:33:15
cure -> curve
One would hope the shader compilers
dvonbeck
2016/08/03 16:39:24
Do you think they will, or should I make it explic
dvonbeck
2016/08/03 21:04:20
Done.
|
| + // cure |
| + fb->codeAppendf("float slope = %s * sqrt(t) / (%s * (sqrt(%s) - sqrt(t)));", |
| + width, height, width); |
| + // calculating a value so that when appended to the distance vector and |
| + // normalized, it would result in a normal with the correct slope |
| + fb->codeAppend("float z_prenorm = slope * t;"); |
| + // Multiplying with the height's sign to orient the vector inwards for bevels of |
| + // negative height |
|
robertphillips
2016/08/03 16:33:15
Is sign() verboten?
dvonbeck
2016/08/03 21:04:20
No longer necessary.
|
| + fb->codeAppendf("normal = normalize(vec3(%s, z_prenorm)) * normalize(%s);", |
| + distanceVector, height); |
| + break; |
| + default: |
| + SkDEBUGFAIL("Invalid bevel type passed to emitMath"); |
| + } |
| + } |
| + |
| private: |
| SkScalar fPrevWidth; |
| GrGLSLProgramDataManager::UniformHandle fWidthUni; |
| @@ -107,9 +161,12 @@ private: |
| }; |
| sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor( |
| - const SkShader::AsFPArgs&) const { |
| + const SkShader::AsFPArgs& args) const { |
| + |
| + SkScalar maxScale = args.fViewMatrix->getMaxScale(); |
| - return sk_make_sp<NormalBevelFP>(fType, fWidth, fHeight); |
| + // Providing device-space width and height |
| + return sk_make_sp<NormalBevelFP>(fType, maxScale * fWidth, maxScale * fHeight); |
| } |
| #endif // SK_SUPPORT_GPU |