Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Terrain Rain & Snow Effects

Discussion in 'Shaders' started by GreedyVox, Oct 3, 2016.

  1. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    Hello everybody,
    have a question to do with my terrain triplanar texture atlas surface shader, and needing advice or direction in solving a problem that I am having when adding effects for rain and snow, both effects I believe can be solved with the one solution, but what I am struggling with is my limitation on shader maths (Matrix).

    Problem:
    Snow building up or water ripples effects being render when inside of caves and tunnels or beneath terrain overhangs.

    Solution:
    looking for a solution similar to how shadows work inside shaders, what I have been trying to achieve is, by calculating a vertex position with a up vector against the world matrix, and if no object detected than calculate snow and rain effects, but I have no idea how to detect an object, or even if an object is above or below the current model vertex position, Is this even possible?

    Truly believe maths is the solution, or will I need to think up another approach, currently used up all of the vertex colors and texture coords channels for rendering and blending the textures of the terrain, which rules out those as a solution, have tried messing with image effect shader but that didn't workout well at all.

    Any help, ideas or direction will be much appreciated.
     
  2. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    Examples:
    TestSunnyDay.png

    TestSnowyDay.png

    DayBlizzard.png

    TestSnowCave.png



    DayCloudy.png
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Shadows work by rendering the scene from the point of view of a light and storing the closest distance from the light to the first object and storing it as a texture, these are shadow maps. Shaders are given the same matrix as used by the light to see the world and that texture when rendering to the screen, then the shader checks if it's location is further away from the light than the value recorded on the shadow map for that direction.

    For your terrain you'd need to do some similar; you need to find some way to store the information about if each part of the terrain can see the sky or not. A shadowmap like solution could be possible, but you're probably better off storing that data in the terrain vertices themselves if possible, like the alpha of the vertex color. I don't know what you're doing to generate your terrain, but I wouldn't be surprised if the system you're using didn't already have some method of determining sky visibility.
     
    GreedyVox likes this.
  4. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    Thank you! Also thanks for the great example of shaders calculating shadows too!


    Yes you are right, would be much easier and less work of my shader, to calculate this information during the mesh generation and would be a better approach.


    Having used all the color channels (RGBA) for blending textures, I might try and use the texture coord channel 2 that is reserved for light-maps, pass through the snow texture coords of any surfaces that is in the open terrain, or the same coords for a texture that isn't on the surface, and being a procedural terrain, dont think I will be requiring light-maps.


    Closing this thread, as it has been answered by bgolus.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Note the texture coordinates can be float3 or float4 values, it's just that they're usually treated as float2 values. You can use the first two components of texcoord0 (xy) for your texture coordinates, and then use z and w for whatever data you want.
     
    GreedyVox likes this.
  6. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    bgolus
    I have implement a triplanar bump fragment shader code you shared in another post, and by the way, very noice fragment shader too.

    https://forum.unity3d.com/threads/triplanar-shader-using-world-normals-bump-mapping-help.426757/

    However having issuse with the normals and have tried and tried to fix it, my problem seems to be with implementing into my triplanar atlas fragment shader and appears though its a seaming issue within the atlas coords.

    I have tried messing with unity filter and mip maps options of the bump textures, also messed around with the uv continuous of tex2D coords without success.

    I am really liking your triplanar bump fragment shader look, and wondering if you able help me to spot my error implementing the code or suggestions on where to focus in hunting down a solution, but if this is impossible, thats no biggie, will use the triplanar atlas fragment shader created earlier.

    Screenshot from 2017-04-06 09_36_42.png Screenshot from 2017-04-06 09_37_58.png Screenshot from 2017-04-06 09_38_28.png Screenshot from 2017-04-06 09_39_23.png Screenshot from 2017-04-06 09_39_48.png

    The shader code below is still in a hacky kind of state as I am still testing a playing around with it, but all advice is totally welcomed.

    Code (CSharp):
    1. Shader "Custom/Terrain/Triplanar/Atlas/Diffuse Bump"
    2. {
    3.     Properties {
    4.         _TexOffset ("Texture offset alignment", Range(0, 1)) = 0
    5.         _TexPower ("Textures merging", Range(1, 20)) = 7
    6.         _TileCount ("Texture atlas total tiles", Float) = 16  
    7.         // Diffuse Settings
    8.         [HideInInspector] _TopTex ("Top Texture", 2D) = "white" {}
    9.         _TopBump ("Top normal map", 2D) = "bump" {}
    10.         _TopColor ("Top color tint", Color) = (1.0, 1.0, 1.0, 1.0)
    11.         [HideInInspector] _SideTex ("Side Texture", 2D) = "White" {}
    12.         _SideBump ("Side normal map", 2D) = "bump" {}
    13.         _SideColor ("Side color tint", Color) = (1.0, 1.0, 1.0, 1.0)
    14.         [HideInInspector] _BotTex ("Bottom Texture", 2D) = "white" {}
    15.         _BotBump ("Bottom normal map", 2D) = "bump" {}
    16.         _BotColor ("Bottom color tint", Color) = (1.0, 1.0, 1.0, 1.0)
    17.         _TileLookup ("Texture atlas total tiles for lookup texture", Range(1, 32)) = 8  
    18.         _LightTex ("Lighting Map (RGB)", 2D) = "white" {}
    19.         // Ramp Settings
    20.         _SpecExp("Specular Exponent", Range(0.1, 150)) = 20.0
    21.         _SpecBoost("Specular Boost", Float) = 0.3
    22.     }
    23.  
    24.     CGINCLUDE      
    25.         #include "UnityCG.cginc"
    26.          #ifndef ATLAS_INCLUDED
    27.             #define ATLAS_INCLUDED
    28.             #include "Assets/Resources/Shader Bowl/Shaders/IncludeAtlas.cginc"
    29.         #endif
    30.         #ifndef SNOW_INCLUDED
    31.             #define SNOW_INCLUDED
    32.             #include "Assets/Resources/Shader Bowl/Shaders/IncludeSnow.cginc"
    33.         #endif
    34.  
    35.         // Textures
    36.         uniform sampler2D _TopTex;
    37.         uniform sampler2D _TopBump;
    38.         uniform sampler2D _SideTex;
    39.         uniform sampler2D _SideBump;
    40.         uniform sampler2D _BotTex;
    41.         uniform sampler2D _BotBump;
    42.         uniform sampler2D _LightTex;
    43.  
    44.         uniform half4 _TopTex_ST;
    45.         uniform half4 _BotTex_ST;
    46.         uniform half4 _SideTex_ST;
    47.         uniform half4 _LightTex_ST;
    48.  
    49.         // Properties
    50.         uniform half4 _TopColor;
    51.         uniform half4 _SideColor;
    52.         uniform half4 _BotColor;
    53.         uniform half  _TexOffset;
    54.         uniform half  _TexPower;
    55.         uniform float _SpecExp;
    56.         uniform float _SpecBoost;
    57.         uniform float3  blendingWeights;
    58.  
    59.         float3 BlendNormalWeights(float2 main, float3 pos, float3 norm) {
    60.             // extract world normal from the unused w component of world to tangent matrix
    61.             float3 projNormal = saturate(pow(norm * 1.4, 4));
    62.    
    63.             // "normalize" projNormal x+y+z to equal 1, ensures even blend
    64.             projNormal /= projNormal.x + projNormal.y + projNormal.z;                  
    65.  
    66.             float xsign = sign(norm.x);
    67.             float2 zy = pos.zy * float2(xsign, 1.0) * _SideTex_ST.xy + _SideTex_ST.zw;
    68.             float3 xNorm = BumpMain(_SideBump, main.xy, zy);
    69.  
    70.             float ysign = sign(norm.y);
    71.             float2 zx = pos.zx * _TopTex_ST.xy + _TopTex_ST.zw;
    72.             float3 yNorm = ysign > 0 ? BumpMain(_TopBump, main.xy, zx) : BumpMain(_BotBump, main.xy, zx);
    73.  
    74.             float zsign = sign(norm.z);
    75.             float2 xy = pos.xy * float2(-zsign, 1.0) * _SideTex_ST.xy + _SideTex_ST.zw;
    76.             float3 zNorm = BumpMain(_SideBump, main.xy, xy);
    77.  
    78.             // use normal blending to wrap normal map to surface normal
    79.             xNorm = normalize(half3(xNorm.xy * float2(xsign, 1.0) + norm.zy, norm.x));
    80.             yNorm = normalize(half3(yNorm.xy + norm.zx, norm.y));
    81.             zNorm = normalize(half3(zNorm.xy * float2(-zsign, 1.0) + norm.xy, norm.z));
    82.    
    83.             // reorient normals to their world axis
    84.             xNorm = xNorm.zyx; // hackily swizzle channels to match unity "right"
    85.             yNorm = yNorm.yzx; // hackily swizzle channels to match unity "up"
    86.             zNorm = zNorm.xyz; // no swizzle needed
    87.    
    88.             // blend normals together
    89.             return xNorm * projNormal.x + yNorm * projNormal.y + zNorm * projNormal.z;
    90.         }
    91.  
    92.         fixed4 BlendTexWeights(float2 main, float4 splat1, float4 splat2, fixed4 color, float3 norm) {              
    93.             float y = sign(norm.y);
    94.  
    95.             fixed4 top;
    96.             if (y > 0) {
    97.                 top = lerp(TexMain(_TopTex, main.xy, UVy),
    98.                     TexMain(_TopTex, splat1.xy, UVy), color.r);
    99.                 top = lerp(top, TexMain(_TopTex, splat1.zw, UVy), color.b);
    100.                 top = lerp(top, TexMain(_TopTex, splat2.xy, UVy), color.g);
    101.                 top = lerp(top, TexMain(_TopTex, splat2.zw, UVy), color.a);
    102.             } else {
    103.                 top = lerp(TexMain(_BotTex, main.xy, UVy),
    104.                     TexMain(_BotTex, splat1.xy, UVy), color.r);
    105.                 top = lerp(top, TexMain(_BotTex, splat1.zw, UVy), color.b);
    106.                 top = lerp(top, TexMain(_BotTex, splat2.xy, UVy), color.g);
    107.                 top = lerp(top, TexMain(_BotTex, splat2.zw, UVy), color.a);
    108.             }
    109.  
    110.             fixed4 side = lerp(TexMain(_SideTex, main.xy, UVx),
    111.                 TexMain(_SideTex, splat1.xy, UVx), color.r);
    112.             side = lerp(side, TexMain(_SideTex, splat1.zw, UVx), color.b);
    113.             side = lerp(side, TexMain(_SideTex, splat2.xy, UVx), color.g);
    114.             side = lerp(side, TexMain(_SideTex, splat2.zw, UVx), color.a);
    115.  
    116.             fixed4 face = lerp(TexMain(_SideTex, main.xy, UVz),
    117.                 TexMain(_SideTex, splat1.xy, UVz), color.r);
    118.             face = lerp(face, TexMain(_SideTex, splat1.zw, UVz), color.b);
    119.             face = lerp(face, TexMain(_SideTex, splat2.xy, UVz), color.g);
    120.             face = lerp(face, TexMain(_SideTex, splat2.zw, UVz), color.a);
    121.  
    122.             top *= _TopColor;
    123.             side *= _SideColor;
    124.             face *= _BotColor;
    125.  
    126.             if(_Snow > 0) {          
    127.                 top.rgb =  Snow_Blend(top, norm);
    128.                 side.rgb = Snow_Blend(side, norm);
    129.             }
    130.  
    131.             return side.xyzw * blendingWeights.xxxx + top.xyzw * blendingWeights.yyyy  + face.xyzw * blendingWeights.zzzz;
    132.         }
    133.     ENDCG
    134.  
    135.     Subshader
    136.     {
    137.         Tags{"Queue"="Geometry" "IgnoreProjector"="True" "RenderType"="Opaque"}
    138.         LOD 200
    139.  
    140.         Pass {
    141.             Tags {"LightMode"="ForwardBase"}
    142.  
    143.             CGPROGRAM
    144.                 #include "Lighting.cginc"
    145.                 #include "AutoLight.cginc"                            
    146.  
    147.                 #pragma target 3.0
    148.                 #pragma vertex vert
    149.                 #pragma fragment frag
    150.                 #pragma multi_compile_fog
    151.                 #pragma multi_compile_fwdbase
    152.  
    153.                 struct appdata {
    154.                     fixed4 color : COLOR;
    155.                     float4 vertex : POSITION;
    156.                     float4 tangent : TANGENT;
    157.                     float3 normal : NORMAL;
    158.                     float2 texcoord : TEXCOORD;
    159.                     float4 texcoord1 : TEXCOORD1;
    160.                     float4 texcoord2 : TEXCOORD2;
    161.                     float4 texcoord3 : TEXCOORD3;
    162.                 };
    163.  
    164.                 struct v2f {
    165.                     fixed4 color : COLOR0;
    166.                     float3 normal : NORMAL0;
    167.                     float3 worldNorm : NORMAL1;
    168.                     float4 pos : SV_POSITION;
    169.                     float3 worldPos    : POSITION1;
    170.                     float2 tc_Main : TEXCOORD0;
    171.                     float2 tc_Light : TEXCOORD1;
    172.                     float4 tc_Splat1 : TEXCOORD2;
    173.                     float4 tc_Splat2 : TEXCOORD3;
    174.                     float3 viewDir : TEXCOORD4;
    175.                     float3 lightDir : TEXCOORD5;
    176.                     SHADOW_COORDS(6)
    177.                     UNITY_FOG_COORDS(7)
    178.                 };
    179.  
    180.                 v2f vert(in appdata v) {
    181.                     v2f o;
    182.                     o.color = v.color;
    183.                     o.pos = UnityObjectToClipPos(v.vertex);
    184.                     o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    185.                     o.worldNorm = UnityObjectToWorldNormal(v.normal);
    186.  
    187.                     o.normal = mul(float4(v.normal, 0.0), unity_WorldToObject).xyz;
    188.                     o.viewDir = WorldSpaceViewDir(v.vertex);
    189.                     o.lightDir = UnityWorldSpaceLightDir(o.worldPos);
    190.  
    191.                     o.tc_Main.xy = TRANSFORM_TEX(v.texcoord.xy, _TopTex);
    192.                     o.tc_Splat1.xy = TRANSFORM_TEX(v.texcoord2.xy, _TopTex);
    193.                     o.tc_Splat1.zw = TRANSFORM_TEX(v.texcoord2.zw, _TopTex);
    194.  
    195.                     o.tc_Splat2.xy = TRANSFORM_TEX(v.texcoord3.xy, _TopTex);
    196.                     o.tc_Splat2.zw = TRANSFORM_TEX(v.texcoord3.zw, _TopTex);
    197.  
    198.                     float width = (1.0 / _TileLookup);
    199.                     o.tc_Light = TRANSFORM_TEX(v.texcoord1.xy, _LightTex);
    200.                     float uu = ((o.tc_Light.x - 1.0) * width) + (width * _LightTex_ST.x);
    201.                     float vv = (o.tc_Light.y * 1.0) + (1.0 * _LightTex_ST.y);
    202.                     o.tc_Light = float2(uu, vv);
    203.  
    204.                     TRANSFER_SHADOW(o);
    205.                     UNITY_TRANSFER_FOG(o, o.pos);
    206.  
    207.                     return o;
    208.                 }
    209.  
    210.                 fixed4 frag(in v2f i) : SV_TARGET {                  
    211.                     // Tile counter
    212.                     INV_TILE_COUNT = 1 / _TileCount;
    213.                     INV_TILE_LOOKUP = 1 / _TileLookup;
    214.  
    215.                     // Bending texture weights
    216.                     blendingWeights = pow(abs(normalize(i.worldNorm)), _TexPower);
    217.                     blendingWeights = (blendingWeights - 0.2) * _TexPower;
    218.                     blendingWeights = max(blendingWeights, 0);
    219.                     blendingWeights /= (blendingWeights.x + blendingWeights.y + blendingWeights.z).x;
    220.  
    221.                     // Triplanar UVs
    222.                     UVx = i.worldPos.yz * _SideTex_ST.xy + _SideTex_ST.zw - _TexOffset;
    223.                     UVy = i.worldPos.xz * _TopTex_ST.xy + _TopTex_ST.zw - _TexOffset;
    224.                     UVz = float2(i.worldPos.x, -i.worldPos.y) * _BotTex_ST.xy + _BotTex_ST.zw - _TexOffset;
    225.  
    226.                     // Albedo
    227.                     fixed4 albedo = BlendTexWeights(i.tc_Main, i.tc_Splat1, i.tc_Splat2, i.color, i.worldNorm);
    228.  
    229.                     // Normal
    230.                     float3 normal = BlendNormalWeights(i.tc_Main, i.worldPos, i.worldNorm);
    231.  
    232.                     // Compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed).
    233.                     UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
    234.  
    235.                     // Diffuse
    236.                     float4 diffuse = saturate(dot(normalize(normal), _WorldSpaceLightPos0.xyz)) * _LightColor0 * atten;
    237.  
    238.                     float4 lighting;
    239.                     if(0.0 == _WorldSpaceLightPos0.w) {
    240.                         // Directional light
    241.                         float4 light = tex2D(_LightTex, i.tc_Light);
    242.  
    243.                         // Darken light's illumination with shadow, keep ambient intact.
    244.                         lighting = float4(diffuse + ShadeSH9(half4(normal, 1)), 1) * light;
    245.                     } else {
    246.                         // Directions
    247.                         i.normal = normalize(i.normal);
    248.                         i.viewDir = normalize(i.viewDir);
    249.                         i.lightDir = normalize(i.lightDir);
    250.                         float3 reflLightDir = reflect(-i.lightDir, i.normal);
    251.  
    252.                         // Specular
    253.                         float vDotR = max(0.0, dot(i.viewDir, reflLightDir));
    254.                         float4 specular = atten * _LightColor0 * _SpecBoost * pow(vDotR, _SpecExp);
    255.  
    256.                         // Point or spot light
    257.                         lighting = diffuse + specular;
    258.                     }
    259.  
    260.                     fixed3 col = albedo.rgb * lighting.rgb;
    261.                     UNITY_APPLY_FOG(i.fogCoord, col);
    262.  
    263.                     return fixed4(col, 1);
    264.                 }
    265.             ENDCG
    266.         }
    267.  
    268.         Pass {
    269.             Tags { "LightMode" = "ForwardAdd" }
    270.             ZWrite Off
    271.             BlendOp Max
    272.  
    273.             CGPROGRAM
    274.                 #include "Lighting.cginc"
    275.                 #include "AutoLight.cginc"
    276.  
    277.                 #pragma target 3.0
    278.                 #pragma vertex vert
    279.                 #pragma fragment frag
    280.                 #pragma multi_compile_fog
    281.                 #pragma multi_compile_fwdadd_fullshadows
    282.  
    283.                 struct appdata {
    284.                     fixed4 color : COLOR;
    285.                     float4 vertex : POSITION;
    286.                     float3 normal : NORMAL;
    287.                     float2 texcoord : TEXCOORD;
    288.                     float4 texcoord1 : TEXCOORD1;
    289.                     float4 texcoord2 : TEXCOORD2;
    290.                     float4 texcoord3 : TEXCOORD3;
    291.                 };
    292.  
    293.                 struct v2f {
    294.                     fixed4 color : COLOR0;
    295.                     float3 normal : NORMAL0;
    296.                     float3 worldNorm : NORMAL1;
    297.                     float4 pos : SV_POSITION;
    298.                     float3 worldPos    : POSITION1;
    299.                     float2 tc_Main : TEXCOORD0;
    300.                     float2 tc_Light : TEXCOORD1;
    301.                     float4 tc_Splat1 : TEXCOORD2;
    302.                     float4 tc_Splat2 : TEXCOORD3;
    303.                     float3 viewDir : TEXCOORD4;
    304.                     float3 lightDir : TEXCOORD5;
    305.                     SHADOW_COORDS(6)
    306.                     UNITY_FOG_COORDS(7)
    307.                 };
    308.  
    309.                 v2f vert(in appdata v) {
    310.                     v2f o;
    311.  
    312.                     o.color = v.color;
    313.                     o.pos = UnityObjectToClipPos(v.vertex);
    314.                     o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    315.                     o.worldNorm = UnityObjectToWorldNormal(v.normal);
    316.  
    317.                     o.viewDir = WorldSpaceViewDir(v.vertex);
    318.                     o.normal = mul(float4(v.normal, 0.0), unity_WorldToObject).xyz;
    319.                     o.lightDir = UnityWorldSpaceLightDir(o.worldPos);
    320.  
    321.                     o.tc_Main.xy = TRANSFORM_TEX(v.texcoord.xy, _TopTex);
    322.                     o.tc_Light.xy = TRANSFORM_TEX(v.texcoord1.xy, _LightTex);
    323.  
    324.                     o.tc_Splat1.xy = TRANSFORM_TEX(v.texcoord2.xy, _TopTex);
    325.                     o.tc_Splat1.zw = TRANSFORM_TEX(v.texcoord2.zw, _TopTex);
    326.  
    327.                     o.tc_Splat2.xy = TRANSFORM_TEX(v.texcoord3.xy, _TopTex);
    328.                     o.tc_Splat2.zw = TRANSFORM_TEX(v.texcoord3.zw, _TopTex);
    329.  
    330.                     TRANSFER_SHADOW(o);
    331.                     UNITY_TRANSFER_FOG(o, o.pos);
    332.  
    333.                     return o;
    334.                 }
    335.  
    336.                 fixed4 frag(in v2f i) : SV_TARGET {
    337.                     // Tile counter
    338.                     INV_TILE_COUNT = 1 / _TileCount;
    339.  
    340.                     // Bending texture weights
    341.                     blendingWeights = pow(abs(normalize(i.worldNorm)), _TexPower);
    342.                     blendingWeights = (blendingWeights - 0.2) * _TexPower;
    343.                     blendingWeights = max(blendingWeights, 0);
    344.                     blendingWeights /= (blendingWeights.x + blendingWeights.y + blendingWeights.z).x;
    345.  
    346.                     // Triplanar UVs
    347.                     UVx = i.worldPos.yz * _SideTex_ST.xy + _SideTex_ST.zw - _TexOffset;
    348.                     UVy = i.worldPos.xz * _TopTex_ST.xy + _TopTex_ST.zw - _TexOffset;
    349.                     UVz = float2(i.worldPos.x, -i.worldPos.y) * _BotTex_ST.xy + _BotTex_ST.zw - _TexOffset;
    350.  
    351.                     // Albedo
    352.                     fixed4 albedo = BlendTexWeights(i.tc_Main, i.tc_Splat1, i.tc_Splat2, i.color, i.worldNorm);
    353.  
    354.                     // Normal
    355.                     float3 normal = BlendNormalWeights(i.tc_Main, i.worldPos, i.worldNorm);
    356.  
    357.                     // Compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed).
    358.                     UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
    359.  
    360.                     #ifndef USING_DIRECTIONAL_LIGHT
    361.                         // Lighting
    362.                         float4 lighting = saturate(dot(normalize(normal),
    363.                             normalize(UnityWorldSpaceLightDir(i.worldPos)))) * _LightColor0 * atten;  
    364.                     #else
    365.                         // Directions
    366.                         i.normal = normalize(i.normal);
    367.                         i.viewDir = normalize(i.viewDir);
    368.                         i.lightDir = normalize(i.lightDir);
    369.                         float3 reflLightDir = reflect(-i.lightDir, i.normal);
    370.  
    371.                         // Specular
    372.                         float vDotR = max(0.0, dot(i.viewDir, reflLightDir));
    373.                         float4 specular = atten * _LightColor0 * _SpecBoost * pow(vDotR, _SpecExp);
    374.  
    375.                         // Diffuse
    376.                         float4 diffuse = saturate(dot(normalize(normal), _WorldSpaceLightPos0.xyz)) * _LightColor0 * atten;  
    377.  
    378.                         // Lighting
    379.                         float4 lighting = specular + diffuse;
    380.                     #endif
    381.  
    382.                     fixed3 col = albedo.rgb * lighting.rgb;  
    383.                     UNITY_APPLY_FOG(i.fogCoord, col);
    384.  
    385.                     return fixed4(col, 1);
    386.             }
    387.             ENDCG
    388.         }
    389.  
    390.         Pass {
    391.             Tags {"LightMode"="ShadowCaster"}
    392.    
    393.             CGPROGRAM
    394.                 #pragma vertex vert
    395.                 #pragma fragment frag
    396.                 #pragma multi_compile_shadowcaster
    397.        
    398.                 struct v2fs {
    399.                     V2F_SHADOW_CASTER;
    400.                 };
    401.        
    402.                 v2fs vert(appdata_base v) {
    403.                     v2fs o;
    404.                     TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    405.                     return o;
    406.                 }
    407.        
    408.                 float4 frag(v2fs i) : SV_Target {
    409.                     SHADOW_CASTER_FRAGMENT(i)
    410.                 }
    411.             ENDCG
    412.         }
    413.     }
    414.     FallBack "Diffuse"
    415. }
    Included
    Code (CSharp):
    1. // Global variables
    2. uniform half  INV_TILE_COUNT;
    3. uniform half INV_TILE_LOOKUP;
    4. uniform float2 UVx, UVy, UVz;
    5.  
    6. uniform half  _TileCount;
    7. uniform half _TileLookup;
    8.  
    9. // Functions
    10. inline fixed3 BumpMain(sampler2D bump, float2 coords, float2 uv) {
    11.     coords.x = coords.x - 1;
    12.     coords.y = _TileCount - coords.y;
    13.     float2 uvContinuous = (coords + uv) * INV_TILE_COUNT;
    14.     return UnpackNormal(tex2D(bump, float2((coords + frac(uv)) * INV_TILE_COUNT), ddx(uvContinuous), ddy(uvContinuous)));
    15. }
    16.  
    17. inline fixed4 TexMain(sampler2D tex, float2 coords, float2 uv) {
    18.     coords.x = coords.x - 1;
    19.     coords.y = _TileCount - coords.y;
    20.     float2 uvContinuous = (coords + uv) * INV_TILE_COUNT;
    21.     return tex2D(tex, float2((coords + frac(uv)) * INV_TILE_COUNT), ddx(uvContinuous), ddy(uvContinuous));
    22. }
    Thanks for any type of help.
     
    Last edited: Apr 6, 2017
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    To me it just looks like your average atlas issues when not using a gutter between tiles. It's just being accentuated by the normal map rendering (which looks like it's a lower resolution than the albedo textures?).
     
  8. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    ahhh, I never thought about trying a gutter, very nice idea! hmmm, if I remember correctly the normal maps are just a copy of the original, however will go over all settings and make sure that the resolution are indeed the correct size.

    Would be nice to see if this works, and thank you a tone for such a fast response, keep you updated if you are interested?
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    You might also want to spend the time looking into using Texture2DArray instead of an atlas. A little more work, but removes the pain of adding gutters to the atlas, and having to do manual repeating of the UVs.
     
  10. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    Interesting, I never heard of or come across this type of concept, would you mind enlightening me? Is it hard?
     
  11. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    GreedyVox likes this.
  12. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    Thank you kind sir, weighing the pros and cons, as I am seeing a bit of work needed for implementing into the game engine, but the rendering benefits might tip the scales :)
     
  13. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    Hey bgolus,

    Would you mind helping me out again? And by the way, thank you with helping me out in the past, have also including a few screen-shots of the texture array and bump mapping, as your suggested solution in fixing my shader in earlier posts, worked like a charm!



    I am having issues with the lighting in my fragment shader, it appears though its calculating light sources as per vertex instead of per pixel, pretty sure my code should be calculating per pixel, would this be correct or am I missing something?

    One directional light source



    One directional & one spot light source



    In these screen-shots one can see the procedural chunk meshes lighting calculated as a whole mesh (kinda like vertex lighting), is it possible to calculate the lighting from a source instead?

    Ocean Shader
    Code (CSharp):
    1. Pass {
    2.             Tags {"LightMode"="ForwardBase"}
    3.  
    4.             CGPROGRAM
    5.                 #include "Lighting.cginc"
    6.                 #include "AutoLight.cginc"            
    7.                 #ifndef FRAG_LIGHTING_INCLUDED
    8.                     #define FRAG_LIGHTING_INCLUDED
    9.                     #include "Assets/Resources/Shader Bowl/Shaders/FragmentLighting.cginc"
    10.                 #endif      
    11.  
    12.                 #pragma target 3.5
    13.                 #pragma vertex vert
    14.                 #pragma fragment frag
    15.                 #pragma multi_compile_fog
    16.                 #pragma multi_compile_fwdbase
    17.  
    18.                 struct appdata {
    19.                     fixed4 color : COLOR;
    20.                     float4 vertex : POSITION;
    21.                     float3 normal : NORMAL;
    22.                     float2 texcoord : TEXCOORD;
    23.                     float4 texcoord1 : TEXCOORD1;
    24.                 };
    25.  
    26.                 struct v2f {
    27.                     fixed4 color : COLOR0;
    28.                     float3 normal : NORMAL0;
    29.                     float3 worldNorm : NORMAL1;
    30.                     float4 pos : SV_POSITION;
    31.                     float3 worldPos    : POSITION1;
    32.                     float2 uvMain     : TEXCOORD0;
    33.                     float darkness : TEXCOORD1;
    34.                     half4 screenPos : TEXCOORD4;
    35.                     float4 grabPos     : TEXCOORD5;
    36.                     float4 bumpCoords : TEXCOORD6;
    37.                     float4 viewInterpolator : TEXCOORD7;
    38.                     SHADOW_COORDS(8)
    39.                     UNITY_FOG_COORDS(9)
    40.                 };
    41.  
    42.                 v2f vert(in appdata v) {
    43.                     float ns = snoise(float3(v.vertex.x * _NoiseScale, v.vertex.z * _NoiseScale, _Time.x * _WaveSpeed));
    44.                     v.vertex.y += ns * _HeightScale;
    45.  
    46.                     v2f o;
    47.                     o.color = v.color;
    48.                     o.normal = mul(float4(v.normal, 0.0), unity_WorldToObject).xyz;
    49.  
    50.                     o.pos = UnityObjectToClipPos(v.vertex);
    51.                     o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    52.                     o.worldNorm = UnityObjectToWorldNormal(v.normal);
    53.  
    54.                     o.screenPos = ComputeScreenPos(o.pos);
    55.                     o.grabPos = ComputeGrabScreenPos(o.pos);
    56.  
    57.                     o.darkness = pow((v.texcoord1.x - 1) / (_LightCount - 1), _DarknessExp);
    58.                     o.uvMain = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
    59.  
    60.                     half2 tileableUv = mul(unity_ObjectToWorld,(v.vertex)).xz;
    61.                     o.bumpCoords.xyzw = (tileableUv.xyxy + _Time.xxxx * _BumpDirection.xyzw) * _BumpTiling.xyzw;
    62.  
    63.                     o.viewInterpolator.xyz = o.worldPos - _WorldSpaceCameraPos;
    64.                     o.viewInterpolator.w = saturate(OFFSETS.y);
    65.  
    66.                     TRANSFER_SHADOW(o);
    67.                     UNITY_TRANSFER_FOG(o, o.pos);
    68.  
    69.                     return o;
    70.                 }
    71.  
    72.             fixed4 frag(in v2f i, fixed facing : VFACE) : SV_TARGET {
    73.                  // Using VFACE to calculate lighting for back and front faces of the quad.
    74.                 i.normal.z *= facing; // flip Z based on facing
    75.  
    76.                 // Directions
    77.                 i.normal = normalize(i.normal);
    78.  
    79.                 // Ambient
    80.                 float4 ambient;
    81.                 CalculateAmbientLight(i.worldNorm, ambient);
    82.  
    83.                 // Compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed).
    84.                 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
    85.  
    86.                 // Diffuse
    87.                 float4 diffuse = saturate(dot(normalize(i.normal), _WorldSpaceLightPos0.xyz))
    88.                                  * _LightColor0 * atten;
    89.  
    90.                 // Darken light's illumination with shadow, keep ambient intact.
    91.                 float3 lighting = (diffuse * atten + ambient) * i.darkness;
    92.  
    93.                 // Albedo texture
    94.                 fixed4 albedo = TexMain(i.worldPos, i.uvMain);
    95.  
    96.                 // Depth test
    97.                 float depth = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos));
    98.                 depth = LinearEyeDepth(depth);
    99.  
    100.                 // Blending edges
    101.                 half4 edgeBlendFactors = saturate(_InvFadeParemeter * (depth - i.screenPos.w));
    102.                 edgeBlendFactors.y = 1.0 - edgeBlendFactors.y;
    103.  
    104.                 // Alpha shoreline
    105.                 albedo += edgeBlendFactors.y;
    106.                 albedo.a = edgeBlendFactors.w * edgeBlendFactors.x;      
    107.  
    108.                 // Final shoreline color
    109.                 fixed4 bgColor = tex2Dproj(_BackgroundTexture, i.grabPos);
    110.                 albedo = lerp(bgColor * edgeBlendFactors.z, albedo, albedo.a);
    111.                 albedo = lerp(albedo, bgColor, edgeBlendFactors.y);
    112.  
    113.                 // Foam shoreline
    114.                 half4 foam = Foam(_ShoreTex, i.bumpCoords * 2.0);
    115.                 albedo.rgb += foam.rgb * _Foam.x * (edgeBlendFactors.y + saturate(i.viewInterpolator.w - _Foam.y));
    116.  
    117.                 // Final color
    118.                 fixed3 col = albedo.rgb * lighting;
    119.                 fixed alpha = albedo.a;
    120.  
    121.                 // Fog color
    122.                 UNITY_APPLY_FOG(i.fogCoord, col);
    123.                 return fixed4(col, alpha);
    124.             }
    125.         ENDCG
    126.         }

    Code (CSharp):
    1. Pass
    2.         {
    3.             Tags { "LightMode" = "ForwardAdd" }
    4.             ZWrite Off
    5.             BlendOp Max
    6.  
    7.             CGPROGRAM
    8.                 #include "Lighting.cginc"
    9.  
    10.                 #pragma target 3.5
    11.                 #pragma vertex vert
    12.                 #pragma fragment frag
    13.                 #pragma multi_compile_fog
    14.                 #pragma multi_compile_fwdadd_fullshadows
    15.  
    16.                 struct appdata {
    17.                     fixed4 color : COLOR;
    18.                     float4 vertex : POSITION;
    19.                     float3 normal : NORMAL;
    20.                     float2 texcoord : TEXCOORD;
    21.                     float4 texcoord1 : TEXCOORD1;
    22.                 };
    23.  
    24.                 struct v2f {
    25.                     fixed4 color : COLOR0;
    26.                     float3 normal : NORMAL0;
    27.                     float3 worldNorm : NORMAL1;
    28.                     float4 pos : SV_POSITION;
    29.                     float3 worldPos    : POSITION1;
    30.                     float2 uvMain     : TEXCOORD0;
    31.                     float2 uvLight     : TEXCOORD1;
    32.                     float3 viewDir : TEXCOORD2;
    33.                     float3 lightDir : TEXCOORD3;
    34.                     half4 screenPos : TEXCOORD4;
    35.                     float4 grabPos     : TEXCOORD5;
    36.                     float4 bumpCoords : TEXCOORD6;
    37.                     float4 viewInterpolator : TEXCOORD7;              
    38.                     UNITY_FOG_COORDS(8)
    39.                 };
    40.  
    41.                 v2f vert(in appdata v) {
    42.                     float ns = snoise(float3(v.vertex.x * _NoiseScale, v.vertex.z * _NoiseScale, _Time.x * _WaveSpeed));
    43.                     v.vertex.y += ns * _HeightScale;
    44.  
    45.                     v2f o;
    46.                     o.color = v.color;
    47.                     o.pos = UnityObjectToClipPos(v.vertex);
    48.                     o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    49.                     o.worldNorm = UnityObjectToWorldNormal(v.normal);                          
    50.  
    51.                     o.normal = mul(float4(v.normal, 0.0), unity_WorldToObject).xyz;
    52.                     o.viewDir = WorldSpaceViewDir(v.vertex);
    53.                     o.lightDir = UnityWorldSpaceLightDir(o.worldPos);
    54.  
    55.                     o.screenPos = ComputeScreenPos(o.pos);
    56.                     o.grabPos = ComputeGrabScreenPos(o.pos);
    57.  
    58.                     o.uvLight = v.texcoord1.xy;
    59.                     o.uvMain = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
    60.  
    61.                     half2 tileableUv = mul(unity_ObjectToWorld,(v.vertex)).xz;
    62.                     o.bumpCoords.xyzw = (tileableUv.xyxy + _Time.xxxx * _BumpDirection.xyzw) * _BumpTiling.xyzw;
    63.  
    64.                     o.viewInterpolator.xyz = o.worldPos - _WorldSpaceCameraPos;
    65.                     o.viewInterpolator.w = saturate(OFFSETS.y);
    66.  
    67.                     UNITY_TRANSFER_FOG(o, o.pos);
    68.  
    69.                     return o;
    70.                 }
    71.  
    72.                 fixed4 frag(in v2f i, fixed facing : VFACE) : SV_TARGET {              
    73.                     // Using VFACE to calculate lighting for back and front faces of the quad.
    74.                     i.normal.z *= facing; // flip Z based on facing
    75.                     #ifndef USING_DIRECTIONAL_LIGHT
    76.                         // Lighting
    77.                         float3 lighting = saturate(dot(normalize(i.normal), normalize(UnityWorldSpaceLightDir(i.worldPos))))
    78.                                         * _LightColor0.rgb;
    79.                     #else
    80.                         // Directions
    81.                         i.normal = normalize(i.normal);
    82.                         i.lightDir = normalize(i.lightDir);
    83.                         i.viewDir = normalize(i.lightDir);
    84.  
    85.                         // Light directions
    86.                         half3 reflViewDir = reflect(-i.viewDir, i.normal);
    87.                         half3 reflLightDir = reflect(-i.lightDir, i.normal);
    88.  
    89.                         // Specular
    90.                         float vDotR = max(0.0, dot(i.viewDir, reflLightDir));
    91.                         float3 specular = _LightColor0.rgb * _SpecBoost * pow(vDotR, _SpecExp);
    92.  
    93.                         // Diffuse
    94.                         float3 diffuse = saturate(dot(i.worldNorm, _WorldSpaceLightPos0.xyz))
    95.                                         * _LightColor0.rgb;
    96.  
    97.                         // Lighting
    98.                         float3 lighting = diffuse + specular;
    99.                     #endif
    100.  
    101.                     // Albedo texture
    102.                     fixed4 albedo = TexMain(i.worldPos, i.uvMain);
    103.  
    104.                     // Depth test
    105.                     float depth = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos));
    106.                     depth = LinearEyeDepth(depth);
    107.  
    108.                     // Blending edges
    109.                     half4 edgeBlendFactors = saturate(_InvFadeParemeter * (depth - i.screenPos.w));
    110.                     edgeBlendFactors.y = 1.0 - edgeBlendFactors.y;
    111.  
    112.                     // Alpha shoreline
    113.                     albedo += edgeBlendFactors.y;
    114.                     albedo.a = edgeBlendFactors.w * edgeBlendFactors.x;      
    115.  
    116.                     // Final shoreline color
    117.                     fixed4 bgColor = tex2Dproj(_BackgroundTexture, i.grabPos);
    118.                     albedo = lerp(bgColor * edgeBlendFactors.z, albedo, albedo.a);
    119.                     albedo = lerp(albedo, bgColor, edgeBlendFactors.y);
    120.  
    121.                     // Foam shoreline
    122.                     half4 foam = Foam(_ShoreTex, i.bumpCoords * 2.0);
    123.                     albedo.rgb += foam.rgb * _Foam.x * (edgeBlendFactors.y + saturate(i.viewInterpolator.w - _Foam.y));
    124.  
    125.                     // Final color
    126.                     fixed3 col = albedo.rgb * lighting;
    127.                     fixed alpha = albedo.a;
    128.  
    129.                     // Fog
    130.                     UNITY_APPLY_FOG(i.fogCoord, col);
    131.                     return fixed4(col, alpha);
    132.                 }
    133.             ENDCG
    134.         }

    Terrain Shader

    Code (CSharp):
    1. Pass {
    2.             Tags {"LightMode"="ForwardBase"}
    3.  
    4.             CGPROGRAM
    5.                 #include "Lighting.cginc"
    6.                 #include "AutoLight.cginc"
    7.                 #ifndef FRAG_LIGHTING_INCLUDED
    8.                     #define FRAG_LIGHTING_INCLUDED
    9.                     #include "Assets/Resources/Shader Bowl/Shaders/FragmentLighting.cginc"
    10.                 #endif
    11.  
    12.                 #pragma target 3.5
    13.                 #pragma vertex vert
    14.                 #pragma fragment frag
    15.                 #pragma multi_compile_fog
    16.                 #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynligtmap novertexlight
    17.  
    18.                 struct appdata {
    19.                     fixed4 color : COLOR;
    20.                     float4 vertex : POSITION;
    21.                     float3 normal : NORMAL;
    22.                     float2 texcoord : TEXCOORD;
    23.                     float4 texcoord1 : TEXCOORD1;
    24.                     float4 texcoord2 : TEXCOORD2;
    25.                     float4 texcoord3 : TEXCOORD3;
    26.                 };
    27.  
    28.                 struct v2f {
    29.                     fixed4 color : COLOR0;
    30.                     float ambient : COLOR1;
    31.                     float3 normal : NORMAL0;
    32.                     float3 worldNorm : NORMAL1;
    33.                     float4 pos : SV_POSITION;
    34.                     float3 worldPos : POSITION1;
    35.                     float tc_Main : TEXCOORD0;
    36.                     float tc_Light : TEXCOORD1;
    37.                     float4 tc_Splat : TEXCOORD2;
    38.                     float3 viewDir : TEXCOORD3;
    39.                     float3 lightDir : TEXCOORD4;
    40.                     float3 brightness : TEXCOORD5;
    41.                     float darkness : TEXCOORD6;
    42.                     SHADOW_COORDS(7)
    43.                     UNITY_FOG_COORDS(8)
    44.                 };
    45.        
    46.                 v2f vert (appdata v) {
    47.                     v2f o;
    48.                     o.color = v.color;
    49.                     o.normal = mul(float4(v.normal, 0.0), unity_WorldToObject).xyz;
    50.  
    51.                     o.pos = UnityObjectToClipPos(v.vertex);
    52.                     o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    53.                     o.worldNorm = UnityObjectToWorldNormal(v.normal);
    54.  
    55.                     o.viewDir = WorldSpaceViewDir(v.vertex);
    56.                     o.lightDir = UnityWorldSpaceLightDir(o.worldPos);
    57.  
    58.                     o.brightness = float3(1, 1, 1);
    59.                     o.tc_Light = v.texcoord1.x - 1;
    60.                     o.darkness = pow(o.tc_Light / (_LightCount - 1), _DarknessExp);
    61.  
    62.                     o.ambient = smoothstep(0, 1, dot(float3(0,1,0), _WorldSpaceLightPos0.xyz));
    63.                     o.ambient = dot(float3(0,1,0), _WorldSpaceLightPos0.xyz);
    64.  
    65.                     o.tc_Main = v.texcoord.x - 1 + ((v.texcoord.y - 1) * _TileCount);
    66.                     o.tc_Splat.x = v.texcoord2.x - 1 + ((v.texcoord2.y - 1) * _TileCount);
    67.                     o.tc_Splat.y = v.texcoord2.z - 1 + ((v.texcoord2.w - 1) * _TileCount);
    68.                     o.tc_Splat.z = v.texcoord3.x - 1 + ((v.texcoord3.y - 1) * _TileCount);
    69.                     o.tc_Splat.w = v.texcoord3.z - 1 + ((v.texcoord3.w - 1) * _TileCount);
    70.  
    71.                     TRANSFER_SHADOW(o);
    72.                     UNITY_TRANSFER_FOG(o,o.pos);
    73.  
    74.                     return o;
    75.                 }
    76.        
    77.                 half4 frag (v2f i) : SV_Target {              
    78.                     // Extract world normal from the unused w component of world to tangent matrix
    79.                     _ProjectNormal = saturate(pow(i.worldNorm * 1.4, 4));
    80.  
    81.                     // "normalize" project normal x+y+z to equal 1, ensures even blend
    82.                     _ProjectNormal /= _ProjectNormal.x + _ProjectNormal.y + _ProjectNormal.z;
    83.  
    84.                     // Directions
    85.                     i.normal = normalize(i.normal);
    86.                     i.lightDir = normalize(i.lightDir);
    87.  
    88.                     half3 normal;
    89.                     fixed4 albedo;
    90.                     GetTriplanarTextures(i.worldPos, i.worldNorm, i.tc_Main, i.tc_Splat, i.color, albedo, normal);
    91.  
    92.                     // Exposure
    93.                     fixed4 exposure;
    94.                     GetLighting(i.worldPos, i.worldNorm, i.tc_Light, exposure);                                
    95.  
    96.                     // Blending
    97.                     float weight = smoothstep(0.9, 1, dot(exposure.rgb, i.brightness) / 3);
    98.  
    99.                      // Compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed).
    100.                     UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);                                
    101.  
    102.                     // Diffuse
    103.                     float nDotL = dot(normalize(normal), i.lightDir) * 0.5 + 0.5;
    104.                     float4 ramp = tex2D(_RampTex, nDotL.xx);
    105.  
    106.                     // Snow
    107.                     fixed3 snow = Snow_Blend(albedo, normal);
    108.                     float snowing = _Snow * i.darkness;
    109.                     albedo.rgb = lerp(albedo.rgb, snow, snowing) * ramp;
    110.  
    111.                     // Ambient
    112.                     float4 ambient;
    113.                     CalculateAmbientLight(normal, ambient);
    114.  
    115.                     // Diffuse
    116.                     float3 diffuse = saturate(dot(normalize(normal), _WorldSpaceLightPos0.xyz)) *
    117.                                      _LightColor0.rgb * ramp.rgb * i.ambient;
    118.  
    119.                     atten = pow(atten, weight);
    120.                     float3 lighting = (diffuse * atten + ambient.rgb) * i.darkness;
    121.  
    122.                     // Final color
    123.                     fixed3 col = albedo.rgb * lighting;
    124.  
    125.                     // Fog color
    126.                     UNITY_APPLY_FOG(i.fogCoord, col);
    127.                     return half4(col, 1);
    128.                 }
    129.             ENDCG
    130.         }
    Code (CSharp):
    1. Pass {
    2.             Tags {"LightMode"="ForwardAdd"}
    3.             ZWrite Off
    4.             BlendOp Max
    5.  
    6.             CGPROGRAM
    7.                 #include "Lighting.cginc"
    8.  
    9.                 #pragma target 3.5
    10.                 #pragma vertex vert
    11.                 #pragma fragment frag
    12.                 #pragma multi_compile_fog
    13.                 #pragma multi_compile_fwdadd_fullshadows
    14.                 #pragma multi_compile_fwdadd nolightmap nodirlightmap nodynligtmap novertexlight
    15.  
    16.                 struct appdata {
    17.                     fixed4 color : COLOR;
    18.                     float4 vertex : POSITION;
    19.                     float3 normal : NORMAL;
    20.                     float2 texcoord : TEXCOORD;
    21.                     float4 texcoord1 : TEXCOORD1;
    22.                     float4 texcoord2 : TEXCOORD2;
    23.                     float4 texcoord3 : TEXCOORD3;
    24.                 };
    25.  
    26.                 struct v2f {
    27.                     fixed4 color : COLOR0;
    28.                     float3 normal : NORMAL0;
    29.                     float3 worldNorm : NORMAL1;
    30.                     float4 pos : SV_POSITION;
    31.                     float3 worldPos : POSITION1;
    32.                     float tc_Main : TEXCOORD0;
    33.                     float2 tc_Light : TEXCOORD1;
    34.                     float4 tc_Splat : TEXCOORD2;
    35.                     float3 viewDir : TEXCOORD3;
    36.                     float3 lightDir : TEXCOORD4;
    37.                     float3 brightness : TEXCOORD5;
    38.                     float darkness : TEXCOORD6;
    39.                     UNITY_FOG_COORDS(7)
    40.                 };
    41.        
    42.                 v2f vert (appdata v) {
    43.                     v2f o;
    44.                     o.color = v.color;
    45.                     o.normal = mul(float4(v.normal, 0.0), unity_WorldToObject).xyz;
    46.  
    47.                     o.pos = UnityObjectToClipPos(v.vertex);
    48.                     o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    49.                     o.worldNorm = UnityObjectToWorldNormal(v.normal);
    50.  
    51.                     o.viewDir = WorldSpaceViewDir(v.vertex);
    52.                     o.lightDir = UnityWorldSpaceLightDir(o.worldPos);
    53.  
    54.                     o.brightness = float3(1, 1, 1);
    55.                     o.tc_Light = v.texcoord1.x - 1;
    56.                     o.darkness = pow(o.tc_Light / (_LightCount - 1), _DarknessExp);
    57.  
    58.                     o.tc_Main = v.texcoord.x - 1 + ((v.texcoord.y - 1) * _TileCount);
    59.                     o.tc_Splat.x = v.texcoord2.x - 1 + ((v.texcoord2.y - 1) * _TileCount);
    60.                     o.tc_Splat.y = v.texcoord2.z - 1 + ((v.texcoord2.w - 1) * _TileCount);
    61.                     o.tc_Splat.z = v.texcoord3.x - 1 + ((v.texcoord3.y - 1) * _TileCount);
    62.                     o.tc_Splat.w = v.texcoord3.z - 1 + ((v.texcoord3.w - 1) * _TileCount);
    63.  
    64.                     UNITY_TRANSFER_FOG(o,o.pos);
    65.  
    66.                     return o;
    67.                 }
    68.        
    69.                 half4 frag (v2f i) : SV_Target {              
    70.                     // Extract world normal from the unused w component of world to tangent matrix
    71.                     _ProjectNormal = saturate(pow(i.worldNorm * 1.4, 4));
    72.  
    73.                     // "normalize" project normal x+y+z to equal 1, ensures even blend
    74.                     _ProjectNormal /= _ProjectNormal.x + _ProjectNormal.y + _ProjectNormal.z;
    75.  
    76.                     // Directions
    77.                     i.normal = normalize(i.normal);
    78.                     i.lightDir = normalize(i.lightDir);
    79.  
    80.                     half3 normal;
    81.                     fixed4 albedo;
    82.                     GetTriplanarTextures(i.worldPos, i.worldNorm, i.tc_Main, i.tc_Splat, i.color, albedo, normal);
    83.  
    84.                     // Exposure
    85.                     fixed4 exposure;
    86.                     GetLighting(i.worldPos, i.worldNorm, i.tc_Light, exposure);
    87.  
    88.                     // Blending
    89.                     float weight = smoothstep(0.9, 1, dot(exposure.rgb, i.brightness) / 3);
    90.  
    91.                     // Ramp
    92.                     float nDotL = dot(normalize(normal), i.lightDir);
    93.                     float4 ramp = tex2D(_RampTex, float2(nDotL * 0.5 + 0.5, 0.5));
    94.  
    95.                     // Snow
    96.                     fixed3 snow = Snow_Blend(albedo, normal);
    97.                     float snowing = _Snow * i.darkness;
    98.                     albedo.rgb = lerp(albedo.rgb, snow, snowing) * ramp;
    99.  
    100.                     #ifndef USING_DIRECTIONAL_LIGHT                  
    101.                         // Lighting
    102.                         float3 lighting = saturate(dot(normalize(normal), normalize(UnityWorldSpaceLightDir(i.worldPos))))
    103.                                           * _LightColor0.rgb * ramp.rgb;
    104.                     #else                      
    105.                         // Directions
    106.                         i.viewDir = normalize(i.viewDir);
    107.                         float3 reflLightDir = reflect(-i.lightDir, normal);
    108.  
    109.                         // Specular
    110.                         float vDotR = max(0.0, dot(i.viewDir, reflLightDir));
    111.                         float3 specular = _LightColor0.rgb * _SpecBoost * pow(vDotR, _SpecExp);
    112.  
    113.                         // Rim
    114.                         float fr = pow(1 - max(0.0, dot(normal, i.viewDir)), 4);
    115.                         float rim = fr * _RimBoost * pow(vDotR, _RimExp);
    116.  
    117.                         // Diffuse
    118.                         float3 diffuse = saturate(dot(normalize(normal), _WorldSpaceLightPos0.xyz))
    119.                                          * _LightColor0.rgb * ramp.rgb;
    120.  
    121.                         // Point or spot light
    122.                         float3 lighting = diffuse + specular + rim;
    123.                     #endif
    124.  
    125.                     half3 col = albedo.rgb * lighting;
    126.                     UNITY_APPLY_FOG(i.fogCoord, col);
    127.  
    128.                     return half4(col, 1);
    129.                 }
    130.             ENDCG
    131.         }
     

    Attached Files:

    Last edited: Jun 4, 2017
  14. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Your shaders aren't calculating any kind of attenuation (distance falloff) or cone for your lights, just the lighting angle is calculated from a point rather than a direction, so it's not too surprising that the entire surface is being lit with near uniform brightness. The way Unity does additional per-pixel lights is by rendering the entire object again for each light that touches it, up to the number of per pixel lights you have in the quality settings, so if you're not calculating a falloff you're going to see the entire mesh lit.

    Usually Unity will limit the light's affect to only the region on screen the light covers, based on the light's bounds, but either your light is really big and thus covering the entire screen, or it doesn't do it on transparent objects.
     
    GreedyVox likes this.
  15. GreedyVox

    GreedyVox

    Joined:
    Nov 18, 2015
    Posts:
    33
    Ahhhhh, thank you bgolus!
    After going through the cat code rendering documents, makes total sense, your bloods worth bottling.

    Time to byte the bullet and implement correct lighting, and may as well try out deferred lighting, shadows and fog too, hoping to gain frames with trees and grass with lights and shadows (which forward rendering was struggling with in my engine).

    Thanks mate!