Skip to content

Commit efc1869

Browse files
committed
tracking 7.5; number steps and mgcb screenshot
1 parent aac4d2d commit efc1869

File tree

2 files changed

+39
-32
lines changed
  • articles/tutorials/advanced/2d_shaders/07_sprite_vertex_effect

2 files changed

+39
-32
lines changed
51.1 KB
Loading

articles/tutorials/advanced/2d_shaders/07_sprite_vertex_effect/index.md

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,15 @@ Now that you understand the default vertex shader being used by `SpriteBatch`, w
123123
1. convert the vertices from world-space to clip-space
124124
2. provide the input semantics required for the pixel shader.
125125

126-
To experiment with this, create a new Sprite Effect called `3dEffect` in the _MonoGameLibrary_'s shared content effects folder. We need to add a vertex shader function. To do that, we need a new `struct` that holds all the input semantics passed from `SpriteBatch`:
126+
To experiment with this, create a new Sprite Effect called `3dEffect` in the _MonoGameLibrary_'s shared content effects folder.
127+
128+
| ![Figure 7-3: Adding the `3dEffect` to MGCB](./images/mgcb.png) |
129+
| :----------------------------------------------------------------------------------------: |
130+
| **Figure 7-3: Adding the `3dEffect` to MGCB** |
131+
132+
Follow along with the steps to set up the effect.
133+
134+
1. We need to add a vertex shader function. To do that, we need a new `struct` that holds all the input semantics passed from `SpriteBatch`:
127135

128136
> [!tip]
129137
> Use a struct for inputs and outputs.
@@ -132,45 +140,44 @@ To experiment with this, create a new Sprite Effect called `3dEffect` in the _Mo
132140
133141
[!code-hlsl[](./snippets/snippet-7-09.hlsl)]
134142

135-
Now add the stub for the vertex shader function:
143+
2. Now add the stub for the vertex shader function:
136144

137145
[!code-hlsl[](./snippets/snippet-7-10.hlsl)]
138146

139-
And finally modify the `technique` to _include_ the vertex shader function. Until now, the `MainVS()` function is just considered as any average function in your shader, and since it wasn't used from the `MainPS` pixel shader, it would be compiled out of the shader. When you specify the `MainVS()` function as the vertex shader function, you are overriding the default `SpriteBatch` vertex shader function:
147+
3. And finally modify the `technique` to _include_ the vertex shader function. Until now, the `MainVS()` function is just considered as any average function in your shader, and since it wasn't used from the `MainPS` pixel shader, it would be compiled out of the shader. When you specify the `MainVS()` function as the vertex shader function, you are overriding the default `SpriteBatch` vertex shader function:
140148

141149
[!code-hlsl[](./snippets/snippet-7-11.hlsl)]
142150

143-
The shader will not compile yet, because the `VertexShaderOutput` has not been completely initialized. We need to replicate the `MatrixTransform` step to convert the vertices from world-space to clip-space.
144-
145-
Add the `MatrixTransform` shader parameter:
151+
4. The shader will not compile yet, because the `VertexShaderOutput` has not been completely initialized. We need to replicate the `MatrixTransform` step to convert the vertices from world-space to clip-space.
152+
Add the `MatrixTransform` shader parameter:
146153

147154
[!code-hlsl[](./snippets/snippet-7-12.hlsl)]
148155

149-
And then assign all of the output semantics in the vertex shader:
156+
5. And then assign all of the output semantics in the vertex shader:
150157

151158
[!code-hlsl[](./snippets/snippet-7-13.hlsl)]
152159

153-
To validate this is working, we should try to use the new effect. For now, we will experiment in the `TitleScene`. Create a class member for the new `Material`:
160+
6. To validate this is working, we should try to use the new effect. For now, we will experiment in the `TitleScene`. Create a class member for the new `Material`:
154161

155162
[!code-csharp[](./snippets/snippet-7-14.cs)]
156163

