TSL에서 법선벡터와 관련된 노드 함수에 대한 고찰

fragmentNode에서 사용할 수 있는 일반적인 법선벡터는 normalWorld 노드이다. normalWorld은 이미 normalize가 되어 있다. transform이 전혀 이뤄지지 않았을지라도 normalLocal은 normalWorld와 다르며 normalLocal을 정규화해야 비로써 normalWorld와 같아진다. 즉, normalWorld.sub(normalLocal)은 0 벡터가 아니며 normalWorld.sub(normalLocal.normalize())가 0 벡터라는 것인데, 전제 조건은 transform이 전혀 이뤄지지 않았을때이다. normalWorld를 직접 계산해 보면 다음과 같다.

const normalView = vertexStage( modelNormalMatrix.mul( normalLocal ) );

vertexStage 노드는 vertex shader에서 varying(보간)으로 fragment로 넘겨준다. varying으로 넘겨줬고 법선벡터는 단위벡터로 사용되어야 하므로 넘겨받은 fragment 측에서 반드시 정규화를 시켜야 한다. 즉, normalWorld와 직접 계산한 normalView가 동일한 값을 가지려면 normalView를 정규화해야 한다.

가끔 시각화를 통해 normal의 동일성 여부를 확인하려고 할때가 있다. 즉, 아래의 코드처럼 말이다.

material.fragmentNode = Fn(([]) => {
  const color = normalWorld.sub(normalLocal);
  return vec4(color, 1);
})();

결과는 마치 normalWorld와 normalLocal이 동일하기라도 한것처럼 까맣게 표시된다. 하지만 아니다. 위의 코드 중 normalWorld.sub(normalLocal)의 결과값에 1000정도 곱해줘 값을 증폭시켜 보면 다음처럼 값에 대한 차이값을 눈으로 볼 수 있다.

쉐이더 프로그래밍의 디버깅은 이처럼 사람의 눈으로 직접 확인하는 방법 이외에 뾰족한 수가 없다는 문제가 있는데, 위와 같은 상황도 있다는 것을 미리 알아두면 좋을 것이다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다