Unity Shader (HLSL)를 작성하는 방법을 기초의 기초 수준에서 배웠습니다.
10527 단어 Unity
개요
업무로 「2개의 텍스처를 혼합하는 셰이더」와 「크로마키 합성을 실시하는 쉐이더」를 합성한 셰이더를 만드는 것이 되어, 거기서 배운 것을 써 둔다.
셰이더 파일의 구조
템플릿이 될 것 같은 내용을 바탕으로 설명을 코멘트에 추가했다.
Shader "シェーダの種類/シェーダーの名前"
{
// Unityインスペクタに表示される項目 (マテリアルプロパティ)
Properties
{
// テクスチャの設定
_MainTex("Texture", 2D) = "white" {}
// 色の設定
_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader
{
// どのようにレンダリングするか
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"IgnoreProjector" = "True"
"PreviewType" = "Plane"
}
// レンダリングを行う
Pass
{
// 実際の処理を書く (HLSL)
CGPROGRAM
// vert関数を頂点シェーダーとして利用する
#pragma vertex vert
// frag関数をフラグメントシェーダーとして利用する
#pragma fragment frag
// 頂点シェーダーへの入力の構造体を定義
struct appdata
{
// 頂点座標
float4 vertex : POSITION;
// テクスチャ座標
float2 uv : TEXCOORD0;
};
// フラグメントシェーダーへの入力の構造体を定義
// 頂点シェーダーで生成して、フラグメントシェーダーの引数で受け取る
struct v2f
{
// クリップスペース位置
float4 vertex : SV_POSITION;
// テクスチャ座標
float2 uv : TEXCOORD0;
};
// マテリアルプロパティを変数に割り当てる
sampler2D _MainTex; // メインテクスチャ
float4 _Color; // 色
// 頂点シェーダーの処理
// 3Dモデルの拡張点で実行されるプログラム (頂点の位置をオブジェクト空間からクリップスペースに変換する)
v2f vert(appdata v)
{
// フラグメントシェーダーの入力になる v2f 構造体変数の定義
// 変数名は Output の o だと思う
v2f o;
// オブジェクト空間の座標からクリップスペースへの変換を行う処理
// クリップスペースはGPU が画面上のオブジェクトをラスタライズするために使用するもの
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
// テクスチャ座標を定義
o.uv = v.uv;
return o;
}
// フラグメントシェーダーの処理
// 画面上に見えるすべてのピクセルで実行されるプログラム (各ピクセルの色を計算する)
// これの最適化がパフォーマンスで重要
fixed4 frag(v2f i) : SV_Target
{
// ここではマテリアルプロパティで設定された色を返しているだけ
return _Color
}
ENDCG
}
}
}
HLSL 처리 흐름
Shader "シェーダの種類/シェーダーの名前"
{
// Unityインスペクタに表示される項目 (マテリアルプロパティ)
Properties
{
// テクスチャの設定
_MainTex("Texture", 2D) = "white" {}
// 色の設定
_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader
{
// どのようにレンダリングするか
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"IgnoreProjector" = "True"
"PreviewType" = "Plane"
}
// レンダリングを行う
Pass
{
// 実際の処理を書く (HLSL)
CGPROGRAM
// vert関数を頂点シェーダーとして利用する
#pragma vertex vert
// frag関数をフラグメントシェーダーとして利用する
#pragma fragment frag
// 頂点シェーダーへの入力の構造体を定義
struct appdata
{
// 頂点座標
float4 vertex : POSITION;
// テクスチャ座標
float2 uv : TEXCOORD0;
};
// フラグメントシェーダーへの入力の構造体を定義
// 頂点シェーダーで生成して、フラグメントシェーダーの引数で受け取る
struct v2f
{
// クリップスペース位置
float4 vertex : SV_POSITION;
// テクスチャ座標
float2 uv : TEXCOORD0;
};
// マテリアルプロパティを変数に割り当てる
sampler2D _MainTex; // メインテクスチャ
float4 _Color; // 色
// 頂点シェーダーの処理
// 3Dモデルの拡張点で実行されるプログラム (頂点の位置をオブジェクト空間からクリップスペースに変換する)
v2f vert(appdata v)
{
// フラグメントシェーダーの入力になる v2f 構造体変数の定義
// 変数名は Output の o だと思う
v2f o;
// オブジェクト空間の座標からクリップスペースへの変換を行う処理
// クリップスペースはGPU が画面上のオブジェクトをラスタライズするために使用するもの
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
// テクスチャ座標を定義
o.uv = v.uv;
return o;
}
// フラグメントシェーダーの処理
// 画面上に見えるすべてのピクセルで実行されるプログラム (各ピクセルの色を計算する)
// これの最適化がパフォーマンスで重要
fixed4 frag(v2f i) : SV_Target
{
// ここではマテリアルプロパティで設定された色を返しているだけ
return _Color
}
ENDCG
}
}
}
어떻게 블렌드 셰이더와 크로마 키 셰이더를 합성 했습니까?
처음에는 단순히 두 개의 셰이더의 "pass"를 나란히 썼는데, 이것은 잘 작동하지 않았다.
셰이더의 구조를 이해하면 간단하지만, 구현하려면 프래그먼트 셰이더에서 "블렌드한 결과의 색 정보에 크로마키 합성 처리를 한다"필요가 있다.
또, 2개의 쉐이더는 코드를 잘 보면 「머티리얼 프로퍼티」와 「프래그먼트 쉐이더」 이외의 부분은 거의 같은 것이 쓰여져 있었기 때문에, 차이가 있던 2개의 부분을 잘 조합했다.
여기서 문제가 된 것은 크로마 키 셰이더의 실제 처리가 ".cginc"라는 별도의 파일에 정의되어 있었기 때문에, 블렌드 셰이더 측의 프래그먼트 셰이더에 크로마 키 셰이더 측의 프래그먼트 셰이더의 처리를 직접 추가해야합니다 했다.
코드 자체는 각각 다른 개발자님이 구현하고, 자신은 그것을 조합했을 뿐이므로, 여기에서는 단편 쉐이더 부분만 간단히 기재해 둔다.
fixed4 frag(v2f i) : SV_Target
{
// メインテクスチャの色情報を取得
fixed4 main = tex2D(_MainTex, i.uv);
// サブテクスチャの色情報を取得
fixed4 sub = tex2D(_SubTex, i.uv);
// メインテクスチャとサブテクスチャをブレンドした結果の色情報を取得
fixed4 col = (main * (1-_Blend) + sub * _Blend) * _Color;
// クロマキー合成した結果の色情報を取得 (実装は ChromaKey.cginc にある)
ChromaKeyApplyAlpha(col);
// FOGを適用する
UNITY_APPLY_FOG(i.fogCoord, col);
// 計算した結果の色情報を返す
return col;
}
그 결과, 블렌딩된 결과를 정확하게 크로마키 합성하는데 성공하였다.
요약
Unity는 배우기 시작한지 4년이 되었지만, 셰이더 코드를 확실히 읽고 손을 넣은 것은 처음이었기 때문에 좋은 경험이 되었다. 실제로 HLSL을 읽는 것으로, 셰이더는 기본적으로 이하의 처리를 하고 있는 것을 이해했다.
fixed4 frag(v2f i) : SV_Target
{
// メインテクスチャの色情報を取得
fixed4 main = tex2D(_MainTex, i.uv);
// サブテクスチャの色情報を取得
fixed4 sub = tex2D(_SubTex, i.uv);
// メインテクスチャとサブテクスチャをブレンドした結果の色情報を取得
fixed4 col = (main * (1-_Blend) + sub * _Blend) * _Color;
// クロマキー合成した結果の色情報を取得 (実装は ChromaKey.cginc にある)
ChromaKeyApplyAlpha(col);
// FOGを適用する
UNITY_APPLY_FOG(i.fogCoord, col);
// 計算した結果の色情報を返す
return col;
}
Unity는 배우기 시작한지 4년이 되었지만, 셰이더 코드를 확실히 읽고 손을 넣은 것은 처음이었기 때문에 좋은 경험이 되었다. 실제로 HLSL을 읽는 것으로, 셰이더는 기본적으로 이하의 처리를 하고 있는 것을 이해했다.
여기에서 더욱 밟으면 좀 더 복잡한 세계가 있다고 생각하지만, 현재의 업무에서는 필요한 충분한 지식을 얻을 수 있었기 때문에 만족했다. 만약 기사에 실수 등이 있으면 코멘트에서 지적해 주시면 감사하겠습니다.
참고 자료
Reference
이 문제에 관하여(Unity Shader (HLSL)를 작성하는 방법을 기초의 기초 수준에서 배웠습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/yakimeron/items/7c635a6cee4a564ba25e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)