157-
Load the shader using the hot reload system:
164+
7. Load the shader using the hot reload system:
158165

159166
[!code-csharp[](./snippets/snippet-7-15.cs)]
160167

161-
And then use the effect when drawing the title text:
168+
8. And then use the effect when drawing the title text:
162169

163170
[!code-csharp[](./snippets/snippet-7-16.cs)]
164171

165-
When the game runs, the text will be missing. This is because we never created a projection matrix to assign to the `MatrixTransform` shader parameter. Add this code when loading the material:
172+
9. When the game runs, the text will be missing. This is because we never created a projection matrix to assign to the `MatrixTransform` shader parameter. Add this code when loading the material:
166173

167174
[!code-csharp[](./snippets/snippet-7-17.cs)]
168175

169-
And now you should see the text normally again.
176+
10. And now you should see the text normally again.
170177

171-
| ![Figure 7-3: The main menu, but rendered with a custom vertex shader](./images/basic.png) |
178+
| ![Figure 7-4: The main menu, but rendered with a custom vertex shader](./images/basic.png) |
172179
| :----------------------------------------------------------------------------------------: |
173-
| **Figure 7-3: The main menu, but rendered with a custom vertex shader** |
180+
| **Figure 7-4: The main menu, but rendered with a custom vertex shader** |
174181

175182
### Making it Move
176183

@@ -184,19 +191,19 @@ And change the vertex shader to add the `DebugOffset` to the `output.Position` a
184191

185192
The sprites now move around as we adjust the shader parameter values.
186193

187-
| ![Figure 7-4: We can control the vertex positions](./gifs/basic.gif) |
194+
| ![Figure 7-5: We can control the vertex positions](./gifs/basic.gif) |
188195
| :------------------------------------------------------------------: |
189-
| **Figure 7-4: We can control the vertex positions** |
196+
| **Figure 7-5: We can control the vertex positions** |
190197

191198
It is important to build intuition for the different coordinate systems involved. Instead of adding the `DebugOffset` _after_ the clip-space conversion, if you try to add it _before_, like in the code below:
192199

193200
[!code-hlsl[](./snippets/snippet-7-20.hlsl)]
194201

195202
Then you will not see much movement at all. This is because the `DebugOffset` values only go from `0` to `1`, and in world space, this really only amounts to a single pixel. In fact, exactly how much an addition of _`1`_ happens to make is entirely defined _by_ the conversion to clip-space. The `projection` matrix we created treats world space coordinates with an origin around the screen's center, where 1 unit maps to 1 pixel. Sometimes this is exactly what you want, and sometimes it can be confusing.
196203

197-
| ![Figure 7-5: Changing coordinates before clip-space conversion](./gifs/basic-2.gif) |
204+
| ![Figure 7-6: Changing coordinates before clip-space conversion](./gifs/basic-2.gif) |
198205
| :----------------------------------------------------------------------------------: |
199-
| **Figure 7-5: Changing coordinates before clip-space conversion** |
206+
| **Figure 7-6: Changing coordinates before clip-space conversion** |
200207

201208
### Perspective Projection
202209

@@ -239,25 +246,25 @@ Moving the `z` value uniformly in the shader will not be visually stimulating. A
239246

240247
And now when the debug parameter is adjusted, the text spins in a way that was never possible with the default `SpriteBatch` vertex shader.
241248

242-
| ![Figure 7-6: A spinning text](./gifs/spin-1.gif) |
249+
| ![Figure 7-7: A spinning text](./gifs/spin-1.gif) |
243250
| :-----------------------------------------------: |
244-
| **Figure 7-6: A spinning text** |
251+
| **Figure 7-7: A spinning text** |
245252

246253
The text disappears for half of the rotation. That happens because as the vertices are rotated, the triangle itself started to point _away_ from the camera. By default, `SpriteBatch` will cull any faces that point away from the camera. Change the `rasterizerState` to `CullNone` when beginning the sprite batch:
247254

