Last active
January 26, 2026 17:35
-
-
Save solrz/19532ac9f015d747d27eca3ea303a827 to your computer and use it in GitHub Desktop.
The shader for naked-eye 3D display Companion 01, which realtime convert RGB-D video on device. Change constant may required for each device.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //!HOOK OUTPUT | |
| //!BIND HOOKED | |
| //!DESC Lenticular 3D - Full-SBS Fix V3 | |
| precision highp float; | |
| // --- 參數設置 --- | |
| #define LINE_NUMBER 19.6401 | |
| #define OBLIQUITY 0.105 | |
| #define DEVIATION 3.589 | |
| #define SCREEN_W 1440.0 | |
| #define SCREEN_H 2560.0 | |
| // --- 3D 強度 --- | |
| #define THRESHOLD 40.0 | |
| #define PROTRUDE 0.0 | |
| #define DEPTH_INVERT 1.0 | |
| // --- 智能突出設置 --- | |
| #define POP_START 0.6 | |
| #define POP_STRENGTH 2.5 | |
| #define POP_SMOOTHNESS 0.2 | |
| // 邏輯開始 | |
| float deform_depth_smart(float d) { | |
| d = clamp(d, 0.0, 1.0); | |
| float start = POP_START - POP_SMOOTHNESS; | |
| float end = POP_START + POP_SMOOTHNESS; | |
| float mask = smoothstep(start, end, d); | |
| float boosted_depth = d + (mask * d * (POP_STRENGTH - 1.0)); | |
| return clamp(boosted_depth, 0.0, 2.0); | |
| } | |
| vec4 sample_quilt(vec2 uv, float viewId) { | |
| // --- 1. 計算比例與縮放 --- | |
| // 強制 Full-SBS 比例: (寬 * 0.5) / 高 | |
| float source_aspect = (input_size.x * 0.5) / input_size.y; | |
| float screen_aspect = target_size.x / target_size.y; | |
| vec2 scale = vec2(1.0); | |
| if (screen_aspect > source_aspect) { | |
| // 螢幕比影片寬 (Pillarbox, 左右黑邊) | |
| scale.x = screen_aspect / source_aspect; | |
| } else { | |
| // 螢幕比影片窄 (Letterbox, 上下黑邊) -> 你的情況 (9:16 螢幕看 4:3) | |
| scale.y = source_aspect / screen_aspect; | |
| } | |
| // 算出縮放後的原始 UV (範圍可能超出 0~1) | |
| vec2 fittedUV = (uv - 0.5) * scale + 0.5; | |
| // --- 2. 邊緣處理 (關鍵修正) --- | |
| // 我們需要分別處理 X 和 Y | |
| // Y 軸 (上下): 我們想要它延伸 (Smear),所以只做簡單的 clamp 0~1 | |
| // X 軸 (左右): 這是 SBS 的分割區,絕對不能延伸,否則會把左眼邊緣顏色拉成一條線蓋在畫面上 | |
| // 先對 Y 軸做延伸 (解決黑邊問題) | |
| // 內縮 0.002 防止讀取到影片外部的黑色像素 | |
| float clampedY = clamp(fittedUV.y, 0.002, 0.998); | |
| // 對 X 軸保持原樣,稍後再處理,但先檢查是否越界 | |
| float currentX = fittedUV.x; | |
| // 如果 X 軸完全超出了影片範圍 (例如左右黑邊的情況),直接 clamp | |
| // 但在你的情況 (左右填滿),這個值通常在 0~1 之間 | |
| float clampedX = clamp(currentX, 0.002, 0.998); | |
| // 組合出用於採樣顏色的 Base UV | |
| // 注意:這裡我們用 clampedX 來取色,防止左右邊緣出現雜訊 | |
| vec2 baseUV = vec2(clampedX, clampedY); | |
| // --- 3. 採樣深度 --- | |
| vec2 depthUV = baseUV * vec2(0.5, 1.0) + vec2(0.5, 0.0); | |
| float depthVal = HOOKED_tex(depthUV).r; | |
| depthVal = deform_depth_smart(depthVal); | |
| // --- 4. 計算視差偏移 --- | |
| float normalizedView = viewId; | |
| float thresh = ((normalizedView - 0.5) * 2.0 / THRESHOLD); | |
| float xOffset = (depthVal - (0.0 - PROTRUDE) - 0.5) * thresh * DEPTH_INVERT; | |
| // --- 5. 最終採樣座標 --- | |
| // 這裡要用 fittedUV.x (未 clamp 的) 加上偏移嗎? | |
| // 不,因為如果 fittedUV.x 已經在邊緣,再加偏移就會錯。 | |
| // 所以我們基於 clampedX 進行偏移 | |
| // 左眼 RGB 區域: 0.0 ~ 0.5 | |
| vec2 finalUV_L = vec2(clampedX * 0.5 + xOffset, clampedY); | |
| // 安全鎖定:這是消除「影片上多餘顏色」的最關鍵一步 | |
| // 無論視差怎麼偏移,絕對不能讓採樣點跑出左眼 (0.0~0.5) 的範圍 | |
| // 同時稍微內縮 (0.001) 避免讀到分割線 | |
| finalUV_L.x = clamp(finalUV_L.x, 0.001, 0.499); | |
| // --- 6. 決定輸出顏色 --- | |
| // 如果原始 fittedUV.x 超出了 0~1 (左右黑邊區域),我們顯示延伸色 | |
| // 但因為你的情況是左右填滿,所以這部分邏輯主要處理 Y 軸延伸 | |
| return HOOKED_tex(finalUV_L); | |
| } | |
| vec4 hook() { | |
| vec2 screenUV = gl_FragCoord.xy / target_size; | |
| float pitch = (SCREEN_W * 3.0) / LINE_NUMBER; | |
| float slope = OBLIQUITY * (SCREEN_H / SCREEN_W); | |
| float subp = 1.0 / (SCREEN_W * 3.0); | |
| float center = (DEVIATION / SCREEN_W) * pitch; | |
| float r, g, b; | |
| float z; | |
| z = (screenUV.x + 0.0 * subp + screenUV.y * slope) * pitch - center; | |
| z = mod(z + ceil(abs(z)), 1.0); | |
| r = sample_quilt(screenUV, z).r; | |
| z = (screenUV.x + 1.0 * subp + screenUV.y * slope) * pitch - center; | |
| z = mod(z + ceil(abs(z)), 1.0); | |
| g = sample_quilt(screenUV, z).g; | |
| z = (screenUV.x + 2.0 * subp + screenUV.y * slope) * pitch - center; | |
| z = mod(z + ceil(abs(z)), 1.0); | |
| b = sample_quilt(screenUV, z).b; | |
| return vec4(r, g, b, 1.0); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment