Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Some Problem when trying to implement ParallaxMapping


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 viX0026   Members   -  Reputation: 191

Like
1Likes
Like

Posted 24 October 2013 - 09:38 PM

Hi, guys, I'm trying to implement parallax mapping in hlsl, I use the algorithm in "ParallaxOcclusionMapping" in D3D Sample, But I always get a complie error X3511: Unable to unroll loop, loop does not appear to terminate in a timely manner (1024 iterations). I have tried on RenderMonkey and D3D9, neither of them works. Here is my code(simplified, I just implemented the height profile-ray intersection):

struct PS_INPUT
{
    float2 texCoord    : TEXCOORD0;
    float3 vLightDirTS : TEXCOORD1;
    float3 vViewDirTS  : TEXCOORD2;
    float3 vNormalWS   : TEXCOORD3;
    float3 vViewDirWS  : TEXCOORD4;
};


float4 CalculateLighting(float3 vViewTS, float3 vLightTS, float2 texCoord)
{
    float3 vNormalTS = normalize(tex2D(tNormalHeightMap, texCoord).xyz * 2 - 1);
    float4 cBaseColor = tex2D(tBase, texCoord);
    float4 cDiffuse = saturate(dot(vLightTS, vNormalTS)) * g_LightDiffuse;
    float4 cFinal = (g_LightAmbient + cDiffuse) * cBaseColor;
    return cFinal;
}

float4 PM_PS( VS_OUTPUT In ) : COLOR0
{ 
    float2 vOffsetTS = float2(In.vViewDirTS.x, In.vViewDirTS.y) / In.vViewDirTS.z;
    float3 vViewTS   = normalize(In.vViewDirTS);   // view direction in tangent space
    float3 vViewWS   = normalize(In.vViewDirWS);   // view direction in world space
    float3 vLightTS  = normalize(In.vLightDirTS);  // light direction in tangent space
    float3 vNormalWS = normalize(In.vNormalWS);    // normal in world space

    vOffsetTS *= g_fHeightMapScale;
    int NumSteps = (int)lerp(g_MaxSample, g_MinSample, max(dot(vNormalWS, vViewWS), 0.0f));
    float fStepSize = 1.0f / (float)NumSteps;
    float fCurrHeight = 0.0f;
    float fPrevHeight = 1.0f;
    float fCurrBound  = 1.0f;
    float fHeight = 0.0f;

    int nStepIndex = 0;
    float2 vTexOffsetPerStep = vOffsetTS * fStepSize;
    float2 vCurrTexCoord = In.texCoord;

	while(nStepIndex < NumSteps)   // height profile-ray intersection
	{
		vCurrTexCoord -= vTexOffsetPerStep;
		fCurrHeight = tex2D(tNormalHeightMap, vCurrTexCoord);
		fCurrBound -= fStepSize;
		if(fCurrHeight > fCurrHeight)   // we have found the intersection point
		{
			float delta1 = fCurrHeight - fCurrBound;
			float delta2 = fCurrBound + fStepSize - fPrevHeight;
			float alpha = delta1 / (delta1 + delta2);
			fHeight = 1.0f - lerp(fCurrHeight, fPrevHeight, alpha);  // calculate height approximately
			nStepIndex = NumSteps + 1;
		}
		else
		{
			fPrevHeight = fCurrHeight;
			nStepIndex++;
		}
	}

    float2 vParallaxOffset = vOffsetTS * fHeight;
    float2 texCoord = In.texCoord - vParallaxOffset;
   
    float4 cFinalColor = CalculateLighting(In.vViewDirTS, In.vLightDirTS, texCoord);
    return cFinalColor;
}

I compiled the "ParallaxOcclusionMapping" in D3D Sample, everything is OK. But mine couldn't work. I can't figure it out how to solve this problem.


Edited by viX0026, 24 October 2013 - 09:40 PM.


Sponsor:

#2 MJP   Moderators   -  Reputation: 11569

Like
2Likes
Like

Posted 25 October 2013 - 01:49 AM

Next time please post the entire shader, since what you posted doesn't include the textures and  constants that you use.

Anyway the problem is that you're using tex2D inside a loop, which isn't allowed since the hardware can't compute gradients for mipmapping inside of dynamic flow control (since neighboring pixels in a 2x2 quad might take different paths at a branch). You should compute the gradients outside the loop and pass them into tex2Dgrad, like the sample does. The reason the compiler isn't giving the right error message is because it's trying to be too clever for its own good. When you try to use gradient operations inside a branch or loop, it will try to either pull the operation out of the loop/branch or flatten/unroll the branch. In your particular case it tried to unroll, but it failed to do it since the loop is meant to be dynamic. If you force the compiler to try to use a dynamic loop instead of unrolling it by putting [loop] above the while loop, it gives the correct error message.

BTW once you fix that you'll also want to change "if(fCurrHeight > fCurrHeight)" to "if(fCurrHeight > fCurrBound)", otherwise it's never going to take that branch and the whole thing will get optimized away.


Edited by MJP, 25 October 2013 - 01:50 AM.


#3 viX0026   Members   -  Reputation: 191

Like
1Likes
Like

Posted 25 October 2013 - 04:10 AM

Next time please post the entire shader, since what you posted doesn't include the textures and  constants that you use.

Anyway the problem is that you're using tex2D inside a loop, which isn't allowed since the hardware can't compute gradients for mipmapping inside of dynamic flow control (since neighboring pixels in a 2x2 quad might take different paths at a branch). You should compute the gradients outside the loop and pass them into tex2Dgrad, like the sample does. The reason the compiler isn't giving the right error message is because it's trying to be too clever for its own good. When you try to use gradient operations inside a branch or loop, it will try to either pull the operation out of the loop/branch or flatten/unroll the branch. In your particular case it tried to unroll, but it failed to do it since the loop is meant to be dynamic. If you force the compiler to try to use a dynamic loop instead of unrolling it by putting [loop] above the while loop, it gives the correct error message.

BTW once you fix that you'll also want to change "if(fCurrHeight > fCurrHeight)" to "if(fCurrHeight > fCurrBound)", otherwise it's never going to take that branch and the whole thing will get optimized away.

 

Thanks, that works ! But I'm a little bit confused about gradient operation in dynamic flow. I read the "Flow Control Limitations" in MSDN. This is how it describes:

 

"When flow control is present in a shader, the result of a gradient calculation requested inside a given branch path is ambiguous when adjacent pixels may execute separate flow control paths. Therefore, it is deemed illegal to use any pixel shader operation that requests a gradient calculation to occur at a location that is inside a flow control construct which could vary across pixels for a given primitive being rasterized."

 

I couldn't imagine how the error occurs when there are some gradient operations inside a dynamic flow. Can you show me some examples about this ? Thanks again !


Edited by viX0026, 25 October 2013 - 04:19 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS