# WebGPU Migration Roadmap - FikoYT 3D Engine

## Genel Bakis

Mevcut sistem: **Three.js 0.177.0** + **WebGL2 Renderer** + **WebGPU Compute**
Hedef: **Tam WebGPU Renderer** + **WebGPU Compute** (Unified Pipeline)

---

## ADIM 1: WebGPU Renderer Factory Servisi

**Amac:** WebGPU destegi varsa kullan, yoksa WebGL2'ye fallback

### Dosya: `FikoRendererFactory.ts`

```typescript
// fikoyt-zorro.com/src/service/fikoyt-ui/src/lib/fiko-three-js/IFikoThreeJS/FikoRendererFactory.ts

import * as THREE from 'three';

export type RendererType = 'webgpu' | 'webgl2' | 'auto';

export interface RendererConfig {
  canvas: HTMLCanvasElement;
  antialias?: boolean;
  alpha?: boolean;
  pixelRatio?: number;
  powerPreference?: 'high-performance' | 'low-power' | 'default';
  logarithmicDepthBuffer?: boolean;
  stencil?: boolean;
}

export interface RendererCapabilities {
  type: 'webgpu' | 'webgl2';
  maxTextureSize: number;
  maxTextures: number;
  supportsCompute: boolean;
  supportsStorageTextures: boolean;
}

export class FikoRendererFactory {
  private static webgpuSupported: boolean | null = null;
  private static webgpuRenderer: any = null; // THREE.WebGPURenderer

  /**
   * WebGPU destegini kontrol et (bir kez)
   */
  static async checkWebGPUSupport(): Promise<boolean> {
    if (this.webgpuSupported !== null) {
      return this.webgpuSupported;
    }

    // Temel kontrol
    if (!navigator.gpu) {
      console.log('[FikoRendererFactory] WebGPU API mevcut degil');
      this.webgpuSupported = false;
      return false;
    }

    try {
      const adapter = await navigator.gpu.requestAdapter({
        powerPreference: 'high-performance'
      });

      if (!adapter) {
        console.log('[FikoRendererFactory] GPU adapter bulunamadi');
        this.webgpuSupported = false;
        return false;
      }

      const device = await adapter.requestDevice();
      if (!device) {
        console.log('[FikoRendererFactory] GPU device alinamadi');
        this.webgpuSupported = false;
        return false;
      }

      // Basarili - device'i temizle
      device.destroy();

      console.log('[FikoRendererFactory] WebGPU destekleniyor!');
      this.webgpuSupported = true;
      return true;

    } catch (error) {
      console.warn('[FikoRendererFactory] WebGPU test hatasi:', error);
      this.webgpuSupported = false;
      return false;
    }
  }

  /**
   * Renderer olustur - async cunku WebGPU init async
   */
  static async createRenderer(
    config: RendererConfig,
    preferredType: RendererType = 'auto'
  ): Promise<THREE.WebGLRenderer | any> {

    const useWebGPU = preferredType === 'webgpu' ||
      (preferredType === 'auto' && await this.checkWebGPUSupport());

    if (useWebGPU) {
      try {
        return await this.createWebGPURenderer(config);
      } catch (error) {
        console.warn('[FikoRendererFactory] WebGPU renderer olusturulamadi, WebGL2 fallback:', error);
        return this.createWebGL2Renderer(config);
      }
    }

    return this.createWebGL2Renderer(config);
  }

  /**
   * WebGPU Renderer olustur
   */
  private static async createWebGPURenderer(config: RendererConfig): Promise<any> {
    // Dynamic import - WebGPURenderer Three.js addons'da
    const { WebGPURenderer } = await import('three/addons/renderers/webgpu/WebGPURenderer.js');

    const renderer = new WebGPURenderer({
      canvas: config.canvas,
      antialias: config.antialias ?? true,
      alpha: config.alpha ?? true,
      powerPreference: config.powerPreference ?? 'high-performance',
      // NOT: logarithmicDepthBuffer WebGPU'da farkli calisabilir
    });

    // WebGPU async init gerektirir
    await renderer.init();

    // Temel ayarlar
    renderer.setPixelRatio(Math.min(config.pixelRatio ?? window.devicePixelRatio, 2));
    renderer.setSize(config.canvas.clientWidth, config.canvas.clientHeight);
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.0;

    // Custom property - tip tespiti icin
    (renderer as any)._fikoRendererType = 'webgpu';

    console.log('[FikoRendererFactory] WebGPU Renderer olusturuldu');
    return renderer;
  }

  /**
   * WebGL2 Renderer olustur (mevcut kod)
   */
  private static createWebGL2Renderer(config: RendererConfig): THREE.WebGLRenderer {
    const renderer = new THREE.WebGLRenderer({
      canvas: config.canvas,
      antialias: config.antialias ?? true,
      alpha: config.alpha ?? true,
      logarithmicDepthBuffer: config.logarithmicDepthBuffer ?? true,
      preserveDrawingBuffer: false,
      failIfMajorPerformanceCaveat: false,
      powerPreference: config.powerPreference ?? 'high-performance',
      precision: 'highp',
      stencil: config.stencil ?? true,
    });

    renderer.setPixelRatio(Math.min(config.pixelRatio ?? window.devicePixelRatio, 1.5));
    renderer.setSize(config.canvas.clientWidth, config.canvas.clientHeight);
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.0;

    // Custom property
    (renderer as any)._fikoRendererType = 'webgl2';

    console.log('[FikoRendererFactory] WebGL2 Renderer olusturuldu');
    return renderer;
  }

  /**
   * Renderer tipini al
   */
  static getRendererType(renderer: THREE.WebGLRenderer | any): 'webgpu' | 'webgl2' {
    return (renderer as any)._fikoRendererType || 'webgl2';
  }

  /**
   * Renderer yeteneklerini al
   */
  static getCapabilities(renderer: THREE.WebGLRenderer | any): RendererCapabilities {
    const type = this.getRendererType(renderer);

    if (type === 'webgpu') {
      return {
        type: 'webgpu',
        maxTextureSize: 16384, // Tipik WebGPU limit
        maxTextures: 16,
        supportsCompute: true,
        supportsStorageTextures: true
      };
    }

    // WebGL2
    const gl = (renderer as THREE.WebGLRenderer).getContext() as WebGL2RenderingContext;
    return {
      type: 'webgl2',
      maxTextureSize: gl?.getParameter(gl.MAX_TEXTURE_SIZE) || 4096,
      maxTextures: gl?.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) || 16,
      supportsCompute: false,
      supportsStorageTextures: false
    };
  }
}
```

