Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: HLSL fWidth problem  (Read 1222 times)
WEst
Customers
Community Member
*****
Posts: 945

Daniel Martinek


WWW
« on: July 20, 2011, 11:14:30 AM »

Hey guys, long time no see ^^.

I'm working on my bachelors dissertation and ran into some kind of problem with a shader and wondered if one of you may be able to help me.

I got this kind of pixel shader:
Code:
float DDNormal = length(fwidth(IN.normal)) * 20;
return float4(DDNormal,DDNormal,DDNormal,1);

The IN.normal is the interpolated and normalized vertex normal. I want to get the change of the normal per screenspace pixel (length of the fwidth), but when I do that I get very hard edges at the polygon edges and it seems as if the partial derivation of the normal is the same for the whole polygon.

Screenshot:


The normal itself is very smooth when displayed. I do the same with the vertex position and it has exactly the same problem. It's also the same when I use ddx/ddy instructions. My card is a DX11 ATI 5xxx card, so there shouldn't be much of a problem there.

 Does anyone know what's wrong here?

Logged

Greetings

Daniel Martinek
Technical Director
23 Volts
ZaPPZion
Moderator
Community Member
*****
Posts: 555


« Reply #1 on: July 20, 2011, 06:31:41 PM »

To be honest, this is exactly what I'd expect this shader to do. It's kinda hard to explain, but this is totally what you're calculating right now. The calculation part is actually calculating the rate of change of the normals' direction, but that's exactly where you hit a major problem.

You are outputting the IN.Normal from the vertex shader, which is (as the name implies) per vertex. For each face, there'll be 3 vertices, so 3 normals that are part of this equation. After the vertex shader, the normals will be applied to all of the polygon in a linear interpolation process, which means the rate of change between all 3 normals actually stays the same all over the polygon.

Imagine the simplest function of all: f(x) = x. If you'd be taking the derative of that (like you're doing), it'd mean that f'(x) = 1, meaning that there's a constant change of 1 every 'step'.

In this case, since the normals are linear interpolated across the triangle, the rate of change won't actually change at all, since that's linear across the triangle.

I don't know exactly what you're going for, but I think you'll be able to do it, the thinking part is just hard Smiley Please share it on the forums, so we can help you think Smiley

Greets,
ZaPP
Logged

Check out my website: www.bartkuipers.com
WEst
Customers
Community Member
*****
Posts: 945

Daniel Martinek


WWW
« Reply #2 on: July 21, 2011, 03:51:11 AM »

You are outputting the IN.Normal from the vertex shader, which is (as the name implies) per vertex. For each face, there'll be 3 vertices, so 3 normals that are part of this equation. After the vertex shader, the normals will be applied to all of the polygon in a linear interpolation process, which means the rate of change between all 3 normals actually stays the same all over the polygon.

Argh, you are of course right when I have linear interpolated normals the change will be the same each step, don't know what I was thinking about.

Well I'm currently implementing Pre-Integrated Skin Shading from the GPU Pro 2 Book. They compute a look-up-table to compute the lighting depending on NdotL and the surface curvature. This I can do. Then they compute the curvature in the shader using:

Code:
float curvature = saturate(length(fwidth(Normal))/length(fwidth(WorldPos))) * tuneCurvature;

This gives about the same artifacts you see in the screenshot above and when I visualized each component independently they showed the same "Per-polygon problem". So I wrongly interpreted this as the actual problem. When using this jagged curvature the artifacts of course continue into the lighting look-up.

What I really need is a way to smoothly compute the curvature of a surface per pixel in screen space.

Greetings
Daniel
Logged

Greetings

Daniel Martinek
Technical Director
23 Volts
ZaPPZion
Moderator
Community Member
*****
Posts: 555


« Reply #3 on: July 21, 2011, 05:10:16 AM »

Ah that's cool Smiley

The problem is quite hard to actually grasp, I've been thinking about it last night (couldn't sleep Smiley) and couldn't come up with an easy solution. There is however one idea that pops in my head that might actually be the solution to this problem.

If you'd calculate the 'straight up' normal from the 3 vertices (so that means the non-interpolated normal), you'd be able to calculate the difference between the two normal vectors, the interpolated and the non-interpolated normal. If the interpolated normal differs a lot from the non-interpolated normal, the polygon is 'bend', there is curvature.

I don't think I've got the whole solution yet, but this is at least part of the solution I think, since you'll be able to correctly calculate the amount of curvature per pixel instead of per polygon.

Another idea might be to calculate the curvature in the vertex shader instead of the pixel shader, to make sure you've got interpolated curvature. If a certain vertex has a curvature and another vertex in the same polygon has another curvature, the curvature across the polygon will be linear interpolated in the pixel shader, but at least it will be a lot smoother than having the same result all over the polygon. This is actually mind boggling to be honest Smiley

I like the complexity of such an 'easy' looking problem. Hope to see more of it Smiley

Greets,
Bart
Logged

Check out my website: www.bartkuipers.com
Toaster
Community Member
*
Posts: 378


WWW
« Reply #4 on: July 21, 2011, 07:05:56 AM »

I recently did my own skin as well and used this:

http://www.gamedev.net/topic/585052-real-time-skin-shader/page__p__4823289__hl__skin__fromsearch__1#entry4823289

I actually had some of his code if you download his crysis mod(adds new shader's to crysis)

Bunch of good stuff in their, I believe their was a function called smooth normals or something.

-Toaster
Logged

Visit my site at: Unknown Abstraction
WizardOfOzzz
Community Member
*
Posts: 1


« Reply #5 on: August 16, 2011, 12:25:13 PM »

Hey There,

The per-triangle curvature is expected. Since it only causes a blur of the lighting, usually it doesn't show up in the final calculation, but if it does there are a few things you can do. Like others have suggested you can use a per-vertex curvature, or a curvature texture that is blurred in advance.

If you do come up with a way to compute a smooth curvature it would definitely be useful. I was thinking that this might be possible by storing extra information per vertex, but couldn't come up with anything that was completely smooth.

Eric
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks