Skip to content

Instantly share code, notes, and snippets.

@NedMakesGames
Last active May 30, 2023 02:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NedMakesGames/646b60da8a817a0a084b1a3bf4a45f96 to your computer and use it in GitHub Desktop.
Save NedMakesGames/646b60da8a817a0a084b1a3bf4a45f96 to your computer and use it in GitHub Desktop.
NedMakesGames Writing Unity URP Shaders with Code Part 1: The Graphics Pipeline and You
// MIT License
// Copyright (c) 2023 NedMakesGames
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
Shader "NedMakesGames/MyLit" {
// Properties are options set per material, exposed by the material inspector
Properties{
[Header(Surface options)] // Creates a text header
// [MainTexture] and [MainColor] allow Material.mainTexture and Material.color to use the correct properties
[MainTexture] _ColorMap("Color", 2D) = "white" {}
[MainColor] _ColorTint("Tint", Color) = (1, 1, 1, 1)
}
// Subshaders allow for different behaviour and options for different pipelines and platforms
SubShader{
// These tags are shared by all passes in this sub shader
Tags{"RenderPipeline" = "UniversalPipeline"}
// Shaders can have several passes which are used to render different data about the material
// Each pass has it's own vertex and fragment function and shader variant keywords
Pass {
Name "ForwardLit" // For debugging
Tags{"LightMode" = "UniversalForward"} // Pass specific tags.
// "UniversalForward" tells Unity this is the main lighting pass of this shader
HLSLPROGRAM // Begin HLSL code
// Register our programmable stage functions
#pragma vertex Vertex
#pragma fragment Fragment
// Include our code file
#include "MyLitForwardLitPass.hlsl"
ENDHLSL
}
}
}
// MIT License
// Copyright (c) 2023 NedMakesGames
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// This file contains the vertex and fragment functions for the forward lit pass
// This is the shader pass that computes visible colors for a material
// by reading material, light, shadow, etc. data
// Pull in URP library functions and our own common functions
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
// Textures
TEXTURE2D(_ColorMap); SAMPLER(sampler_ColorMap); // RGB = albedo, A = alpha
float4 _ColorMap_ST; // This is automatically set by Unity. Used in TRANSFORM_TEX to apply UV tiling
float4 _ColorTint;
// This attributes struct receives data about the mesh we're currently rendering
// Data is automatically placed in fields according to their semantic
struct Attributes {
float3 positionOS : POSITION; // Position in object space
float2 uv : TEXCOORD0; // Material texture UVs
};
// This struct is output by the vertex function and input to the fragment function.
// Note that fields will be transformed by the intermediary rasterization stage
struct Interpolators {
// This value should contain the position in clip space (which is similar to a position on screen)
// when output from the vertex function. It will be transformed into pixel position of the current
// fragment on the screen when read from the fragment function
float4 positionCS : SV_POSITION;
// The following variables will retain their values from the vertex stage, except the
// rasterizer will interpolate them between vertices
float2 uv : TEXCOORD0; // Material texture UVs
};
// The vertex function. This runs for each vertex on the mesh.
// It must output the position on the screen each vertex should appear at,
// as well as any data the fragment function will need
Interpolators Vertex(Attributes input) {
Interpolators output;
// These helper functions, found in URP/ShaderLib/ShaderVariablesFunctions.hlsl
// transform object space values into world and clip space
VertexPositionInputs posnInputs = GetVertexPositionInputs(input.positionOS);
// Pass position and orientation data to the fragment function
output.positionCS = posnInputs.positionCS;
output.uv = TRANSFORM_TEX(input.uv, _ColorMap);
return output;
}
// The fragment function. This runs once per fragment, which you can think of as a pixel on the screen
// It must output the final color of this pixel
float4 Fragment(Interpolators input) : SV_TARGET {
float2 uv = input.uv;
// Sample the color map
float4 colorSample = SAMPLE_TEXTURE2D(_ColorMap, sampler_ColorMap, uv);
return colorSample * _ColorTint;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment