|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| Cubic Interpolation to calculate normal on dynamic heightmap in HLSL |
|
![]() skytiger Member since: 9/28/2007 |
||||
|
|
||||
| Hi I have a 2D uniform grid which is turned into a 3D terrain in a vertex shader by combining it with a heightmap using vertex texture fetch all working just fine I have implemented a trick where I can calculate the heights of the other two vertices in the triangle using this extra information I can calculate a vertex normal but the pixel shader lerps this and the result is not pleasant I am thinking about extending the current system to calculate the heights of 16 vertices and calculate sets of cubic coefficients to pass into the pixel shader then the pixel shader can calculate a smoothly interpolated normal this will require some significant reworking and some performance considerations I am worried that after all the effort the results will be poor Has anybody else any experience with calculating smooth normals dynamically? Maybe I am missing a trick ... |
||||
|
||||
![]() Dave Eberly Member since: 8/22/2004 From: Scottsdale, AZ, United States |
||||
|
|
||||
| The input to the vertex shader includes the (x,y) values for the 2D uniform grid so that you can do the heightmap lookup. For the sake of argument, I will assume that 0 <= x <= 1 and 0 <= y <= 1 (the vertex shader can scale/translate accordingly to produce the output clip-space vertex position). Pass the (x,y) to a TEXCOORD output from the vertex shader. Let the heightmap texture also be assigned to a sampler for the pixel shader. You get the (x,y) value as an input to the pixel shader. Compute the normal at (x,y) by finite differences, doing lookups in the heightmap at (x+e,y), (x-e,y), (x,y+e), and (x,y-e) for some small parameter e (this is effectively the width/height of a texel in the heightmap).
float heightXP = tex2d(sampler, float2(x+e,y)).z;
float heightXM = tex2d(sampler, float2(x-e,y)).z;
float heightYP = tex2d(sampler, float2(x,y+e)).z;
float heightYM = tex2d(sampler, float2(x,y-e)).z;
float3 derivx = float3(2*e,0,heightXP);
float3 derivy = float3(0,2*e,heightYP);
float3 normal = normalize(cross(derivx,derivy));
If you had to scale/translate the (x,y) input to the vertex shader, you will need to do the same scale/translate of (x,y) in the pixel shader *before* you compute the heights. |
||||
|
||||
![]() skytiger Member since: 9/28/2007 |
||||
|
|
||||
float heightXP = tex2d(sampler, float2(x+e,y)).z;
float heightXM = tex2d(sampler, float2(x-e,y)).z;
float heightYP = tex2d(sampler, float2(x,y+e)).z;
float heightYM = tex2d(sampler, float2(x,y-e)).z;
float3 derivx = float3(2*e,0,heightXP);
float3 derivy = float3(0,2*e,heightYP);
float3 normal = normalize(cross(derivx,derivy));
Hi Dave Thanks for the snippet The problem is the lerp performed by the tex2D will cause problems due to the large number of pixels between height samples ie: between two heightmap points there could be up to 100 pixels which creates horrible shading effects along the polygon edges If there were just a couple of pixels between samples it would work OK |
||||
|
||||
![]() Dave Eberly Member since: 8/22/2004 From: Scottsdale, AZ, United States |
||||
|
|
||||
| Given you comments about the poor quality normals from interpolation in the vertex shader and the low-resolution heightmap for displacement, it seems to me the problem is the low resolution. Is there some reason you do not want to consider a higher-resolution heightmap to solve your problem? |
||||
|
||||
![]() skytiger Member since: 9/28/2007 |
||||
|
|
||||
| I have to fit the color and height for the whole planet earth into an XNA Indie Game maximum size of 150mb. I have achieved this by putting height into the alpha channel of a set of square textures of earth and playing around with different resolutions. The results are quite good considering but the terrain shading has this lerp problem - the current workaround is to use very light shading ![]() |
||||
|
||||
![]() Nimbal Member since: 9/11/2009 From: Osnabruck, Germany |
||||
|
|
||||
| Is there a reason why you don't render a normal map from the height map in a pixel shader? See Catalin's blog for details. |
||||
|
||||
![]() skytiger Member since: 9/28/2007 |
||||
|
|
||||
Quote: Three reasons: 1) it will be sampling the same three points many times for no advantage 2) performance will suffer badly as the same sampling could have been done at the vertex stage 3) it will suffer from the same lerp problem - the lerp just happens in the sampler instead of the interpolator between vs and ps Because the average number of pixels per triangle for my approach is higher than typical it shows up the deficiencies in linear interpolation that are usually hidden |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|