### Test Komutu (Adim 1):
```bash
cd fikoyt-zorro.com
ng serve
# Tarayici console'da kontrol et:
# [FikoRendererFactory] WebGPU destekleniyor! (veya desteklenmiyor mesaji)
```

---

## ADIM 2: Component Entegrasyonu

**Dosya:** `fiko-three-js.component.ts` (satir 775-790)

### Degisiklik:

```typescript
// ONCE (mevcut kod):
hazirla(): void {
  THREE.Cache.enabled = true;
  this.sunucu = new THREE.WebGLRenderer({...});
  // ...
}

// SONRA (WebGPU destekli):
async hazirla(): Promise<void> {
  THREE.Cache.enabled = true;

  // WebGPU veya WebGL2 otomatik sec
  this.sunucu = await FikoRendererFactory.createRenderer({
    canvas: this.canvas.nativeElement,
    antialias: this.antiAlias,
    alpha: true,
    pixelRatio: this.pixelRatio,
    powerPreference: 'high-performance',
    logarithmicDepthBuffer: true,
    stencil: true
  }, 'auto'); // 'auto' | 'webgpu' | 'webgl2'

  // Renderer tipine gore ek ayarlar
  const rendererType = FikoRendererFactory.getRendererType(this.sunucu);
  console.log(`[FikoThreeJS] Renderer tipi: ${rendererType}`);

  if (rendererType === 'webgl2') {
    // WebGL2 spesifik ayarlar (mevcut shadow config vs.)
    this.sunucu.shadowMap.enabled = this.enableShadows;
    this.sunucu.shadowMap.type = this.enableShadows ? THREE.PCFShadowMap : THREE.BasicShadowMap;
    this.sunucu.shadowMap.autoUpdate = false;
  } else {
    // WebGPU spesifik ayarlar
    // Shadow desteği WebGPU Renderer'da farklı
  }

  // ... geri kalan kod ayni
}
```

### ngOnInit Guncelleme:

```typescript
// ONCE:
ngOnInit() {
  this.hazirla();
}

// SONRA:
async ngOnInit() {
  await this.hazirla();
}
```

---

