[Unity] 모델의 윤곽선만 묘사하는 셰이더
소개
툰 쉐이딩에서는 모델의 윤곽을 그리는 것이 큰 특징입니다.
흔한 툰 셰이더는 "안쪽으로 면을 향해 조금 부풀어 오른 오브젝트"뒤에 "원래 오브젝트"를 묘사하고, 겹치지 않은 부분을 윤곽으로 하고 있습니다. 이러한 쉐이더로 메인 칼라를 투명하게 해도, 아웃라인마다 투명해져 버리거나, 「안쪽에 면을 향해 조금 부풀린 오브젝트」가 남아 버려, 잘 투과할 수 없습니다.
이번에는 아웃라인만을 그리는 셰이더를 스텐실 버퍼를 사용해 구현합니다.
구현
일반적인 툰 셰이더에서는 아웃라인 부분은 앞에서 설명한 2단계
단계 1. 안쪽으로 면을 향해 약간 부풀어 오른 물체를 묘사합니다.
단계 2. 원래 개체를 묘사합니다. 겹치지 않고 남은 부분이 윤곽이 된다.
하지만 이번에는 아래의 3단계로 구현합니다.
단계 1. 안쪽으로 면을 향해 약간 부풀린 물체로 스텐실을 씁니다.
2단계. 원본 개체에서 스텐실 재설정
3단계. 스텐실이 쓰여진 부분에 색칠
단계 1. 안쪽으로 면을 향해 약간 부풀린 물체로 스텐실을 씁니다.
스텐실을 원래 스텐실 값에 관계없이 42로 덮어씁니다.
outline.hlsl Stencil{
Ref 42
Comp always
Pass replace
}
정점 쉐이더에서는 이 오브젝트를 법선 방향으로 조금 부풀립니다.
outline.hlsl v2f vert (appdata v){
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * 0.05);
return o;
}
조각 셰이더는 적당하고 좋습니다. (ColorMask 0으로 좋음)
2단계. 원본 개체에서 스텐실 재설정
스텐실을 원래 스텐실 값에 관계없이 0으로 재설정합니다.
outline.hlsl Stencil{
Ref 0
Comp always
Pass replace
}
정점 쉐이더는 특별히 괴롭히지 않습니다.
outline.hlsl v2f vert (appdata v){
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
이쪽도 조각 셰이더는 적당하고 좋습니다.
3단계. 스텐실이 쓰여진 부분에 색칠
1단계에서 스텐실이 기록되고 2단계에서 재설정되지 않은 스텐실 값이 42개 부분에만 묘사되도록 합니다.
outline.hlsl Stencil{
Ref 42
Comp eqal
Pass keep
}
정점 쉐이더는 지금까지의 모든 오브젝트를 덮을 필요가 있으므로, 이 오브젝트를 부풀립니다.
outline.hlsl v2f vert (appdata v){
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * 0.05);
return o;
}
프래그먼트 셰이더는 윤곽선의 색상을 그대로 출력합니다.
outline.hlsl fixed4 frag (v2f i) : SV_Target{
return _color;
}
}
완제품
아래와 같은 코드가 되면 완성입니다.
outline.hlslShader "Custom/outline" {
Properties{
_OutlineWidth ("Outline Width", float) = 0.1
_color ("color",Color) = (1.0,0.0,0.0,1.0)
}
SubShader {
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
ZWrite On
Pass {
Stencil {
Ref 42
Comp always
Pass replace //ステンシル42を書き込む
}
Cull Front //面を内側に向ける
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
half3 normal : NORMAL;
};
struct v2f {
half4 pos : SV_POSITION;
};
half _OutlineWidth;
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * _OutlineWidth);//オブジェクトを法線方向に膨らませる
return o;
}
fixed4 frag (v2f i) : SV_Target {
return 0;
}
ENDCG
}
Pass {
Stencil {
Ref 0
Comp always
Pass replace //ステンシルを0でリセット
}
Cull back
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
};
struct v2f{
half4 pos : SV_POSITION;
};
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return 0;
}
ENDCG
}
Pass {
Stencil {
Ref 42
Comp equal
Pass keep //ステンシルが42なら描写
}
Cull back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
half3 normal : NORMAL;
};
struct v2f {
half4 pos : SV_POSITION;
};
half _OutlineWidth;
fixed4 _color;
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * _OutlineWidth);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return _color;
}
ENDCG
}
}
}
© Unity Technologies Japan/UC
Reference
이 문제에 관하여([Unity] 모델의 윤곽선만 묘사하는 셰이더), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/HhotateA/items/6b08dff9babdb08e9f77
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
일반적인 툰 셰이더에서는 아웃라인 부분은 앞에서 설명한 2단계
단계 1. 안쪽으로 면을 향해 약간 부풀어 오른 물체를 묘사합니다.
단계 2. 원래 개체를 묘사합니다. 겹치지 않고 남은 부분이 윤곽이 된다.
하지만 이번에는 아래의 3단계로 구현합니다.
단계 1. 안쪽으로 면을 향해 약간 부풀린 물체로 스텐실을 씁니다.
2단계. 원본 개체에서 스텐실 재설정
3단계. 스텐실이 쓰여진 부분에 색칠
단계 1. 안쪽으로 면을 향해 약간 부풀린 물체로 스텐실을 씁니다.
스텐실을 원래 스텐실 값에 관계없이 42로 덮어씁니다.
outline.hlsl
Stencil{
Ref 42
Comp always
Pass replace
}
정점 쉐이더에서는 이 오브젝트를 법선 방향으로 조금 부풀립니다.
outline.hlsl
v2f vert (appdata v){
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * 0.05);
return o;
}
조각 셰이더는 적당하고 좋습니다. (ColorMask 0으로 좋음)
2단계. 원본 개체에서 스텐실 재설정
스텐실을 원래 스텐실 값에 관계없이 0으로 재설정합니다.
outline.hlsl
Stencil{
Ref 0
Comp always
Pass replace
}
정점 쉐이더는 특별히 괴롭히지 않습니다.
outline.hlsl
v2f vert (appdata v){
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
이쪽도 조각 셰이더는 적당하고 좋습니다.
3단계. 스텐실이 쓰여진 부분에 색칠
1단계에서 스텐실이 기록되고 2단계에서 재설정되지 않은 스텐실 값이 42개 부분에만 묘사되도록 합니다.
outline.hlsl
Stencil{
Ref 42
Comp eqal
Pass keep
}
정점 쉐이더는 지금까지의 모든 오브젝트를 덮을 필요가 있으므로, 이 오브젝트를 부풀립니다.
outline.hlsl
v2f vert (appdata v){
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * 0.05);
return o;
}
프래그먼트 셰이더는 윤곽선의 색상을 그대로 출력합니다.
outline.hlsl
fixed4 frag (v2f i) : SV_Target{
return _color;
}
}
완제품
아래와 같은 코드가 되면 완성입니다.
outline.hlslShader "Custom/outline" {
Properties{
_OutlineWidth ("Outline Width", float) = 0.1
_color ("color",Color) = (1.0,0.0,0.0,1.0)
}
SubShader {
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
ZWrite On
Pass {
Stencil {
Ref 42
Comp always
Pass replace //ステンシル42を書き込む
}
Cull Front //面を内側に向ける
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
half3 normal : NORMAL;
};
struct v2f {
half4 pos : SV_POSITION;
};
half _OutlineWidth;
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * _OutlineWidth);//オブジェクトを法線方向に膨らませる
return o;
}
fixed4 frag (v2f i) : SV_Target {
return 0;
}
ENDCG
}
Pass {
Stencil {
Ref 0
Comp always
Pass replace //ステンシルを0でリセット
}
Cull back
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
};
struct v2f{
half4 pos : SV_POSITION;
};
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return 0;
}
ENDCG
}
Pass {
Stencil {
Ref 42
Comp equal
Pass keep //ステンシルが42なら描写
}
Cull back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
half3 normal : NORMAL;
};
struct v2f {
half4 pos : SV_POSITION;
};
half _OutlineWidth;
fixed4 _color;
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * _OutlineWidth);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return _color;
}
ENDCG
}
}
}
© Unity Technologies Japan/UC
Reference
이 문제에 관하여([Unity] 모델의 윤곽선만 묘사하는 셰이더), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/HhotateA/items/6b08dff9babdb08e9f77
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Shader "Custom/outline" {
Properties{
_OutlineWidth ("Outline Width", float) = 0.1
_color ("color",Color) = (1.0,0.0,0.0,1.0)
}
SubShader {
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
ZWrite On
Pass {
Stencil {
Ref 42
Comp always
Pass replace //ステンシル42を書き込む
}
Cull Front //面を内側に向ける
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
half3 normal : NORMAL;
};
struct v2f {
half4 pos : SV_POSITION;
};
half _OutlineWidth;
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * _OutlineWidth);//オブジェクトを法線方向に膨らませる
return o;
}
fixed4 frag (v2f i) : SV_Target {
return 0;
}
ENDCG
}
Pass {
Stencil {
Ref 0
Comp always
Pass replace //ステンシルを0でリセット
}
Cull back
ColorMask 0
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
};
struct v2f{
half4 pos : SV_POSITION;
};
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return 0;
}
ENDCG
}
Pass {
Stencil {
Ref 42
Comp equal
Pass keep //ステンシルが42なら描写
}
Cull back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
half4 vertex : POSITION;
half3 normal : NORMAL;
};
struct v2f {
half4 pos : SV_POSITION;
};
half _OutlineWidth;
fixed4 _color;
v2f vert (appdata v) {
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex + v.normal * _OutlineWidth);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return _color;
}
ENDCG
}
}
}
Reference
이 문제에 관하여([Unity] 모델의 윤곽선만 묘사하는 셰이더), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/HhotateA/items/6b08dff9babdb08e9f77텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)