Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2017 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 | |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 8 | #include "GrCCQuadraticShader.h" |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 9 | |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 10 | #include "glsl/GrGLSLVertexGeoBuilder.h" |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 11 | #include "glsl/GrGLSLFragmentShaderBuilder.h" |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 12 | #include "glsl/GrGLSLVertexGeoBuilder.h" |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 13 | |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 14 | using Shader = GrCCCoverageProcessor::Shader; |
Chris Dalton | de5a814 | 2017-12-18 10:05:15 -0700 | [diff] [blame] | 15 | |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame^] | 16 | void GrCCQuadraticShader::emitSetupCode(GrGLSLVertexGeoBuilder* s, const char* pts, |
| 17 | const char* /*repetitionID*/, const char* /*wind*/, |
| 18 | GeometryVars* vars) const { |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 19 | s->declareGlobal(fCanonicalMatrix); |
| 20 | s->codeAppendf("%s = float3x3(0.0, 0, 1, " |
| 21 | "0.5, 0, 1, " |
| 22 | "1.0, 1, 1) * " |
| 23 | "inverse(float3x3(%s[0], 1, " |
| 24 | "%s[1], 1, " |
| 25 | "%s[2], 1));", |
| 26 | fCanonicalMatrix.c_str(), pts, pts, pts); |
| 27 | |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 28 | // Find the T value whose tangent is halfway between the tangents at the endpionts. |
| 29 | s->codeAppendf("float2 tan0 = %s[1] - %s[0];", pts, pts); |
| 30 | s->codeAppendf("float2 tan1 = %s[2] - %s[1];", pts, pts); |
| 31 | s->codeAppend ("float2 midnorm = normalize(tan0) - normalize(tan1);"); |
| 32 | s->codeAppend ("float2 T = midnorm * float2x2(tan0 - tan1, tan0);"); |
| 33 | s->codeAppend ("float t = clamp(T.t / T.s, 0, 1);"); // T.s != 0; we cull flat curves on CPU. |
| 34 | |
| 35 | // Clip the bezier triangle by the tangent at our new t value. This is a simple application for |
| 36 | // De Casteljau's algorithm. |
| 37 | s->codeAppendf("float4x2 quadratic_hull = float4x2(%s[0], " |
| 38 | "%s[0] + tan0 * t, " |
| 39 | "%s[1] + tan1 * t, " |
| 40 | "%s[2]);", pts, pts, pts, pts); |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame^] | 41 | vars->fHullVars.fAlternatePoints = "quadratic_hull"; |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 42 | } |
| 43 | |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame^] | 44 | void GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, |
| 45 | GrGLSLVarying::Scope scope, SkString* code, |
| 46 | const char* position, const char* inputCoverage, |
| 47 | const char* wind) { |
Chris Dalton | df04ce2 | 2018-03-07 17:28:07 -0700 | [diff] [blame] | 48 | fCoords.reset(kFloat4_GrSLType, scope); |
| 49 | varyingHandler->addVarying("coords", &fCoords); |
| 50 | code->appendf("%s.xy = (%s * float3(%s, 1)).xy;", |
| 51 | OutName(fCoords), fCanonicalMatrix.c_str(), position); |
| 52 | code->appendf("%s.zw = float2(2 * %s.x, -1) * float2x2(%s);", |
| 53 | OutName(fCoords), OutName(fCoords), fCanonicalMatrix.c_str()); |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame^] | 54 | |
| 55 | fCoverageTimesWind.reset(kHalf_GrSLType, scope); |
| 56 | varyingHandler->addVarying("coverage_times_wind", &fCoverageTimesWind); |
| 57 | code->appendf("%s = %s * %s;", OutName(fCoverageTimesWind), inputCoverage, wind); |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 58 | } |
| 59 | |
Chris Dalton | df04ce2 | 2018-03-07 17:28:07 -0700 | [diff] [blame] | 60 | void GrCCQuadraticShader::onEmitFragmentCode(const GrCCCoverageProcessor& proc, |
| 61 | GrGLSLFPFragmentBuilder* f, |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 62 | const char* outputCoverage) const { |
Chris Dalton | df04ce2 | 2018-03-07 17:28:07 -0700 | [diff] [blame] | 63 | f->codeAppendf("float d = (%s.x * %s.x - %s.y) * inversesqrt(dot(%s.zw, %s.zw));", |
| 64 | fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn(), fCoords.fsIn()); |
| 65 | #ifdef SK_DEBUG |
| 66 | if (proc.debugVisualizationsEnabled()) { |
| 67 | f->codeAppendf("d /= %f;", proc.debugBloat()); |
| 68 | } |
| 69 | #endif |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame^] | 70 | f->codeAppendf("%s = clamp(0.5 - d, 0, 1) * %s;", outputCoverage, fCoverageTimesWind.fsIn()); |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 71 | } |