Shader 섹션 67 에서 템플릿 버퍼를 사용하여 객체 숨기기
쉐더를 할 시간이 얼마 안 남았어요.
하마터면 Shader를 할 뻔했다.쉐더를 할 시간이 많지 않을 것 같아서요.
100부까지 열심히 하겠습니다.10년이 걸려도 돼요.
100편의 글을 배웠다면 초보자라도 이해할 수 있을 것 같아요.
이렇게 하는 거야.
※ 초보자는 필기 레벨로 기록
기술 보도로는 도움이 안 될 것 같습니다.
미리 준비하다
아래 참조
Shader 파트 1Unite 2017 애니메이션을 볼 때가 많지 않아요. (기초지식~종이 스크레이퍼로 색깔 바꾸기)
데모
표제의 인상이 전달하기 어려운 시연은 대상을 엄폐함으로써 형성된 표현이다.
구조
상자의 평면에만 표시할 수 있는 객체를 준비했습니다.
이 퍼레이드는 상자인 만큼 옆면은 4면으로, 각각 상영되는 고양이 4마리를 배치했다.
다음은 위 설명을 이해하기 쉬운 시위 행진.
그리고 제목처럼 이 메커니즘은 템플릿 버퍼를 이용한다.
템플릿 버퍼
템플릿 버퍼는 화면 그리기와 달리 확보된 버퍼입니다.
아주 간단하게 설명하자면 픽셀 값을 설정하고 이 값을 참조할 수 있다.
예를 들어 "그리려고 하는 픽셀의 템플릿 버퍼 값이 1이면 검은색으로 칠하고 그렇지 않으면 흰색으로 칠한다."
이 원리를 이용하여'특정 대상을 그린 후의 픽셀'에만 표시되는 대상을 나타낼 수 있다.
이를 위해 다음 두 가지를 제작한다.
• 템플릿 버퍼에 값만 쓰는 Shader
• [미리 그려진 픽셀 템플릿 버퍼 값]을 지정된 값과 비교하여 일관성 있게 임의의 드로잉 처리를 수행하는 Shader
Shader 샘플
우선
ステンシルバッファに値を書き込むだけのShader
.Shader "Custom/WriteStencil"
{
Properties
{
_Ref("Ref", Int) = 1
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
"Queue" = "Geometry-1"
}
Pass
{
//カラーチャンネルに書き込むレンダーターゲットを設定する
//0の場合、全てのカラーチャンネルが無効化され何も書き込まれない
ColorMask 0
ZWrite Off
//ステンシルバッファに関して
Stencil
{
//ステンシルの値
Ref [_Ref]
//ステンシルバッファの値の判定方法
//Alwaysなのでステンシルバッファのテストは常に通過する
Comp Always
//ステンシルバッファに値を書き込むかどうか
//Replaceなので既存の値をRefの値に置き換える
Pass Replace
}
}
}
}
ColorMask
ColorMask를 통해 RGBA(드로잉 채널)를 지정할 수 있습니다.
이번에'템플릿 버퍼에만 값 쓰기'가 이 Shader의 역할이에요.
값이 0이면 드로잉 채널이 모두 닫힙니다.
단계 명령
Stncil 명령에서 템플릿 버퍼에 대한 작업을 수행합니다.
우선
Ref
에서 값을 설정합니다.그런 다음 비교 함수
Comp
를 사용하여 이전 Ref 값을 그리려는 픽셀의 깊이 버퍼 값과 비교하여 대상 픽셀을 결정합니다.Pass
비교 함수는 실시간 동작이다.Replace
에서 템플릿 버퍼에 Ref
값을 기록합니다.【참조 링크】: ShaderLab command: Stencil
이러한 일련의 작업은 템플릿 버퍼 값을 보려면 드로잉 프로세스 이전에 수행해야 합니다.템플릿 버퍼의 값이 쓰여지지 않으면 '템플릿 버퍼의 값이 1이기 때문에 ○○' 처리를 할 수 없기 때문이다.
따라서 Que에 1999를 지정하여 다른 대상보다 한 단계 먼저 그리기 처리를 했다.
※ 그나저나 이 쉐더는 아무것도 그려지지 않았는데 프레젠테이션 원고에서 하얗게 변한 것은 다른 반투명 대상이 배치되어 있기 때문이다.
다음은
"描画予定であるピクセルのステンシルバッファの値"を指定した値と比較し、合致していた場合に任意の描画処理を行うShader
.Shader "Custom/SimpleGeometryStencil"
{
Properties
{
//ここに書いたものがInspectorに表示される
_MainTex ("Texture", 2D) = "white" {}
_Ref("Ref", Int) = 1
_ScaleFactor ("Scale Factor", Range(0,1.0)) = 0.5
_PositionFactor("Position Factor", Range(0,1.0)) = 0.5
_RotationFactor ("Rotation Factor", Range(0,1.0)) = 0.5
}
SubShader
{
//ステンシルバッファに関して
Stencil
{
//ステンシルの値
Ref [_Ref]
//ステンシルバッファの値の判定方法
//Equalなので"描画しようとしているピクセルのステンシルバッファ"がRefと同じ場合、そのピクセルを描画の処理対象とする
Comp Equal
}
Tags
{
"RenderType"="Opaque"
}
//両面描画
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"
float _PositionFactor;
float _RotationFactor;
float _ScaleFactor;
sampler2D _MainTex;
struct appdata
{
float4 vertex : POSITION;
float3 localPos : TEXCOORD0;
float2 uv : TEXCOORD1;
};
//頂点シェーダー
appdata vert(appdata v)
{
appdata o;
o.localPos = v.vertex.xyz; //ジオメトリーシェーダーで頂点を動かす前に"描画しようとしているピクセル"のローカル座標を保持しておく
o.uv = v.uv;
return v;
}
struct g2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD1;
};
//回転させる
//pは回転させたい座標 angleは回転させる角度 axisはどの軸を元に回転させるか
float3 rotate(float3 p, float angle, float3 axis)
{
float3 a = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float r = 1.0 - c;
float3x3 m = float3x3(
a.x * a.x * r + c, a.y * a.x * r + a.z * s, a.z * a.x * r - a.y * s,
a.x * a.y * r - a.z * s, a.y * a.y * r + c, a.z * a.y * r + a.x * s,
a.x * a.z * r + a.y * s, a.y * a.z * r - a.x * s, a.z * a.z * r + c
);
return mul(m, p);
}
//ランダムな値を返す
float rand(float2 co)
{
return frac(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453);
}
// ジオメトリシェーダー
[maxvertexcount(3)]
void geom(triangle appdata input[3], uint pid : SV_PrimitiveID, inout TriangleStream<g2f> stream)
{
// 法線を計算
float3 vec1 = input[1].vertex - input[0].vertex;
float3 vec2 = input[2].vertex - input[0].vertex;
float3 normal = normalize(cross(vec1, vec2));
//1枚のポリゴンの中心
float3 center = (input[0].vertex + input[1].vertex + input[2].vertex) / 3;
float random = 2.0 * rand(center.xy) - 0.5;
float3 r3 = random.xxx;
[unroll]
for (int i = 0; i < 3; i++)
{
appdata v = input[i];
g2f o;
//ジオメトリーの移動・回転・拡大縮小処理
v.vertex.xyz = center + rotate(v.vertex.xyz - center, (pid + _Time.y) * _RotationFactor, r3);
v.vertex.xyz = center + (v.vertex.xyz - center) * (1.0 - _ScaleFactor);
v.vertex.xyz += normal * _PositionFactor * abs(r3);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
stream.Append(o);
}
}
//フラグメントシェーダー
fixed4 frag(g2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
형상 섀도우가 오랫동안 쓰여 있어 복잡해 보이지만 주의해야 할 것은 스틸 명령이다.비교 함수에 대한 Equal을
//ステンシルバッファに関して
Stencil
{
//ステンシルの値
Ref [_Ref]
//ステンシルバッファの値の判定方法
//Equalなので"描画しようとしているピクセルのステンシルバッファ"がRefと同じ場合、そのピクセルを描画の処理対象とする
Comp Equal
}
Comp
에 지정합니다.따라서 그리려는 픽셀 템플릿 버퍼가 Ref와 함께 있는 경우에만 그리기 작업을 수행할 수 있습니다.
참조 링크
[Unity 면도기 입문] 템플릿 버퍼로 숨겨진 부분 그리기
커튼을 이용한 장치 제작법
홀로렌즈에 동태를 추가해서 맞은편 창문을 볼 수 있어요.
[Unity] 템플릿 버퍼로 창문 만들기
Reference
이 문제에 관하여(Shader 섹션 67 에서 템플릿 버퍼를 사용하여 객체 숨기기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/kento_o/articles/dd99c6c9e98d4a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)