terminal/samples/PixelShaders/README.md

221 lines
9.4 KiB
Markdown
Raw Normal View History

Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
# Pixel Shaders in Windows Terminal
Due to the sheer amount of computing power in GPUs, one can do awesome things with pixel shaders such as real-time fractal zoom, ray tracers and image processing.
Windows Terminal allows user to provide a pixel shader which will be applied to the terminal. To try it out, add the following setting to one of your profiles:
```
"experimental.pixelShaderPath": "<path to a .hlsl pixel shader>"
```
> **Note**: if you specify a shader with `experimental.pixelShaderPath`, the Terminal will use that instead of the `experimental.retroTerminalEffect`.
To get started using pixel shaders in the Terminal, start with the following sample shader. This is `Invert.hlsl` in this directory:
```hlsl
// A minimal pixel shader that inverts the colors
// The terminal graphics as a texture
Texture2D shaderTexture;
SamplerState samplerState;
// Terminal settings such as the resolution of the texture
cbuffer PixelShaderSettings {
Add animated shader samples (#9026) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request - Adds two simple animated shaders to the pixel shaders sample folder - Updates the readme in the pixel shaders sample folder to add a section explaining the animated shaders - Modifies some comments in existing shader samples <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #8994 <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments The two shaders I wrote are not especially pretty or interesting, but they should hopefully serve as simple examples for anyone looking to do animated effects. One simply draws a line of inverted pixels that scrolls down the screen, and the other fades the background back and forth between two colors. I've added a new section to the readme explaining how the shaders work to achieve animated effects. I've also updated the comments on the existing shaders to clear up a couple of things: 1. Be more explicit that `Time` represents seconds since the shader loaded. Though obvious in hindsight, this was not clear to me when I was first learning/experimenting 2. Explain that `tex` ranges from 0,0 to 1,1. This is important because, when trying to port GLSL shaders from shadertoy, I at first assumed `fragCoord` and `tex` are the same thing but the former actually ranges from 0,0 to the resolution of the canvas, so some of the math doesn't work out if you just substitute it with `tex`. Any and all feedback welcome. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed I ran the shaders manually in a dev build of the Terminal. I auto-spellchecked and manually proofread my additions to the readme and verifed the markdown rendering on github.
2021-02-04 14:53:21 +01:00
// The number of seconds since the pixel shader was enabled
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
float Time;
// UI Scale
float Scale;
// Resolution of the shaderTexture
float2 Resolution;
// Background color as rgba
float4 Background;
};
Add animated shader samples (#9026) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request - Adds two simple animated shaders to the pixel shaders sample folder - Updates the readme in the pixel shaders sample folder to add a section explaining the animated shaders - Modifies some comments in existing shader samples <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #8994 <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments The two shaders I wrote are not especially pretty or interesting, but they should hopefully serve as simple examples for anyone looking to do animated effects. One simply draws a line of inverted pixels that scrolls down the screen, and the other fades the background back and forth between two colors. I've added a new section to the readme explaining how the shaders work to achieve animated effects. I've also updated the comments on the existing shaders to clear up a couple of things: 1. Be more explicit that `Time` represents seconds since the shader loaded. Though obvious in hindsight, this was not clear to me when I was first learning/experimenting 2. Explain that `tex` ranges from 0,0 to 1,1. This is important because, when trying to port GLSL shaders from shadertoy, I at first assumed `fragCoord` and `tex` are the same thing but the former actually ranges from 0,0 to the resolution of the canvas, so some of the math doesn't work out if you just substitute it with `tex`. Any and all feedback welcome. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed I ran the shaders manually in a dev build of the Terminal. I auto-spellchecked and manually proofread my additions to the readme and verifed the markdown rendering on github.
2021-02-04 14:53:21 +01:00
// A pixel shader is a program that given a texture coordinate (tex) produces a color.
// tex is an x,y tuple that ranges from 0,0 (top left) to 1,1 (bottom right).
// Just ignore the pos parameter.
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
{
// Read the color value at the current texture coordinate (tex)
// float4 is tuple of 4 floats, rgba
float4 color = shaderTexture.Sample(samplerState, tex);
// Inverts the rgb values (xyz) but don't touch the alpha (w)
color.xyz = 1.0 - color.xyz;
// Return the final color
return color;
}
```
Save this file as `C:\temp\invert.hlsl`, then update a profile with the setting:
```
"experimental.pixelShaderPath": "C:\\temp\\invert.hlsl"
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
```
Once the settings file is saved, open a terminal with the changed profile. It should now invert the colors of the screen!
Default Terminal | Inverted Terminal
---------|---------
![Default Terminal](Screenshots/TerminalDefault.PNG) | ![Inverted Terminal](Screenshots/TerminalInvert.PNG)
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
If your shader fails to compile, the Terminal will display a warning dialog and ignore it temporarily. After fixing your shader, touch the `settings.json` file again, or open a new tab, and the Terminal will try loading the shader again.
## HLSL
The language we use to write pixel shaders is called `HLSL`. It's a `C`-like language, with some restrictions. You can't allocate memory, use pointers or recursion.
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
What you get access to is computing power in the teraflop range on decently recent GPUs. This means writing real-time raytracers or other cool effects are in the realm of possibility.
[shadertoy](https://shadertoy.com/) is a great site that show case what's possible with pixel shaders (albeit in `GLSL`). For example this [menger sponge](https://www.shadertoy.com/view/4scXzn). Converting from `GLSL` to `HLSL` isn't overly hard once you gotten the hang of it.
## Adding some retro raster bars
Let's try a more complicated example. Raster bars was cool in the 80's, so let's add that. Start by modifying shader like so: (This is `Rasterbars.hlsl`)
```hlsl
// A minimal pixel shader that shows some raster bars
// The terminal graphics as a texture
Texture2D shaderTexture;
SamplerState samplerState;
// Terminal settings such as the resolution of the texture
cbuffer PixelShaderSettings {
Add animated shader samples (#9026) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request - Adds two simple animated shaders to the pixel shaders sample folder - Updates the readme in the pixel shaders sample folder to add a section explaining the animated shaders - Modifies some comments in existing shader samples <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #8994 <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments The two shaders I wrote are not especially pretty or interesting, but they should hopefully serve as simple examples for anyone looking to do animated effects. One simply draws a line of inverted pixels that scrolls down the screen, and the other fades the background back and forth between two colors. I've added a new section to the readme explaining how the shaders work to achieve animated effects. I've also updated the comments on the existing shaders to clear up a couple of things: 1. Be more explicit that `Time` represents seconds since the shader loaded. Though obvious in hindsight, this was not clear to me when I was first learning/experimenting 2. Explain that `tex` ranges from 0,0 to 1,1. This is important because, when trying to port GLSL shaders from shadertoy, I at first assumed `fragCoord` and `tex` are the same thing but the former actually ranges from 0,0 to the resolution of the canvas, so some of the math doesn't work out if you just substitute it with `tex`. Any and all feedback welcome. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed I ran the shaders manually in a dev build of the Terminal. I auto-spellchecked and manually proofread my additions to the readme and verifed the markdown rendering on github.
2021-02-04 14:53:21 +01:00
// The number of seconds since the pixel shader was enabled
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
float Time;
// UI Scale
float Scale;
// Resolution of the shaderTexture
float2 Resolution;
// Background color as rgba
float4 Background;
};
Add animated shader samples (#9026) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request - Adds two simple animated shaders to the pixel shaders sample folder - Updates the readme in the pixel shaders sample folder to add a section explaining the animated shaders - Modifies some comments in existing shader samples <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #8994 <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments The two shaders I wrote are not especially pretty or interesting, but they should hopefully serve as simple examples for anyone looking to do animated effects. One simply draws a line of inverted pixels that scrolls down the screen, and the other fades the background back and forth between two colors. I've added a new section to the readme explaining how the shaders work to achieve animated effects. I've also updated the comments on the existing shaders to clear up a couple of things: 1. Be more explicit that `Time` represents seconds since the shader loaded. Though obvious in hindsight, this was not clear to me when I was first learning/experimenting 2. Explain that `tex` ranges from 0,0 to 1,1. This is important because, when trying to port GLSL shaders from shadertoy, I at first assumed `fragCoord` and `tex` are the same thing but the former actually ranges from 0,0 to the resolution of the canvas, so some of the math doesn't work out if you just substitute it with `tex`. Any and all feedback welcome. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed I ran the shaders manually in a dev build of the Terminal. I auto-spellchecked and manually proofread my additions to the readme and verifed the markdown rendering on github.
2021-02-04 14:53:21 +01:00
// A pixel shader is a program that given a texture coordinate (tex) produces a color.
// tex is an x,y tuple that ranges from 0,0 (top left) to 1,1 (bottom right).
// Just ignore the pos parameter.
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
{
// Read the color value at the current texture coordinate (tex)
// float4 is tuple of 4 floats, rgba
float4 color = shaderTexture.Sample(samplerState, tex);
// Read the color value at some offset, will be used as shadow
float4 ocolor = shaderTexture.Sample(samplerState, tex+2.0*Scale*float2(-1.0, -1.0)/Resolution.y);
// Thickness of raster
const float thickness = 0.1;
float ny = floor(tex.y/thickness);
float my = tex.y%thickness;
const float pi = 3.141592654;
// ny is used to compute the rasterbar base color
float cola = ny*2.0*pi;
float3 col = 0.75+0.25*float3(sin(cola*0.111), sin(cola*0.222), sin(cola*0.333));
// my is used to compute the rasterbar brightness
// smoothstep is a great little function: https://en.wikipedia.org/wiki/Smoothstep
float brightness = 1.0-smoothstep(0.0, thickness*0.5, abs(my - 0.5*thickness));
float3 rasterColor = col*brightness;
// lerp(x, y, a) is another very useful function: https://en.wikipedia.org/wiki/Linear_interpolation
float3 final = rasterColor;
// Create the drop shadow of the terminal graphics
// .w is the alpha channel, 0 is fully transparent and 1 is fully opaque
final = lerp(final, float(0.0), ocolor.w);
// Draw the terminal graphics
final = lerp(final, color.xyz, color.w);
// Return the final color, set alpha to 1 (ie opaque)
return float4(final, 1.0);
}
```
Once reloaded, it should show some retro raster bars in the background, with a drop shadow to make the text more readable.
![Rasterbars](Screenshots/TerminalRasterbars.PNG)
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00
## Retro Terminal Effect
As a more complicated example, the Terminal's built-in `experimental.retroTerminalEffect` is included as the `Retro.hlsl` file in this directory.
![Retro](Screenshots/TerminalRetro.PNG)
Add animated shader samples (#9026) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request - Adds two simple animated shaders to the pixel shaders sample folder - Updates the readme in the pixel shaders sample folder to add a section explaining the animated shaders - Modifies some comments in existing shader samples <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #8994 <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments The two shaders I wrote are not especially pretty or interesting, but they should hopefully serve as simple examples for anyone looking to do animated effects. One simply draws a line of inverted pixels that scrolls down the screen, and the other fades the background back and forth between two colors. I've added a new section to the readme explaining how the shaders work to achieve animated effects. I've also updated the comments on the existing shaders to clear up a couple of things: 1. Be more explicit that `Time` represents seconds since the shader loaded. Though obvious in hindsight, this was not clear to me when I was first learning/experimenting 2. Explain that `tex` ranges from 0,0 to 1,1. This is important because, when trying to port GLSL shaders from shadertoy, I at first assumed `fragCoord` and `tex` are the same thing but the former actually ranges from 0,0 to the resolution of the canvas, so some of the math doesn't work out if you just substitute it with `tex`. Any and all feedback welcome. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed I ran the shaders manually in a dev build of the Terminal. I auto-spellchecked and manually proofread my additions to the readme and verifed the markdown rendering on github.
2021-02-04 14:53:21 +01:00
## Animated Effects
You can use the `Time` value in the shader input settings to drive animated effects. `Time` is the number of seconds since the shader first loaded. Heres a simple example with a line of inverted pixels that scrolls down the terminal (`Animate_scan.hlsl`):
```hlsl
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
{
// Read the color value at the current texture coordinate (tex)
float4 color = shaderTexture.Sample(samplerState, tex);
// Here we spread the animation over 5 seconds. We use time modulo 5 because we want
// the timer to count to five repeatedly. We then divide the result by five again
// to get a value between 0.0 and 1.0, which maps to our texture coordinate.
float linePosition = Time % 5 / 5;
// Since TEXCOORD ranges from 0.0 to 1.0, we need to divide 1.0 by the height of the
// texture to find out the size of a single pixel
float lineWidth = 1.0 / Resolution.y;
// If the current texture coordinate is in the range of our line on the Y axis:
if (tex.y > linePosition - lineWidth && tex.y < linePosition)
{
// Invert the sampled color
color.rgb = 1.0 - color.rgb;
}
return color;
}
```
What if we want an animation that goes backwards and forwards? In this example (`Animate_breathe.hlsl`), we'll make the background fade between two colours. Our `Time` value only ever goes up, so we need a way to generate a value that sweeps back and forth from `0.0` to `1.0`. Trigonometric functions like cosine are perfect for this and are very frequently used in shaders.
`cos()` outputs a value between `-1.0` and `1.0`. We can adjust the wave with the following formula:
```
a * cos(b * (x - c)) + d
```
Where `a` adjusts the amplitude, `b` adjusts the wavelength/frequency, `c` adjusts the offset along the x axis, and `d` adjusts the offset along the y axis. You can use a graphing calculator (such as the Windows Calculator) to help visualize the output and experiment:
![Cosine](Screenshots/GraphCosine.png)
As shown above, by halving the output and then adding `0.5`, we can shift the range of the function to `0.0` - `1.0`. Because `cos()` takes input in radians, if we multiply `x` (`Time`) by tau (`2*pi`), we are effectively setting the wavelength to `1.0`.
In other words, our full animation will be one second long. We can modify this duration by dividing tau by the number of seconds we want the animation to run for. In this case, well go for five seconds.
Finally we use linear interpolation to achieve our breathing effect by selecting a color between our two chosen colors based on the output from our cosine.
```hlsl
// pi and tau (2 * pi) are useful constants when using trigonometric functions
#define TAU 6.28318530718
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
{
// Read the color value at the current texture coordinate (tex)
float4 sample = shaderTexture.Sample(samplerState, tex);
// The number of seconds the breathing effect should span
float duration = 5.0;
float3 color1 = float3(0.3, 0.0, 0.5); // indigo
float3 color2 = float3(0.1, 0.1, 0.44); // midnight blue
// Set background colour based on the time
float4 backgroundColor = float4(lerp(color1, color2, 0.5 * cos(TAU / duration * Time) + 0.5), 1.0);
// Draw the terminal graphics over the background
return lerp(backgroundColor, sample, sample.w);
}
```
Feel free to modify and experiment!
Implement user-specified pixel shaders, redux (#8565) Co-authored-by: mrange <marten_range@hotmail.com> I loved the pixel shaders in #7058, but that PR needed a bit of polish to be ready for ingestion. This PR is almost _exactly_ that PR, with some small changes. * It adds a new pre-profile setting `"experimental.pixelShaderPath"`, which lets the user set a pixel shader to use with the Terminal. - CHANGED FROM #7058: It does _not_ add any built-in shaders. - CHANGED FROM #7058: it will _override_ `experimental.retroTerminalEffect` * It adds a bunch of sample shaders in `samples/shaders`. Included: - A NOP shader as a base to build from. - An "invert" shader that inverts the colors, as a simple example - An "grayscale" shader that converts all colors to grayscale, as a simple example - An "raster bars" shader that draws some colored bars on the screen with a drop shadow, as a more involved example - The original retro terminal effects, as a more involved example - It also includes a broken shader, as an example of what heppens when the shader fails to compile - CHANGED FROM #7058: It does _not_ add the "retroII" shader we were all worried about. * When a shader fails to be found or fails to compile, we'll display an error dialog to the user with a relevant error message. - CHANGED FROM #7058: Originally, #7058 would display "error bars" on the screen. I've removed that, and had the Terminal disable the shader entirely then. * Renames the `toggleRetroEffect` action to `toggleShaderEffect`. (`toggleRetroEffect` is now an alias to `toggleShaderEffect`). This action will turn the shader OR the retro effects on/off. `toggleShaderEffect` works the way you'd expect it to, but the mental math on _how_ is a little weird. The logic is basically: ``` useShader = shaderEffectsEnabled ? (pixelShaderProvided ? pixelShader : (retroEffectEnabled ? retroEffect : null ) ) : null ``` and `toggleShaderEffect` toggles `shaderEffectsEnabled`. * If you've got both a shader and retro enabled, `toggleShaderEffect` will toggle between the shader on/off. * If you've got a shader and retro disabled, `toggleShaderEffect` will toggle between the shader on/off. References #6191 References #7058 Closes #7013 Closes #3930 "Add setting to retro terminal shader to control blur radius, color" Closes #3929 "Add setting to retro terminal shader to enable drawing scanlines" - At this point, just roll your own version of the shader.
2020-12-15 21:40:22 +01:00