## ADIM 3: Basit Test Sahnesi

Degisiklikleri test etmek icin minimal test:

```typescript
// Test: Console'da calistir
async function testWebGPURenderer() {
  const canvas = document.createElement('canvas');
  canvas.width = 800;
  canvas.height = 600;
  document.body.appendChild(canvas);

  const { FikoRendererFactory } = await import('./FikoRendererFactory');

  const renderer = await FikoRendererFactory.createRenderer({
    canvas,
    antialias: true,
    alpha: true
  }, 'webgpu');

  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0x222222);

  const camera = new THREE.PerspectiveCamera(75, 800/600, 0.1, 1000);
  camera.position.z = 5;

  // Test objesi
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  // Isik
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(5, 5, 5);
  scene.add(light);
  scene.add(new THREE.AmbientLight(0x404040));

  // Render loop
  function animate() {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
  }
  animate();

  console.log('Test basarili! Renderer tipi:', FikoRendererFactory.getRendererType(renderer));
}
```

---

## ADIM 4: Shadow Sistemi Adaptasyonu

WebGPU'da shadow map sistemi farkli calisir.

### Kontrol Edilecekler:
1. `shadowMap.enabled` - WebGPU'da ayni mi?
2. `shadowMap.type` - PCFShadowMap destegi
3. `shadowMap.autoUpdate` - Manual update

### Cozum:

```typescript
// Shadow wrapper class
export class FikoShadowManager {
  private renderer: THREE.WebGLRenderer | any;
  private isWebGPU: boolean;

  constructor(renderer: THREE.WebGLRenderer | any) {
    this.renderer = renderer;
    this.isWebGPU = FikoRendererFactory.getRendererType(renderer) === 'webgpu';
  }

  enableShadows(enabled: boolean): void {
    if (this.isWebGPU) {
      // WebGPU shadow setup (Three.js r177+)
      // NOT: WebGPU Renderer'da shadowMap API degisebilir
      if ((this.renderer as any).shadowMap) {
        (this.renderer as any).shadowMap.enabled = enabled;
      }
    } else {
      (this.renderer as THREE.WebGLRenderer).shadowMap.enabled = enabled;
      (this.renderer as THREE.WebGLRenderer).shadowMap.type = THREE.PCFShadowMap;
    }
  }

  updateShadowMaps(): void {
    if (!this.isWebGPU) {
      (this.renderer as THREE.WebGLRenderer).shadowMap.needsUpdate = true;
    }
    // WebGPU'da otomatik olabilir
  }
}
```

---

## ADIM 5: Material Uyumlulugu

Three.js WebGPU Renderer'da material'lar otomatik cevrilir, ancak custom shader'lar sorun cikarabilir.

### Kontrol Listesi:

| Material Tipi | WebGL2 | WebGPU | Notlar |
|---------------|--------|--------|--------|
| MeshStandardMaterial | ✅ | ✅ | Otomatik |
| MeshBasicMaterial | ✅ | ✅ | Otomatik |
| ShaderMaterial | ✅ | ⚠️ | GLSL → WGSL gerekebilir |
| RawShaderMaterial | ✅ | ❌ | Manuel ceviri |
| NodeMaterial | ❌ | ✅ | Sadece WebGPU |

### Custom Shader Tespiti:

```typescript
// Sahnedeki custom shader'lari bul
function findCustomShaders(scene: THREE.Scene): THREE.Material[] {
  const customMaterials: THREE.Material[] = [];

  scene.traverse((obj) => {
    if (obj instanceof THREE.Mesh && obj.material) {
      const materials = Array.isArray(obj.material) ? obj.material : [obj.material];
      for (const mat of materials) {
        if (mat instanceof THREE.ShaderMaterial || mat instanceof THREE.RawShaderMaterial) {
          customMaterials.push(mat);
        }
      }
    }
  });

  return customMaterials;
}
```

---

## ADIM 6: Compute Shader Entegrasyonu

Mevcut `FikoWebGPU.ts` zaten WebGPU compute destekliyor. Renderer ile birlestirme:

