-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdwrite.hlsl
131 lines (122 loc) · 6.71 KB
/
dwrite.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
float3 DWrite_UnpremultiplyColor(float4 color)
{
if (color.a != 0)
{
color.rgb /= color.a;
}
return color.rgb;
}
float DWrite_ApplyLightOnDarkContrastAdjustment(float grayscaleEnhancedContrast, float3 color)
{
// The following 1 line is the same as this direct translation of the
// original code, but simplified to reduce the number of instructions:
// float lightness = dot(color, float3(0.30f, 0.59f, 0.11f);
// float multiplier = saturate(4.0f * (0.75f - lightness));
// return grayscaleEnhancedContrast * multiplier;
return grayscaleEnhancedContrast * saturate(dot(color, float3(0.30f, 0.59f, 0.11f) * -4.0f) + 3.0f);
}
float DWrite_CalcColorIntensity(float3 color)
{
return dot(color, float3(0.25f, 0.5f, 0.25f));
}
float DWrite_EnhanceContrast(float alpha, float k)
{
return alpha * (k + 1.0f) / (alpha * k + 1.0f);
}
float3 DWrite_EnhanceContrast3(float3 alpha, float k)
{
return alpha * (k + 1.0f) / (alpha * k + 1.0f);
}
float DWrite_ApplyAlphaCorrection(float a, float f, float4 g)
{
return a + a * (1 - a) * ((g.x * f + g.y) * a + (g.z * f + g.w));
}
float3 DWrite_ApplyAlphaCorrection3(float3 a, float3 f, float4 g)
{
return a + a * (1 - a) * ((g.x * f + g.y) * a + (g.z * f + g.w));
}
// Call this function to get the same gamma corrected alpha blending effect
// as DirectWrite's native algorithm for gray-scale anti-aliased glyphs.
//
// The result is a premultiplied color value, resulting
// out of the blending of foregroundColor with glyphAlpha.
//
// gammaRatios:
// Magic constants produced by DWrite_GetGammaRatios() in dwrite.cpp.
// The default value for this are the 1.8 gamma ratios, which equates to:
// 0.148054421f, -0.894594550f, 1.47590804f, -0.324668258f
// grayscaleEnhancedContrast:
// An additional contrast boost, making the font lighter/darker.
// The default value for this is 1.0f.
// This value should be set to the return value of DWrite_GetRenderParams() or (pseudo-code):
// IDWriteRenderingParams1* defaultParams;
// dwriteFactory->CreateRenderingParams(&defaultParams);
// gamma = defaultParams->GetGrayscaleEnhancedContrast();
// isThinFont:
// This constant is true for certain fonts that are simply too thin for AA.
// Unlike the previous two values, this value isn't a constant and can change per font family.
// If you only use modern fonts (like Roboto) you can safely assume that it's false.
// If you draw your glyph atlas with any DirectWrite method except IDWriteGlyphRunAnalysis::CreateAlphaTexture
// then you must set this to false as well, as not even tricks like setting the
// gamma to 1.0 disables the internal thin-font contrast-boost inside DirectWrite.
// Applying the contrast-boost twice would then look incorrectly.
// foregroundColor:
// The text's foreground color in premultiplied alpha.
// glyphAlpha:
// The alpha value of the current glyph pixel in your texture atlas.
float4 DWrite_GrayscaleBlend(float4 gammaRatios, float grayscaleEnhancedContrast, bool isThinFont, float4 foregroundColor, float glyphAlpha)
{
float3 foregroundStraight = DWrite_UnpremultiplyColor(foregroundColor);
float contrastBoost = isThinFont ? 0.5f : 0.0f;
float blendEnhancedContrast = contrastBoost + DWrite_ApplyLightOnDarkContrastAdjustment(grayscaleEnhancedContrast, foregroundStraight);
float intensity = DWrite_CalcColorIntensity(foregroundColor.rgb);
float contrasted = DWrite_EnhanceContrast(glyphAlpha, blendEnhancedContrast);
return foregroundColor * DWrite_ApplyAlphaCorrection(contrasted, intensity, gammaRatios);
}
// Call this function to get the same gamma corrected alpha blending effect
// as DirectWrite's native algorithm for ClearType anti-aliased glyphs.
//
// The result is a color value with alpha = 1, resulting out of the blending
// of foregroundColor and backgroundColor using glyphColor to do sub-pixel AA.
//
// gammaRatios:
// Magic constants produced by DWrite_GetGammaRatios() in dwrite.cpp.
// The default value for this are the 1.8 gamma ratios, which equates to:
// 0.148054421f, -0.894594550f, 1.47590804f, -0.324668258f
// enhancedContrast:
// An additional contrast boost, making the font lighter/darker.
// The default value for this is 0.5f.
// This value should be set to the return value of DWrite_GetRenderParams() or (pseudo-code):
// IDWriteRenderingParams* defaultParams;
// dwriteFactory->CreateRenderingParams(&defaultParams);
// gamma = defaultParams->GetEnhancedContrast();
// isThinFont:
// This constant is true for certain fonts that are simply too thin for AA.
// Unlike the previous two values, this value isn't a constant and can change per font family.
// If you only use modern fonts (like Roboto) you can safely assume that it's false.
// If you draw your glyph atlas with any DirectWrite method except IDWriteGlyphRunAnalysis::CreateAlphaTexture
// then you must set this to false as well, as not even tricks like setting the
// gamma to 1.0 disables the internal thin-font contrast-boost inside DirectWrite.
// Applying the contrast-boost twice would then look incorrectly.
// backgroundColor:
// The background color in premultiplied alpha (the color behind the text pixel).
// foregroundColor:
// The text's foreground color in premultiplied alpha.
// glyphAlpha:
// The RGB color of the current glyph pixel in your texture atlas.
// The A value is ignored, because ClearType doesn't work with alpha blending.
// RGB is required because ClearType performs sub-pixel AA. The most common ClearType drawing type is 6x1
// overscale (meaning: the glyph is rasterized with 6x the required resolution in the X axis) and thus
// only 7 different RGB combinations can exist in this texture (black/white and 5 states in between).
// If you wanted to you could just store these in a A8 texture and restore the RGB values in this shader.
float4 DWrite_CleartypeBlend(float4 gammaRatios, float enhancedContrast, bool isThinFont, float4 backgroundColor, float4 foregroundColor, float4 glyphColor)
{
float3 foregroundStraight = DWrite_UnpremultiplyColor(foregroundColor);
float contrastBoost = isThinFont ? 0.5f : 0.0f;
float blendEnhancedContrast = contrastBoost + DWrite_ApplyLightOnDarkContrastAdjustment(enhancedContrast, foregroundStraight);
float3 contrasted = DWrite_EnhanceContrast3(glyphColor.rgb, blendEnhancedContrast);
float3 alphaCorrected = DWrite_ApplyAlphaCorrection3(contrasted, foregroundStraight, gammaRatios);
return float4(lerp(backgroundColor.rgb, foregroundStraight, alphaCorrected * foregroundColor.a), 1.0f);
}