Skip to content

Instantly share code, notes, and snippets.

@kraj0t
Last active July 25, 2025 20:02
Show Gist options
  • Save kraj0t/c5a3c79c8b35904a83d0d99104dbb7c0 to your computer and use it in GitHub Desktop.
Save kraj0t/c5a3c79c8b35904a83d0d99104dbb7c0 to your computer and use it in GitHub Desktop.
Shader notes, tips and tricks

Misc

  • Use [ToggleUI] attribute for checkboxes. Never use [Toggle] as it implicitly creates a keyword.
  • Apply default textures to shaders in their inspector.
  • Related to the previous point, the [NonModifiableTextureData] attribute forbids the user from assigning a different texture.
  • Remember that there are special HLSL semantics that are rarely used, such as SV_Depth or SV_Face
  • Add #pragma editor_sync_compilation to avoid the cyan color blink when shader gets recompiled

Links of interest

  • Many Gists by Ben Golus here
  • Shader tricks for VRChat by Perma99 here
  • Orel's tips (check the shader section) here

Reconstruct faceted normal from position

normalWS = normalize(cross(ddy(IN.positionWS), ddx(IN.positionWS)));


_ScreenParams vs _ScreenSize

Unity documentation is wrong when it explains _ScreenParams, and _ScreenSize is not documented. _ScreenParams contains the actual screen size, while _ScreenSize contains the size of the camera’s target texture. This is important because the camera's texture (the buffer) can vary with Render Scale. Also, note that the .z and .w components are calculated differently.

Use custom clamp & filtering for textures

You don't always have to respect the settings defined in the texture's import settings. Instead of using SAMPLER(sampler_MyTex) you can hardcode the sampling.

In GlobalSamplers.hlsl 6 different samplers are defined. If those 6 are not enough, you can define a custom texture sampler when a shader needs a specific sampling by defining it like this: SamplerState my_point_clamp_sampler;

This is useful in case your shader must use certain sampling mode, or if the texture is a global texture without a sampler, or if the shader's texture properties are hidden from the user.

For example, if your shader must always work with trilinear filtering, such as for reflection cubemaps, you could use sampler_TrilinearClamp.

Also, as stated in GlobalSamplers.hlsl, there is a limit to how many active samplers a shader can have.


How to check if a texture has not been defined

If a texture is undefined in the material, then it will use the built-in texture. Since those textures are at most 4x4, we can check the size of the texture in the shader and avoid having another boolean that the artist needs to set:

if (_MyTexture_TexelSize.z > 4)

This also applies to global textures that may not have been set, such as the _CameraOpaqueBuffer.


Default values for texture properties

Other than "white" and "black", there are quite a few other undocumented ones:

red
gray
grey
linearGray
linearGrey
grayscaleRamp
greyscaleRamp
bump
blackCube
lightmap
unity_Lightmap
unity_LightmapInd
unity_ShadowMask
unity_DynamicLightmap
unity_DynamicDirectionality
unity_DynamicNormal
unity_DitherMask
_DitherMaskLOD
_DitherMaskLOD2D
unity_RandomRotation16
unity_NHxRoughness
unity_SpecCube0
unity_SpecCube1
unity_ProbeVolumeSH

Globally overridable texture properties

If you declare a texture property without any default texture specified, like so:

Properties
{
    _Udon_GlobalTexture("Texture", 2D) = "" {}
}

You are able to override it globally with Shader.SetGlobalTexture(). If you give it a default value, like "white", this doesn't work.


Different matcap techniques

Implementation here, as explained by Ben Golus here

3 Matcap implementation techniques by Ben Golus here. Select among them with unity_OrthoParams.w


Draw full screen triangle

This is the same as doing a Blitter.BlitTexture with a material.

context.cmd.DrawProcedural(Matrix4x4.identity, passData.DilateAndBlurMaterial, 0, MeshTopology.Triangles, 3, 1, null);

However, you are responsible for setting the material properties sending a MaterialPropertyBlock as the last parameter.


Use ObjectFactory in editor for creating objects and components with Undo support

Internally, Unity uses ObjectFactory (most of the time, at least). You can also use it to react to components being added in the editor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment