gfx/2d/ShadersD2D1.hlsl

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/2d/ShadersD2D1.hlsl	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,97 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 +  * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 +  * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 +  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +Texture2D InputTexture : register(t0);
    1.10 +SamplerState InputSampler : register(s0);
    1.11 +Texture2D GradientTexture : register(t1);
    1.12 +SamplerState GradientSampler : register(s1);
    1.13 +
    1.14 +cbuffer constants : register(b0)
    1.15 +{
    1.16 +    // Precalculate as much as we can!
    1.17 +    float3 diff : packoffset(c0.x);
    1.18 +    float2 center1 : packoffset(c1.x);
    1.19 +    float A : packoffset(c1.z);
    1.20 +    float radius1 : packoffset(c1.w);
    1.21 +    float sq_radius1 : packoffset(c2.x);
    1.22 +    float3x2 transform : packoffset(c3.x);
    1.23 +}
    1.24 +
    1.25 +float4 SampleRadialGradientPS(
    1.26 +    float4 clipSpaceOutput  : SV_POSITION,
    1.27 +    float4 sceneSpaceOutput : SCENE_POSITION,
    1.28 +    float4 texelSpaceInput0 : TEXCOORD0
    1.29 +    ) : SV_Target
    1.30 +{
    1.31 +  // Radial gradient painting is defined as the set of circles whose centers
    1.32 +  // are described by C(t) = (C2 - C1) * t + C1; with radii
    1.33 +  // R(t) = (R2 - R1) * t + R1; for R(t) > 0. This shader solves the
    1.34 +  // quadratic equation that arises when calculating t for pixel (x, y).
    1.35 +  //
    1.36 +  // A more extensive derrivation can be found in the pixman radial gradient
    1.37 +  // code.
    1.38 +
    1.39 +  float2 p = float2(sceneSpaceOutput.x * transform._11 + sceneSpaceOutput.y * transform._21 + transform._31,
    1.40 +                    sceneSpaceOutput.x * transform._12 + sceneSpaceOutput.y * transform._22 + transform._32);
    1.41 +  float3 dp = float3(p - center1, radius1);
    1.42 +
    1.43 +  // dpx * dcx + dpy * dcy + r * dr
    1.44 +  float B = dot(dp, diff);
    1.45 +
    1.46 +  float C = pow(dp.x, 2) + pow(dp.y, 2) - sq_radius1;
    1.47 +
    1.48 +  float det = pow(B, 2) - A * C;
    1.49 +
    1.50 +  float sqrt_det = sqrt(abs(det));
    1.51 +
    1.52 +  float2 t = (B + float2(sqrt_det, -sqrt_det)) / A;
    1.53 +
    1.54 +  float2 isValid = step(float2(-radius1, -radius1), t * diff.z);
    1.55 +
    1.56 +  float upper_t = lerp(t.y, t.x, isValid.x);
    1.57 +
    1.58 +  float4 output = GradientTexture.Sample(GradientSampler, float2(upper_t, 0.5));
    1.59 +  // Premultiply
    1.60 +  output.rgb *= output.a;
    1.61 +  // Multiply the output color by the input mask for the operation.
    1.62 +  output *= InputTexture.Sample(InputSampler, texelSpaceInput0.xy);
    1.63 +
    1.64 +  // In order to compile for PS_4_0_level_9_3 we need to be branchless.
    1.65 +  // This is essentially returning nothing, i.e. bailing early if:
    1.66 +  // det < 0 || max(isValid.x, isValid.y) <= 0
    1.67 +  return output * abs(step(max(isValid.x, isValid.y), 0) - 1.0f) * step(0, det);
    1.68 +};
    1.69 +
    1.70 +float4 SampleRadialGradientA0PS(
    1.71 +    float4 clipSpaceOutput  : SV_POSITION,
    1.72 +    float4 sceneSpaceOutput : SCENE_POSITION,
    1.73 +    float4 texelSpaceInput0 : TEXCOORD0
    1.74 +    ) : SV_Target
    1.75 +{
    1.76 +  // This simpler shader is used for the degenerate case where A is 0,
    1.77 +  // i.e. we're actually solving a linear equation.
    1.78 +
    1.79 +  float2 p = float2(sceneSpaceOutput.x * transform._11 + sceneSpaceOutput.y * transform._21 + transform._31,
    1.80 +                    sceneSpaceOutput.x * transform._12 + sceneSpaceOutput.y * transform._22 + transform._32);
    1.81 +  float3 dp = float3(p - center1, radius1);
    1.82 +
    1.83 +  // dpx * dcx + dpy * dcy + r * dr
    1.84 +  float B = dot(dp, diff);
    1.85 +
    1.86 +  float C = pow(dp.x, 2) + pow(dp.y, 2) - pow(radius1, 2);
    1.87 +
    1.88 +  float t = 0.5 * C / B;
    1.89 +
    1.90 +  float4 output = GradientTexture.Sample(GradientSampler, float2(t, 0.5));
    1.91 +  // Premultiply
    1.92 +  output.rgb *= output.a;
    1.93 +  // Multiply the output color by the input mask for the operation.
    1.94 +  output *= InputTexture.Sample(InputSampler, texelSpaceInput0.xy);
    1.95 +
    1.96 +  // In order to compile for PS_4_0_level_9_3 we need to be branchless.
    1.97 +  // This is essentially returning nothing, i.e. bailing early if:
    1.98 +  // -radius1 >= t * diff.z
    1.99 +  return output * abs(step(t * diff.z, -radius1) - 1.0f);
   1.100 +};

mercurial