WE WANT YOU: Two bumpmaps with different tiling

We are working on a bonestructure for our 3d-model viewing program. A normal map tiled 1:1 is needed to visualize the rough topology and another normal map tiled 500-100:1 is needed to create good-looking graininess of the bone when zoomed in really close.

See attachments for illustrations of the macro and micro bumping (using mipmapping). We want to combine both of these bumps in one shader.

We can’t just blend the two bump maps in advance, because we want to preserv all details when zooming in max on object.

We want to create something like this
http://forum.unity3d.com/viewtopic.php?t=40266
but with different tiling for the two maps.

Shader "TwoLayerBumped mix" { 

Properties { 
    _Color ("Main Color", Color) = (1,1,1,0.5) 
    _MainTex ("Base (RGB)", 2D) = "white" {} 
    _MainTex2 ("Base 2 (RGB)", 2D) = "white" {} 
    _BumpMap ("Bumpmap (RGB)", 2D) = "bump" {} 
   _BumpMap2 ("Bumpmap2 (RGB)", 2D) = "bump" {} 
   _Mask ("Mix Mask (A)", 2D) = "gray" {} 
} 
  
Category { 
    Blend AppSrcAdd AppDstAdd 
    Fog { Color [_AddFog] } 
  
    // ------------------------------------------------------------------ 
    // ARB fragment program 
    
    SubShader { 
        // Ambient pass 
        Pass { 
            Tags {"LightMode" = "PixelOrNone"} 
            Color [_PPLAmbient] 
            SetTexture [_MainTex] { combine texture } 
            SetTexture [_Mask] { combine previous, texture } 
            SetTexture [_MainTex2] { combine texture lerp (previous) previous } 
            SetTexture [_MainTex2] { constantColor [_Color] combine previous * primary DOUBLE, previous * constant } 
        } 
        // Vertex lights 
        Pass { 
            Tags {"LightMode" = "Vertex"} 
            Lighting On 
            Material { 
                Diffuse [_Color] 
                Emission [_PPLAmbient] 
            } 
            SetTexture [_MainTex] { combine texture } 
            SetTexture [_Mask] { combine previous, texture } 
            SetTexture [_MainTex2] { combine texture lerp (previous) previous } 
            SetTexture [_MainTex2] { constantColor [_Color] combine previous * primary DOUBLE, previous * constant } 
        } 
        
        // Pixel lights 
        Pass { 
            Name "PPL" 
            Tags { "LightMode" = "Pixel" } 
                
CGPROGRAM 
#pragma vertex vert 
#pragma fragment frag 
#pragma fragmentoption ARB_fog_exp2 
#pragma fragmentoption ARB_precision_hint_fastest 
#pragma multi_compile_builtin 
  
#include "UnityCG.cginc" 
#include "AutoLight.cginc" 
  
struct v2f { 
    V2F_POS_FOG; 
    LIGHTING_COORDS 
    float2  uv[5] ;    
    float3  lightDirT; 
}; 

float4 _MainTex_ST, _MainTex2_ST, _Mask_ST, _BumpMap_ST, _BumpMap2_ST; 
  
v2f vert (appdata_tan v) 
{ 
    v2f o; 
    PositionFog( v.vertex, o.pos, o.fog ); 
    o.uv[0] = TRANSFORM_TEX(v.texcoord, _MainTex); 
    o.uv[1] = TRANSFORM_TEX(v.texcoord, _MainTex2); 
    o.uv[2] = TRANSFORM_TEX(v.texcoord, _Mask); 
   o.uv[3] = TRANSFORM_TEX(v.texcoord, _BumpMap); 
   o.uv[4] = TRANSFORM_TEX(v.texcoord, _BumpMap2);    
    
    TANGENT_SPACE_ROTATION; 
    o.lightDirT = mul( rotation, ObjSpaceLightDir( v.vertex ) );    
    
    TRANSFER_VERTEX_TO_FRAGMENT(o); 
    return o; 
} 
  
uniform sampler2D _MainTex; 
uniform sampler2D _MainTex2; 
uniform sampler2D _BumpMap; 
uniform sampler2D _BumpMap2; 
uniform sampler2D _Mask; 
  
float4 frag (v2f i) : COLOR 
{ 
    half4 col1 = tex2D(_MainTex,i.uv[0]); 
    half4 col2 = tex2D(_MainTex2,i.uv[1]); 
    half mix = tex2D(_Mask,i.uv[2]).a; 
    half4 texcol = lerp(col1,col2,mix); 
    
    // get normal from the normal maps    
    float3 normal = tex2D(_BumpMap, i.uv[3]).xyz * 2 - 1; 
   float3 normal2 = tex2D(_BumpMap2, i.uv[4]).xyz * 2 - 1; 
   float3 normcol = lerp(normal ,normal2, mix); 
    
    return DiffuseLight( i.lightDirT, normcol, texcol, LIGHT_ATTENUATION(i) ); 
} 
ENDCG              
        } 
    } 
    
    // ------------------------------------------------------------------ 
    // Four texture cards 
    
    SubShader { 
        // Vertex lit 
        Pass { 
            Lighting On 
            Material { 
                Diffuse [_Color] 
                Ambient [_Color] 
            } 
            SetTexture [_MainTex] { combine texture } 
            SetTexture [_Mask] { combine previous, texture } 
            SetTexture [_MainTex2] { combine texture lerp (previous) previous } 
            SetTexture [_MainTex2] { constantColor [_Color] combine previous * primary DOUBLE, previous * constant } 
        } 
    } 
} 
  
FallBack "VertexLit" 
  
}

