Skip to content

Commit a7d3c48

Browse files
committed
chapter 3 updates
1 parent f6094a5 commit a7d3c48

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

articles/tutorials/advanced/2d_shaders/02_hot_reload/snippets/snippet-2-37.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public static void StartContentWatcherTask()
3030

3131
// if no valid project was identified, then it is impossible to start the watcher
3232
if (string.IsNullOrEmpty(projectDirectory)) return;
33-
33+
3434
// start the watcher process
3535
var process = Process.Start(new ProcessStartInfo
3636
{
@@ -41,7 +41,7 @@ public static void StartContentWatcherTask()
4141
UseShellExecute = false,
4242
CreateNoWindow = false
4343
});
44-
44+
4545
// when this program exits, make sure to emit a kill signal to the watcher process
4646
AppDomain.CurrentDomain.ProcessExit += (_, __) =>
4747
{
@@ -57,4 +57,18 @@ public static void StartContentWatcherTask()
5757
/* ignore */
5858
}
5959
};
60+
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
61+
{
62+
try
63+
{
64+
if (!process.HasExited)
65+
{
66+
process.Kill(entireProcessTree: true);
67+
}
68+
}
69+
catch
70+
{
71+
/* ignore */
72+
}
73+
};
6074
}

articles/tutorials/advanced/2d_shaders/03_the_material_class/index.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: "Chapter 03: The Material Class"
33
description: "Create a wrapper class to help manage shaders"
44
---
55

6-
In [Chapter 24](../../../building_2d_games/24_shaders/index.md) of the original [2D Game Series](../../../building_2d_games/index.md), you learned about MonoGame's [`Effect`](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) class. When `.fx` shaders are compiled, the compiled code is then loaded into MonoGame as an `Effect` instance. The `Effect` class provides a few powerful utilities for setting shader parameters, but otherwise, it is a fairly bare-bones container for the compiled shader code.
6+
In [Chapter 24](../../../building_2d_games/24_shaders/index.md) of the original [2D Game Series](../../../building_2d_games/index.md), you learned about MonoGame's [`Effect`](xref:Microsoft.Xna.Framework.Graphics.Effect) class. When `.fx` shaders are compiled, the compiled code is then loaded into MonoGame as an `Effect` instance. The `Effect` class provides a few powerful utilities for setting shader parameters, but otherwise, it is a fairly bare-bones container for the compiled shader code.
77

88
> [!NOTE]
99
> MonoGame also ships with standard `Effect` sub-classes that can be useful for bootstrapping a game without needing to write any custom shader code. However, all of these standard `Effect` types are geared towards 3D games, except for _1_, called the [`SpriteEffect`](xref:Microsoft.Xna.Framework.Graphics.SpriteEffect). This will be discussed in [Chapter 7: Sprite Vertex Effect](../07_sprite_vertex_effect/index.md).
@@ -19,7 +19,7 @@ If you are following along with code, here is the code from the end of the [prev
1919
2020
## The Material Class
2121

22-
The `_grayscaleEffect` serves a very specific purpose, but imagine instead of just _decreasing_ the saturation, the effect could also _increase_ the saturation. In that hypothetical, then calling it a "grayscale" effect only captures _some_ of the shader's value. Setting the `Saturation` to `0` would configure the shader to be a grayscale effect, but setting the `Saturation` really high would configure the shader to be a super-saturation effect. A single shader can configured to create multiple distinct visuals. Many game engines use the term, _Material_, to recognize each _configuration_ of a shader effect.
22+
The `_grayscaleEffect` serves a very specific purpose, but imagine instead of just _decreasing_ the saturation, the effect could also _increase_ the saturation. In that hypothetical, then calling it a "grayscale" effect only captures _some_ of the shader's value. Setting the `Saturation` to `0` would configure the shader to be a grayscale effect, but setting the `Saturation` really high would configure the shader to be a super-saturation effect. A single shader can be configured to create multiple distinct visuals. Many game engines use the term, _Material_, to recognize each _configuration_ of a shader effect.
2323

2424
A material definition represents a compiled `Effect` **and** the runtime configuration for the `Effect`. For example, the `_grayscaleEffect` shader has a single property called `Saturation`. The _**value**_ of the property is essential to the existence of the `_grayscaleEffect`. It would also be useful to have logic that _owns_ these shader parameter values.
2525

@@ -80,11 +80,14 @@ For example, in the `grayscaleEffect.fx` file, change the last few lines of the
8080

8181
[!code-hlsl[](./snippets/snippet-3-08.hlsl?highlight=17-18)]
8282

83-
If you run the game and enter the `GameScene`, you will see a `NullReferenceException` (and the game will hard-crash) when the greyscale effect is used, e.g. Game Over. The `Saturation` shader parameter no longer exists in the shader because it was stripped out, so when the `Draw()` method tries to _set_ it, the game crashes.
83+
If you run the game, enter the `GameScene`, and wait for the game over screen to appear, you will see a `NullReferenceException` (and the game will hard-crash) when the greyscale effect is used, e.g. Game Over. The `Saturation` shader parameter no longer exists in the shader because it was stripped out, so when the `Draw()` method tries to _set_ it, the game crashes.
8484

8585
> [!NOTE]
8686
> Leave this change in for now, to demonstrate the way to handle this error through extensions in the `Material` class.
8787
88+
> [!NOTE]
89+
> You may not _actually_ see the `NullReferenceException`, because the `DungeonSlime.csproj` is configured to be a `WinExe`, which means the standard error and output of the application are hidden. The game may appear to _just_ crash with no warning. You can change the `OutputType` to `Exe`, which means you will see the standard error directed to the terminal.
90+
8891
The aggressive optimization is good for your game's performance, but when combined with the hot-reload system, it will lead to unexpected bugs. As you iterate on shader code, it is likely that at some point a shader parameter will be optimized out of the compiled shader. The hot-reload system will automatically load the newly compiled shader, and if the C# code attempts to set the previously available parameter, the game may crash.
8992

9093
To solve this problem, the `Material` class can encapsulate the setting of shader properties and handle the potential error scenario. The `Effect.Parameters` variable is an instance of the [`EffectParameterCollection`](xref:Microsoft.Xna.Framework.Graphics.EffectParameterCollection) class.

0 commit comments

Comments
 (0)