우리가 그려온 점은 빨간색이었습니다. 프래그먼트 셰이더에 이 색상을 하드코딩했었죠:
#version 450
layout (location=0) out vec4 theColour;
void main(){
theColour= vec4(1.0,0.0,0.0,1.0);
}
물론, 다른 색을 원한다면 여기서 그냥 바꾸면 됩니다. 예를 들어
theColour= vec4(1.0,0.5,0.0,1.0);
이나
theColour= vec4(0.0,0.0,1.0,1.0);
을 시도해 보세요. 하지만 각기 다른 지점에서 다른 색상을 얻는 방법을 보는 것이 더 흥미로울 수 있습니다. 또는 더 일반적으로, 값을 하드코딩하지 않고 프래그먼트 셰이더로 데이터를 가져오는 방법을 알아보는 것이죠.
프래그먼트 셰이더를 위한 데이터의 한 가지 출처는… 버텍스 셰이더일 수 있습니다. 버텍스 셰이더가 프래그먼트 셰이더 직전에 실행된다는 점을 고려하면 말이죠.
우리의 계획에 대해 양쪽 셰이더 모두에게 알려줘야 합니다: 프래그먼트 셰이더에게는 어떤 값이 들어온다고 알려주고:
#version 450
layout (location=0) out vec4 theColour;
layout (location=0) in vec4 data_from_the_vertexshader;
void main(){
theColour= vec4(1.0,0.0,0.0,1.0);
}
그리고 그 값을 어떻게 처리할지도 알려줘야겠죠 (이전에 사용했던 빨간색 값 대신 사용하도록):
#version 450
layout (location=0) out vec4 theColour;
layout (location=0) in vec4 data_from_the_vertexshader;
void main(){
theColour= data_from_the_vertexshader;
}
그리고 버텍스 셰이더에게는 이 데이터를 출력하라고 알려주고 (그리고 어떤 값을 줘야겠죠):
#version 450
layout (location=0) out vec4 data_from_the_vertexshader;
void main() {
gl_PointSize=10.0;
gl_Position = vec4(0.4,0.2,0.0,1.0);
data_from_the_vertexshader=vec4(0.0,0.6,1.0,1.0);
}
자, 이제 점은 더 이상 빨간색이 아닙니다. 성공했네요.
우리가 추가한 코드를 살펴봅시다: vec4라는 데이터 타입이 있었고, 좋습니다. 그리고 셰이더로 들어오는 데이터를 위한 in과, 음, 출력을 위한 out이라는 꽤 명확한 키워드가 있었습니다.
그럼 변수 이름은 어떨까요? 제 말은, 양쪽 셰이더에서 변수 이름을 data_from_the_vertexshader라고 지었는데, 이게 꼭 필요했을까요?
한번 시험해 보죠. 프래그먼트 셰이더는 그대로 두고, 버텍스 셰이더를 다음과 같이 바꿔봅시다:
#version 450
layout (location=0) out vec4 colourdata_for_the_fragmentshader;
void main() {
gl_PointSize=10.0;
gl_Position = vec4(0.4,0.2,0.0,1.0);
colourdata_for_the_fragmentshader=vec4(1.0,0.6,1.0,1.0);
}
여전히 잘 작동하나요? 유효성 검사 레이어에서 오류 메시지도 없고요? 아주 좋습니다.
참고: 변수들은 다른 셰이더에서 그 이름으로 식별되지 않습니다.
그리고 바로 이 지점에서 layout (location=0)의 의미가 중요해집니다. 한번 바꿔보죠:
#version 450
layout (location=1) out vec4 colourdata_for_the_fragmentshader;
void main() {
gl_PointSize=10.0;
gl_Position = vec4(0.4,0.2,0.0,1.0);
colourdata_for_the_fragmentshader=vec4(1.0,0.6,0.0,1.0);
}
모든 것이 검은색입니다. (그리고 제가 색상을 다시 바꿨기 때문이 아닙니다. 숫자를 보면 여전히 전혀 검은색이 아니거든요. 정말 고맙게도 말이죠.)
하지만 이 문제의 해결책은 그리 터무니없어 보이지 않습니다: 프래그먼트 셰이더도 수정해서 입력 변수의 location을 맞춰줍시다.
#version 450
layout (location=0) out vec4 theColour;
layout (location=1) in vec4 data_from_the_vertexshader;
void main(){
theColour= data_from_the_vertexshader;
}
이제 다시 괜찮아졌습니다.
이건 어떨까요?
#version 450
layout (location=0) out vec4 theColour;
layout (location=5) in vec4 data_from_the_vertexshader;
void main(){
theColour= data_from_the_vertexshader;
}
와 이걸 함께 사용하면요?
#version 450
layout (location=5) out vec4 colourdata_for_the_fragmentshader;
void main() {
gl_PointSize=10.0;
gl_Position = vec4(0.4,0.2,0.0,1.0);
colourdata_for_the_fragmentshader=vec4(0.4,1.0,0.5,1.0);
}
다시 한번: 작동합니다. 한 셰이더의 변수 출력은 다음 셰이더에서 그 위치(location)로 인식됩니다. 이 위치는 셰이더 프로그램에서 변수를 선언할 때 in 또는 out 키워드 앞에 layout (location=5)와 같은 레이아웃 지시자(layout directive) 형태로 주어집니다.
프래그먼트 셰이더에서
#version 450
layout (location=0) out vec4 theColour;
layout (location=0) in vec4 data_from_the_vertexshader;
void main(){
theColour= data_from_the_vertexshader;
}
우리는 또한 “in”과 “out” 변수가 이 슬롯들에 대해 별도의 열거를 가진다는 것을 알 수 있습니다. 입력(in)의 location 0은 출력(out)의 location 0과 같지 않습니다.
이제 색상은 더 이상 프래그먼트 셰이더에 하드코딩되어 있지 않습니다. 버텍스 셰이더에 하드코딩되어 있죠. 이제 버텍스 셰이더로 데이터를 가져올 차례입니다.