본문으로 바로가기

Tri-Planar Texture Mapping

category Technical Report/Unity Shader 2012. 12. 8. 01:03
반응형


Height Map을 활용한 Terrain 제작에서 세로 경사값이 늘어날수록 Texture가 늘어나는것을 보정하는 방법.

이런 증상에 대한 해결책으로 생각한것이 Terrain 폴리를 맥스로 export해서 UV를 수정해주면 되지 않을까.. 라고 생각했었는데 아무리 뒤져봐도 Height Map을 추출하는것은 가능해도 Terrain Mesh를 export하는 툴은 찾아보기 힘들었다.(UDK3, Unity3D 포함)...

(와이어 흐름을 쪼개어 UV를 보정하면 되지 않을까라는 생각도 해봤는데 2의 N승 기반의 Terrain이다보니 한쪽만 와이어를 늘리려하면 전체 폴리카운터가 무식하게 늘어나는 문제도 있으니 이것도 엄청 비효율적....)


이러한 증상에 대해 기술적으로 보완하는 방법에 대한 기술 문서.

결국 디자이너가 작업하는 단계에서는 불가능하고 프로그래밍적인 지원을 받는 방법밖에 없다는게 좀 아쉽다.... 사견으로는 기술문서만으로 보았을때 이를 디자이너가 작업할때 단독으로 적용하는 방법에 대해서는 아직 이해 못한 상태... 누군가 간단하게 해당 Terrain 쉐이더에 해당 코드를 첨부하면 된다 하는 방식으로 설명해주면 참 좋으련만....


기능적으로 이렇게 보완이 가능하다는 사실을 안것으로 일단 만족...(프로젝트 TA에게 요청하면 되니...)




 적용전



적용후.



참조 블로그 : http://cagetu.egloos.com/5700144


기술 문서 : GPU Based Algorithms for Terrain Texturing



참조 문서 : http://gamedevelopment.tutsplus.com/articles/use-tri-planar-texture-mapping-for-better-terrain--gamedev-13821



The first part it to calculate the blend factor for each direction:

1
2
3
4
5
  // in wNorm is the world-space normal of the fragment
  vec3 blending = abs( wNorm );
  blending = normalize(max(blending, 0.00001)); // Force weights to 4  sum to 1.0
  float b = (blending.x + blending.y + blending.z);
  blending /= vec3(b, b, b);



Here it takes in the world-space normal of the fragment (which will be normalized and each component will be within the range of -1 and 1) and we make it an absolute value. We do not care if a normal is facing in -X or X, just that is it on the X-axis. If we did worry about the absolute direction we would be painting the shape from the front, back, left, right, top and bottom; 3 more times than we need.


Next we force it to be within the range of 0 to 1 so we end up with a percentage multiplier for each of the axis components. If the normal is facing upwards on the Y-axis, we get a Y value of 1 and it gets all of the Y-axis painting while the other axes will have values of 0 and get none.


That's the hard part. Next we just mix the three blend values (x,y,z) with the texture at that texture coordinate. Remember, the texture coordinate is in world-space:


1
2
3
4
5
  vec4 xaxis = texture2D( rockTexture, coords.yz);
  vec4 yaxis = texture2D( rockTexture, coords.xz);
  vec4 zaxis = texture2D( rockTexture, coords.xy);
  // blend the results of the 3 planar projections.
   vec4 tex = xaxis * blending.x + xaxis * blending.y + zaxis * blending.z;


And there we have it. "tex" is the final color of the fragment, blended three times from the 3 axes.

It can be very handy to apply a scale factor to the texture as you will no doubt want to scale it:


1
2
3
4
5
  // in float scale
  vec4 xaxis = texture2D( rockTexture, coords.yz * scale);
  vec4 yaxis = texture2D( rockTexture, coords.xz * scale);
  vec4 zaxis = texture2D( rockTexture, coords.xy * scale);
  vec4 tex = xaxis * blending.x + xaxis * blending.y + zaxis * blending.z;

Normals

If you are using tri-planar mapping and normal maps, you will also want to apply the same procedure to the normals in the fragment shader, like so:


1
2
3
4
  vec4 xaxis = texture2D( rockNormalTexture, coords.yz * scale);
  vec4 yaxis = texture2D( rockNormalTexture, coords.xz * scale);
  vec4 zaxis = texture2D( rockNormalTexture, coords.xy * scale);
  vec4 tex = xaxis * blending.x + xaxis * blending.y + zaxis * blending.z;


TIP:
Create a getTriPlanarBlend() function to calculate the blend for diffuse, normal, and specular textures.



반응형

'Technical Report > Unity Shader' 카테고리의 다른 글

Unity3D lightmapping 2nd UV를 활용한 lightmap 추출  (0) 2013.01.31
Zbrush plug in - MatCap Baker  (0) 2013.01.20
Deferred Lighting  (0) 2012.11.15
Crazy Bump 사용법(2)  (0) 2012.11.13
Unity3D lightmapping Menu 설명  (0) 2012.11.08