描画に関して ・C#スクリプトからshaderファイルをいじる方法 ・C#スクリプト内でMeshの作成から行う方法 ・HLSLやCG言語で書く方法 ・Shader Graphを使用する方法 ・HDRPやURPの機能を使う方法 など色々あります。
使用したい目的や表現のShader記事を検索してヒットすれば、それを模倣すればいいと思いますが、ある程度shaderのスクリプトの意味を理解したい場合は、少し勉強してみましょう
公式Youtube シェーダを書けるプログラマになろう #1
そろそろShaderをやる
https://zenn.dev/kento_o
Unity ShaderGraph CookBook
https://zenn.dev/r_ngtm/books/shadergraph-cookbook
https://zenn.dev/r_ngtm
【Unity】無料のオススメシェーダまとめ(110個) https://baba-s.hatenablog.com/entry/2018/10/29/090000
7日間でマスターするUnityシェーダ入門 https://nn-hokuson.hatenablog.com/entry/2018/02/15/140037
【Unity】シェーダに関するオススメ記事まとめ(120個) https://baba-s.hatenablog.com/entry/2018/03/02/090000
第1章 Unityではじめるプロシージャルモデリング
第2章 ComputeShader入門
第3章 群のシミュレーションのGPU実装
第4章 格子法による流体シミュレーション
第5章 SPH法による流体シミュレーション
第6章 ジオメトリシェーダーで草を生やす
第7章 雰囲気で始めるMarchingCubes入門
第8章 MCMCで行う3次元空間サンプリング
第9章 MultiPlanePerspectiveProjection
サンプル https://github.com/IndieVisualLab/UnityGraphicsProgramming?tab=readme-ov-file
Document https://github.com/IndieVisualLab/UnityGraphicsProgrammingSeries?tab=readme-ov-file
Unityでの描画計算の順番についてのスライドでもみた通り、
UnityのShaderでは、Vertex ShaderとFragment Shaderの2つを主に使用します。
この2つは、シェーダープログラムの主要な部分を構成し、それぞれ異なる役割を果たします。
Unityでは、シェーダーを記述する方法としてShaderLabという高レベルのスクリプト言語が使用されます。ShaderLabは、HLSL(High-Level Shading Language)コードを含むことができます。
この例は、基本的なテクスチャマッピングシェーダーの流れを示しています。Vertex Shaderで頂点を処理し、Fragment Shaderでテクスチャから色をサンプリングして出力しています。
Shader "Custom/MyShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
float4 frag (v2f i) : SV_Target
{
float4 texColor = tex2D(_MainTex, i.uv);
return texColor;
}
ENDCG
}
}
}
// HLSL for Unity's vertex shader
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
// HLSL for Unity's fragment shader
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
float4 frag (v2f i) : SV_Target
{
float4 texColor = tex2D(_MainTex, i.uv);
return texColor;
}
下記シェーダーは、Shader
構文を使って定義され、Custom/MyVertexShader
という名前が付けられています。Properties
ブロックとSubShader
ブロックを持ち、頂点シェーダー(Vertex Shader)とフラグメントシェーダー(Fragment Shader)を含んでいます。
Shader "Custom/MyVertexShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
// ここでVertex Shaderとして使用する関数を指定
#pragma vertex vert
#pragma fragment frag
// サンプラー変数の宣言
sampler2D _MainTex;
// 頂点データの構造体
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
// Vertex ShaderからFragment Shaderに渡されるデータの構造体
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
// Vertex Shaderの関数
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
// Fragment Shaderの関数
float4 frag (v2f i) : SV_Target
{
float4 texColor = tex2D(_MainTex, i.uv);
return texColor;
}
ENDCG
}
}
}
_MainTex
を宣言しています。 Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
_MainTex ("Texture", 2D) = "white" {}
: _MainTex
という名前の2Dテクスチャプロパティを宣言しています。デフォルト値は白(”white”)です。SubShader
ブロックには、シェーダーパスを定義するPass
ブロックが含まれています。 SubShader
{
Pass
{
CGPROGRAM
// ここでVertex Shaderとして使用する関数を指定
#pragma vertex vert
#pragma fragment frag
// サンプラー変数の宣言
sampler2D _MainTex;
// 頂点データの構造体
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
// Vertex ShaderからFragment Shaderに渡されるデータの構造体
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
// Vertex Shaderの関数
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
// Fragment Shaderの関数
float4 frag (v2f i) : SV_Target
{
float4 texColor = tex2D(_MainTex, i.uv);
return texColor;
}
ENDCG
}
}
vert
を指定します。frag
を指定します。_MainTex
を宣言します。この変数はテクスチャをサンプリングするために使用されます。appdata
と v2f
:
appdata
構造体は、頂点データを表します。vertex
フィールドは頂点位置、uv
フィールドはテクスチャ座標を含みます。v2f
構造体は、Vertex ShaderからFragment Shaderに渡されるデータを表します。uv
フィールドはテクスチャ座標、pos
フィールドはクリップ空間の頂点位置を含みます。 struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
vert
:
appdata
構造体を入力とし、v2f
構造体を出力します。UnityObjectToClipPos(v.vertex)
関数を使って、頂点位置をオブジェクト空間からクリップ空間に変換します。 v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
frag
:
v2f
構造体を入力とし、色値を出力します。tex2D(_MainTex, i.uv)
関数を使って、テクスチャ _MainTex
からサンプリングした色を取得します。float4 frag (v2f i) : SV_Target
{
float4 texColor = tex2D(_MainTex, i.uv);
return texColor;
}
このシェーダーは、テクスチャマッピングされたオブジェクトをレンダリングするシンプルなシェーダーです。
頂点シェーダーで頂点の位置とUV座標を計算し、フラグメントシェーダーでテクスチャから色をサンプリングして出力します。
高度なシェーダーでは、Geometry ShaderやCompute Shaderなども使用されることがありますが、基本的なシェーダーの理解としては、Vertex ShaderとFragment Shaderをしっかりと押さえておくことが重要です。