diff --git a/Assets/Shaders/GrassBlade.shader b/Assets/Shaders/GrassBlade.shader index 094ea57..d5cb8f6 100644 --- a/Assets/Shaders/GrassBlade.shader +++ b/Assets/Shaders/GrassBlade.shader @@ -24,7 +24,7 @@ } SubShader { LOD 100 - Cull Off + // Cull Off //Render Pass Pass { diff --git a/Assets/Shaders/include/GrassBladePass.hlsl b/Assets/Shaders/include/GrassBladePass.hlsl index a3dc1e9..9998f3c 100644 --- a/Assets/Shaders/include/GrassBladePass.hlsl +++ b/Assets/Shaders/include/GrassBladePass.hlsl @@ -25,11 +25,11 @@ struct g2f { float4 pos : SV_POSITION; #ifdef IS_IN_BASE_PASS float3 normal : NORMAL; - float3 worldPos : TEXCOORD3; float2 uv : TEXCOORD0; // bottom left 0.0 top right 1.1 (values converge - 0 and 1 meet at the tip) SHADOW_COORDS(1) // put shadows data into TEXCOORD1 - float transitionInterpolator : TEXCOORD2; + float3 worldPos : TEXCOORD2; #endif + float3 debug : TEXCOORD3; }; v2g vert (MeshData v) { @@ -87,6 +87,8 @@ void geom(point v2g IN[1], inout TriangleStream triStream) { #endif g2f o; + o.debug = float3(0,0,0); + float3 previousSegmentCenter = basePos - float3(0,-1,0); // point beneath the basePos int numSegments; @@ -101,86 +103,70 @@ void geom(point v2g IN[1], inout TriangleStream triStream) { #endif float3 localCameraPos = mul(unity_WorldToObject, float4(_MainCameraPosition.xyz, 1.0)).xyz; + const float lowerThickness = 0.8; - for (int i = 0; i < numSegments; i++) { - const float lowerThickness = 0.8; - // LOD 3 has a different algorithm #if _LOD_LOD_3 - { - - - const float segmentWidth = halfWidth * pow(sin(lowerThickness * 3.141), .8); - const float3 widthOffset = getWidthOffset(segmentWidth, tipOffset.xz) * max(1, cameraDistance / 10); - float3 segmentCenterBase = basePos; - float3 segmentCenterTip = basePos + tipOffset; - const float3 vertLeftBase = segmentCenterBase + widthOffset * 2.5; - const float3 vertRightBase = segmentCenterBase - widthOffset * 2.5; - const float3 vertLeftTip = segmentCenterTip + widthOffset * 0.4; - const float3 vertRightTip = segmentCenterTip - widthOffset * 0.4; - - const float3 surfTangent1 = vertLeftBase - vertLeftTip; - const float3 surfTangent2 = vertLeftBase - vertRightBase; - const float3 normal = normalize(cross(surfTangent1, surfTangent2)); // TODO remove normalize - float3 normalWS = UnityObjectToWorldNormal(normal); - + const float segmentWidth = halfWidth * pow(sin(lowerThickness * 3.141), .8); + const float3 widthOffset = getWidthOffset(segmentWidth, tipOffset.xz) * max(1, cameraDistance / 10); + float3 segmentCenterBase = basePos; + float3 segmentCenterTip = basePos + tipOffset; + const float3 vertLeftBase = segmentCenterBase + widthOffset * 2.5; + const float3 vertRightBase = segmentCenterBase - widthOffset * 2.5; + const float3 vertLeftTip = segmentCenterTip + widthOffset * 0.4; + const float3 vertRightTip = segmentCenterTip - widthOffset * 0.4; + + const float3 surfTangent1 = vertRightBase - segmentCenterTip; + const float3 surfTangent2 = vertLeftBase - segmentCenterTip; + const float3 normal = normalize(cross(surfTangent1, surfTangent2)); // TODO remove normalize + float3 normalWS = UnityObjectToWorldNormal(normal); + + const float3 camVec = normalize(segmentCenterTip - localCameraPos); - const float3 camVec = normalize(vertLeftBase - localCameraPos); + // at which side of the blade are we looking? + const bool lookingFromAbove = dot(camVec, normal) > 0; + if (lookingFromAbove) { + // normalWS = -normalWS; + } - // at which side of the blade are we looking? - const bool lookingFromAbove = dot(camVec, normalWS) > 0; - if (lookingFromAbove) { - normalWS = -normalWS; - } - - //normalWS = float3(1,1,1) * lookingFromAbove; - //normalWS = basePosWS - _MainCameraPosition.xyz; - //normalWS = camVec; - - o.pos = UnityObjectToClipPos(vertLeftBase); - #ifndef IS_IN_SHADOW_PASS - - o.uv = float2(0, 0); - TRANSFER_SHADOW(o) - o.transitionInterpolator = interpolator; - o.normal = normalWS; - o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftBase,1.0)).xyz; - #endif - triStream.Append(o); - - o.pos = UnityObjectToClipPos(vertRightBase); - #ifndef IS_IN_SHADOW_PASS - o.uv = float2(1, 0); - TRANSFER_SHADOW(o) - o.transitionInterpolator = interpolator; - o.normal = normalWS; - o.worldPos = mul(unity_ObjectToWorld, float4(vertRightBase,1.0)).xyz; - #endif - triStream.Append(o); - - o.pos = UnityObjectToClipPos(vertLeftTip); - #ifndef IS_IN_SHADOW_PASS - o.uv = float2(0, 1); - TRANSFER_SHADOW(o) - o.transitionInterpolator = interpolator; - o.normal = normalWS; - o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftTip,1.0)).xyz; - #endif - triStream.Append(o); - - o.pos = UnityObjectToClipPos(vertRightTip); - #ifndef IS_IN_SHADOW_PASS - o.uv = float2(1, 1); - TRANSFER_SHADOW(o) - o.transitionInterpolator = interpolator; - o.normal = normalWS; - o.worldPos = mul(unity_ObjectToWorld, float4(vertRightTip,1.0)).xyz; - #endif - triStream.Append(o); - } - continue; + o.pos = UnityObjectToClipPos(vertRightBase); +#ifdef IS_IN_BASE_PASS + o.uv = float2(1, 0); + TRANSFER_SHADOW(o) + o.normal = normalWS; + o.worldPos = mul(unity_ObjectToWorld, float4(vertRightBase,1.0)).xyz; #endif - + triStream.Append(o); + + o.pos = UnityObjectToClipPos(vertLeftBase); +#ifdef IS_IN_BASE_PASS + o.uv = float2(0, 0); + TRANSFER_SHADOW(o) + o.normal = normalWS; + o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftBase,1.0)).xyz; +#endif + triStream.Append(o); + + o.pos = UnityObjectToClipPos(vertRightTip); +#ifdef IS_IN_BASE_PASS + o.uv = float2(1, 1); + TRANSFER_SHADOW(o) + o.normal = normalWS; + o.worldPos = mul(unity_ObjectToWorld, float4(vertRightTip,1.0)).xyz; +#endif + triStream.Append(o); + + o.pos = UnityObjectToClipPos(vertLeftTip); +#ifdef IS_IN_BASE_PASS + o.uv = float2(0, 1); + TRANSFER_SHADOW(o) + o.normal = normalWS; + o.worldPos = mul(unity_ObjectToWorld, float4(vertLeftTip,1.0)).xyz; +#endif + triStream.Append(o); + +#else + for (int i = 0; i < numSegments; i++) { // in "blade space" const float segmentWidth = halfWidth * pow(sin(lowerThickness * 3.141 * (numSegments - i) / numSegments), .8); const float segmentHeightNormalized = i / (float)numSegments; @@ -195,14 +181,13 @@ void geom(point v2g IN[1], inout TriangleStream triStream) { const float3 vertRight = segmentCenter - widthOffset; //const float3 nextSegmentCenter = basePos + bendParabula(tipPos, nextSegmentHeight01); -#ifndef IS_IN_SHADOW_PASS +#ifdef IS_IN_BASE_PASS // calculate normal const float3 surfTangent1 = previousSegmentCenter - segmentCenter; const float3 surfTangent2 = previousSegmentCenter - vertLeft; const float3 normal = normalize(cross(surfTangent1, surfTangent2)); // TODO remove normalize float3 normalWS = UnityObjectToWorldNormal(normal); - const float3 camVec = normalize(segmentCenter - localCameraPos); // at which side of the blade are we looking? @@ -211,41 +196,43 @@ void geom(point v2g IN[1], inout TriangleStream triStream) { normalWS = -normalWS; } #endif - o.pos = UnityObjectToClipPos(vertLeft); -#ifndef IS_IN_SHADOW_PASS - o.uv = float2(0, segmentHeightNormalized); - TRANSFER_SHADOW(o) - o.transitionInterpolator = interpolator; - o.normal = normalize(lerp(normalWS, UnityObjectToWorldNormal(normalize(widthOffset)), _BladeBow)); - o.worldPos = mul(unity_ObjectToWorld, float4(vertLeft,1.0)).xyz; -#endif - triStream.Append(o); - o.pos = UnityObjectToClipPos(vertRight); -#ifndef IS_IN_SHADOW_PASS +#ifdef IS_IN_BASE_PASS o.uv = float2(1, segmentHeightNormalized); TRANSFER_SHADOW(o) - - o.transitionInterpolator = interpolator; o.normal = normalize(lerp(normalWS, UnityObjectToWorldNormal(-normalize(widthOffset)), _BladeBow)); o.worldPos = mul(unity_ObjectToWorld, float4(vertRight,1.0)).xyz; #endif triStream.Append(o); previousSegmentCenter = segmentCenterSnapshot; + + o.pos = UnityObjectToClipPos(vertLeft); +#ifdef IS_IN_BASE_PASS + o.uv = float2(0, segmentHeightNormalized); + TRANSFER_SHADOW(o) + o.normal = normalize(lerp(normalWS, UnityObjectToWorldNormal(normalize(widthOffset)), _BladeBow)); + o.worldPos = mul(unity_ObjectToWorld, float4(vertLeft,1.0)).xyz; +#endif + triStream.Append(o); } + +#endif o.pos = UnityObjectToClipPos(basePos + tipOffset * float3(_BendStrength, 1, _BendStrength)); -#ifndef IS_IN_SHADOW_PASS +#ifdef IS_IN_BASE_PASS o.uv = float2(.5, 1); TRANSFER_SHADOW(o) - o.transitionInterpolator = interpolator; o.normal = o.normal > 0 ? float3(0, 1, 0) : float3(0, -1, 0); #endif triStream.Append(o); } float4 frag(g2f i) : SV_Target{ -#ifndef IS_IN_SHADOW_PASS +#ifdef IS_IN_BASE_PASS + float3 localPos = mul(unity_WorldToObject, float4(i.worldPos, 1)).xyz; + float d = distance(localPos, i.debug) * 5; + return float4(i.debug, 1); + float3 worldNormal = normalize(i.normal); float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);