Home Technical Talk

Detail / Micro Diffuse maps

TSM
TSM
So,

I'm trying to find a way on getting detailed diffuse maps look good (not desaturating) in my shader. Currently, my detail diffuse is from my standard diffuse, just a smaller res, greyscale and edited for a weebit better tiling.

In my shader I'm simply adding the detail diffuse to the standard diffuse but I get overly white / desaturated results.

Any ideas?

Replies

  • Ryan Clark
    Options
    Offline / Send Message
    Ryan Clark polycounter lvl 18
    Four ideas spring to mind:

    Idea #1: Try multiplying your two diffuse maps, instead of adding them.

    Idea #2: Try adding your two diffuse maps, and then subtracting .5 from the result.

    Idea #3: Try adding your two diffuse maps, and then dividing the result by two.

    Idea #4: Experiment with different blend modes in Photoshop. If you find a good one, look up the math on this webpage: http://www.nathanm.com/photoshop-blending-math/
  • TSM
    Options
    Offline / Send Message
    TSM
    Thanks Ryan! I'll try those and get back sometime.

    By the way - off topic just a little. Which is more expensive in regards to CPU/GPU computing.. Dividing or Multiplying?
  • Ryan Clark
    Options
    Offline / Send Message
    Ryan Clark polycounter lvl 18
    The answer to that question will vary depending on the particular processor.

    In some cases (ARM9, for example), division is more expensive. In other cases, there's no difference.
  • TSM
    Options
    Offline / Send Message
    TSM
    I got good results multiplying both textures together, and dividing the total by .15 </shrug>

    Only issue is that my buildings look great but my terrain is WAAAY too bright (yes, they share the same shader).

    Continuing debugging ...
  • Ryan Clark
    Options
    Offline / Send Message
    Ryan Clark polycounter lvl 18
    Sounds like your building is using a dark detail texture, and your terrain is using a light one. That's not gonna work.

    I recommend making all your detail textures with an average shade of mid-gray (127 in photoshop). Adjust levels in photoshop to ensure this.

    Once that's done, you can balance your shader correctly because you know that your detail texture has an average value of .5

    If you add your detail texture, compensate by subtracting .5 from the result.

    If you multiply against your detail texture, compensate by doubling the result.

    etc.
  • TSM
    Options
    Offline / Send Message
    TSM
    Yup, already did that. :)

    Turns out the problem is being caused from my baked in AO map... still trying to fit the AO bake into the pipeline (since I've been trying Xnormal and 3Ds max for the AO bake... not sure which one I like better).
  • Ryan Clark
    Options
    Offline / Send Message
    Ryan Clark polycounter lvl 18
    Generally, you bake the AO into your diffuse texture in photoshop. There's not usually a reason to include AO separately in your shader.
  • TSM
    Options
    Offline / Send Message
    TSM
    That doesn't work for me, since I have many general materials (stone, steel, wood, sand, water, etc) that I repeat many times on the objects in my world to give them a more detailed appearance. If I baked in the AO in the diffuse, it would screw it all up since it would tile aswell (undesired result), so I use the AO and keep the original UV coords and use those for the AO. It looks the same as what you've mentioned, but more flexible (albeit a tad slower too).
  • Ryan Clark
    Options
    Offline / Send Message
    Ryan Clark polycounter lvl 18
    Ahh, I understand. In that case I'd imagine that a good shader would be:

    DiffuseTexture * DetailTexture * AmbientOcclusion * 2

    or

    (DiffuseTexture + DetailTexture - .5) * AmbientOcclusion



    As long as your detail textures are mostly middle-gray, either of those oughtta work ok.
  • Kevin Albers
    Options
    Offline / Send Message
    Kevin Albers polycounter lvl 18
    If you make sure you detail maps are pretty high contrast, you can get away with mixing in just a small amount of the detail map, which might help a bit.
  • TSM
    Options
    Offline / Send Message
    TSM
    Alright, detail everything is working fine but now specular is borked.

    http://img204.imageshack.us/my.php?image=specularwtf1mn3.jpg

    The left side is the back, right side is the front. Last time this happened it was with detail normals and so I decided to just rewrite the shader... detail normals work fine but now speculars jacked up. :P

    Any help? (I wish there was a HLSL forum here)

    (I don't know how to attach files here so here's a snippet of the pixel shader)
    float4 p(v2p In, uniform float4 lightColor) : COLOR
    {		
    	/*** Custom UV Texture Coords ***/
    	
    	float2 DetailN_UV    = In.uv * DetailN_Tile;                                            // Texture UV's for Detail Normal
    	float2 DetailD_UV    = In.uv * DetailD_Tile;                                            // Texture UV's for Detail Diffuse
    	float2 DiffuseTile   = In.uv * D_Tile;                                                  // Texture UV's for 
    	
    	float4 AO            = tex2D(aomapSampler, In.uv);
    	float4 DetailDiffuse = tex2D(detaildiffusemapSampler, DetailD_UV);
    	float4 Diffuse       = ((tex2D(diffusemapSampler, DiffuseTile) * DetailDiffuse) * AO) / .15;
    	//float4 NewDiffuse  = Overlay(Diffuse, DetailDiffuse) / .29;
    	float4 Specular      = tex2D(specularmapSampler, DiffuseTile);	
    	float3 DetailNormal  = tex2D(detailnormalmapSampler, DetailN_UV) * 2 - 1;
    	float3 Normal        = tex2D(normalmapSampler, DiffuseTile) * 2 - 1;
    	float3 NormalComp    = normalize (Normal + DetailNormal);
    	
    	float3 Nn = normalize(In.worldNormal);                                                    // Normalzing the input world space vectors
    	float3 Tn = normalize(In.worldTangent);
    	float3 Bn = normalize(In.worldBinormal);
    	
    	float3 N = (NormalComp.z * Nn) + (NormalComp.x * Bn) + (NormalComp.y * -Tn);
    	N = normalize(N);                                                                         // Putting the tangent space normal map into world space
    	
    	float3 L = normalize(In.lightVec.xyz);
    	float3 V = normalize(In.eyeVec.xyz);
    	float3 H = normalize(L + V);                                                               //The half-angle vector, used for blinn specular
    	
    	float4 fNDotL   = saturate(dot(N,L));
    	float4 cDiffuse = fNDotL * Diffuse;
    
    	float fNDotH     = saturate(dot(N,H));
    	float fSpecLevel = pow(fNDotH, g_fGlossiness);
    	float4 cSpecular = fSpecLevel * Specular;
    	
    	float4 lighting = ((cDiffuse + cSpecular) * lightColor );
    	
    	return float4(lighting.xyz, 1);
    }
    
  • Ryan Clark
    Options
    Offline / Send Message
    Ryan Clark polycounter lvl 18
    A bit of trial-and-error might be useful here.

    What happens if you leave off the detail normal map, and just use your original normal map? Does the problem go away?

    thanks

    -Ryan
  • TSM
    Options
    Offline / Send Message
    TSM
    Well holy crap! Detail normals DO screw it up! (Funny...) What's the reason behind that?
  • Ryan Clark
    Options
    Offline / Send Message
    Ryan Clark polycounter lvl 18
    What about if you use just the detail normals by themselves? Does that work?

    If so, then the problem must lie in the code by which you combine the two normal maps.

    Simply adding two normal maps is not going to achieve quite the effect that you desire, btw. Even though you renormalize them afterward, you'll find details will be reduced... but I don't think thats the cause of this problem.
  • Kawe
    Options
    Offline / Send Message
    Kawe polycounter lvl 8
    Just a thought.

    I think you have to zero out the detail normal map's z channel.. which I assume is the blue channel? You can do it either in shader code or in the texture itself.

    iirc when you make materials in UT3 you have to zero out the blue channel on the detail normal maps.

    not entirely sure though.

    right now you are just adding the two normal maps together and normalizing them I believe and well... I think it will give you undesired results.

    sadly I'm not sure at all of what I'm saying.. just something I picked up. but it's an idea at least.
  • TSM
    Options
    Offline / Send Message
    TSM
    Yes, they work by themselves.

    They are using totally separate UV coords, how could this happen?

    Kawe, I believe you have to half the blue channel (thanks for reminding me to do so), since the blue channel only goes 0 - 1. So adding two blue channels could screw things up!

    Thanks!
  • TSM
    Options
    Offline / Send Message
    TSM
    Alright, sorry for the double posts!
    float3 NormalComp    = normalize (Normal);//+ DetailNormal);
    

    This line screws things up (commented out so my scene still looks good :D), like Ryan was hinting at. :)

    *thinks of the solution* ... I know you can't really 'mix' shaders although there is 'stacking' but that's still on in the same shader (right?).

    The funny thing is, detail diffuse works fine, no issues there. Why would normals be different?

    btw, I added this too
    float3 DNormalPRE    = tex2D(detailnormalmapSampler, DetailN_UV) * 2 - 1;
    float3 DetailNormal  = normalize (DNormalPRE.b * .5);
    

    That still didn't help.
  • Kawe
    Options
    Offline / Send Message
    Kawe polycounter lvl 8
    Looking at Unreal Editor's material editor they make sure that the sum of the blue channel is always 1. The other channels don't seem to matter as much.

    So if you have 0.5 of the detail normal map's blue channel you would have to take 0.5 for the normal.. normal map's blue channel. In UE3 they vary it.. sometimes they zero it out and sometimes they take 0.3.. and so on.. but they adjust the other normal map's blue channel accordingly so it always adds up as 1.

    I think you should give it a shot :)

    If it doesn't work try posting your normal maps too. Hard to determine what is going wrong from the renders only.
  • TSM
    Options
    Offline / Send Message
    TSM
    Interesting, I know the blue cannot have a negative number because it must always point outward, but why always have it equal to one? I doubt that would have to do with this 'streaking' issue.

    I'll post normals soon.
  • Kawe
    Options
    Offline / Send Message
    Kawe polycounter lvl 8
    Well, there are no standards for normal maps so you can't really say what does what.

    A quote I just googled up from blender's homepage.
    Since normals all point towards a viewer, negative values are not stored. In Blender we store a full blue range, although some other implementations also map blue colors (128-255) to (0.0 - 1.0). The latter convention is used in "Doom 3" for example.

    So if your implementation only uses 128-255 then normalizing something that is off the scale would most likely push values below 128 and get you into the minus range.

    If it uses the full blue range then I suppose there shouldn't be any problems?

    Not entirely sure though...

    And not even sure if it has anything to do with your streaking issues. Heh.
  • TSM
    Options
    Offline / Send Message
    TSM
    Kawe,

    Thanks for you help man! I really appreciate it. :)

    I'll look into it more. From what I understand, it's 'standard' to half the blue channel in normal maps when using more than one.

    If anyone else has any insight to this weird 'streaking' problem, feel free to let me know! :D
  • Pseudopus
    Options
    Offline / Send Message
    Sorry to necropost. this thread is linked in the polycount wiki for detail maps, and I might be able to give some help in case anyone else stumbles across this thread. http://wiki.polycount.net/Detail_Map

    The way I do it is to basically the method of combining normal maps in photoshop (halve the blue channel on one, set to overlay);
    There might be a cheaper way to do it out there, and this only works for tangent normal maps.

    First create an overlay function outside of the pixel shader:
    float Overlay(float input2, float input1)
    { 
        float result = 0.0; 
        if (input2 < 0.5) result =  2 * input1 * input2;
        else result =  1 - 2 * (1 - input1) * (1 - input2); 
        return result; 
    }
    
    This is the overlay formula from shaderFX; I believe this to be the way photoshop's overlay modifier works as well.

    You use it to combine the individual channels of your sampled base normal map and detail map before expanding, transform into worldspace, or normalizing either of the maps.
    float tileMultiplier = 10; // how many times the detail map is tiled across UV space
    float3 baseNormal= tex2D(normalSampler, In.texCoord.xy).xyz;
    float3 detailNormal= tex2D(detailSampler, In.texCoord.xy*tileMultiplier).xyz;
    
    detailNormal.b /= 2; //halve the blue channel. You can do this before you export your normal detail map and skip this step;
    
    float3 combinedNormal = float3( (Overlay(detailNormal.x,baseNormal.x)),(Overlay(detailNormal.y,baseNormal.y)),(Overlay(detailNormal.z,baseNormal.z)) );
    
    //expand, and transform into worldspace, and normalize etc
    
    This shouldn't weaken or distort the existing normals.
    Heres a pic of it at work with a maya cgfx node:
    http://img12.imageshack.us/img12/1266/normalk.jpg

    If there is a method of combining objectspace normal maps in photoshop, you could probably modify this to overlay them after the tangent maps have been transformed into worldspace.
Sign In or Register to comment.