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, |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame^] | 17 | const char* wind, const char** tighterHull) const { |
Chris Dalton | 52076d1 | 2018-03-21 12:14:10 -0600 | [diff] [blame] | 18 | s->declareGlobal(fQCoordMatrix); |
| 19 | s->codeAppendf("%s = float2x2(1, 1, .5, 0) * inverse(float2x2(%s[2] - %s[0], %s[1] - %s[0]));", |
| 20 | fQCoordMatrix.c_str(), pts, pts, pts, pts); |
| 21 | |
| 22 | s->declareGlobal(fQCoord0); |
| 23 | s->codeAppendf("%s = %s[0];", fQCoord0.c_str(), pts); |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 24 | |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 25 | s->declareGlobal(fEdgeDistanceEquation); |
| 26 | s->codeAppendf("float2 edgept0 = %s[%s > 0 ? 2 : 0];", pts, wind); |
| 27 | s->codeAppendf("float2 edgept1 = %s[%s > 0 ? 0 : 2];", pts, wind); |
| 28 | Shader::EmitEdgeDistanceEquation(s, "edgept0", "edgept1", fEdgeDistanceEquation.c_str()); |
| 29 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame^] | 30 | if (tighterHull) { |
| 31 | // Find the T value whose tangent is halfway between the tangents at the endpionts. |
| 32 | s->codeAppendf("float2 tan0 = %s[1] - %s[0];", pts, pts); |
| 33 | s->codeAppendf("float2 tan1 = %s[2] - %s[1];", pts, pts); |
| 34 | s->codeAppend ("float2 midnorm = normalize(tan0) - normalize(tan1);"); |
| 35 | s->codeAppend ("float2 T = midnorm * float2x2(tan0 - tan1, tan0);"); |
| 36 | s->codeAppend ("float t = clamp(T.t / T.s, 0, 1);"); // T.s!=0; we cull flat curves on CPU. |
| 37 | |
| 38 | // Clip the bezier triangle by the tangent at our new t value. This is a simple application |
| 39 | // for De Casteljau's algorithm. |
| 40 | s->codeAppendf("float4x2 quadratic_hull = float4x2(%s[0], " |
| 41 | "%s[0] + tan0 * t, " |
| 42 | "%s[1] + tan1 * t, " |
| 43 | "%s[2]);", pts, pts, pts, pts); |
| 44 | *tighterHull = "quadratic_hull"; |
| 45 | } |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 46 | } |
| 47 | |
| 48 | void GrCCQuadraticShader::onEmitVaryings(GrGLSLVaryingHandler* varyingHandler, |
| 49 | GrGLSLVarying::Scope scope, SkString* code, |
Chris Dalton | 04a1de5 | 2018-03-14 02:04:09 -0600 | [diff] [blame] | 50 | const char* position, const char* coverage, |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame^] | 51 | const char* attenuatedCoverage) { |
| 52 | fCoord.reset(kFloat4_GrSLType, scope); |
| 53 | varyingHandler->addVarying("coord", &fCoord); |
| 54 | code->appendf("%s.xy = %s * (%s - %s);", // Quadratic coords. |
| 55 | OutName(fCoord), fQCoordMatrix.c_str(), position, fQCoord0.c_str()); |
| 56 | code->appendf("%s.zw = 2*bloat * float2(2 * %s.x, -1) * %s;", // Gradient. |
| 57 | OutName(fCoord), OutName(fCoord), fQCoordMatrix.c_str()); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 58 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame^] | 59 | // Coverages need full precision since distance to the opposite edge can be large. |
| 60 | fCoverages.reset(attenuatedCoverage ? kFloat4_GrSLType : kFloat2_GrSLType, scope); |
| 61 | varyingHandler->addVarying("coverages", &fCoverages); |
| 62 | code->appendf("%s.x = dot(%s, float3(%s, 1));", // Distance to flat edge opposite the curve. |
| 63 | OutName(fCoverages), fEdgeDistanceEquation.c_str(), position); |
| 64 | code->appendf("%s.y = %s;", OutName(fCoverages), coverage); // Wind. |
| 65 | if (attenuatedCoverage) { |
| 66 | code->appendf("%s.zw = %s;", // Attenuated corner coverage. |
| 67 | OutName(fCoverages), attenuatedCoverage); |
| 68 | } |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | void GrCCQuadraticShader::onEmitFragmentCode(GrGLSLFPFragmentBuilder* f, |
| 72 | const char* outputCoverage) const { |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame^] | 73 | f->codeAppendf("float x = %s.x, y = %s.y;", fCoord.fsIn(), fCoord.fsIn()); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 74 | f->codeAppend ("float f = x*x - y;"); |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame^] | 75 | f->codeAppendf("float2 grad = %s.zw;", fCoord.fsIn()); |
| 76 | f->codeAppendf("%s = clamp(0.5 - f * inversesqrt(dot(grad, grad)), 0, 1);", outputCoverage); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 77 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame^] | 78 | f->codeAppendf("half d = min(%s.x, 0);", fCoverages.fsIn()); // Flat edge opposite the curve. |
| 79 | f->codeAppendf("half wind = %s.y;", fCoverages.fsIn()); |
| 80 | f->codeAppendf("%s = (%s + d) * wind;", outputCoverage, outputCoverage); |
| 81 | |
| 82 | if (kFloat4_GrSLType == fCoverages.type()) { |
| 83 | f->codeAppendf("%s = %s.z * %s.w + %s;", // Attenuated corner coverage. |
| 84 | outputCoverage, fCoverages.fsIn(), fCoverages.fsIn(), outputCoverage); |
| 85 | } |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 86 | } |