Advertisement
Guest User

TerrainEngine.cginc

a guest
Jan 2nd, 2018
425
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.93 KB | None | 0 0
  1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
  2.  
  3. #ifndef TERRAIN_ENGINE_INCLUDED
  4. #define TERRAIN_ENGINE_INCLUDED
  5.  
  6. // Terrain engine shader helpers
  7.  
  8. CBUFFER_START(UnityTerrain)
  9.     // grass
  10.     fixed4 _WavingTint;
  11.     float4 _WaveAndDistance;    // wind speed, wave size, wind amount, max sqr distance
  12.     float4 _CameraPosition;     // .xyz = camera position, .w = 1 / (max sqr distance)
  13.     float3 _CameraRight, _CameraUp;
  14.  
  15.     // trees
  16.     fixed4 _TreeInstanceColor;
  17.     float4 _TreeInstanceScale;
  18.     float4x4 _TerrainEngineBendTree;
  19.     float4 _SquashPlaneNormal;
  20.     float _SquashAmount;
  21.  
  22.     // billboards
  23.     float3 _TreeBillboardCameraRight;
  24.     float4 _TreeBillboardCameraUp;
  25.     float4 _TreeBillboardCameraFront;
  26.     float4 _TreeBillboardCameraPos;
  27.     float4 _TreeBillboardDistances; // x = max distance ^ 2
  28. CBUFFER_END
  29.  
  30.  
  31. // ---- Vertex input structures
  32.  
  33. struct appdata_tree {
  34.     float4 vertex : POSITION;       // position
  35.     float4 tangent : TANGENT;       // directional AO
  36.     float3 normal : NORMAL;         // normal
  37.     fixed4 color : COLOR;           // .w = bend factor
  38.     float4 texcoord : TEXCOORD0;    // UV
  39.     UNITY_VERTEX_INPUT_INSTANCE_ID
  40. };
  41.  
  42. struct appdata_tree_billboard {
  43.     float4 vertex : POSITION;
  44.     fixed4 color : COLOR;           // Color
  45.     float4 texcoord : TEXCOORD0;    // UV Coordinates
  46.     float2 texcoord1 : TEXCOORD1;   // Billboard extrusion
  47.     UNITY_VERTEX_INPUT_INSTANCE_ID
  48. };
  49.  
  50. // ---- Grass helpers
  51.  
  52. // Calculate a 4 fast sine-cosine pairs
  53. // val:     the 4 input values - each must be in the range (0 to 1)
  54. // s:       The sine of each of the 4 values
  55. // c:       The cosine of each of the 4 values
  56. void FastSinCos (float4 val, out float4 s, out float4 c) {
  57.     val = val * 6.408849 - 3.1415927;
  58.     // powers for taylor series
  59.     float4 r5 = val * val;                  // wavevec ^ 2
  60.     float4 r6 = r5 * r5;                        // wavevec ^ 4;
  61.     float4 r7 = r6 * r5;                        // wavevec ^ 6;
  62.     float4 r8 = r6 * r5;                        // wavevec ^ 8;
  63.  
  64.     float4 r1 = r5 * val;                   // wavevec ^ 3
  65.     float4 r2 = r1 * r5;                        // wavevec ^ 5;
  66.     float4 r3 = r2 * r5;                        // wavevec ^ 7;
  67.  
  68.  
  69.     //Vectors for taylor's series expansion of sin and cos
  70.     float4 sin7 = {1, -0.16161616, 0.0083333, -0.00019841};
  71.     float4 cos8  = {-0.5, 0.041666666, -0.0013888889, 0.000024801587};
  72.  
  73.     // sin
  74.     s =  val + r1 * sin7.y + r2 * sin7.z + r3 * sin7.w;
  75.  
  76.     // cos
  77.     c = 1 + r5 * cos8.x + r6 * cos8.y + r7 * cos8.z + r8 * cos8.w;
  78. }
  79.  
  80. fixed4 TerrainWaveGrass (inout float4 vertex, float waveAmount, fixed4 color)
  81. {
  82.     float4 _waveXSize = float4(0.012, 0.02, 0.06, 0.024) * _WaveAndDistance.y;
  83.     float4 _waveZSize = float4 (0.006, .02, 0.02, 0.05) * _WaveAndDistance.y;
  84.     float4 waveSpeed = float4 (0.3, .5, .4, 1.2) * 4;
  85.  
  86.     float4 _waveXmove = float4(0.012, 0.02, -0.06, 0.048) * 2;
  87.     float4 _waveZmove = float4 (0.006, .02, -0.02, 0.1);
  88.  
  89.     float4 waves;
  90.     waves = vertex.x * _waveXSize;
  91.     waves += vertex.z * _waveZSize;
  92.  
  93.     // Add in time to model them over time
  94.     waves += _WaveAndDistance.x * waveSpeed;
  95.  
  96.     float4 s, c;
  97.     waves = frac (waves);
  98.     FastSinCos (waves, s,c);
  99.  
  100.     s = s * s;
  101.  
  102.     s = s * s;
  103.  
  104.     float lighting = dot (s, normalize (float4 (1,1,.4,.2))) * .7;
  105.  
  106.     s = s * waveAmount;
  107.  
  108.     float3 waveMove = float3 (0,0,0);
  109.     waveMove.x = dot (s, _waveXmove);
  110.     waveMove.z = dot (s, _waveZmove);
  111.  
  112.     vertex.xz -= waveMove.xz * _WaveAndDistance.z;
  113.  
  114.     // apply color animation
  115.  
  116.     // fix for dx11/etc warning
  117.     fixed3 waveColor = lerp (fixed3(0.5,0.5,0.5), _WavingTint.rgb, fixed3(lighting,lighting,lighting));
  118.  
  119.     // Fade the grass out before detail distance.
  120.     // Saturate because Radeon HD drivers on OS X 10.4.10 don't saturate vertex colors properly.
  121.     float3 offset = vertex.xyz - _CameraPosition.xyz;
  122.     color.a = saturate (2 * (_WaveAndDistance.w - dot (offset, offset)) * _CameraPosition.w);
  123.  
  124.     return fixed4(2 * waveColor * color.rgb, color.a);
  125. }
  126.  
  127. void TerrainBillboardGrass( inout float4 pos, float2 offset )
  128. {
  129.     float3 grasspos = pos.xyz - _CameraPosition.xyz;
  130.     if (dot(grasspos, grasspos) > _WaveAndDistance.w)
  131.         offset = 0.0;
  132.     pos.xyz += offset.x * _CameraRight.xyz;
  133.     pos.xyz += offset.y * _CameraUp.xyz;
  134. }
  135.  
  136. // Grass: appdata_full usage
  137. // color        - .xyz = color, .w = wave scale
  138. // normal       - normal
  139. // tangent.xy   - billboard extrusion
  140. // texcoord     - UV coords
  141. // texcoord1    - 2nd UV coords
  142.  
  143. void WavingGrassVert (inout appdata_full v)
  144. {
  145.     // MeshGrass v.color.a: 1 on top vertices, 0 on bottom vertices
  146.     // _WaveAndDistance.z == 0 for MeshLit
  147.     float waveAmount = v.color.a * _WaveAndDistance.z;
  148.  
  149.     v.color = TerrainWaveGrass (v.vertex, waveAmount, v.color);
  150. }
  151.  
  152. void WavingGrassBillboardVert (inout appdata_full v)
  153. {
  154.     TerrainBillboardGrass (v.vertex, v.tangent.xy);
  155.     // wave amount defined by the grass height
  156.     float waveAmount = v.tangent.y;
  157.     v.color = TerrainWaveGrass (v.vertex, waveAmount, v.color);
  158. }
  159.  
  160.  
  161. // ---- Tree helpers
  162.  
  163.  
  164. inline float4 Squash(in float4 pos)
  165. {
  166.     // To squash the tree the vertex needs to be moved in the direction
  167.     // of the squash plane. The plane is defined by the the:
  168.     // plane point - point lying on the plane, defined in model space
  169.     // plane normal - _SquashPlaneNormal.xyz
  170.  
  171.     // we're pushing squashed tree plane in direction of planeNormal by amount of _SquashPlaneNormal.w
  172.     // this squashing has to match logic of tree billboards
  173.  
  174.     float3 planeNormal = _SquashPlaneNormal.xyz;
  175.  
  176.     // unoptimized version:
  177.     //float3 planePoint = -planeNormal * _SquashPlaneNormal.w;
  178.     //float3 projectedVertex = pos.xyz + dot(planeNormal, (planePoint - pos)) * planeNormal;
  179.  
  180.     // optimized version:
  181.     float3 projectedVertex = pos.xyz - (dot(planeNormal.xyz, pos.xyz) + _SquashPlaneNormal.w) * planeNormal;
  182.  
  183.     pos = float4(lerp(projectedVertex, pos.xyz, _SquashAmount), 1);
  184.  
  185.     return pos;
  186. }
  187.  
  188. void TerrainAnimateTree( inout float4 pos, float alpha )
  189. {
  190.     pos.xyz *= _TreeInstanceScale.xyz;
  191.     float3 bent = mul(_TerrainEngineBendTree, float4(pos.xyz, 0.0)).xyz;
  192.     pos.xyz = lerp( pos.xyz, bent, alpha );
  193.  
  194.     pos = Squash(pos);
  195. }
  196.  
  197.  
  198. // ---- Billboarded tree helpers
  199.  
  200.  
  201. void TerrainBillboardTree( inout float4 pos, float2 offset, float offsetz )
  202. {
  203.     float3 treePos = pos.xyz - _TreeBillboardCameraPos.xyz;
  204.     float treeDistanceSqr = dot(treePos, treePos);
  205.     if( treeDistanceSqr > _TreeBillboardDistances.x )
  206.         offset.xy = offsetz = 0.0;
  207.  
  208.     // positioning of billboard vertices horizontally
  209.     pos.xyz += _TreeBillboardCameraRight.xyz * offset.x;
  210.  
  211.     // tree billboards can have non-uniform scale,
  212.     // so when looking from above (or bellow) we must use
  213.     // billboard width as billboard height
  214.  
  215.     // 1) non-compensating
  216.     //pos.xyz += _TreeBillboardCameraUp.xyz * offset.y;
  217.  
  218.     // 2) correct compensating (?)
  219.     //float alpha = _TreeBillboardCameraPos.w;
  220.     //float a = offset.y;
  221.     //float b = offsetz;
  222.         // 2a) using elipse-radius formula
  223.         ////float r = abs(a * b) / sqrt(sqr(a * sin(alpha)) + sqr(b * cos(alpha))) * sign(b);
  224.         //float r = abs(a) * b / sqrt(sqr(a * sin(alpha)) + sqr(b * cos(alpha)));
  225.         // 2b) sin-cos lerp
  226.         //float r = b * sin(alpha) + a * cos(alpha);
  227.     //pos.xyz += _TreeBillboardCameraUp.xyz * r;
  228.  
  229.     // 3) incorrect compensating (using lerp)
  230.     // _TreeBillboardCameraPos.w contains ImposterRenderTexture::GetBillboardAngleFactor()
  231.     //float billboardAngleFactor = _TreeBillboardCameraPos.w;
  232.     //float r = lerp(offset.y, offsetz, billboardAngleFactor);
  233.     //pos.xyz += _TreeBillboardCameraUp.xyz * r;
  234.  
  235.     // so now we take solution #3 and complicate it even further...
  236.     //
  237.     // case 49851: Flying trees
  238.     // The problem was that tree billboard was fixed on it's center, which means
  239.     // the root of the tree is not fixed and can float around. This can be quite visible
  240.     // on slopes (checkout the case on fogbugz for screenshots).
  241.     //
  242.     // We're fixing this by fixing billboards to the root of the tree.
  243.     // Note that root of the tree is not necessary the bottom of the tree -
  244.     // there might be significant part of the tree bellow terrain.
  245.     // This fixation mode doesn't work when looking from above/below, because
  246.     // billboard is so close to the ground, so we offset it by certain distance
  247.     // when viewing angle is bigger than certain treshold (40 deg at the moment)
  248.  
  249.     // _TreeBillboardCameraPos.w contains ImposterRenderTexture::billboardAngleFactor
  250.     float billboardAngleFactor = _TreeBillboardCameraPos.w;
  251.     // The following line performs two things:
  252.     // 1) peform non-uniform scale, see "3) incorrect compensating (using lerp)" above
  253.     // 2) blend between vertical and horizontal billboard mode
  254.     float radius = lerp(offset.y, offsetz, billboardAngleFactor);
  255.  
  256.     // positioning of billboard vertices veritally
  257.     pos.xyz += _TreeBillboardCameraUp.xyz * radius;
  258.  
  259.     // _TreeBillboardCameraUp.w contains ImposterRenderTexture::billboardOffsetFactor
  260.     float billboardOffsetFactor = _TreeBillboardCameraUp.w;
  261.     // Offsetting billboad from the ground, so it doesn't get clipped by ztest.
  262.     // In theory we should use billboardCenterOffsetY instead of offset.x,
  263.     // but we can't because offset.y is not the same for all 4 vertices, so
  264.     // we use offset.x which is the same for all 4 vertices (except sign).
  265.     // And it doesn't matter a lot how much we offset, we just need to offset
  266.     // it by some distance
  267.     pos.xyz += _TreeBillboardCameraFront.xyz * abs(offset.x) * billboardOffsetFactor;
  268. }
  269.  
  270.  
  271. // ---- Tree Creator
  272.  
  273. float4 _Wind;
  274.  
  275. // Expand billboard and modify normal + tangent to fit
  276. inline void ExpandBillboard (in float4x4 mat, inout float4 pos, inout float3 normal, inout float4 tangent)
  277. {
  278.     // tangent.w = 0 if this is a billboard
  279.     float isBillboard = 1.0f - abs(tangent.w);
  280.  
  281.     // billboard normal
  282.     float3 norb = normalize(mul(float4(normal, 0), mat)).xyz;
  283.  
  284.     // billboard tangent
  285.     float3 tanb = normalize(mul(float4(tangent.xyz, 0.0f), mat)).xyz;
  286.  
  287.     pos += mul(float4(normal.xy, 0, 0), mat) * isBillboard;
  288.     normal = lerp(normal, norb, isBillboard);
  289.     tangent = lerp(tangent, float4(tanb, -1.0f), isBillboard);
  290. }
  291.  
  292. float4 SmoothCurve( float4 x ) {
  293.     return x * x *( 3.0 - 2.0 * x );
  294. }
  295. float4 TriangleWave( float4 x ) {
  296.     return abs( frac( x + 0.5 ) * 2.0 - 1.0 );
  297. }
  298. float4 SmoothTriangleWave( float4 x ) {
  299.     return SmoothCurve( TriangleWave( x ) );
  300. }
  301.  
  302. // Detail bending
  303. inline float4 AnimateVertex(float4 pos, float3 normal, float4 animParams)
  304. {
  305.     // animParams stored in color
  306.     // animParams.x = branch phase
  307.     // animParams.y = edge flutter factor
  308.     // animParams.z = primary factor
  309.     // animParams.w = secondary factor
  310.  
  311.     float fDetailAmp = 0.1f;
  312.     float fBranchAmp = 0.3f;
  313.  
  314.     // Phases (object, vertex, branch)
  315.     float fObjPhase = dot(unity_ObjectToWorld._14_24_34, 1);
  316.     float fBranchPhase = fObjPhase + animParams.x;
  317.  
  318.     float fVtxPhase = dot(pos.xyz, animParams.y + fBranchPhase);
  319.  
  320.     // x is used for edges; y is used for branches
  321.     float2 vWavesIn = _Time.yy + float2(fVtxPhase, fBranchPhase );
  322.  
  323.     // 1.975, 0.793, 0.375, 0.193 are good frequencies
  324.     float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0);
  325.  
  326.     vWaves = SmoothTriangleWave( vWaves );
  327.     float2 vWavesSum = vWaves.xz + vWaves.yw;
  328.  
  329.     // Edge (xz) and branch bending (y)
  330.     float3 bend = animParams.y * fDetailAmp * normal.xyz;
  331.     bend.y = animParams.w * fBranchAmp;
  332.     pos.xyz += ((vWavesSum.xyx * bend) + (_Wind.xyz * vWavesSum.y * animParams.w)) * _Wind.w;
  333.  
  334.     // Primary bending
  335.     // Displace position
  336.     pos.xyz += animParams.z * _Wind.xyz;
  337.  
  338.     return pos;
  339. }
  340.  
  341. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement