Shader "ChivaVR/JD_RotShader" { Properties{ [Header(JD Config Fixed)] _RotLineLength("缠绕部分长度",Float) = 1 _Width("缠绕部分宽度",Float) = 0.2 _JDJuanLength("胶带卷长度",Float) = 0.1 [Header(JD Control Parameter)] _Radius("缠绕半径",Float) = 0.2 _MaxAngle("最大缠绕角度",Float) = 500 _Value("Value",Float) = 720 _BackAngle("伸出部分旋转角度",Range(0,180)) = 0 [Header(JD Shape Parameter)] _MoveOffset("旋转偏移量",Float) = 0.3 _DampOffsetAngle("不参与偏移角度",Range(0,450)) = 0 _UpOffset("单侧高度偏移量",Float) = 0.1 _Warp("Warp扭曲系数(默认0)",Range(-1,1)) = 0 _WarpPos("WarpPos",Range(0,4)) = 0 [Header(JD Line Parameter)] [Toggle]_HiddenLine("是否隐藏伸展部分",Float) = 0 [Toggle]_HiddenJDJuan("是否隐藏胶带卷",Float) = 0 _LineShowLength("连接部分长度",Float) = 0.2 [Header(JD Texture)] _Color("Color", Color) = (0.5019608,0.5019608,0.5019608,1) _MainTex("胶带贴图", 2D) = "white" {} _BumpMap("胶带法线贴图", 2D) = "bump" {} _SecondTex("胶带卷贴图", 2D) = "bump" {} _SecondMap("胶带卷法线贴图", 2D) = "bump" {} _Metallic("Metallic", Range(0, 1)) = 0 _Gloss("Gloss", Range(0, 1)) = 0.8 } SubShader{ Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Name "FORWARD" Tags { "LightMode" = "ForwardBase" } // 关闭深度写入 //ZWrite Off // 开启混合模式,并设置混合因子为SrcAlpha和OneMinusSrcAlpha Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #define UNITY_PASS_FORWARDBASE #define SHOULD_SAMPLE_SH ( defined (LIGHTMAP_OFF) && defined(DYNAMICLIGHTMAP_OFF) ) #define _GLOSSYENV 1 #include "UnityCG.cginc" #include "AutoLight.cginc" #include "Lighting.cginc" #include "UnityPBSLighting.cginc" #include "UnityStandardBRDF.cginc" #pragma multi_compile_fwdbase_fullshadows #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON #pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE #pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON #pragma multi_compile_fog #pragma only_renderers d3d9 d3d11 glcore gles #pragma target 3.0 #pragma shader_feature _HIDDENLINE_ON #pragma shader_feature _HIDDENJDJUAN_ON float _RotLineLength; float _Width; float _JDJuanLength; float _Radius; float _MaxAngle; float _Value; float _BackAngle; float _MoveOffset; float _DampOffsetAngle; float _UpOffset; float _Warp; float _WarpPos; float _HiddenLine; float _HiddenJDJuan; float _LineShowLength; uniform float4 _Color; uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform sampler2D _BumpMap; uniform float4 _BumpMap_ST; uniform sampler2D _SecondTex; uniform float4 _SecondTex_ST; uniform sampler2D _SecondMap; uniform float4 _SecondMap_ST; uniform float _Metallic; uniform float _Gloss; struct VertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 tangent : TANGENT; float2 texcoord0 : TEXCOORD0; float2 texcoord1 : TEXCOORD1; float2 texcoord2 : TEXCOORD2; }; struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; float2 uv1 : TEXCOORD1; float2 uv2 : TEXCOORD2; float4 posWorld : TEXCOORD3; float3 normalDir : TEXCOORD4; float3 tangentDir : TEXCOORD5; float3 bitangentDir : TEXCOORD6; float flag : TEXCOORD11; LIGHTING_COORDS(7,8) UNITY_FOG_COORDS(9) #if defined(LIGHTMAP_ON) || defined(UNITY_SHOULD_SAMPLE_SH) float4 ambientOrLightmapUV : TEXCOORD10; #endif }; VertexOutput vert(VertexInput v) { VertexOutput o = (VertexOutput)0; float s; float c; v.vertex += float4(0, _Radius, 0, 0); _Value = clamp(_Value,0, _MaxAngle); //缠绕区域 if ((v.vertex.x / _RotLineLength) < (_Value / _MaxAngle)) { float pAngel = _MaxAngle / _RotLineLength; sincos(radians(v.vertex.x*pAngel % 360), s, c); float4x4 rotate = { c,s,0,0, -s,c,0,0, 0,0,1,0, 0,0,0,1 }; float vertexZ = v.vertex.z; if (_Value < 0) { vertexZ = 0; } if (vertexZ < 0) { vertexZ = 0; } float warpY = _Warp * sin(_WarpPos + v.vertex.x / _RotLineLength); //偏移量控制 if ((v.vertex.x / _RotLineLength * _MaxAngle) > _DampOffsetAngle) { v.vertex.z += clamp((v.vertex.x / _RotLineLength * _MaxAngle) - _DampOffsetAngle,0, _MaxAngle) / 360 * _MoveOffset; } if (v.vertex.x / _RotLineLength * _MaxAngle > 2) { v.vertex = mul(rotate, float3(0, -vertexZ / _Width / 2 * _UpOffset + v.vertex.y + warpY, v.vertex.z)); } else { v.vertex = mul(rotate, float3(0, _Radius + warpY, v.vertex.z)); } v.normal = normalize(mul(rotate,v.normal)); v.tangent = normalize(mul(rotate, v.tangent)); } else //伸出区域 { sincos(radians(_Value % 360), s, c); float4x4 rotate = { c,s,0,0, -s,c,0,0, 0,0,1,0, 0,0,0,1 }; float warpY = _Warp * sin(_WarpPos + (_Value / _MaxAngle)* _RotLineLength); float vertexZ = v.vertex.z; if (_Value < 0) { _Value = 0; } float3 currentPoint = mul(rotate, float3(0, _Radius + warpY, 0)); float3 currentPointNormalize = normalize(float3(currentPoint.x, currentPoint.y, currentPoint.z)); float3 dirNormail = normalize(cross(currentPointNormalize, float3(0, 0, 1))); float sC; float cC; sincos(radians(-_BackAngle), sC, cC); float4x4 rotateCAngle = { cC,sC,0,0, -sC,cC,0,0, 0,0,1,0, 0,0,0,1 }; if (_Value > _DampOffsetAngle) { v.vertex.z += clamp(_Value - _DampOffsetAngle, 0, _Value) / 360 * _MoveOffset; } v.normal = normalize(mul(rotate, v.normal)); v.tangent = normalize(mul(rotate, v.tangent)); #if _HIDDENLINE_ON //隐藏伸出区域 _HiddenLine = 1; v.vertex = float4(currentPoint + float3(0, 0, v.vertex.z) , 0); #else //显示伸出区域 _HiddenLine = 0; o.flag = v.vertex.x; if ((_RotLineLength*((_MaxAngle - _Value) / _MaxAngle))*3.1415 > _LineShowLength) { if ((v.vertex.x - _RotLineLength) > 0) { #ifdef _HIDDENJDJUAN_ON _HiddenJDJuan = 1; v.vertex = float4(currentPoint + dirNormail * _LineShowLength + float3(0, 0, v.vertex.z) , 0); #else _HiddenJDJuan = 0; v.vertex = float4(currentPoint + dirNormail * (v.vertex.x - _RotLineLength + _LineShowLength) + float3(0, 0, v.vertex.z) + currentPointNormalize * (v.vertex.y - _Radius) , 0); #endif } else if ((v.vertex.x - (_Value / _MaxAngle)*_RotLineLength)*3.1415 < _LineShowLength) { v.vertex = float4(currentPoint + dirNormail * (v.vertex.x - (_Value / _MaxAngle)*_RotLineLength)*3.1415 + float3(0, 0, v.vertex.z) + currentPointNormalize * (v.vertex.y - _Radius) , 0); } else { v.vertex = float4(currentPoint + dirNormail * _LineShowLength + float3(0, 0, v.vertex.z) + currentPointNormalize * (v.vertex.y - _Radius) , 0); } } else { #ifdef _HIDDENJDJUAN_ON _HiddenJDJuan = 1; v.vertex = float4(currentPoint + dirNormail * ((((_MaxAngle - _Value) / _MaxAngle)* _RotLineLength) / _JDJuanLength * _LineShowLength) + float3(0, 0, v.vertex.z) , 0); #else v.vertex = float4(currentPoint + dirNormail * (v.vertex.x - (_Value / _MaxAngle)* _RotLineLength) + float3(0, 0, v.vertex.z) + currentPointNormalize * (v.vertex.y - _Radius) , 0); #endif } #endif v.vertex = float4(mul(rotateCAngle, (v.vertex.rgb - currentPoint)) + currentPoint,0); v.normal = normalize(mul(rotateCAngle, v.normal)); v.tangent = normalize(mul(rotateCAngle, v.tangent)); } o.uv0 = v.texcoord0; o.uv1 = v.texcoord1; o.uv2 = v.texcoord2; #ifdef LIGHTMAP_ON o.ambientOrLightmapUV.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw; o.ambientOrLightmapUV.zw = 0; #elif UNITY_SHOULD_SAMPLE_SH #endif #ifdef DYNAMICLIGHTMAP_ON o.ambientOrLightmapUV.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; #endif o.normalDir = UnityObjectToWorldNormal(v.normal); o.tangentDir = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz); o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); o.posWorld = mul(unity_ObjectToWorld, v.vertex); float3 lightColor = _LightColor0.rgb; o.pos = UnityObjectToClipPos(v.vertex); UNITY_TRANSFER_FOG(o,o.pos); TRANSFER_VERTEX_TO_FRAGMENT(o) return o; } float4 frag(VertexOutput i) : COLOR { i.normalDir = normalize(i.normalDir); float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir); float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); float3 _BumpMap_var = UnpackNormal(tex2D(_BumpMap,TRANSFORM_TEX(i.uv0, _BumpMap))); if (i.flag < _RotLineLength) { _BumpMap_var = UnpackNormal(tex2D(_BumpMap, TRANSFORM_TEX(i.uv0, _BumpMap))); } else { _BumpMap_var = UnpackNormal(tex2D(_SecondMap, TRANSFORM_TEX(i.uv0, _SecondMap))); } float3 normalLocal = _BumpMap_var.rgb; float3 normalDirection = normalize(mul(normalLocal, tangentTransform)); // Perturbed normals float3 viewReflectDirection = reflect(-viewDirection, normalDirection); float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz); float3 lightColor = _LightColor0.rgb; float3 halfDirection = normalize(viewDirection + lightDirection); ////// Lighting: float attenuation = LIGHT_ATTENUATION(i); float3 attenColor = attenuation * _LightColor0.xyz; float Pi = 3.141592654; float InvPi = 0.31830988618; ///////// Gloss: float gloss = _Gloss; float perceptualRoughness = 1.0 - _Gloss; float roughness = perceptualRoughness * perceptualRoughness; float specPow = exp2(gloss * 10.0 + 1.0); /////// GI Data: UnityLight light; #ifdef LIGHTMAP_OFF light.color = lightColor; light.dir = lightDirection; light.ndotl = LambertTerm(normalDirection, light.dir); #else light.color = half3(0.f, 0.f, 0.f); light.ndotl = 0.0f; light.dir = half3(0.f, 0.f, 0.f); #endif UnityGIInput d; d.light = light; d.worldPos = i.posWorld.xyz; d.worldViewDir = viewDirection; d.atten = attenuation; #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) d.ambient = 0; d.lightmapUV = i.ambientOrLightmapUV; #else d.ambient = i.ambientOrLightmapUV; #endif #if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION d.boxMin[0] = unity_SpecCube0_BoxMin; d.boxMin[1] = unity_SpecCube1_BoxMin; #endif #if UNITY_SPECCUBE_BOX_PROJECTION d.boxMax[0] = unity_SpecCube0_BoxMax; d.boxMax[1] = unity_SpecCube1_BoxMax; d.probePosition[0] = unity_SpecCube0_ProbePosition; d.probePosition[1] = unity_SpecCube1_ProbePosition; #endif d.probeHDR[0] = unity_SpecCube0_HDR; d.probeHDR[1] = unity_SpecCube1_HDR; Unity_GlossyEnvironmentData ugls_en_data; ugls_en_data.roughness = 1.0 - gloss; ugls_en_data.reflUVW = viewReflectDirection; UnityGI gi = UnityGlobalIllumination(d, 1, normalDirection, ugls_en_data); lightDirection = gi.light.dir; lightColor = gi.light.color; ////// Specular: float NdotL = saturate(dot(normalDirection, lightDirection)); float LdotH = saturate(dot(lightDirection, halfDirection)); float3 specularColor = _Metallic; float specularMonochrome; float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex)); if (i.flag < _RotLineLength) { _MainTex_var = tex2D(_MainTex, TRANSFORM_TEX(i.uv0, _MainTex)); } else { _MainTex_var = tex2D(_SecondTex, TRANSFORM_TEX(i.uv0, _SecondTex)); } float3 diffuseColor = (_MainTex_var.rgb*_Color.rgb); // Need this for specular when using metallic diffuseColor = DiffuseAndSpecularFromMetallic(diffuseColor, specularColor, specularColor, specularMonochrome); specularMonochrome = 1.0 - specularMonochrome; float NdotV = abs(dot(normalDirection, viewDirection)); float NdotH = saturate(dot(normalDirection, halfDirection)); float VdotH = saturate(dot(viewDirection, halfDirection)); float visTerm = SmithJointGGXVisibilityTerm(NdotL, NdotV, roughness); float normTerm = GGXTerm(NdotH, roughness); float specularPBL = (visTerm*normTerm) * UNITY_PI; #ifdef UNITY_COLORSPACE_GAMMA specularPBL = sqrt(max(1e-4h, specularPBL)); #endif specularPBL = max(0, specularPBL * NdotL); #if defined(_SPECULARHIGHLIGHTS_OFF) specularPBL = 0.0; #endif half surfaceReduction; #ifdef UNITY_COLORSPACE_GAMMA surfaceReduction = 1.0 - 0.28*roughness*perceptualRoughness; #else surfaceReduction = 1.0 / (roughness*roughness + 1.0); #endif specularPBL *= any(specularColor) ? 1.0 : 0.0; float3 directSpecular = attenColor * specularPBL*FresnelTerm(specularColor, LdotH); half grazingTerm = saturate(gloss + specularMonochrome); float3 indirectSpecular = (gi.indirect.specular); indirectSpecular *= FresnelLerp(specularColor, grazingTerm, NdotV); indirectSpecular *= surfaceReduction; float3 specular = (directSpecular + indirectSpecular); /////// Diffuse: NdotL = max(0.0,dot(normalDirection, lightDirection)); half fd90 = 0.5 + 2 * LdotH * LdotH * (1 - gloss); float nlPow5 = Pow5(1 - NdotL); float nvPow5 = Pow5(1 - NdotV); float3 directDiffuse = ((1 + (fd90 - 1)*nlPow5) * (1 + (fd90 - 1)*nvPow5) * NdotL) * attenColor; float3 indirectDiffuse = float3(0,0,0); indirectDiffuse += gi.indirect.diffuse; float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor; /// Final Color: float3 finalColor = diffuse + specular; fixed4 finalRGBA = fixed4(finalColor, _Color.a); UNITY_APPLY_FOG(i.fogCoord, finalRGBA); return finalRGBA; } ENDCG } } }