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 |