248255
[!code-csharp[](./snippets/snippet-7-26.cs)]
249256

250257
And voilà, the text no longer disappears on its flip side.
251258

252-
| ![Figure 7-7: A spinning text with reverse sides](./gifs/spin-2.gif) |
259+
| ![Figure 7-8: A spinning text with reverse sides](./gifs/spin-2.gif) |
253260
| :------------------------------------------------------------------: |
254-
| **Figure 7-7: A spinning text with reverse sides** |
261+
| **Figure 7-8: A spinning text with reverse sides** |
255262

256263
You may find that the field of view is too high for your taste. Try lowering the field of view to 60, and you'll see something similar to this,
257264

258-
| ![Figure 7-8: A spinning text with reverse sides with smaller fov](./gifs/spin-3.gif) |
265+
| ![Figure 7-9: A spinning text with reverse sides with smaller fov](./gifs/spin-3.gif) |
259266
| :-----------------------------------------------------------------------------------: |
260-
| **Figure 7-8: A spinning text with reverse sides with smaller fov** |
267+
| **Figure 7-9: A spinning text with reverse sides with smaller fov** |
261268

262269
As a final touch, we should remove the hard-coded `screenSize` variable from the shader, and extract it as a shader parameter. While we are at it, clean up and remove the debug parameters as well:
263270

@@ -271,9 +278,9 @@ And instead of manually controlling the spin angle, we can make the title spin g
271278

272279
[!code-csharp[](./snippets/snippet-7-29.cs)]
273280

274-
| ![Figure 7-9: Spin controlled by the mouse](./gifs/spin-4.gif) |
281+
| ![Figure 7-10: Spin controlled by the mouse](./gifs/spin-4.gif) |
275282
| :------------------------------------------------------------: |
276-
| **Figure 7-9: Spin controlled by the mouse** |
283+
| **Figure 7-10: Spin controlled by the mouse** |
277284

278285
## Applying it to the Game
279286

@@ -359,9 +366,9 @@ And then apply all of the parameters to the single material:
359366

360367
Any place where the old `_colorSwapMaterial` is being referenced should be changed to use the `_gameMaterial` instead. Now, if you run the game, the color swap controls are still visible, but we can also manually control the tilt of the map.
361368

362-
| ![Figure 7-10: All of the effects in one](./gifs/uber.gif) |
369+
| ![Figure 7-11: All of the effects in one](./gifs/uber.gif) |
363370
| :-------------------------------------------------------: |
364-
| **Figure 7-10: All of the effects in one** |
371+
| **Figure 7-11: All of the effects in one** |
365372

366373
### Adjusting the Game
367374

@@ -371,19 +378,19 @@ Add this snippet to the top of the `GameScene`'s `Update()` method:
371378

372379
[!code-csharp[](./snippets/snippet-7-43.cs)]
373380

374-
| ![Figure 7-11: Camera follows the slime](./gifs/cam-follow.gif) |
381+
| ![Figure 7-12: Camera follows the slime](./gifs/cam-follow.gif) |
375382
| :------------------------------------------------------------: |
376-
| **Figure 7-11: Camera follows the slime** |
383+
| **Figure 7-12: Camera follows the slime** |
377384

378385
The clear color of the scene can be seen in the corners (the `CornflowerBlue`). Pick whatever clear color you think looks good for the color swapping:
379386

380387
[!code-csharp[](./snippets/snippet-7-44.cs)]
381388

382389
And to finish this chapter, the game looks like this,
383390

384-
| ![Figure 7-12: vertex shaders make it pop](./gifs/final.gif) |
391+
| ![Figure 7-13: vertex shaders make it pop](./gifs/final.gif) |
385392
| :---------------------------------------------------------: |
386-
| **Figure 7-12: vertex shaders make it pop** |
393+
| **Figure 7-13: vertex shaders make it pop** |
387394

388395
## Conclusion
389396

0 commit comments

Comments
 (0)