The problem with the shader above is that unity thinks that _BumpMap and _BumpMap2 is one and the same. When changing tiling for one of the two bumpmaps, the other is changed too.

Does this require Cg editing?

Any ideas on how to achieve this?


Dude, what if you used this: o.Normal = UnpackNormal((tex2D(_BumpMap, IN.uv_BumpMap)+tex2D(_BumpMapTwo, IN.uv_BumpMapTwo))/2);

It allows different tiling, and it does give you the bump mixing… just not perfect, I know, but check it.

Evenmore:

Shader “doubleBumpForChosen” {
Properties {

_Color (“Main Color”, Color) = (1,1,1,1)
_MainTex (“Base (RGB) Gloss (A)”, 2D) = “white” {}
_BumpMap (“Normalmap”, 2D) = “bump” {}
_BumpMapTwo (“Normalmap2”, 2D) = “bump” {}
}

SubShader {
Tags { “RenderType”=“Opaque” }
LOD 400

CGPROGRAM

#pragma surface surf BlinnPhong

sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _BumpMapTwo;
fixed4 _Color;

struct Input {

float2 uv_MainTex;
float2 uv_BumpMap;
float2 uv_BumpMapTwo;
};

void surf (Input IN, inout SurfaceOutput o) {

fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
fixed4 c = tex * _Color;

o.Albedo = c.rgb;
o.Normal = UnpackNormal((tex2D(_BumpMap, IN.uv_BumpMap)+tex2D(_BumpMapTwo, IN.uv_BumpMapTwo))/2);

}

ENDCG

}

may have a few details to take care of…

No problem XD… i am in need of this problem.
already had a post HERE

i’m no Hero in shader scripting… :frowning:
but there are a few errors:

Shader error in 'Reflective/Bumped Specular Water': Program 'frag_surf', cannot locate suitable resource to bind parameter "_ShadowCoord" at line 68

Keywords: DIRECTIONAL, LIGHTMAP_OFF, DIRLIGHTMAP_OFF, SHADOWS_SCREEN
Shader error in 'Reflective/Bumped Specular Water': Program 'frag_surf', input semantic attribute "TEXCOORD" has too big of a numeric index (8) at line 68

Keywords: DIRECTIONAL, LIGHTMAP_OFF, DIRLIGHTMAP_OFF, SHADOWS_SCREEN

i realy have no clue… but i gues it isn’t working

well… the shader does work, and the two bumpmaps are visible, but as this is just an average is not exactly what’s needed/correct, I’m checking on how normal maps work to see if I can come up with a math function for it, but the unpacking normals with a math function involving two textures looks like the way to go, if it shows an error, it must be something else cause it works just fine for me, check it.

float3 normal1 = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
float3 normal2 = UnpackNormal(tex2D(_BumpMapTwo, IN.uv_BumpMapTwo)); // Detail normal.
normal2.z *= 0.5;
normal2.z += 0.5;
o.Normal = normalize(normal1 + normal2);

@Farfarer thanks a lot, been trying implementing your script and on a couple primitives it got kind of funny, its like the normals involved in the process are changin the overall direction light is coming from… i mean, like if you rotate the directional light around 70 degrees… its kind of weird, has it happened to you?

yep your shader works :slight_smile:

is there a way to build a reflection cube map in? did ty it… but i get an error when copying out of the standard unity shaders :frowning:
has something to do with:

float3 worldRefl = WorldReflectionVector (IN, o.Normal);
	fixed4 reflcol = texCUBE (_Cube, worldRefl);
	reflcol *= tex.a;
	o.Emission = reflcol.rgb * _ReflectColor.rgb;
	o.Alpha = reflcol.a * _ReflectColor.a;

whole script:

Shader "doubleBumpForChosen" {
Properties {

_Color ("Main Color", Color) = (1,1,1,1)
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
_SpecColor ("Specular Color", Color) = (0.5,0.5,0.5,1)
_ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
_BumpMap ("Normalmap", 2D) = "bump" {}
_BumpMapTwo ("Normalmap2", 2D) = "bump" {}
_Cube ("Reflection Cubemap", Cube) = "" { TexGen CubeReflect }

}

SubShader {
Tags { "RenderType"="Opaque" }
LOD 400

CGPROGRAM

#pragma surface surf BlinnPhong 

sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _BumpMapTwo;
samplerCUBE _Cube;

fixed4 _Color;
fixed4 _ReflectColor;
half _Shininess;

struct Input {

float2 uv_MainTex;
float2 uv_BumpMap;
float2 uv_BumpMapTwo;
float3 worldRefl;
INTERNAL_DATA
};


void surf (Input IN, inout SurfaceOutput o) {

fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
fixed4 c = tex * _Color;
o.Albedo = c.rgb;
o.Specular = _Shininess;

float3 normal1 = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
float3 normal2 = UnpackNormal(tex2D(_BumpMapTwo, IN.uv_BumpMapTwo)); // Detail normal.
normal2.z *= 0.5;
normal2.z += 0.5;
o.Normal = normalize(normal1 + normal2);


float3 worldRefl = WorldReflectionVector (IN, o.Normal);
fixed4 reflcol = texCUBE (_Cube, worldRefl);
reflcol *= tex.a;
o.Emission = reflcol.rgb * _ReflectColor.rgb;
o.Alpha = reflcol.a * _ReflectColor.a;

}

ENDCG

}
FallBack "Reflective/Bumped Diffuse"
}

does anyone know this? still can’t fix it :frowning:
trying to get a cube reflection in the shader…