Jump to content
• Advertisement

# Displacement Mapping

This topic is 2069 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

## Recommended Posts

Hi,

I'm trying to do displacement mapping, but it doesn't work(I think). I draw and tessellate simple cube and I use stone texture. If I draw and tessellate it, it works fine, but if I apply height map I get this:

1. I've got white holes, why?

2. Why is geometry so devastated ?

If I looked on YouTube videos, it looks nice and correct.

Here is my shaders code:

VS

cbuffer cbPerFrame : register(b0)
{
float3 gEyesPositionW;
float gMinTessDistance;
float gMaxTessDistance;
float gMinTessFactor;
float gMaxTessFactor;
};
cbuffer cbPerObject : register(b1)
{
float4x4 gWorld;
float4x4 gWorldInverseTranspose;
float4x4 gTextureTransform;
};
struct VertexIn
{
float3 PositionL : POSITION;
float3 NormalL : NORMAL;
float3 TangentL : TANGENT;
float2 TextCoord : TEXTCOORD;
};
struct VertexOut
{
float3 PositionW : POSITION;
float3 NormalW : NORMAL;
float3 TangentW : TANGENT;
float2 TextCoord : TEXTCOORD;
float TessFactor : TESSFACTOR;
};
VertexOut main(VertexIn vin)
{
VertexOut vout;
vout.PositionW = mul(float4(vin.PositionL, 1.f), gWorld).xyz;
vout.NormalW = mul(vin.NormalL, (float3x3) gWorldInverseTranspose);
vout.TangentW = mul(vin.TangentL, (float3x3) gWorld);
vout.TextCoord = mul(float4(vin.TextCoord, 0.f, 1.f), gTextureTransform).xy;

float d = distance(vout.PositionW, gEyesPositionW);
float Tess = saturate((gMinTessDistance - d) / (gMinTessDistance - gMaxTessDistance));
vout.TessFactor = gMinTessFactor + Tess * (gMaxTessFactor - gMinTessFactor);

return vout;
}


HS

struct PatchTess
{
float EdgeTessFactor[3] : SV_TessFactor;
float InsideTessFactor : SV_InsideTessFactor;
};
struct VertexOut
{
float3 PositionW : POSITION;
float3 NormalW : NORMAL;
float3 TangentW : TANGENT;
float2 TextCoord : TEXTCOORD;
float TessFactor : TESSFACTOR;
};
struct HullOut
{
float3 PositionW : POSITION;
float3 NormalW : NORMAL;
float3 TangentW : TANGENT;
float2 TextCoord : TEXTCOORD;
};
PatchTess ConstantHS(InputPatch<VertexOut, 3> Patch)
{
PatchTess pt;
pt.EdgeTessFactor[1] = 0.5f * (Patch[1].TessFactor + Patch[2].TessFactor);
pt.EdgeTessFactor[2] = 0.5f * (Patch[2].TessFactor + Patch[0].TessFactor);
pt.EdgeTessFactor[0] = 0.5f * (Patch[0].TessFactor + Patch[1].TessFactor);
pt.InsideTessFactor = pt.EdgeTessFactor[0];

return pt;
}
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("ConstantHS")]
//[maxtessfactor(64.f)]
HullOut main(InputPatch<VertexOut, 3> Patch, uint i : SV_OutputControlPointID)
{
HullOut hout;
hout.PositionW = Patch[i].PositionW;
hout.NormalW = Patch[i].NormalW;
hout.TangentW = Patch[i].TangentW;
hout.TextCoord = Patch[i].TextCoord;
return hout;
}


DS

cbuffer cbPerFrame : register(b0)
{
float4x4 gViewProj;
float3 gEyesPositionW;
float gScaleHeight;
};
Texture2D gNormalTexture : register(t0);
SamplerState gAnisotropicSS : register(s0);
struct HullOut
{
float3 PositionW : POSITION;
float3 NormalW : NORMAL;
float3 TangentW : TANGENT;
float2 TextCoord : TEXTCOORD;
};
struct PatchTess
{
float EdgeTessFactor[3] : SV_TessFactor;
float InsideTessFactor : SV_InsideTessFactor;
};
struct DomainOut
{
float4 PositionH : SV_POSITION;
float3 PositionW : POSITION;
float3 NormalW : NORMAL;
float3 TangentW : TANGENT;
float2 TextCoord : TEXTCOORD;
};
[domain("tri")]
DomainOut main(PatchTess patchTess, float3 bary : SV_DomainLocation, const OutputPatch<HullOut, 3> Patch)
{
DomainOut dout;
dout.PositionW = bary.x * Patch[0].PositionW + bary.y * Patch[1].PositionW + bary.z * Patch[2].PositionW;
dout.NormalW = bary.x * Patch[0].NormalW + bary.y * Patch[1].NormalW + bary.z * Patch[2].NormalW;
dout.TangentW = bary.x * Patch[0].TangentW + bary.y * Patch[1].TangentW + bary.z * Patch[2].TangentW;
dout.TextCoord = bary.x * Patch[0].TextCoord + bary.y * Patch[1].TextCoord + bary.z * Patch[2].TextCoord;

dout.NormalW = normalize(dout.NormalW);

float MipInterval = 20.f;
float MipLevel = clamp((distance(dout.PositionW, gEyesPositionW) - MipInterval) / MipInterval, 0.f, 6.f);

float HeightMap = gNormalTexture.SampleLevel(gAnisotropicSS, dout.TextCoord, MipLevel).a;

dout.PositionW += (gScaleHeight *(HeightMap - 1.f)) * dout.NormalW;
dout.PositionH = mul(float4(dout.PositionW, 1.f), gViewProj);

return dout;
}


Edited by Xperience

#### Share this post

##### Share on other sites
Advertisement

The weirdness at the corners and edges is something I've seen before.  Basically, you're pushing in the top and side according to the heightmap, but what's happening is that the side face is getting pushed in without taking into consideration the amount that the top face is getting pushed in.  Using a smaller gScaleHeight makes this less noticeable, but it will still happen.  Maybe it would make sense to calculate the distance from the center of the object in your vertex shader, and use that to help offset the generated vertices in your domain shader?  I'm just spitballing here, so I'm not sure; when I was implementing displacement mapping I just lived with the small amount of messed-up-ness that I saw at the edges of my cubes.

As for the white patches, it almost looks like you are missing triangles.  Is it possible that some of them are getting tessellated with a bad winding order?  The hull shader code looks right, although I suppose it is possible that if something is wrong with your tessellation factor calculation, it might drop triangles too.

This shader looks very much like the one from Chapter 18 of Frank Luna's D3D11 book, so you might want to compare your code with mine at http://www.richardssoftware.net/2013/09/bump-and-displacement-mapping-with.html.  I had the same discontinuities of the edges, but not the missing triangle problem.  The only difference I'm seeing is that I used a linear texture filter, rather than anisotropic.

#### Share this post

##### Share on other sites

Thanks for advice. Yes, it's from Frank Luna's book.I rebuild project and this white patches dissapeared(I have no idea why). In Frank's book, he use gScaleFactor 0.07, but if I use this factor it looks essentially the same as with Factor 0.

I know that sides go to the center, but how I can prevent this?

Maybe it would make sense to calculate the distance from the center of the object in your vertex shader, and use that to help offset the generated vertices in your domain shader?

This probably will work on simple symmetric objects like cube, but what about more complex objects?

I've found this video and it look amazing:

Autor must used higher ScaleFactor and sides are in good positions(no weirdness)

#### Share this post

##### Share on other sites

I'm only seeing a cylinder and a flat quad in that video.  These meshes don't suffer the same kind of discontinuities in their surface normals as a cube model does.

I haven't attempted to use displacement mapping on non-geometric meshes, since I don't have an artist, and I'm not good enough to create a heightmap for the models I've been working with...

#### Share this post

##### Share on other sites

• Advertisement
• Advertisement

• ### Popular Now

• 11
• 9
• 17
• 13
• 11
• Advertisement
×

## Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!