Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AtlasEngine: Implement support for custom shaders #13885

Merged
merged 12 commits into from
Aug 31, 2022
55 changes: 27 additions & 28 deletions samples/PixelShaders/Retro.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,46 @@
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
float Time;
float Scale;
float2 Resolution;
float4 Background;
cbuffer PixelShaderSettings
{
float time;
float scale;
float2 resolution;
float4 background;
};

#define SCANLINE_FACTOR 0.5
#define SCALED_SCANLINE_PERIOD Scale
#define SCALED_GAUSSIAN_SIGMA (2.0*Scale)
#define SCANLINE_FACTOR 0.5f
#define SCALED_SCANLINE_PERIOD scale
#define SCALED_GAUSSIAN_SIGMA (2.0f * scale)

static const float M_PI = 3.14159265f;

float Gaussian2D(float x, float y, float sigma)
{
return 1/(sigma*sqrt(2*M_PI)) * exp(-0.5*(x*x + y*y)/sigma/sigma);
return 1 / (sigma * sqrt(2 * M_PI)) * exp(-0.5 * (x * x + y * y) / sigma / sigma);
}

float4 Blur(Texture2D input, float2 tex_coord, float sigma)
{
uint width, height;
float width, height;
shaderTexture.GetDimensions(width, height);

float texelWidth = 1.0f/width;
float texelHeight = 1.0f/height;
float texelWidth = 1.0f / width;
float texelHeight = 1.0f / height;

float4 color = { 0, 0, 0, 0 };

int sampleCount = 13;
float sampleCount = 13;

for (int x = 0; x < sampleCount; x++)
for (float x = 0; x < sampleCount; x++)
{
float2 samplePos = { 0, 0 };
samplePos.x = tex_coord.x + (x - sampleCount / 2.0f) * texelWidth;

samplePos.x = tex_coord.x + (x - sampleCount/2) * texelWidth;
for (int y = 0; y < sampleCount; y++)
for (float y = 0; y < sampleCount; y++)
{
samplePos.y = tex_coord.y + (y - sampleCount/2) * texelHeight;
if (samplePos.x <= 0 || samplePos.y <= 0 || samplePos.x >= width || samplePos.y >= height) continue;

color += input.Sample(samplerState, samplePos) * Gaussian2D((x - sampleCount/2), (y - sampleCount/2), sigma);
samplePos.y = tex_coord.y + (y - sampleCount / 2.0f) * texelHeight;
color += input.Sample(samplerState, samplePos) * Gaussian2D(x - sampleCount / 2.0f, y - sampleCount / 2.0f, sigma);
Comment on lines +43 to +44
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI with D3D11_TEXTURE_ADDRESS_BORDER we already ensure that Sample() returns float4(0, 0, 0, 0). This removes the need for the if condition, which is one of the things that produces a warning by default (and for a good reason - loops like that are impossible on GPUs).

}
}

Expand All @@ -51,7 +50,7 @@ float4 Blur(Texture2D input, float2 tex_coord, float sigma)

float SquareWave(float y)
{
return 1 - (floor(y / SCALED_SCANLINE_PERIOD) % 2) * SCANLINE_FACTOR;
return 1.0f - (floor(y / SCALED_SCANLINE_PERIOD) % 2.0f) * SCANLINE_FACTOR;
}

float4 Scanline(float4 color, float4 pos)
Expand All @@ -60,24 +59,24 @@ float4 Scanline(float4 color, float4 pos)

// TODO:GH#3929 make this configurable.
// Remove the && false to draw scanlines everywhere.
if (length(color.rgb) < 0.2 && false)
if (length(color.rgb) < 0.2f && false)
{
return color + wave*0.1;
return color + wave * 0.1f;
}
else
{
return color * wave;
}
}

// clang-format off
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
// clang-format on
{
Texture2D input = shaderTexture;

// TODO:GH#3930 Make these configurable in some way.
float4 color = input.Sample(samplerState, tex);
color += Blur(input, tex, SCALED_GAUSSIAN_SIGMA)*0.3;
float4 color = shaderTexture.Sample(samplerState, tex);
color += Blur(shaderTexture, tex, SCALED_GAUSSIAN_SIGMA) * 0.3f;
color = Scanline(color, pos);

return color;
}
}
36 changes: 25 additions & 11 deletions src/renderer/atlas/AtlasEngine.api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ HRESULT AtlasEngine::Enable() noexcept

[[nodiscard]] bool AtlasEngine::GetRetroTerminalEffect() const noexcept
{
return false;
return _api.useRetroTerminalEffect;
}

[[nodiscard]] float AtlasEngine::GetScaling() const noexcept
Expand Down Expand Up @@ -332,7 +332,7 @@ void AtlasEngine::SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasin
if (_api.antialiasingMode != mode)
{
_api.antialiasingMode = mode;
_resolveAntialiasingMode();
_resolveTransparencySettings();
WI_SetFlag(_api.invalidations, ApiInvalidations::Font);
}
}
Expand All @@ -344,11 +344,10 @@ void AtlasEngine::SetCallback(std::function<void()> pfn) noexcept

void AtlasEngine::EnableTransparentBackground(const bool isTransparent) noexcept
{
const auto mixin = !isTransparent ? 0xff000000 : 0x00000000;
if (_api.backgroundOpaqueMixin != mixin)
if (_api.enableTransparentBackground != isTransparent)
{
_api.backgroundOpaqueMixin = mixin;
_resolveAntialiasingMode();
_api.enableTransparentBackground = isTransparent;
_resolveTransparencySettings();
WI_SetFlag(_api.invalidations, ApiInvalidations::SwapChain);
}
}
Expand All @@ -369,10 +368,22 @@ void AtlasEngine::SetForceFullRepaintRendering(bool enable) noexcept

void AtlasEngine::SetPixelShaderPath(std::wstring_view value) noexcept
{
if (_api.customPixelShaderPath != value)
{
_api.customPixelShaderPath = value;
_resolveTransparencySettings();
WI_SetFlag(_api.invalidations, ApiInvalidations::Device);
}
}

void AtlasEngine::SetRetroTerminalEffect(bool enable) noexcept
{
if (_api.useRetroTerminalEffect != enable)
{
_api.useRetroTerminalEffect = enable;
_resolveTransparencySettings();
WI_SetFlag(_api.invalidations, ApiInvalidations::Device);
}
}

void AtlasEngine::SetSelectionBackground(const COLORREF color, const float alpha) noexcept
Expand Down Expand Up @@ -451,13 +462,15 @@ void AtlasEngine::UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept

#pragma endregion

void AtlasEngine::_resolveAntialiasingMode() noexcept
void AtlasEngine::_resolveTransparencySettings() noexcept
{
// If the user asks for ClearType, but also for a transparent background
// (which our ClearType shader doesn't simultaneously support)
// then we need to sneakily force the renderer to grayscale AA.
const auto forceGrayscaleAA = _api.antialiasingMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && !_api.backgroundOpaqueMixin;
_api.realizedAntialiasingMode = forceGrayscaleAA ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : _api.antialiasingMode;
_api.realizedAntialiasingMode = _api.enableTransparentBackground && _api.antialiasingMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : _api.antialiasingMode;
// An opaque background allows us to use true "independent" flips. See AtlasEngine::_createSwapChain().
// We can't enable them if custom shaders are specified, because it's unknown, whether they support opaque inputs.
_api.backgroundOpaqueMixin = _api.enableTransparentBackground || !_api.customPixelShaderPath.empty() || _api.useRetroTerminalEffect ? 0x00000000 : 0xff000000;
}

void AtlasEngine::_updateFont(const wchar_t* faceName, const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes)
Expand Down Expand Up @@ -606,7 +619,8 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo
// Point sizes are commonly treated at a 72 DPI scale
// (including by OpenType), whereas DirectWrite uses 96 DPI.
// Since we want the height in px we multiply by the display's DPI.
const auto fontSizeInPx = std::roundf(requestedSize.Y / 72.0f * _api.dpi);
const auto fontSizeInDIP = requestedSize.Y / 72.0f * 96.0f;
const auto fontSizeInPx = requestedSize.Y / 72.0f * _api.dpi;

const auto designUnitsPerPx = fontSizeInPx / static_cast<float>(metrics.designUnitsPerEm);
const auto ascent = static_cast<float>(metrics.ascent) * designUnitsPerPx;
Expand Down Expand Up @@ -687,7 +701,7 @@ void AtlasEngine::_resolveFontMetrics(const wchar_t* requestedFaceName, const Fo

fontMetrics->fontCollection = std::move(fontCollection);
fontMetrics->fontName = std::move(fontName);
fontMetrics->fontSizeInDIP = fontSizeInPx / static_cast<float>(_api.dpi) * 96.0f;
fontMetrics->fontSizeInDIP = fontSizeInDIP;
fontMetrics->baselineInDIP = baseline / static_cast<float>(_api.dpi) * 96.0f;
fontMetrics->advanceScale = cellWidth / advanceWidth;
fontMetrics->cellSize = { cellWidth, cellHeight };
Expand Down
Loading