194 lines
6.0 KiB
Markdown
194 lines
6.0 KiB
Markdown
# RFCP v3.10.5 Session Summary - 2026-02-06
|
||
|
||
## Що зробили сьогодні
|
||
|
||
### 1. WebGL Texture-Based Coverage (ЗАВЕРШЕНО ✅)
|
||
|
||
**Проблема:** Canvas heatmap був blocky, хотіли smooth interpolation.
|
||
|
||
**Рішення:** Texture-based WebGL з smoothstep shader + nearest neighbor fill.
|
||
|
||
**Файл:** `frontend/src/components/map/WebGLCoverageLayer.tsx`
|
||
|
||
**Як працює:**
|
||
1. Створюємо texture де кожен pixel = RSRP value
|
||
2. Nearest neighbor fill для заповнення gaps (circular coverage → rectangular texture)
|
||
3. Smoothstep shader для C2 continuity interpolation
|
||
4. Colormap applied AFTER interpolation
|
||
|
||
**Статус:** Працює, але все ще blocky на zoom in через nearest neighbor fill.
|
||
|
||
---
|
||
|
||
### 2. WebGL Radial Gradients Coverage (В ПРОЦЕСІ 🔄)
|
||
|
||
**Мета:** Красиві smooth gradients як Canvas heatmap, але GPU-accelerated.
|
||
|
||
**Файл:** `frontend/src/components/map/WebGLRadialCoverageLayer.tsx`
|
||
|
||
**Як працює:**
|
||
1. Кожна точка = quad з Gaussian radial falloff
|
||
2. Additive blending в float framebuffer: (weight × rsrp, weight)
|
||
3. Final composite pass: normalize (R/G) + colormap
|
||
|
||
**Поточний статус:**
|
||
- ✅ Framebuffer створюється правильно
|
||
- ✅ Points рендеряться (framebuffer має дані)
|
||
- ✅ Composite pass працює (final pixel має колір)
|
||
- ✅ 50m показує beautiful smooth gradients!
|
||
- ✅ 200m тепер теж показує (після radius fix)
|
||
- ⚠️ Coverage radius не повний (обрізається раніше ніж 10km)
|
||
- ⚠️ Темне коло на периферії (falloff занадто різкий?)
|
||
- ⚠️ Selector dropdown сірий на білому (CSS issue)
|
||
|
||
---
|
||
|
||
### 3. Coverage Renderer Selector (ЗАВЕРШЕНО ✅)
|
||
|
||
**Файл:** `frontend/src/store/settings.ts`
|
||
|
||
**Додано:** `coverageRenderer: 'radial' | 'texture' | 'canvas'`
|
||
|
||
**UI:** Dropdown в Coverage Settings panel
|
||
|
||
**Fallback chain:**
|
||
- Radial fails → Texture
|
||
- Texture fails → Canvas
|
||
|
||
---
|
||
|
||
## Залишилось зробити (Next Session)
|
||
|
||
### Priority 1: Fix Radial Coverage Radius
|
||
|
||
**Симптом:** Coverage не покриває повні 10km, обрізається раніше.
|
||
|
||
**Можливі причини:**
|
||
1. Canvas bounds не включають padding для point radius
|
||
2. Points на краю мають gradient що виходить за canvas
|
||
3. Normalized coordinates calculation wrong at edges
|
||
|
||
**Debug:**
|
||
```javascript
|
||
// Перевірити bounds vs actual coverage extent
|
||
console.log('Canvas bounds:', bounds);
|
||
console.log('Points extent:', {
|
||
minLat: Math.min(...points.map(p => p.lat)),
|
||
maxLat: Math.max(...points.map(p => p.lat)),
|
||
// ...
|
||
});
|
||
```
|
||
|
||
**Fix approach:**
|
||
1. Додати padding до canvas bounds = point radius
|
||
2. Або clip points що виходять за межі
|
||
|
||
---
|
||
|
||
### Priority 2: Fix Dark Ring on Periphery
|
||
|
||
**Симптом:** Темне коло на краю coverage area.
|
||
|
||
**Причина:** Точки на периферії мають менше сусідів → менший total weight → темніший колір після normalization.
|
||
|
||
**Fix options:**
|
||
1. Збільшити radius multiplier (3.0× замість 2.5×)
|
||
2. Або додати edge detection і boost alpha там
|
||
3. Або використати min weight threshold перед normalization
|
||
|
||
---
|
||
|
||
### Priority 3: Fix Selector Dropdown Styling
|
||
|
||
**Симптом:** Сірий текст на білому фоні (погано видно).
|
||
|
||
**Fix:** Update CSS classes в App.tsx для dropdown.
|
||
|
||
---
|
||
|
||
### Priority 4: Performance Testing
|
||
|
||
Протестувати з великою кількістю точок:
|
||
- 10,000+ points
|
||
- 50,000+ points
|
||
- Measure frame time
|
||
|
||
Якщо повільно — implement instanced rendering.
|
||
|
||
---
|
||
|
||
## Files Changed Today
|
||
|
||
```
|
||
frontend/src/components/map/
|
||
├── WebGLCoverageLayer.tsx # Texture-based (updated with NN fill)
|
||
├── WebGLRadialCoverageLayer.tsx # NEW - Radial gradients
|
||
└── GeographicHeatmap.tsx # Canvas fallback (unchanged)
|
||
|
||
frontend/src/store/
|
||
└── settings.ts # Added coverageRenderer option
|
||
|
||
frontend/src/
|
||
└── App.tsx # Integrated renderer selector
|
||
```
|
||
|
||
---
|
||
|
||
## Console Debug Commands
|
||
|
||
```javascript
|
||
// Check which renderer is active
|
||
document.querySelectorAll('canvas').forEach(c =>
|
||
console.log(c.className, c.width, c.height)
|
||
);
|
||
|
||
// Check WebGL errors
|
||
const canvas = document.querySelector('.webgl-radial-coverage');
|
||
const gl = canvas?.getContext('webgl');
|
||
console.log('WebGL error:', gl?.getError());
|
||
|
||
// Read center pixel
|
||
gl?.readPixels(canvas.width/2, canvas.height/2, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
|
||
```
|
||
|
||
---
|
||
|
||
## Key Insights Learned
|
||
|
||
1. **Texture-based vs Radial:** Texture good for terrain detail accuracy, Radial good for beautiful visualization.
|
||
|
||
2. **Float framebuffer:** Need `EXT_color_buffer_float` extension. Fallback: use RGBA8 with encoding.
|
||
|
||
3. **Additive blending:** `gl.blendFunc(gl.ONE, gl.ONE)` for accumulation, then `gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)` for final composite.
|
||
|
||
4. **Weighted average in shader:** Store (weight × value, weight), then normalize: value = R / G.
|
||
|
||
5. **Radius scaling:** Higher resolution = more points = smaller radius. Lower resolution = fewer points = larger radius to compensate.
|
||
|
||
---
|
||
|
||
## Git Status
|
||
|
||
- ✅ Pushed working WebGL texture-based coverage
|
||
- 🔄 WebGL radial in progress (functional but incomplete)
|
||
|
||
---
|
||
|
||
## Next Session Start Point
|
||
|
||
1. Відкрити RFCP project
|
||
2. `npm run dev` в frontend
|
||
3. Test radial coverage з 50m і 200m
|
||
4. Fix radius issue (Priority 1)
|
||
5. Fix dark ring (Priority 2)
|
||
6. Polish UI (Priority 3)
|
||
|
||
---
|
||
|
||
## Session Stats
|
||
|
||
- **Duration:** ~6 hours
|
||
- **Iterations:** 15+ fix attempts
|
||
- **Final result:** Working radial gradients renderer (90% complete)
|
||
- **Key breakthrough:** Discovering framebuffer had data but composite pass wasn't reading it
|