```typescript
// FikoUnifiedGPU.ts - Renderer + Compute birlesik sistem
export class FikoUnifiedGPU {
  private renderer: any; // WebGPURenderer
  private device: GPUDevice;

  async init(canvas: HTMLCanvasElement): Promise<void> {
    // WebGPU Renderer olustur
    const { WebGPURenderer } = await import('three/addons/renderers/webgpu/WebGPURenderer.js');

    this.renderer = new WebGPURenderer({ canvas, antialias: true });
    await this.renderer.init();

    // Ayni device'i compute icin kullan
    // NOT: Three.js internal device'a erisim
    // Bu API degisebilir!
    if ((this.renderer as any)._device) {
      this.device = (this.renderer as any)._device;
    }
  }

  getDevice(): GPUDevice | null {
    return this.device || null;
  }

  getRenderer(): any {
    return this.renderer;
  }
}
```

---

## ADIM 7: Post-Processing

Three.js EffectComposer WebGPU ile uyumlu degil (r177'de). Alternatif:

### Secenekler:
1. **PostProcessing.js** - WebGPU destekli yeni kutuphane
2. **Three.js TSL (Three Shading Language)** - Node-based effects
3. **Manuel compute shader** - WGSL ile post-processing

### Gecici Cozum (WebGPU'da post-processing devre disi):

```typescript
function setupPostProcessing(renderer: any, scene: THREE.Scene, camera: THREE.Camera) {
  const rendererType = FikoRendererFactory.getRendererType(renderer);

  if (rendererType === 'webgl2') {
    // Mevcut EffectComposer kullan
    const composer = new EffectComposer(renderer);
    // ... effects
    return composer;
  }

  // WebGPU icin simdilik bypass
  console.warn('[PostProcessing] WebGPU modunda post-processing devre disi');
  return null;
}
```

---

## ADIM 8: Performans Testi

### Benchmark Script:

```typescript
interface BenchmarkResult {
  rendererType: 'webgpu' | 'webgl2';
  fps: number;
  frameTime: number;
  triangleCount: number;
  drawCalls: number;
}

async function benchmarkRenderer(
  renderer: any,
  scene: THREE.Scene,
  camera: THREE.Camera,
  duration: number = 5000
): Promise<BenchmarkResult> {
  const rendererType = FikoRendererFactory.getRendererType(renderer);

  let frameCount = 0;
  const startTime = performance.now();

  return new Promise((resolve) => {
    function frame() {
      renderer.render(scene, camera);
      frameCount++;

      if (performance.now() - startTime < duration) {
        requestAnimationFrame(frame);
      } else {
        const elapsed = performance.now() - startTime;
        const info = renderer.info || { render: { triangles: 0, calls: 0 } };

        resolve({
          rendererType,
          fps: (frameCount / elapsed) * 1000,
          frameTime: elapsed / frameCount,
          triangleCount: info.render?.triangles || 0,
          drawCalls: info.render?.calls || 0
        });
      }
    }
    frame();
  });
}

// Karsilastirma testi
async function compareRenderers() {
  const scene = createTestScene(); // 10K triangle sahne
  const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);

  // WebGL2 test
  const webgl2Renderer = await FikoRendererFactory.createRenderer({...}, 'webgl2');
  const webgl2Result = await benchmarkRenderer(webgl2Renderer, scene, camera);

  // WebGPU test
  const webgpuRenderer = await FikoRendererFactory.createRenderer({...}, 'webgpu');
  const webgpuResult = await benchmarkRenderer(webgpuRenderer, scene, camera);

  console.table([webgl2Result, webgpuResult]);
}
```

---

## Uygulama Sirasi

| Adim | Dosya | Risk | Tahmini Is |
|------|-------|------|------------|
| 1 | FikoRendererFactory.ts | Dusuk | Yeni dosya |
| 2 | fiko-three-js.component.ts | Orta | Mevcut kodu degistir |
| 3 | Test sahnesi | Dusuk | Konsol testi |
| 4 | Shadow sistemi | Orta | Uyumluluk |
| 5 | Material kontrolu | Dusuk | Sadece kontrol |
| 6 | Compute entegrasyonu | Yuksek | Renderer-Compute birlestirme |
| 7 | Post-processing | Yuksek | Bypass veya ceviri |
| 8 | Performans testi | Dusuk | Benchmark |

---

## Baslarken

**Ilk adim:** `FikoRendererFactory.ts` dosyasini olustur ve test et.

```bash
# Dosya konumu:
fikoyt-zorro.com/src/service/fikoyt-ui/src/lib/fiko-three-js/IFikoThreeJS/FikoRendererFactory.ts
```

Hazir misin? "devam" de, ilk dosyayi olusturalim.
