Variable furFragmentShaderConst
furFragmentShader: "\n uniform vec3 colorBase;\n uniform vec3 colorTip;\n \n varying vec2 vUv;\n varying float vLayer;\n varying vec3 vNormal;\n \n // Improved noise for fur strand variation\n float rand(vec2 n) { \n return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); \n }\n \n float noise(vec2 p) {\n vec2 i = floor(p);\n vec2 f = fract(p);\n f = f * f * (3.0 - 2.0 * f);\n float a = rand(i);\n float b = rand(i + vec2(1.0, 0.0));\n float c = rand(i + vec2(0.0, 1.0));\n float d = rand(i + vec2(1.0, 1.0));\n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n }\n \n void main() {\n // Multi-octave noise for more natural fur pattern\n float n = noise(vUv * 40.0) * 0.6 + noise(vUv * 80.0) * 0.4;\n \n // Alpha test - tapering strands toward tips with better distribution\n float threshold = 0.35 + vLayer * 0.65;\n if (n < threshold) discard;\n \n // Color gradient from base to tip with subtle variation\n vec3 col = mix(colorBase, colorTip, vLayer);\n \n // Enhanced ambient occlusion at roots\n float ao = 0.4 + 0.6 * vLayer;\n col *= ao;\n \n // Rim lighting effect for better depth perception\n float rim = 1.0 - abs(dot(vNormal, vec3(0.0, 0.0, 1.0)));\n col += vec3(0.1) * rim * vLayer;\n \n gl_FragColor = vec4(col, 1.0);\n }\n" = ...