유니티셰이더의기초 1~6까지 따라하면서 정리한 것
ShaderLab : 기본형식
기본 형식
Shader "BasicShader" {
SubShader {
// Shaderlab code
}
}
SubShader
개념상 (그럴걸이라고 믿고 가는) 지원 되는 디바이스 대응
Shader "BasicShader" {
SubShader {
// 매우 좋은 스펙 디바이스
}
SubShader {
// 좋은 스펙 디바이스
}
SubShader {
// 낮은 스펙 디바이스
}
}
Fallback
Shader "BasicShader" {
SubShader {
// Shaderlab code
}
Fallback "Diffuse"
}
Pass
Shader "BasicShader" {
SubShader {
// Shaderlab code
Pass { }
Pass { }
}
Fallback "Diffuse"
}
ShaderLab 키워드
색 입히기
오브젝트를 퍼렇게 칠한다 |
Shader "Study/SolidBlue"
{
SubShader {
Pass {
Color (0,0,1,1)
}
}
}
| |
재질과 조명추가
매트리얼 설정
셰이더의 목적은 재질과 라이팅에 반응되도록 하는 것이므로,
SubShader 의 Pass 내부에 Material 키워드로 조명 방식을 추가한다.
Material {
Diffuse (0,0,1,1)
Ambient (0,0,1,1)
}
라이팅추가
재질이 표시되려면 조명을 (재질은 조명을 받은 반응이므로) 추가하는데,
Lighting On
매트리얼, 조명 추가된 셰이더
Material, Lighting 키워드가 Pass 블럭 내부에 있다.
조명과 함께 퍼렇게 칠한다. |
Shader "Study/VertexLitBlue"
{
SubShader {
Pass {
Material {
Diffuse (0,0,1,1)
Ambient (0,0,1,1)
}
Lighting On
}
}
}
| |
Fixed Function Shader
프로퍼티
변수다,생각.
Material {
Diffuse (0,0,1,1)
Ambient (0,0,1,1)
}
위의 예제에서는 매트리얼에 값을 고정 값으로 설정 했는데,
Properties 키워드와 구문 블럭 내부에, 변수 역할의 프로퍼티를 추가할 수 있다.
(유니티 인스펙터에 노출되는 그것들)
Diffuse와 Ambient에 대한 프로퍼티를 추가. 다른 색상을 지정하도록 코드를 변경.
재질 색상을 프로퍼티로 받아들인다. |
Shader "Study/VertexLitBlue2"
{
Properties {
_DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)
_AmbientColor ("AmbientColor", COLOR) = (0,0,1,1)
}
SubShader {
Pass {
Material {
Diffuse [_DiffuseColor]
Ambient [_AmbientColor]
}
Lighting On
}
}
}
| |
|
_DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)
_DiffuseColor : 셰이더에서 사용할 변수 이름
“DiffuseColor” : 인스펙터에서 보여질 이름
COLOR : 이 프로퍼티의 타입
(0,0,1,1) : 기본 값. 값을 변경하지 않는 경우 사용할 값.
사용 가능한 타입
name (“display name”, Range (min, max)) = number
: Defines a float property, represented as a slider from min to max in the inspector.
name (“display name”, Color) = (number,number,number,number)
: Defines a color property.
name (“display name”, 2D) = “name” { options }
: 2D texture 정의 프로퍼티
name (“display name”, Rect) = “name” { options }
: Defines a rectangle (non power of 2) texture property.
name (“display name”, Cube) = “name” { options }
: Defines a cubemap texture property.
name (“display name”, Float) = number
: Defines a float property.
name (“display name”, Vector) = (number,number,number,number)
: Defines a four component vector property.
SetTexutre
SetTexutre: 텍스쳐 프로퍼티
2D 프로퍼티로 텍스쳐를 설정해서 오브젝트에 입힐 수 있다.
텍스쳐 프로퍼티 설정
텍스쳐를 오브젝트 적용하는 스크립트
텍스쳐를 입힌다. |
Shader "Study/VertexLitTex"
{
Properties {
_DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)
_AmbientColor ("AmbientColor", COLOR) = (0,0,1,1)
_MainTex ("MainTex", 2D) = "white"
}
SubShader {
Pass {
Material {
Diffuse [_DiffuseColor]
Ambient [_AmbientColor]
}
Lighting On
SetTexture [_MainTex]
}
}
}
| 최초의 화면
|
텍스쳐를 등록한 후의 결과
|
위의 결과는, 텍스쳐를 오브젝트에 적용되었지만 라이팅 연산이 반영되지 않았다.
SetTexutre: 라이팅 연산 추가
SetTexture 구문을 확장해서 ( {, }를 추가한다 ) 텍스쳐 연산 방법을 추가한다.
SetTexture [_MainTex] { Combine texture * primary }
Shader "Study/VertexLitTex2"
{
Properties {
_DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)
_AmbientColor ("AmbientColor", COLOR) = (0,0,1,1)
_MainTex ("MainTex", 2D) = "white"
}
SubShader {
Pass {
Material {
Diffuse [_DiffuseColor]
Ambient [_AmbientColor]
}
Lighting On
SetTexture [_MainTex] {
Combine texture * primary
}
}
}
}
| |
텍스쳐 색상(texture)과 이전 라이팅 계산 결과(primary)를 곱해서 화면에 표시한다.
Combine
Combine에 대한 온라인 도움말
Combine의 조합 방식
combine <src1> * <src2> | 곱한다. 결과는 다소 어두워진다. 하지만 색상 결합의 기본은 곱이므로 이걸 사용한다. |
(0.2 * 0.2 = 0.04) 색상이 점점 0(검정)에 가까워지므로. |
하지만 1(white)로 곱하면 원래 색상이 나오므로. |
combine <src1> + <src2> | 더한다. 밝아진다.
점점 1에 가까워지니까. |
combine <src1> - <src2> | 빼는데.. 이건 좀 미묘. |
combine <src1> +- <src2> | src1을 src2에 더한 다음, 0.5를 뺀다. (signed add?) |
combine <src1> lerp(<src2>) <src3> | src2의 알파값으로 src1(=1)과 src3(=0)사이의 보간 값을 사용한다. |
숫자 범위가 (1~0)임의 주의 |
combine <src1> * <src2> + <src3> | src1.rgba * src2.a + src3 . 이건 뭘까.. |
combine <src1> * <src2> +- <src3> | src1.rgba * src2.a + src3 - 0.5 |
combine <src1> * <src2> - <src3> | src1(전체) * src2(알파값) - src3(전체) |
src 프로퍼티는 아래 키워드로 변경 가능
Texture : SetTexture [<텍스쳐 이름>]에서 지정한 텍스쳐. (SetTexture 구문에서 텍스쳐를 제어하려면 가리키는 키워드가 필요하잖아.)
Primary : 정점 색상을 사용한 라이팅 계산 결과. Material에 지정한 조명 모델에 대한 계산 결과.
Previous : 바로 직전까지 계산한 텍스쳐 연산 결과.
Constant : Constant is the color specified in ConstantColor
combine <연산> <보정용 키워드>
src1 * src2 | src1 + src2 | src1 - src2 |
| | |
색상과 알파분리
combine src1 src2, color(alpha)
“,” 로 색상과 알파 부분을 분리.
“src1 src2”에서는 원래 그대로 적용
color(alpha)에서는 (1)번 연산에서 적용된 결과에 알파값을 적용
그외
SetTexutre: 두장의 텍스쳐
combine lerp 활용
텍스쳐만 표시되도록 재질 설정을 삭제하고 텍스쳐만 받는 셰이더 작성
Shader "Study/TwoTexture"
{
Properties {
_MainTex ("MainTex", 2D) = "white"
_SubTex ("SubTex", 2D) = "white"
}
SubShader {
Pass {
SetTexture [_MainTex]
SetTexture [_SubTex] { Combine texture * previous }
}
}
}
|
|
primary 삭제 : primary를 넣으면, 연산된 라이팅 결과가 없기 때문에 검게 처리된다.
_MainTex 지정 후,
바로 _SubTex로 previous로 “곱”연산.
결과는 두장의 이미지가 겹쳐 보인다.
두번째 텍스쳐는 알파값이 있는 투명한 이미지인데, 투명 처리를 하지 않아서 그림이 깨져보인다.
combine lerp()로 알파를 반영 해본다.
// texture의 알파값으로 src1, src2의 비율을 조정한다. 알파가 1(not 투명) _SubTex값을 사용, 0에 가까워질수록 previous를 사용
SetTexture [_SubTex] {
Combine texture lerp(texture) previous
}
셰이더 수정
Shader "Study/TwoTexture"
{
Properties {
_MainTex ("MainTex", 2D) = "white"
_SubTex ("SubTex", 2D) = "white"
}
SubShader {
Pass {
SetTexture [_MainTex]
SetTexture [_SubTex] {
Combine texture lerp(texture) previous
}
}
}
}
| |
Blend
반투명 효과 같은, “색상섞은 후 효과”를 얻으려면 Blend 로 조합 방법을 적는다.
기본 포맷
Blend <SrcFactor> <DstFactor>
(새로 찍을 색상 값) SrcFactor * (기존 배경의 색상) DstColor
색상을 섞겠다는 뜻인데, SrcFactor와 DstFactor에는 블렌딩에 사용될 색상 속성(Blend Factor)을 지정해야 한다.
Blend SrcAlpha OneMinusSrcAlpha
원래 문서의 설명(이 명료해서)
이 경우에 만약 오브젝트의 알파값이 0.6 이라고 한다면, SrcAlpha = 0.6 이고 OneMinusSrcAlpha = 0.4 이므로 오브젝트 색상과 배경 색상은 60% 대 40% 비율로 섞여서 결국 오브젝트가 반투명하게 보이는 효과를 나타내는 것입니다.
0~1 사이의 색상이나 알파 값을 어디에서 가져올 것이냐에 대한 선택 구문
잡…
Blend SrcAlpha DstAlpha
| 이 경우, 둘다 0.6이면 어떻게 될려나. 최대값은 1이니까 |
구문의 위치
오브젝트를 반투명하게 표시
텍스쳐 두장만 표시하는 셰이더에, Blend를 넣어 봅니다.
Shader "Study/TransObject"
{
Properties {
_MainTex ("MainTex", 2D) = "white" {}
_SubTex ("SubTex", 2D) = "white" {}
}
SubShader {
Pass {
Blend SrcAlpha OneMinusSrcAlpha
SetTexture [_MainTex]
SetTexture [_SubTex] { Combine texture lerp(texture) previous }
}
}
}
| |
Blend만 넣어서는 결과가 나오지 않음.
어느 정도의 알파값을 SrcAlpha로 지정할 것인지 정할 수 있는 코드를 넣어야 하는데,
색상값을 입력 받아
이 색상의 알파값을 최종 알파값으로 사용하도록 코드를 추가.
Shader "Study/TransObject"
{
Properties {
_Alpha ("AlphaColor", COLOR) = (0,0,0,1)
_MainTex ("MainTex", 2D) = "white" {}
_SubTex ("SubTex", 2D) = "white" {}
}
SubShader {
Pass {
Blend SrcAlpha OneMinusSrcAlpha
SetTexture [_MainTex]
SetTexture [_SubTex] {
ConstantColor[_Alpha]
Combine texture lerp(texture) previous, constant
}
}
}
}
| |
|
_Alpha라는 컬러 값을 받는 프로퍼티 추가
SubShader > Pass > 두번째 SetTexutre 에, ConstantColor 키워드로 색상 숫자값을 선언하고,
combine에서 텍스쳐 연산 이후에
얼마나 알파 값을 적용할 것인지 _Alpha를 사용하도록 코드 추가
렌더링 큐를 설정하지 않는데도 앞뒤 제대로 나오니.. 쩝인데.
혹시 모르니,
오브젝트의 앞 뒤로 반투명하게 나와야 할게 제대로 나오지 않는다면 렌더링 큐 설정이 필요하다는 뜻.
Shader “Study/TransObject”
{
Properties {
_Alpha ("AlphaColor", COLOR) = (0,0,0,1)
_MainTex ("MainTex", 2D) = "white" {}
_SubTex ("SubTex", 2D) = "white" {}
}
SubShader {
Tags { “Queue” = “Transparent” }
Pass {
Blend SrcAlpha OneMinusSrcAlpha
SetTexture [_MainTex]
SetTexture [_SubTex] {
ConstantColor[_Alpha]
Combine texture lerp(texture) previous, constant
}
}
}
}
</code>
렌더링 큐를 Transparent로 설정해서, Transparent 에 해당되는 녀석들이 그려질때 같이 그려지도록 설정한다.
렌더링 큐
오브젝트가 렌더링 되는 순서를 정할 수 있는데, 5단계가 기본이다.
키워드 | 숫자인덱스 | 설명 |
Background | 1000 | 가장 먼저 그린다. 다른 것들에 가린다는 뜻 |
Geometry
기본값 | 2000 | 대부분 여기에 해당됨. 반투명 오브젝트 위주 |
AlphaTest | 2450 | 반투명한 Geometry? 가 뭐지? 나무? 알파 테스트를 필요 있는 것. |
Transparent | 3000 | 투명한 (유리, 파티클) 오브젝트는 여기로 와야 함. 이게 거의 많이 쓰일 것 같은데.. |
Overlay | 4000 | 가장 나중에 그리는데, 언제든 보이는 가장 앞에 있는 (렌즈플레어 같은) 오브젝트 |
렌더링 큐는 Tag 키워드로 입력하는데,
SubShader에 위치할 수도 있고,
Pass 구문 안에도 넣을 수 있다.
Tags = { "Queue" = "Transparent" }
또한 기본 키워드에 숫자를 더하거나 빼서 렌더링 순서를 임의 설정할 수 있다.
Tags = { "Queue" = "Geometry+1" }
색상
셰이더에서도 색상값은 (0~1) 사이의 값을 사용.
순서 : RGBA
Color( 1, 1, 1, 1 ) : Color ( <R>, <G>, <B>, <A> )
색상 연산
범위 값이, 0~1 사이 값인 것만 주의 하면 연산할때 도움이 된다.
곱
합
곱보다는 숫자 변화가 적지만
더한다는건 더 흰색에 가까워진다는 뜻이므로