Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...
    CAPSULE_LINE_FRAGMENT_SHADER: "\n precision highp float;\n \n // Refraction split (glass-partition.ts): 0 off, 1 keep behind-or-none, 2 keep front.\n uniform int uGlassPartition;\n // Refracting-glass front-face window depth; the cleared 1.0 means \"no glass here\".\n uniform sampler2D uGlassDepth;\n\n\n uniform float uOpacity;\n uniform float uInvGamma;\n uniform float uIntensity;\n uniform float uOffset;\n uniform float uAbsorption;\n uniform float uHasElementAlpha;\n #ifdef USE_COLORMAP\n uniform sampler2D uColormapTex;\n uniform float uScalarMin;\n uniform float uScalarScale;\n #endif\n\n in vec2 vLocal;\n flat in vec4 vCutN;\n flat in uvec4 vPack;\n flat in float vAbLen;\n in float vFade;\n in float vAlpha;\n in float vSharp;\n #ifdef USE_COLORMAP\n in float vScalar;\n #else\n in vec3 vColor;\n #endif\n\n out vec4 fragColor;\n\n // The PARTNER leg's tapered-capsule field at a pixel offset rel from\n // the shared vertex (my local frame). Its axis is my inward axis\n // reflected across the cut plane (q = m − 2(m·n)n — exact); its\n // radius starts at rEnd, the SHARED-VERTEX radius handed in by the\n // caller from the packed vPack.z lane (#1494); it tapers by the\n // packed gradient, freezes past its far end,\n // and the far cap term closes the rod there (#1490). Sharpness is\n // taken from OUR fragment — the joint region is local.\n float luxarPartnerProfile(vec4 cut, vec2 rel, float mSign, float rEnd, float sharp) {\n vec2 n = cut.xy;\n // Partner axis = my inward axis reflected across the cut plane\n // (q = m − 2(m·n)n — exact; both cut normals are normalize(q − m)\n // up to sign).\n vec2 qdir = vec2(mSign - 2.0 * (mSign * n.x) * n.x, -2.0 * (mSign * n.x) * n.y);\n float xp = dot(rel, qdir);\n float yp2 = max(dot(rel, rel) - xp * xp, 0.0);\n // Radius from the SHARED VERTEX radius (rEnd, #1494) tapered by\n // the packed gradient, FROZEN past the partner's far end; the far\n // cap term closes the rod there (#1490).\n float rp = max(rEnd + cut.z * clamp(xp, 0.0, cut.w), 1e-4);\n float op = max(max(-xp, xp - cut.w), 0.0);\n float qp = (yp2 + op * op) / (rp * rp);\n float wp = 1.0 - qp;\n if (wp <= 0.0) return 0.0;\n return (abs(sharp - 0.5) < 1e-3) ? wp * wp : pow(wp, exp2(3.0 - 4.0 * sharp));\n }\n\n void main() {\n \n if (uGlassPartition != 0) {\n float glassDepth = texelFetch(uGlassDepth, ivec2(gl_FragCoord.xy), 0).r;\n bool inFrontOfGlass = glassDepth < 1.0 && gl_FragCoord.z < glassDepth;\n if (uGlassPartition == 1 && inFrontOfGlass) discard;\n if (uGlassPartition == 2 && !inFrontOfGlass) discard;\n }\n\n // Undo the w-premultiplication: screen-linear local coordinates.\n // gl_FragCoord.w IS the perspective-interpolated 1/w (spec identity\n // — PC-interp of a per-vertex w equals 1/gl_FragCoord.w exactly), so\n // the vW varying and its per-fragment divide are both unnecessary.\n float invW = gl_FragCoord.w;\n float x = vLocal.x * invW;\n float y = vLocal.y * invW;\n // Unpack the flat joint state (4 cheap ALU unpacks; see the vertex\n // declaration note — this bought back flat-register pressure).\n vec2 pkA = unpackHalf2x16(vPack.x); // (gradA, qlA)\n vec2 pkB = unpackHalf2x16(vPack.y); // (gradB, qlB)\n vec2 pkR = unpackHalf2x16(vPack.z); // (rA, rB)\n vec2 pkM = unpackHalf2x16(vPack.w); // (1/abLen, capFlags)\n // Interior joints: the joint plane (the 2D bisector) spans the FULL\n // stencil — cap and body — and composes by the DEFICIT rule over a\n // 1 px AA ramp (see _shared/line-capsule.ts and the blocks below).\n float cutFlagA = mod(pkM.y, 2.0);\n float cutFlagB = pkM.y >= 2.0 ? 1.0 : 0.0;\n // EXACT per-fragment radius without a divide: 1/abLen rides the\n // vLocal lane, and constant-width segments (the fill/thin-heavy\n // cases) take a mix-free fast path.\n float rPx;\n if (pkR.x == pkR.y) {\n rPx = max(pkR.x, 1e-4);\n } else {\n rPx = max(mix(pkR.x, pkR.y, clamp(x * pkM.x, 0.0, 1.0)), 1e-4);\n }\n // Squared distance in the local frame — the TRUE point-to-segment\n // distance, cap term included at BOTH ends: every end is capped (a\n // free end keeps the whole disc, a cut end its half of the joint\n // disc, carved out of that same cap by the bisector above).\n float ox = max(max(-x, x - vAbLen), 0.0);\n float q = (y * y + ox * ox) / (rPx * rPx);\n float w = 1.0 - q;\n if (w <= 0.0) discard;\n\n // Gaussian-like quartic bump (see _shared/line-capsule.ts): exactly 0\n // at the 2σ rim, no exp, no floor constants. The sharpness knob bends\n // the bump via pow only off the default (n = 2^(3−4s); SMALLER\n // exponents are boxier in w-space).\n float profile = (abs(vSharp - 0.5) < 1e-3)\n ? w * w\n : pow(w, exp2(3.0 - 4.0 * vSharp));\n\n // Joint DEFICIT rule: on the partner's side of the joint bisector I\n // render only what the partner CANNOT — max(mine − partner, 0) — so\n // the additive pair composes to max(mine, partner). For congruent\n // legs this is exactly the hard partition (zero contribution, no\n // double-count, no bead); where the partner tapers away or its\n // apparent radius diverges under perspective, it fills exactly the\n // light the partition used to chop (a fat vertex's disc no longer\n // loses its far half to a thin neighbour). A packet length of 0\n // means no usable partner (slice clip, behind-near joint, decode\n // failure) — hard cut, nothing drawn past the plane.\n // The cut is a 1 px AA RAMP, not a hard step: each leg's fragment\n // evaluates the plane in its OWN local frame, so pixels within float\n // noise of the line would otherwise flip independently — sprinkling\n // black (both discard) and double-bright (both keep) speckles along\n // every joint. Complementary ramps sum to exactly 1 instead, and\n // anti-alias the cut for free. The DEFICIT term blends in over the\n // same ramp: full profile on my side, max(mine − partner, 0) beyond.\n if (cutFlagA > 0.5) {\n float sideA = vCutN.x * x + vCutN.y * y;\n if (sideA > -0.5) {\n float coverA = clamp(0.5 - sideA, 0.0, 1.0);\n float defA = 0.0;\n if (pkA.y > 0.0) {\n defA = max(\n profile - luxarPartnerProfile(vec4(vCutN.xy, pkA), vec2(x, y), 1.0, pkR.x, vSharp),\n 0.0\n );\n }\n profile = profile * coverA + defA * (1.0 - coverA);\n if (profile <= 0.0) discard;\n }\n }\n if (cutFlagB > 0.5) {\n float sideB = vCutN.z * (x - vAbLen) + vCutN.w * y;\n if (sideB > -0.5) {\n float coverB = clamp(0.5 - sideB, 0.0, 1.0);\n float defB = 0.0;\n if (pkB.y > 0.0) {\n defB = max(\n profile - luxarPartnerProfile(vec4(vCutN.zw, pkB), vec2(x - vAbLen, y), -1.0, pkR.y, vSharp),\n 0.0\n );\n }\n profile = profile * coverB + defB * (1.0 - coverB);\n if (profile <= 0.0) discard;\n }\n }\n float intensity = profile * vFade;\n\n #ifdef USE_COLORMAP\n float st = clamp((vScalar - uScalarMin) * uScalarScale, 0.0, 1.0);\n #ifndef LUXAR_GAMMA_ONE\n st = pow(st, uInvGamma);\n #endif\n vec3 color = texture(uColormapTex, vec2(st, 0.5)).rgb;\n #else\n vec3 color = vColor;\n #endif\n\n #ifdef LUXAR_NO_GOG\n vec3 adjusted = color;\n #else\n vec3 adjusted = color * uIntensity + uOffset;\n adjusted = max(adjusted, vec3(0.0));\n #endif\n\n #ifdef LUXAR_VOLUMETRIC\n // Volumetric blending: alpha composes as optical depth via\n // w(a) = −ln(1 − a), gated by uHasElementAlpha (identity 1.0 written\n // for RGB data must NOT map to w ≈ 6.24). Mirrors the quad/point/\n // gsplat shaders; constants from ../_shared/volumetric.\n float alpha = intensity * uOpacity;\n alpha *= mix(1.0, -log(1.0 - min(vAlpha, 0.998046875)), uHasElementAlpha);\n float tau = uAbsorption * alpha;\n // A black line still absorbs — discard only when colour AND τ vanish.\n if (max(adjusted.r, max(adjusted.g, adjusted.b)) < 1e-4 && tau < 1e-4) discard;\n #else\n // Per-endpoint alpha is a plain linear contribution scale in every\n // non-volumetric mode.\n intensity *= vAlpha;\n #ifdef LUXAR_OPAQUE_RGB_CONTRIBUTION\n if (max(adjusted.r, max(adjusted.g, adjusted.b)) * intensity * uOpacity < 1e-4) discard;\n #else\n if (max(adjusted.r, max(adjusted.g, adjusted.b)) < 1e-4) discard;\n #endif\n #endif\n\n #if defined(USE_COLORMAP) || defined(LUXAR_GAMMA_ONE)\n vec3 gammaColor = adjusted;\n #else\n vec3 gammaColor = pow(adjusted, vec3(uInvGamma));\n #endif\n\n #if defined(LUXAR_VOLUMETRIC)\n // Emission–absorption tail (Max 1995) — identical to the quad's.\n float volAlpha = 1.0 - exp(-tau);\n float screen = (tau < 0.001) ? 1.0 - 0.5 * tau + tau * tau / 6.0\n : volAlpha / max(tau, 1e-20);\n fragColor = vec4(gammaColor * alpha * screen, volAlpha);\n #elif defined(LUXAR_MAX_RGB_CONTRIBUTION)\n // max-mode premultiplication (MaxEquation + One/One) — identical to\n // the quad's rationale.\n float a = intensity * uOpacity;\n fragColor = vec4(gammaColor * a, a);\n #else\n fragColor = vec4(gammaColor, intensity * uOpacity);\n #endif\n }\n" = ...