You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+134-8Lines changed: 134 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Unity-Shader-Basics-Tutorial
2
2
3
-
Welcome, this tutorial is supposed to be a gentle introduction into writing shaders for Unity. It assume you have some previous knowledge in working with Unity but have never touched shaders or materials.
3
+
Welcome, this tutorial is supposed to be a gentle introduction into writing shaders for Unity. It assumes you have some previous knowledge in working with Unity but have never touched shaders or materials.
4
4
5
5
We'll be building up the shader in parts, stopping along the way to show what everything does.
First thing we'll do is get the correct positions of the vertices. We'll do this using a function called UnityObjectToClipPos() like so:
310
+
```
311
+
v2f vertexFunction (appdata IN) {
312
+
v2f OUT;
313
+
314
+
OUT.position = UnityObjectToClipPos(IN.vertex);
315
+
316
+
return OUT;
317
+
}
318
+
```
319
+
What this function does is take a vertex that is represented in local object space, and tranforms it into the rendering camera's clip space. Notice we're passing along the transformed point by setting OUT.position's value.
320
+
Next, we'll give an output to our fragment function:
321
+
```
322
+
fixed4 fragmentFunction (v2f IN) : SV_TARGET {
323
+
return fixed4(0, 1, 0, 1); //(R, G, B, A)
324
+
}
325
+
```
326
+
And now, the moment you've been waiting for! Save your shader and return to Unity and you'll see our beautiful green objects!
Okay, this probably not that impressive to you, so lets keep building. How about, instead of returning a basic green colour, we edit our shader to return any colour we want? What we'll need to do to achieve this is start working with custom properties.
331
+
332
+
We can add properties we want to use by following this syntax:
333
+
```
334
+
name ("display name", type) = default value
335
+
```
336
+
So for example, we'll expose a colour value like so:
337
+
```
338
+
Properties {
339
+
_Colour ("Totally Rad Colour!", Color) = (1, 1, 1, 1)
340
+
}
341
+
```
342
+
Here we're defining a colour for us to use, called *_Colour* and it will be shown as "Totally Rad Colour!" in the Unity inspector. We're also giving it a default value of white.
343
+
If you save and return to Unity now, when inspect the material, you should see this:
Before we can use this colour, we need to actually pass it into the CG code. Unity does this automatically by binding it by variable name like so:
348
+
349
+
```
350
+
CGPROGRAM
351
+
#pragma vertex vertexFunction
352
+
#pragma fragment fragmentFunction
353
+
354
+
#include "UnityCG.cginc"
355
+
356
+
struct appdata {
357
+
float4 vertex : POSITION;
358
+
float2 uv : TEXCOORD0;
359
+
};
360
+
361
+
struct v2f {
362
+
float4 position : SV_POSITION;
363
+
float2 uv : TEXCOORD0;
364
+
};
365
+
366
+
//Get our properties into CG
367
+
float4 _Colour;
368
+
369
+
v2f vertexFunction (appdata IN) {
370
+
v2f OUT;
371
+
OUT.position = UnityObjectToClipPos(IN.vertex);
372
+
return OUT;
373
+
}
374
+
375
+
fixed4 fragmentFunction (v2f IN) : SV_TARGET {
376
+
return fixed4(0, 1, 0, 1);
377
+
}
378
+
ENDCG
379
+
```
380
+
*I like to put properties after my structs to keep my code organized, but you can put it anywhere so long as its in the top scope of the CGPROGRAM*
381
+
382
+
We can now use our _Colour value in our fragment function. Instead of returning that green, lets just return whatever colour we want:
383
+
```
384
+
fixed4 fragmentFunction (v2f IN) : SV_TARGET {
385
+
return _Colour;
386
+
}
387
+
```
388
+
And now, we can save and return to Unity. If you inspect the material and start changing our colour value, you should see all the colours of the objects change accordingly!
Since we now know how to add properties, lets try adding a standard texture map. We'll need a new property for our texture:
393
+
394
+
```
395
+
Properties {
396
+
_Colour ("Colour", Color) = (1, 1, 1, 1)
397
+
_MainTexture ("Main Texture", 2D) = "white" {}
398
+
}
399
+
```
400
+
Notice how it's of type *2D* (2D Texture), and we're defaulting to a blank white texture. We've also need to get the property into CG to use it:
401
+
402
+
```
403
+
float4 _Colour;
404
+
sampler2D _MainTexture;
405
+
```
406
+
Then, we need to give our fragment function the UV coordinates from the model. We can do this by going back to our vertex function and passing them into the v2f struct we return like so:
407
+
408
+
```
409
+
v2f vertexFunction (appdata IN) {
410
+
v2f OUT;
411
+
OUT.position = UnityObjectToClipPos(IN.vertex);
412
+
OUT.uv = IN.uv;
413
+
return OUT;
414
+
}
415
+
```
416
+
Now in order to use the colours from the texture for our fragment function, we need to *sample* it as certain points. Thankfully, CG has a function that does this for us, called *tex2D*.
417
+
418
+
```
419
+
fixed4 fragmentFunction (v2f IN) : SV_TARGET {
420
+
return tex2D(_MainTexture, IN.uv);
421
+
}
422
+
```
423
+
tex2D takes in the texture (ie: sample2D) we want to sample, and the UV coordinate we want to sample with. In this case, we're providing it with out main texture and giving it the point on the model where we want to get the colour from, then returning that result as our final colour. Now, if you save and return back to Unity and inspect the material, we can select the bowl texture for our "Main Texture". You'll see the models update, and the bowl model in particular (the model the texture was made for) should look like a bowl of soup!
0 commit comments