01 CGPROGRAM Section
The sections we have examined earlier are composed in the ShaderLab declarative language. The true challenge in graphics programming begins here with the CGPROGRAM or HLSLPROGRAM declaration.
Shader "CustomPath/ShaderName_simpleColor"
{
// ====================================================
// 1. MATERIAL PROPERTIES - Inspector Interface
// ====================================================
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1, 1, 1, 1)
}
// ====================================================
// 2. SUBSHADER - Render Pipeline Configuration
// ====================================================
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
// ====================================================
// 3. PASS - Contains the shader program code
// ====================================================
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "UnityCG.cginc"
// Global Uniforms
sampler2D _MainTex;
fixed4 _Color;
// ====================================================
// 4. DATA STRUCTURES (Vertex Input / Output)
// ====================================================
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
};
// ====================================================
// 5. VERTEX SHADER STAGE
// ====================================================
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o, o.vertex);
return o;
}
// ====================================================
// 6. FRAGMENT SHADER STAGE
// ====================================================
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv) * _Color;
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
// ====================================================
// 7. SHADER FALLBACK
// ====================================================
FallBack "Diffuse"
}02 Shader Architecture Technical Reference
A Pass refers to a Render Pass literally. For those who have worked with rendering in 3D software (e.g., Maya or Blender), this concept will be easier to understand since when an image is being processed, it can generate different layers or passes separately (e.g., color Pass, light Pass, occlusion Pass, etc.) and thus obtain a separate composition in different layers.
!Each Pass renders one object at a time: That is, if we have two passes in our shader, the object will be rendered twice on the GPU and the equivalent of that would be two draw calls.
CGPROGRAM / ENDCG
Shader will appear with the declaration of HLSLPROGRAM instead of CGPROGRAM since HLSL is currently the official graphics programming language (in fact, Shader Graph is based on it). Anyway, we can update our shader simply by replacing the word CGPROGRAM for HLSLPROGRAM and ENDCG for ENDHLSL, and then our program will compile both in Built-in RP as in Universal RP and High Definition RP.
HLSL Pragma
The pragma is a directive that is used to give instructions to the compiler. In the case of shaders, it is used to indicate the vertex and fragment functions that we will use in shader. Their function is to help our shader recognize and compile certain functions that could not otherwise be recognized as such.
#pragma vertex vert— indicates the vertex function that we will use in the shader.#pragma fragment frag— indicates the fragment function that we will use in the shader.
Multi-compile Pragma Variant Flags:
#pragma multi_compile_fwdbase— indicates that the shader will be compiled in the forward base pass.#pragma multi_compile_fwdadd— indicates that the shader will be compiled in the forward add pass.#pragma multi_compile_fwdaddfullshadows— indicates that the shader will be compiled in the forward add full shadows pass.#pragma multi_compile_fwdaddshadow— indicates that the shader will be compiled in the forward add shadow pass.#pragma multi_compile_fwdaddshadowcaster— indicates that the shader will be compiled in the forward add shadow caster pass.#pragma multi_compile_fwdaddshadowcasterfullshadows— indicates that the shader will be compiled in the forward add shadow caster full shadows pass.#pragma multi_compile_fog— indicates that the shader will be compiled with fog.
HLSL Include
The include is a directive that is used to include a file in the shader. This is useful when we want to use a function that is already defined in another file and we do not want to write it again in the current shader. In Unity, the most common include is “UnityCG.cginc”, which contains a series of functions that are used in the shader (e.g. lighting, texture sampling, etc.).
UNITY_FOG_COORDS(texcoordindex)UnityObjectToClipPos(inputVertex)TRANSFORM_TEX(tex, name)UNITY_TRANSFER_FOG(outputStruct, clipSpacePos)UNITY_APPLY_FOG(inputCoords, colorOutput)
Another defined function that we can find in UnityCG.cginc is UNITY_PI, which equals 3.14159265359f. The latter is not included in our default shader because it is used only in specific cases (e.g. when calculating a triangle or Sphere).
Review Path:
Windows:{unity install path}/Data/CGIncludes/UnityCG.cginc
We can create our own directives using ".cginc" files, which will help us to organize our code and make it more readable. For example, we can create a file called "MyFunctions.cginc" and inside it, we can define the functions that we will use in our shader.
HLSL vertex input & vertex output
A data type that we will use frequently in the creation of our shaders is “struct”. For those who know the C language, a struct is a compound data type declaration, which defines a grouped list of multiple elements of the same type and allows access to different variables through a single pointer. We will use structs to define both inputs and outputs in our shader.
Its syntax is as follows:
struct name
{
vector[n] name : SEMANTIC[n];
};- Appdata: Corresponds to the “vertex input” the place where we store our object properties (e.g. position of vertices, normals, etc.) as an “entrance” to take them to the “vertex shader stage”.
- v2f: Refers to the “vertex output”. The rasterized properties to take them to the “fragment shader stage”.
A semantic is a chain connected to a shader input or output that transmits usage information of the intended use of a parameter:
POSITION[n]— Vertex position semantics.TEXCOORD[n]— allows access to the UV coordinates of our primitive and has up to four dimensions (x, y, z, w).TANGENT[n]— gives access to the tangents of our primitive. If we want to create normal maps, it will be necessary to work with a semantic that has up to four dimensions as well.NORMAL[n]— we can access the normals of our primitive, and it has up to four dimensions. We must use this semantic if we want to work with lighting within our shader.COLOR[n]— Vertex color allocation channels.BINORMAL[n]— corresponds to the binormal of the vertices.
System Value (SV) Semantics Matrix
| Semantic | Description |
|---|---|
SV_POSITION |
Corresponds to the position of the vertices in screen space. |
SV_TARGET |
Corresponds to the target of the vertices (Render Target / Frame Buffer color output). |
SV_DEPTH |
Corresponds to the depth of the vertices. |
SV_COVERAGE |
Corresponds to the coverage of the vertices. |
SV_CLIPDISTANCE |
Corresponds to the clipping distance of the vertices. |
SV_STENCILREF |
Corresponds to the stencil reference of the vertices. |
SV_VERTEXID |
Corresponds to the vertex ID. |
SV_PRIMITIVEID |
Corresponds to the primitive ID. |
SV_INSTANCEID |
Corresponds to the instance ID. |
SV_ISFRONTFACE |
Corresponds to the front face of the vertices. |
SV_SAMPLEINDEX |
Corresponds to the sample index of the vertices. |
SV_DISPATCHTHREADID |
Corresponds to the dispatch thread ID. |
SV_GROUPID |
Corresponds to the group ID. |
SV_GROUPINDEX |
Corresponds to the group index. |
SV_GROUPTHREADID |
Corresponds to the group thread ID. |
SV_GROUPTHREADFLATTENED |
Corresponds to the group thread flattened. |
SV_RENDERTARGETARRAYINDEX |
Corresponds to the render target array index. |
SV_VIEWPORTARRAYINDEX |
Corresponds to the viewport array index. |
Cg / HLSL vertex shader stage
The vertex shader corresponds to a rendering pipeline’s programmable stage, where the vertices are transformed from a 3D space to a two-dimensional projection on the screen. Its smallest unit of calculation corresponds to an independent vertex.
"vert" is the name of the function that we will use to transform the vertices which corresponds to the vertex shader stage. Vertex shader was declared as such in the #pragma vertex.
This Shader in an Unlit type means it doesn't have light it includes a function for the vertex shader and another for the fragment shader #pragma fragment frag. It is essential to mention this since Unity provides a quick way to write shaders in the form of “Surface Shader” (surf) that generates Cg code automatically, exclusively for materials that are affected by lighting.
The first operation that occurs within the vertex shader stage is the transformation of the object vertices from object-space to clip-space through the “UnityObjectToClipPos” method. Let’s remember that our objects are within a three-dimensional space in the scene, and we must transform those coordinates into a two-dimensional projection of pixels on the screen. That transformation occurs precisely within the “UnityObjectToClipPos” function.
This function multiplies the matrix of the current model (unity_ObjectToWorld) by the factor of the multiplication between the current view and the projection matrix (UNITY_MATRIX_VP):
$$UnityObjectToClipPos = mul(\text{UNITY\_MATRIX\_VP}, mul(\text{unity\_ObjectToWorld}, float4(\text{pos}, 1.0)))$$Cg / HLSL fragment shader stage
Our next and last function in the Pass corresponds to the fragment shader stage that appears in our shader with the name “frag”. The reason we can tell that frag is the function of the fragment shader stage is because it has been declared as such in the #pragma fragment.
The word “fragment” refers to a pixel on the screen; to an individual fragment or to a group that together cover an object area. This means that the fragment shader stage will process every pixel on the computer screen concerning the object we are viewing.
This shader is currently written in Cg, so it will only compile in Built-in RP. If we want our shader to compile both in Universal RP and High Definition RP, we will have to change this data type for “half4 or float4”, otherwise our program could generate an error.
// Cg language architecture configuration
fixed4 frag (v2f i) : SV_Target { … }
// HLSL language architecture configuration
half4 frag (v2f i) : SV_Target { … }Unlike the vertex shader stage, this function has an output called “SV_Target”, which allows us to render our scene in an intermediate buffer (render target) instead of sending the data to the Frame Buffer. In previous versions of Direct3D (version 9 and lower), the color output in the fragment shader appeared with the COLOR semantic. However, in modern GPUs (version 10 onwards), this semantics is updated to SV_Target, which means “system value target”. It can apply additional effects to the image before projecting them on the computer screen.
Inside the fragment shader stage we can find a fixed4 vector type called “col” which is the same as the tex2D function, where, as an argument, it receives the _MainTex texture and UV coordinate input. Basically what this operation does is store a texture within the col vector.
Data Types Precision & Optimization
- “Float” (Cg and HLSL): A high-precision data type, it is 32 bit and generally used in calculating positions in world-space, texture coordinates (UV), or scalar calculations involving complex functions such as trigonometry or exponentiation.
- “Half” (Cg and HLSL): Half-precision, is 16 bit and is mostly used in the calculation of low magnitude vectors, directions, object-space positions, and high dynamic range colors.
- “Fixed” (Cg): Low precision, it is only 11 bits and is mainly used in the calculation of simple operations (e.g. basic color storage).
Note: A high-precision data type has more decimals, therefore, the GPU will take longer to calculate it, increasing times and generating heat. It is essential to use vectors and/or variables in their required data type, thus we can optimize our program, reducing the graphic load on the GPU.
“Sampler” refers to the sampling state of a texture. Within this type of data, we can store a texture and its UV coordinates. Scalar values are real number integers or floating-point numbers (float, half, fixed, etc.) and vectors are a set of scalar values (float2, half3, fixed4, etc.). Matrix types are used mainly for shearing, rotation and changes of vertex positions:
// three rows and three columns matrix execution layout
float3x3 name = float3x3(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
// two rows and two columns matrix execution layout
half2x2 name = half2x2(
1, 0,
0, 1
);
// four rows and four columns matrix execution layout
fixed4x4 name = fixed4x4(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);The data type “sampler” allows us to store both the texture and the sampling status in a single variable:
// declare the _MainTex texture as a global variable
Texture2D _MainTex;
// declare the _MainTex sampler as a global variable
SamplerState sampler_MainTex;
half4 frag(v2f i) : SV_Target {
// inside the col vector sample the texture in UV coordinates.
half4 col = _MainTex.Sample(sampler_MainTex, i.uv);
return col;
}The above process can be optimized by simply using a unified legacy structural macro assignment statement:
// declare the sampler for _MainTex
sampler2D _MainTex;
half4 frag(v2f i) : SV_Target {
// sample the texture in UV coordinates using the function tex2D().
half4 col = tex2D(_MainTex, i.uv);
return col;
}Intrinsic Functions Reference Matrix
| Function | Description Evaluation |
|---|---|
abs(x) |
returns the absolute value of a scalar or vector. |
ceil(x) |
returns the smallest integer value greater than or equal to the input value. |
clamp(x, min, max) |
restricts the value of a scalar or vector to a range. |
cos(x) |
returns the cosine of a scalar or vector. |
sin(x) |
returns the sine of a scalar or vector. |
tan(x) |
returns the tangent of a scalar or vector. |
exp(x) |
returns the exponential value of a scalar or vector. |
exp2(x) |
returns the exponential value of a scalar or vector in base 2. |
floor(x) |
returns the largest integer value less than or equal to the input value. |
step(edge, x) |
returns 0.0 if the value is less than the edge, and 1.0 if the value is greater than or equal to the edge. |
smoothstep(min, max, x) |
returns a smooth interpolation between 0.0 and 1.0 when the value is between the minimum and maximum values. |
frac(x) |
returns the fractional part of a scalar or vector. |
length(v) |
returns the length of a vector. |
lerp(a, b, t) |
returns the linear interpolation between two values. |
min(a, b) |
returns the minimum value between two values. |
max(a, b) |
returns the maximum value between two values. |
pow(x, y) |
returns the value of the first parameter raised to the power of the second parameter. |
03 Unity Render Pipeline Fundamentals
Unity utilizes three distinct rendering architectures, each tailored to different performance requirements, hardware targets, and pipeline capabilities.
Key Unity Rendering Architectures
- Built-In Render Pipeline (BIRP): The legacy rendering system using Cg/HLSL. It relies on
CGPROGRAMblocks and includesUnityCG.cginc. Best suited for legacy projects or older mobile hardware where optimization must be manually tuned. - Universal Render Pipeline (URP): The modern, highly scalable replacement for BIRP. It requires
HLSLPROGRAMblocks and utilizes modern HLSL includes (such asCore.hlsl). Features include a single-pass forward renderer, a dedicated 2D Renderer, and native Shader Graph support. Highly recommended for cross-platform deployments spanning mobile, PC, and consoles. - High Definition Render Pipeline (HDRP): A physically-based rendering (PBR) pipeline built specifically for high-end fidelity. It heavily utilizes compute shaders, advanced lighting models, and volumetric effects. Best suited for AAA-grade visual productions on high-performance PC and console hardware.
Pipeline Comparison Table
| Feature | BIRP | URP | HDRP |
|---|---|---|---|
| Shader Language | Cg / HLSL | HLSL | HLSL |
| Base Include File | UnityCG.cginc |
Core.hlsl |
Common.hlsl |
| Lightmap Support | ✓ | ✓ | ✓ |
| Deferred Rendering | ✓ | Limited | ✓ |
| Shader Graph Support | No | ✓ | ✓ |
04 GPU Optimization Essentials for Shaders
Writing efficient shader code requires understanding how modern GPU hardware executes logic at the silicon level. Minor syntax adjustments can drastically alter instruction latency and register pressure.
Math Operations & Instruction Latency
GPUs are optimized for parallel multiply-accumulate (MAC) operations, which form the structural building blocks of linear algebra:
- Multiplication: Implemented directly in dedicated ALU hardware silicon, executing in 1–2 cycles.
- Division: Requires iterative approximation algorithms (such as the Newton-Raphson method) or internal hardware lookup tables. This introduces significant pipeline latency, taking 5–20 cycles.
// BAD: Division is expensive and stalls the ALU pipeline
float result = value / 2.0;
// GOOD: Use multiplication by a precalculated reciprocal literal
float result = value * 0.5;When to Actually Use Division
While multiplication should always be favored, division is structurally unavoidable under the following mathematical conditions:
-
Dynamic Divisors: When values alter dynamically per-fragment or per-vertex, making reciprocal precomputation impossible:
C++ · Implementation example float t = saturate(time / duration); -
Reciprocal Interdependence: When the divisor is derived from dynamic evaluations:
C++ · Implementation example float specular = energy / (distance * distance); -
Numerical Stability & Precision Preservation: Normalizing operations require division to maintain bounds accurately without risking structural clipping:
C++ · Implementation example float3 normalized = vector / length(vector);
Data Type Precision Optimization
Choosing the correct variable precision directly influences register allocation and memory bandwidth usage on mobile and embedded architectures:
float4 position;— 32-bit high precision. Mandatory for world-space coordinates, transform matrices, and complex texture coordinates (UVs).half4 color;— 16-bit medium precision. Optimal for lighting vectors, localized directions, normal maps, and high dynamic range (HDR) colors.fixed4 light;— 11-bit low precision. Legacy data type (Cg only) restricted to simple low-magnitude color math and basic UI masks. In modern HLSL pipelines, this automatically maps tomin16floatorhalf.
Texture Sampling Optimizations
- Explicit Level-of-Detail: Prefer utilizing
tex2Dlodwith explicit mipmap levels for sampling distant objects, or inside loops/vertex functions where automatic derivative calculation is disabled. - Texture Compression: Target standardized hardware compression profiles such as ASTC (for cross-platform mobile architectures) or ETC2 to optimize cache locality.
- Lookup Minimization: Eliminate redundant sample calls in fragment stages; instead, pack scalar masks into combined vector channels (e.g., RGBA packing for Metallic, Roughness, and Ambient Occlusion).
Branching Efficiency & Conditional Overhead
Dynamic branching in a fragment shader causes divergent execution paths within a warp/wavefront, forcing the GPU to execute both paths sequentially while masking off threads.
// BAD: Dynamic branch causing execution divergence in fragment stages
if (distance > threshold) {
// Code path A
} else {
// Code path B
}
// GOOD: Mathematical interpolation eliminating physical branch execution
float lerpFactor = saturate(distance / threshold);
return lerp(a, b, lerpFactor);SRP Batcher Compatibility
To leverage the Scriptable Render Pipeline (SRP) Batcher and eliminate CPU-side draw call overhead, all material properties must be grouped within a standardized constant buffer block named UnityPerMaterial.
// Proper constant buffer declaration for SRP Batcher compliance
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
half4 _Color;
CBUFFER_END- Keep all custom material parameters restricted to a single unified
CBUFFERblock. - Declare parameters using the minimum necessary data precision to conserve GPU constant buffer cache slots.
Vectorization Tips
Modern GPUs run vectorized instructions efficiently. Consolidate your linear algebra into parallel vector calculations rather than component-by-component scalar operations.
// GOOD: Unified parallel vector math (processed simultaneously by SIMD hardware)
float3 result = a * b + c;
// Swizzling: Reconstructing component layouts efficiently via native routing
float4 color = texture.rrrg; // Maps channels natively to create float4(r, r, r, g)Manual Mipmap Calculations
When implementing custom screen-space mappings or procedural patterns, automatic mipmap generation fails due to missing texture coordinates. Screen-space partial derivatives must be evaluated manually:
// Manual mip selection based on screen-space coordinate differentials
float2 derivatives = ddx(uv) + ddy(uv);
float mip = 0.5 * log2(max(dot(derivatives, derivatives), 1e-6));
// Sample texture with explicitly resolved mip level
color = tex2Dlod(_MainTex, float4(uv, 0, mip));Shader Variant Reduction
Shaders generate massive keyword combinations (permutations) that can explode compile times and memory footprints. Differentiate keyword behavior strategically:
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS— Compiles and includes all variations in the build. Required for engine-driven runtime global pipeline states.#pragma shader_feature _ALPHATEST_ON— Strips unused permutations out of the final build if no active materials utilize the keyword state, saving disk space and memory footprint.
Debugging & Profiling
- Frame Debugger: Use Unity's native profiling tool to inspect active render states, evaluate drawing order draw-by-draw, analyze render target binding patterns, and isolate state change hazards.
-
Platform-Specific Optimization Blocks: Condition target compilation blocks based on destination hardware profiles:
C++ · Simplified execution paths for low-bandwidth mobile units #if defined(SHADER_API_MOBILE) // Simplified execution paths for low-bandwidth mobile units #elif defined(SHADER_API_D3D11) // Full high-end feature set utilizing PC hardware capability #endif -
Precision Emulation & Safety Checking: Test lower precision artifacts manually on desktop configurations by masking floating-point bitwise patterns, and detect division-by-zero anomalies:
C++ · Simulate half-precision behavior on a 32-bit float register // Simulate half-precision behavior on a 32-bit float register float simulatedHalf = asfloat(asuint(value) & 0xFFFF0000); // Check for unhandled NaN (Not-a-Number) values bool isInvalid = isnan(value);
05 Cross-Pipeline Shader Adaptation (Built-in, URP, HDRP)
Porting legacy shaders into Scriptable Render Pipelines (SRP) requires rewriting architectural layout blocks. Modern pipelines abandon old Cg compiler abstractions in favor of direct, cross-platform HLSL structures.
URP Shader Implementation Example
Shader "URPExamples/SimpleColor"
{
Properties
{
_BaseColor("Color", Color) = (1,1,1,1)
_BaseMap("Texture", 2D) = "white" {}
}
SubShader
{
Tags
{
"RenderType"="Opaque"
"RenderPipeline"="UniversalPipeline"
}
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// Data structure for Vertex Input
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
// Data structure for Vertex Output (Rasterizer Input)
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
};
// Textures and Samplers API macros
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
// SRP Batcher constant buffer configuration
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
half4 _BaseColor;
CBUFFER_END
Varyings vert(Attributes IN)
{
Varyings OUT;
// Transform positions from object space to homogenous clip space
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
// Core macro-based sampling
half4 color = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
return color * _BaseColor;
}
ENDHLSL
}
}
}06 Key Pipeline Differences & Architectural Mappings
When migrating shaders across pipelines, use the following structural conversions for include files, space transformations, and sampling macros:
Structural Include Files
Modern render pipelines break up global dependencies into target-specific shader libraries to avoid bloating memory allocations:
- BIRP (Built-in): Relies on
UnityCG.cgincorAutoLight.cgincfor light and shadows calculations. - URP: Uses
Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlslfor structural transforms, plus specialized files likeLighting.hlslorShadows.hlsl. - HDRP: Demands
Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlslandPackages/com.unity.render-pipelines.high-definition/ShaderLibrary/ShaderVariables.hlslto interface with advanced volumetric, area lighting, and physically-based rendering data buffers.
Matrix & Space Operations
Modern hardware pipelines standardize vertex operations using specific, explicitly named functions rather than combined utility macros:
- BIRP:
UnityObjectToClipPos(v.vertex) - URP / HDRP:
TransformObjectToHClip(positionOS.xyz)(Object Space to Homogeneous Clip Space).
Note: SRP requires passing a 3-componentfloat3variable containing raw geometric position coordinates, discarding the explicit 4th component translation vector ($w$) prior to internal matrix multiplications.
Texture Sampling Architectures
To preserve compile-time API compatibility across platform backends (such as Vulkan, Metal, and Direct3D), explicit texture sampling macros must replace legacy sampler2D layouts:
| Pipeline Stage | Legacy System (BIRP) | Modern SRP Architecture (URP / HDRP) |
|---|---|---|
| Global Allocation | sampler2D _BaseMap; |
TEXTURE2D(_BaseMap); |
| Fragment Sample | fixed4 col = tex2D(_BaseMap, uv); |
half4 col = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv); |
07 References & Technical Sources
Below is the verified verification index of external engineering resources, documentation modules, and research papers utilized throughout this technical pipeline review:
-
[ NVIDIA Technical Paper ]
Transparency or Translucency Rendering Spatially Coherent Pipelines:
developer.nvidia.com/content/transparency-or-translucency-rendering -
[ Unity Core Documentation ]
High Definition Render Pipeline (HDRP) Overview & Architecture Specifications (v17.2):
docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@17.2/manual/index.html -
[ Pipeline Debugging ]
Z-Sorting in Transparent Shaders — Depth Buffer Contention Resolution:
ru.stackoverflow.com/questions/869171/Проблема-z-sortingа-в-transparent-шейдерах -
[ Hardware Rasterization ]
The Stencil Buffer Execution and Matrix Masking in Unity3D:
liu-if-else.github.io/stencil-buffer's-uses-in-unity3d/ -
[ Production Cheat Sheet ]
Unity Shaders Reference & Syntax Structural Mapping Gist:
gist.github.com/Split82/d1651403ffb05e912d9c3786f11d6a44
