world normals and surface shaders

Hi, I haven’t figured out how to get world normals into surface shaders. If I try to propagate them through manually, I run out of texcoords.

I’m fairly certain that a tangent to world matrix is available in the surface shader ( for getting world reflection vector ), but it is abstracted away with INTERNAL_DATA macro.

Is there any reason that the tangent to world matrix isn’t available for us to use in the surface shader?

thanks,
-s

Hey snakeylake,

Have you found a way to access these parameters? I am looking for the same right now… :frowning:
Thanks,

Jan

So you want to transform normals coming from a normalmap into world space?

Yeah, internally this is used for reflective shaders. The only reason why it’s not exposed in surface shaders… no one asked for it, and I haven’t thought about it! :wink:

Aras, that would be great!

I vote for, :slight_smile:
that would be great (i was searching for it :p)

That would be great…

The viewDir and lightDir is in tangent space anyway, right? It would be great if the World2Tangent or Object2Tangent matrix (Pre-3.0 → TANGENT_SPACE_ROTATION) would be exposed too… this way arbitrary vectors can be used in a custom lighting function. In my current case this would be a vector to a certain world space position…

[Edit]
Sorry… I should check this, before posting. The TANGENT_SPACE_ROTATION still seems to be available! :roll_eyes:

They are in “some space”. When you use normal maps, they are in tangent space. When you don’t, they are in world space (I think…), and the interpolated per-vertex normals are in that space as well.

That is, all lighting related vectors (normal, light, view) are in the same space. But the space itself might be different based on the situation.

I would really like this. Whenever I use INTERNAL_DATA I feel like there is some magic going on behind the scenes that I don’t have control over. It also adds a lot of interpolators into the vert → fragment, which means that it makes it possible to run out of them easily. This wouldn’t be so bad an issue if you had control over which compiled shader permutations added INTERNAL_DATA, but currently we don’t and it’s included for some permutations and not in others.

If using INTERNAL_DATA / TBN exposing it to be used in all shader permutations would make it then possible to access per pixel world normal and other useful shader properties. I’m going to assume that if you are using deferred and per pixel normals that special permutation of the shader is compiled that has INTERNAL_DATA implicitly defined, unlike the manual definition that is required for things like world reflection.

The other thing I would love would be a flag to apply texture matrix application in the pixel shader instead of in the vertex shader. Doing it in the vertex shader requires each sampler to have an interpolated output, this really pushes the number of interpolators up and makes it easy to go over the limitations of SM2.0/3.0. If the mesh UV was passed through and then the texture matrix was applied in the pixel shader this would help with the issue of too many interpolators.

Just some things I have been experiencing when developing the shader editor that you might like to know about.

Built-in variable for world space normal (“worldNormal”) is coming in next release soon-ish. This will just use interpolated per-vertex normal when no bumpmapping is used, and will compute it via hidden tangent-to-world matrix in INTERNAL_DATA when bumpmapping is used. Just like worldRefl does now.

Awesome! That’ll be very useful for simple cubemap diffuse lighting. Thanks Aras!

That’s good news for me, as I’m in the same boat as unisip. My artist wants good ambient lighting for dynamic objects to go along with our RNM lighting for static objects. So I eagerly await the next release! :slight_smile:

Though I have a quick question. Will we be able to use worldRefl in conjunction with worldNormal? I’d hate to have to give up one for the other.

Yes, I specifically added tests for that to our testing suite (for both bumpmapped non bumpmapped cases).

hello,
i did some kind of car paint using “surface shader’s magic” like INTERNAL_DATA
it looks like its’ ok :

but if i do a UNIFORM SCALE (in the editor with the scale tool) it’s look like the normal are changing (like scaled too) :


look at the color change on the truck…

look’s weird… so i try non-uniform scale… (first z, then x and y … looks like order don’t really matter) and it works…


looks like there is no problem… :

so my shader don’t support" Uniform scale" i don’t really understand why…
I wonder if it is some kind of Unity bug, or if I did something wrong
any idea ?

thanks

454879--15928--$bug_01.jpg
454879--15929--$bug_02.jpg
454879--15930--$bug_03.jpg

Nice shader, but strange problem…
I guess you use a custom lighting function? Have you tried to normalize the normal before using the shader to see if the problem still occurs? If that doesn’t help try the same with the other input vectors like worldRefl, lightDir,…

I am just trying to figure out a work around until you make that fix by calculating the world space normal from worldRefl and viewDir but I am completely confused by what space viewDir is in presently!

Would you care to suggest the correct work around?

hello, thank’s DerWoDaSo, that’s it, i normalized the normals and now every things working nicely now :slight_smile:
thank you again!

@tokyob: Your welcome, glad it works now!

Maybe adding a custom vertex program and calculating the world normal there? This requires to create a struct for the appdata (adding the worldNormal parameter). Just making it up from my memory…

void vert (inout appdata_custom v) {
   half3 v.worldNormal = mul(object2world(vertex), v.normal);
}

I am not sure about the Object2World syntax though! :wink:

You know for some reason I was thinking you couldn’t specify a vertex shader if you used the surface shaders stuff but now I realise of course that wouldn’t quite make sense.

And I now see that in Unity - Manual: Surface Shader examples there is an example with a vertex shader.

Thank you for making realise :slight_smile:

The original problem that I had was that once I defined INTERNAL_DATA, I didn’t have enough texcoords to pass through worldNormal from the vertex shader…

At some point, I realized that when you define INTERNAL_DATA, IN.worldRefl is the world view vector ( when calculating world reflection it converts tangent space normal to world space normal and reflects it with world view ).

If you normalize IN.worldView, you can calculate world normal like this once you’ve calculated world reflection.
float3 worldNormal = normalize( worldRefl - IN.worldRefl );

This is wasted instructions as we already calculated worldNormal inside of the macro when calculating world reflection vector… but it works ( right now anyway :slight_smile:

Hey guys,

I’ve been hassling and googling, but I still can’t figure out how one would get the world normal when creating custom lighting functions?

I’ve been looking for a tangent to world space matrix, but alas, no luck.

Any suggestions?