Skip to content

Commit 0ba680a

Browse files
mrangezadjii-msftlhecker
authored
Added experimental.pixelShaderImagePath (#14073)
I realize I might be one of the few developers that care about custom shader support in terminal but I thought it's worth proposing it and see what you think. This is to support custom shaders with custom textures. I was thinking of exposing the background image to the shader but that felt complicated after looking into it. I have tested exploratively. I think the texture loader is possible to unit test so that is a possible improvement. The error reporting (as with other custom pixel shader code) is not very good. That is also an area that I could improve upon. I do think the risk of adding this is rather low as the new code is only executed when experimental.pixelShaderImagePath is set. ### Details Only added to the Atlas engine. Instead I load the texture using WIC into a shader resource view. When binding shader resources I test for presence of custom texture and bind it to register t1. The image loading code was found in [the D3D Texture documentation]. It's a mouthful but seems rather robust. Tested setting: "experimental.pixelShaderImagePath" 1. Tested not specifying it. 2. Tested setting it. 3. Tested changing it (the changes are picked up) 4. Tested invalid path 5. Tested a custom shader that made use of the custom texture. [the D3D Texture documentation]: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-textures-how-to Co-authored-by: Mike Griese <[email protected]> Co-authored-by: Leonard Hecker <[email protected]>
1 parent 8a1e8ac commit 0ba680a

File tree

21 files changed

+250
-61
lines changed

21 files changed

+250
-61
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Demo shader to show passing in an image using
2+
// experimental.pixelShaderImagePath. This shader simply displays the Terminal
3+
// contents on top of the given image.
4+
//
5+
// The image loaded by the terminal will be placed into the `image` texture.
6+
7+
SamplerState samplerState;
8+
Texture2D shaderTexture : register(t0);
9+
Texture2D image : register(t1);
10+
11+
cbuffer PixelShaderSettings {
12+
float Time;
13+
float Scale;
14+
float2 Resolution;
15+
float4 Background;
16+
};
17+
18+
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
19+
{
20+
float4 terminalColor = shaderTexture.Sample(samplerState, tex);
21+
float4 imageColor = image.Sample(samplerState, tex);
22+
return lerp(imageColor, terminalColor, terminalColor.a);
23+
}

src/cascadia/TerminalControl/ControlCore.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
387387

388388
_renderEngine->SetRetroTerminalEffect(_settings->RetroTerminalEffect());
389389
_renderEngine->SetPixelShaderPath(_settings->PixelShaderPath());
390+
_renderEngine->SetPixelShaderImagePath(_settings->PixelShaderImagePath());
390391
_renderEngine->SetForceFullRepaintRendering(_settings->ForceFullRepaintRendering());
391392
_renderEngine->SetSoftwareRendering(_settings->SoftwareRendering());
392393

@@ -914,6 +915,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
914915
_renderEngine->SetSelectionBackground(til::color{ newAppearance->SelectionBackground() });
915916
_renderEngine->SetRetroTerminalEffect(newAppearance->RetroTerminalEffect());
916917
_renderEngine->SetPixelShaderPath(newAppearance->PixelShaderPath());
918+
_renderEngine->SetPixelShaderImagePath(newAppearance->PixelShaderImagePath());
917919

918920
// Incase EnableUnfocusedAcrylic is disabled and Focused Acrylic is set to true,
919921
// the terminal should ignore the unfocused opacity from settings.

src/cascadia/TerminalControl/IControlAppearance.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ namespace Microsoft.Terminal.Control
1818
// Experimental settings
1919
Boolean RetroTerminalEffect { get; };
2020
String PixelShaderPath { get; };
21+
String PixelShaderImagePath { get; };
2122
};
2223
}

src/cascadia/TerminalCore/Terminal.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ til::point Terminal::GetViewportRelativeCursorPosition() const noexcept
16021602
// These functions are used by TerminalInput, which must build in conhost
16031603
// against OneCore compatible signatures. See the definitions in
16041604
// VtApiRedirection.hpp (which we cannot include cross-project.)
1605-
// Since we do nto run on OneCore, we can dispense with the compatibility
1605+
// Since we don't run on OneCore, we can dispense with the compatibility
16061606
// shims.
16071607
extern "C" UINT OneCoreSafeMapVirtualKeyW(_In_ UINT uCode, _In_ UINT uMapType)
16081608
{

src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ namespace Microsoft.Terminal.Settings.Model
5151

5252
INHERITABLE_APPEARANCE_SETTING(Boolean, RetroTerminalEffect);
5353
INHERITABLE_APPEARANCE_SETTING(String, PixelShaderPath);
54+
INHERITABLE_APPEARANCE_SETTING(String, PixelShaderImagePath);
5455
INHERITABLE_APPEARANCE_SETTING(IntenseStyle, IntenseTextStyle);
5556
INHERITABLE_APPEARANCE_SETTING(Microsoft.Terminal.Core.AdjustTextMode, AdjustIndistinguishableColors);
5657
INHERITABLE_APPEARANCE_SETTING(Double, Opacity);

src/cascadia/TerminalSettingsModel/MTSMSettings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ Author(s):
124124
X(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, "backgroundImageStretchMode", winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill) \
125125
X(bool, RetroTerminalEffect, "experimental.retroTerminalEffect", false) \
126126
X(hstring, PixelShaderPath, "experimental.pixelShaderPath") \
127+
X(hstring, PixelShaderImagePath, "experimental.pixelShaderImagePath") \
127128
X(ConvergedAlignment, BackgroundImageAlignment, "backgroundImageAlignment", ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center) \
128129
X(hstring, BackgroundImagePath, "backgroundImage") \
129130
X(Model::IntenseStyle, IntenseTextStyle, "intenseTextStyle", Model::IntenseStyle::Bright) \

src/cascadia/TerminalSettingsModel/TerminalSettings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
256256

257257
_RetroTerminalEffect = appearance.RetroTerminalEffect();
258258
_PixelShaderPath = winrt::hstring{ wil::ExpandEnvironmentStringsW<std::wstring>(appearance.PixelShaderPath().c_str()) };
259+
_PixelShaderImagePath = winrt::hstring{ wil::ExpandEnvironmentStringsW<std::wstring>(appearance.PixelShaderImagePath().c_str()) };
259260

260261
_IntenseIsBold = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bold);
261262
_IntenseIsBright = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bright);

src/cascadia/TerminalSettingsModel/TerminalSettings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
160160
INHERITABLE_SETTING(Model::TerminalSettings, bool, ForceVTInput, false);
161161

162162
INHERITABLE_SETTING(Model::TerminalSettings, hstring, PixelShaderPath);
163+
INHERITABLE_SETTING(Model::TerminalSettings, hstring, PixelShaderImagePath);
163164

164165
INHERITABLE_SETTING(Model::TerminalSettings, bool, Elevate, false);
165166

src/cascadia/inc/ControlProperties.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
X(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center) \
2828
X(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center) \
2929
X(bool, RetroTerminalEffect, false) \
30-
X(winrt::hstring, PixelShaderPath)
30+
X(winrt::hstring, PixelShaderPath) \
31+
X(winrt::hstring, PixelShaderImagePath)
3132

3233
// --------------------------- Core Settings ---------------------------
3334
// All of these settings are defined in ICoreSettings.

src/renderer/atlas/AtlasEngine.api.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,11 @@ HRESULT AtlasEngine::Enable() noexcept
328328
return _api.s->misc->customPixelShaderPath;
329329
}
330330

331+
[[nodiscard]] std::wstring_view AtlasEngine::GetPixelShaderImagePath() noexcept
332+
{
333+
return _api.s->misc->customPixelShaderImagePath;
334+
}
335+
331336
[[nodiscard]] bool AtlasEngine::GetRetroTerminalEffect() const noexcept
332337
{
333338
return _api.s->misc->useRetroTerminalEffect;
@@ -400,6 +405,17 @@ try
400405
}
401406
CATCH_LOG()
402407

408+
void AtlasEngine::SetPixelShaderImagePath(std::wstring_view value) noexcept
409+
try
410+
{
411+
if (_api.s->misc->customPixelShaderImagePath != value)
412+
{
413+
_api.s.write()->misc.write()->customPixelShaderImagePath = value;
414+
_resolveTransparencySettings();
415+
}
416+
}
417+
CATCH_LOG()
418+
403419
void AtlasEngine::SetRetroTerminalEffect(bool enable) noexcept
404420
{
405421
if (_api.s->misc->useRetroTerminalEffect != enable)

0 commit comments

Comments
 (0)