- Home /
Shade Based on Normal Map World Position Angle (Updated)
Hi,
I have been reading for days to try and figure this out, but I can't find a way to make this happen. I'm a decent shader programmer I'm just not familiar with how to get angles through shader scripting.
Maybe this:
float3 viewN = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
How can I shade based on the normal map and world angle so that a texture is only rendered at the normal map angles? From what I understand normals don't render past a certain angle, unless I'm mistaken. How do you do this through shaders?
I'd like to have a diffuse shader with normals that would be used to calculate the angle for the overlay texture to render onto. So I'd have a diffuse, normal, and an overlay that would be in the middle because it would only render according to the normals of the texture.
For a visual something like the video below, except this would only be based off the normal map not heightmaps: http://www.youtube.com/watch?v=otedqKHET1w&feature=youtube_gdata_player
Update Newer: Alright I've got a decent shader working, but it only works because the main snow texture is partially transparent. The bump acts as a map for the snow to lay, so it kind of works. I also have to have 2 materials, the original bump specular, and the snow shader. This also allows your to control the alpha level of the texture. This way is unpractical as I can't make a transparent texture for every texture in the game, the shader needs to do it itself.
How can I make it so I can place just a normal transparent white texture and the bump map will guide that white texture to lay where it's supposed to, according to the bumps only. Also only laying till a certain angle to act like snow. I thought I'd receive more help on Unity Answers, I've been doing everything myself. It'd be nice to get some help as I'm literally just guessing with most of this stuff.
Update Old: So I managed to make some progress. I found a shader on the Unity wiki that shades the object based on light shinning on the normals of the texture. It gives a similar looking effect, we just need to change it so it only works on certain angles, is always on; not just affected by light, and to make sure the density can be controlled.
Here's a screen shot: 9595
Here's the shader, that allows the object's normals to be affected by by light, we can use this as a reference as this is the closest thing I've found as a starting point:
This link contains all the parameters and shader inputs needed to make this happen: http://unity3d.com/support/documentation/Components/SL-SurfaceShaders
shader "Bump Spec Rim" {
Properties {
_Color ("Main Color", Color) = (1,1,1,0.5)
_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
_Shininess ("Shininess", Range (0.03, 1)) = 0.078125
_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
_BumpMap ("Bumpmap (RGB) Rim-Light Ramp (A)", 2D) = "bump" {}
_RimLightColor ("Rimlight Color", Color) = (0.6, 0.6, 0.7, 1.0)
_RimLightRamp ("Rimlight Ramp", 2D) = "white" {}
}
SubShader {
//Self-Illumination Depending on Facing Rotation
Pass {
Tags {"LightMode" = "PixelOrNone"}
Blend AppSrcAdd AppDstAdd
Color [_PPLAmbient]
CGPROGRAM
// profiles arbfp1
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_fog_exp2
#include "UnityCG.cginc"
sampler2D _BumpMap;
sampler2D _RimLightRamp;
sampler2D _MainTex;
float4 _RimLightColor;
float4 _Color;
struct v2f {
V2F_POS_FOG;
float2 uv;
float3 tangentSpaceLightDir;
};
v2f vert (appdata_tan v)
{
v2f o;
PositionFog( v.vertex, o.pos, o.fog );
o.uv = TRANSFORM_UV(0);
float3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
float3 binormal = cross( normalize(v.normal),
normalize(v.tangent.xyz) );
float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal );
o.tangentSpaceLightDir = mul(rotation, viewDir);
return o;
}
half4 frag (v2f i) : COLOR
{
half3 tangentSpaceNormal = (tex2D(_BumpMap, i.uv).rgb * 2.0) - 1.0;
half4 result = float4(0, 0, 0, 1);
//You might want to normalize tangentSpaceNormal and
i.tangentSpaceLightDir,
//but for most meshes this will most likely have minimal, if any, impact
on quality.
float rampSample = dot(tangentSpaceNormal, i.tangentSpaceLightDir);
float intensity = tex2D(_RimLightRamp, rampSample.xx).r;
result.rgb = intensity * _RimLightColor.rgb;
result.rgb += tex2D(_MainTex, i.uv).rgb * _PPLAmbient.rgb;
return result;
}
ENDCG
}
UsePass "Bumped Specular/PPL"
}
FallBack "Bumped Specular", 1
}
Total side note, but did you check out how they did it in snowscape just been playing with that....
Yes, snowscape used this technique, but I'm not quite sure how. I can confirm this because I read the developer saying so.
Well it's in the asset store is what I was thinking...
Yes, I'm aware of snowscape, but I'd like to create my own similar shader.
Answer by ScroodgeM · Jul 14, 2012 at 09:16 AM
internally for shader any normal-mapped surface is flat, in your case you need (as i understand) to hide some areas from surface by another ones based on normal-map.
the problem is shader while rendering surface's pixel can't get any information about any other surface's pixels. so it can't calculate overlapping by other pixel.
the solution is:
make a geometry-based big areas and normal-map based small details
make a polygon with normal-map more detailed (more vertexes and tris) and use vertex shader to move verts along normals
limit view angle and don't let user to look at surface in sharp angles
Your answer
Follow this Question
Related Questions
Outlines Defined by Shading Groups? 0 Answers
Shader Color Bumped elements 0 Answers
Render depth seperately 0 Answers
Lower-level way to find NEARBY TRIANGLES on the mesh? (Answered.) 4 Answers
Why is my shader showing hard edge artifacts on mesh planes? 0 Answers