Skip to content

📌 Ne Zaman Kullanılır?

  • ✅ 3D web, ürün görselleştirme, interaktif deneyim, oyun, WebGL
  • ⚠️ Performans yönetimi zor, öğrenme eğrisi yüksek
  • ❌ 2D animasyon (CSS/Framer yeterli), basit grafik

Önerilen Kullanım: Three.js veya React Three Fiber + Blender modeller Alternatifler: Babylon.js, PlayCanvas, A-Frame (VR)

Three.js & React Three Fiber — 3D Web Rehberi

Three.js, tarayicida 3D sahne oluşturmak için en yaygin JavaScript kutuphanesidir. React Three Fiber (R3F) ise Three.js'i React icinde deklaratif olarak kullanmayi sağlar.

Temel Kavramlar

Sahne Yapisi

Bir Three.js sahnesi 3 temel bilesenden olusur:

javascript
import * as THREE from 'three';

// 1. Sahne (Scene) — tum nesneleri icerir
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);

// 2. Kamera (Camera) — bakis acisi
const camera = new THREE.PerspectiveCamera(
  75,                           // FOV (goris acisi)
  window.innerWidth / window.innerHeight,  // Aspect ratio
  0.1,                          // Near clipping plane
  1000                          // Far clipping plane
);
camera.position.set(0, 2, 5);

// 3. Renderer — sahneyi cizer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);

Mesh = Geometry + Material

javascript
// Geometry (sekil)
const geometry = new THREE.BoxGeometry(1, 1, 1);

// Material (gorunum)
const material = new THREE.MeshStandardMaterial({
  color: 0x3b82f6,
  roughness: 0.4,
  metalness: 0.6
});

// Mesh (geometry + material)
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

Animasyon Dongusu

javascript
function animate() {
  requestAnimationFrame(animate);
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  renderer.render(scene, camera);
}
animate();

Responsive (Pencere Boyutu Degisimi)

javascript
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

Geometri ve Mesh

Temel Geometriler

GeometriAçıklamaParametreler
BoxGeometryKup/kutuwidth, height, depth
SphereGeometryKureradius, widthSegments, heightSegments
CylinderGeometrySilindirradiusTop, radiusBottom, height
PlaneGeometryDuz yuzeywidth, height
TorusGeometryHalkaradius, tube, radialSegments
ConeGeometryKoniradius, height
RingGeometryHalka yuzeyinnerRadius, outerRadius

BufferGeometry (Custom Geometri)

javascript
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
  -1, -1, 0,
   1, -1, 0,
   0,  1, 0,
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));

InstancedMesh (Performansli Cok Obje)

Ayni geometri ve materyali binlerce kez verimli render etme:

javascript
const count = 1000;
const mesh = new THREE.InstancedMesh(geometry, material, count);
const dummy = new THREE.Object3D();

for (let i = 0; i < count; i++) {
  dummy.position.set(
    Math.random() * 20 - 10,
    Math.random() * 20 - 10,
    Math.random() * 20 - 10
  );
  dummy.updateMatrix();
  mesh.setMatrixAt(i, dummy.matrix);
}
scene.add(mesh);

Materials ve Shading

Material Turleri

MaterialKullanımIsik Gerekli
MeshBasicMaterialDuz renk, isik yokHayir
MeshStandardMaterialPBR, gercekciEvet
MeshPhysicalMaterialCam, clearcoat, iridescenceEvet
MeshLambertMaterialHafif golgeleme, hızlıEvet
MeshPhongMaterialParlak yuzeylerEvet
ShaderMaterialCustom GLSL shaderOzel

MeshStandardMaterial Parametreleri

javascript
const material = new THREE.MeshStandardMaterial({
  color: 0x3b82f6,        // Renk
  roughness: 0.5,          // 0 = ayna, 1 = mat
  metalness: 0.5,          // 0 = plastik, 1 = metal
  map: diffuseTexture,     // Diffuse texture
  normalMap: normalTexture, // Normal map (yuzey detayi)
  roughnessMap: roughTex,  // Roughness map
  envMap: envTexture,      // Environment map (yansima)
  transparent: true,       // Saydamlik aktif
  opacity: 0.8,            // Saydamlik degeri
});

Environment Map (HDRI)

javascript
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';

new RGBELoader().load('/env.hdr', (texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping;
  scene.environment = texture;  // Tum materyallere yansima
  scene.background = texture;   // Arka plan
});

Isiklandirma (Lighting)

Isik Turleri

IsikAçıklamaKullanım
AmbientLightHer yone esit isik (golge yok)Genel aydinlatma
DirectionalLightParalel isik (gunes)Dis mekan
PointLightNoktasal (ampul)Ic mekan
SpotLightKonik (spot)Sahne isigi
HemisphereLightGokyuzu + zemin renk gecisiDogal ortam
RectAreaLightDikdortgen yuzey isikStudyo

Three-Point Lighting

javascript
// Key light (ana isik)
const keyLight = new THREE.DirectionalLight(0xffffff, 1.5);
keyLight.position.set(5, 5, 5);
keyLight.castShadow = true;
scene.add(keyLight);

// Fill light (dolgu)
const fillLight = new THREE.DirectionalLight(0x8888ff, 0.5);
fillLight.position.set(-5, 3, 5);
scene.add(fillLight);

// Rim light (arka kenar)
const rimLight = new THREE.DirectionalLight(0xffffff, 0.8);
rimLight.position.set(0, 5, -5);
scene.add(rimLight);

Golge (Shadow)

javascript
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

// Isik golge atar
keyLight.castShadow = true;
keyLight.shadow.mapSize.set(2048, 2048);

// Nesne golge atar
cube.castShadow = true;

// Zemin golge alir
floor.receiveShadow = true;

Interaction (Etkilesim)

OrbitControls

javascript
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;       // Yumusak hareket
controls.dampingFactor = 0.05;
controls.maxPolarAngle = Math.PI / 2; // Asagi bakmayi sinirla
controls.minDistance = 2;
controls.maxDistance = 20;

// Animasyon dongusunde guncelle
function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}

Raycasting (Tikla ve Sec)

javascript
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

window.addEventListener('click', (event) => {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(scene.children);

  if (intersects.length > 0) {
    const selected = intersects[0].object;
    selected.material.color.set(0xff0000); // Secilen nesneyi kirmizi yap
    console.log('Secilen:', selected.name);
  }
});

Hover Efekti

javascript
window.addEventListener('mousemove', (event) => {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(meshes);

  // Tum nesneleri sifirla
  meshes.forEach(m => m.material.emissive.setHex(0x000000));

  // Hover olan nesneyi parlat
  if (intersects.length > 0) {
    intersects[0].object.material.emissive.setHex(0x333333);
    document.body.style.cursor = 'pointer';
  } else {
    document.body.style.cursor = 'default';
  }
});

Physics (Fizik) Entegrasyonu

Rapier (WASM, hızlı)

bash
npm install @dimforge/rapier3d-compat
javascript
import RAPIER from '@dimforge/rapier3d-compat';

await RAPIER.init();

const world = new RAPIER.World({ x: 0, y: -9.81, z: 0 }); // Yerekimi

// Zemin (static body)
const groundDesc = RAPIER.RigidBodyDesc.fixed();
const groundBody = world.createRigidBody(groundDesc);
const groundCollider = RAPIER.ColliderDesc.cuboid(10, 0.1, 10);
world.createCollider(groundCollider, groundBody);

// Kup (dynamic body)
const cubeDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(0, 5, 0);
const cubeBody = world.createRigidBody(cubeDesc);
const cubeCollider = RAPIER.ColliderDesc.cuboid(0.5, 0.5, 0.5);
world.createCollider(cubeCollider, cubeBody);

// Animasyon dongusunde fizik guncelle
function animate() {
  requestAnimationFrame(animate);
  world.step();

  const pos = cubeBody.translation();
  const rot = cubeBody.rotation();
  cube.position.set(pos.x, pos.y, pos.z);
  cube.quaternion.set(rot.x, rot.y, rot.z, rot.w);

  renderer.render(scene, camera);
}

Post-Processing

EffectComposer

javascript
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass';

const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));

// Bloom efekti (parlama)
const bloomPass = new UnrealBloomPass(
  new THREE.Vector2(window.innerWidth, window.innerHeight),
  0.5,  // strength
  0.4,  // radius
  0.85  // threshold
);
composer.addPass(bloomPass);

// Render dongusunde composer kullan
function animate() {
  requestAnimationFrame(animate);
  composer.render(); // renderer.render() yerine
}

Diger Post-Processing Efektleri

EfektAçıklama
BloomParlak alanlarda isik tasmasi
SSAOAmbient occlusion (koseler koyu)
DOFDerinlik alani bulanikligi
OutlineSecilen nesne etrafinda kontur
FXAA/SMAAAnti-aliasing
Film/GlitchStilize efektler

Model Yukleme (GLTF/GLB)

GLTFLoader

javascript
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';

// Draco decoder (sikistirilmis modeller icin)
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/draco/');

const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader(dracoLoader);

gltfLoader.load(
  '/models/product.glb',
  (gltf) => {
    const model = gltf.scene;
    model.scale.set(1, 1, 1);
    model.position.set(0, 0, 0);
    scene.add(model);

    // Animasyon varsa
    if (gltf.animations.length > 0) {
      const mixer = new THREE.AnimationMixer(model);
      gltf.animations.forEach((clip) => mixer.clipAction(clip).play());
    }
  },
  (progress) => {
    console.log(`Yukleniyor: ${(progress.loaded / progress.total * 100).toFixed(0)}%`);
  },
  (error) => {
    console.error('Model yuklenemedi:', error);
  }
);

Model Optimizasyon

YöntemAçıklamaArac
Draco compressionMesh sikistirma (%80-90 kucultme)gltf export ayari
Texture boyut512x512 veya 1024x1024 web içinPhotoshop, Sharp
Polygon azaltmaDecimate modifierBlender
gltf-transformCLI ile optimizenpx @gltf-transform/cli
gltfpackMesh quantizationmeshoptimizer

React Three Fiber (R3F)

Temel Kullanım

bash
npm install @react-three/fiber @react-three/drei
jsx
import { Canvas } from '@react-three/fiber';
import { OrbitControls, Environment } from '@react-three/drei';

function Box({ position, color }) {
  const [hovered, setHovered] = useState(false);
  const meshRef = useRef();

  useFrame((state, delta) => {
    meshRef.current.rotation.y += delta * 0.5;
  });

  return (
    <mesh
      ref={meshRef}
      position={position}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
    >
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : color} />
    </mesh>
  );
}

export default function Scene() {
  return (
    <Canvas camera={{ position: [0, 2, 5], fov: 75 }}>
      <ambientLight intensity={0.5} />
      <directionalLight position={[5, 5, 5]} />
      <Box position={[-1.5, 0, 0]} color="blue" />
      <Box position={[1.5, 0, 0]} color="green" />
      <OrbitControls enableDamping />
      <Environment preset="sunset" />
    </Canvas>
  );
}

@react-three/drei Yardimci Bilesenler

BileşenAçıklama
OrbitControlsKamera kontrolu
EnvironmentHDRI ortam isigi
useGLTFGLTF model yükleme hook
Text / Text3D3D yazi
Html3D sahne icinde HTML
FloatYuzme animasyonu
ContactShadowsZemin golge
PresentationControlsSürüm modeli gosterim
SparklesParlti efekti
SkyGokyuzu

useGLTF ile Model Yukleme

jsx
import { useGLTF } from '@react-three/drei';

function Product() {
  const { scene } = useGLTF('/models/product.glb');
  return <primitive object={scene} scale={1} />;
}

// Preload (onceden yukle)
useGLTF.preload('/models/product.glb');

R3F + Post-Processing

bash
npm install @react-three/postprocessing
jsx
import { EffectComposer, Bloom, Vignette } from '@react-three/postprocessing';

function Scene() {
  return (
    <Canvas>
      {/* ... sahne icerigi ... */}
      <EffectComposer>
        <Bloom intensity={0.5} luminanceThreshold={0.9} />
        <Vignette offset={0.3} darkness={0.7} />
      </EffectComposer>
    </Canvas>
  );
}

R3F + Physics (@react-three/rapier)

bash
npm install @react-three/rapier
jsx
import { Physics, RigidBody } from '@react-three/rapier';

function Scene() {
  return (
    <Canvas>
      <Physics gravity={[0, -9.81, 0]}>
        {/* Dusen kup */}
        <RigidBody>
          <mesh position={[0, 5, 0]}>
            <boxGeometry />
            <meshStandardMaterial color="blue" />
          </mesh>
        </RigidBody>

        {/* Zemin (sabit) */}
        <RigidBody type="fixed">
          <mesh position={[0, -1, 0]}>
            <boxGeometry args={[20, 0.2, 20]} />
            <meshStandardMaterial color="gray" />
          </mesh>
        </RigidBody>
      </Physics>
    </Canvas>
  );
}

Vanilla Three.js vs R3F

ÖzellikThree.js (vanilla)React Three Fiber
YaklasimImperativeDeclarative (JSX)
React entegrasyonuManuelDogal
State yönetimiManuelReact hooks
Ekosistemthree/examples@react-three/drei
PerformansBiraz daha hızlıCok yakin
ÖğrenmeThree.js bilgisi gerekliReact + Three.js
IdealNon-React projeReact proje

Web Export ve Optimizasyon

Performans Hedefleri

MetrikHedefAçıklama
Dosya boyutu< 5 MBModel + texture toplam
Triangle sayisi10K - 100KSahne toplami
Texture boyutu512x512 - 1024x1024Web için yeterli
FPS60 FPSMobilde 30 FPS kabul edilebilir
Ilk yükleme< 3 saniyeLazy load kullan

Optimizasyon Teknikleri

  • InstancedMesh: Ayni objeyi binlerce kez verimli render
  • LOD (Level of Detail): Uzaktaki nesneler için düşük polygon
  • Frustum Culling: Kamera gorusunun disindaki nesneleri render etme (Three.js varsayılan)
  • Texture Compression: KTX2 format (GPU compressed)
  • Draco: Mesh boyutunu %80-90 azaltir
  • Lazy loading: Modelleri gorunur oldugunda yükle
  • dispose(): Kullanilmayan geometry, material, texture'lari temizle

dispose() ile Bellek Temizleme

javascript
// Sahne temizleme — mutlaka yapin, yoksa bellek sizintisi olur
function cleanup(scene) {
  scene.traverse((child) => {
    if (child.isMesh) {
      child.geometry.dispose();
      if (child.material.isMaterial) {
        cleanMaterial(child.material);
      }
    }
  });
}

function cleanMaterial(material) {
  material.dispose();
  // Texture'lari temizle
  for (const key of Object.keys(material)) {
    const value = material[key];
    if (value && typeof value === 'object' && 'dispose' in value) {
      value.dispose();
    }
  }
}

model-viewer (Google — Kolay 3D Gosterim)

HTML tag ile 3D model gosterimi — JavaScript bilgisi gerektirmez:

html
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.4.0/model-viewer.min.js"></script>

<model-viewer
  src="/models/product.glb"
  alt="Urun 3D Model"
  auto-rotate
  camera-controls
  shadow-intensity="1"
  style="width: 100%; height: 400px;"
></model-viewer>

Güvenlik

  • Kullanici yuklenen 3D model riskleri: Kullanici yukledigi .glb/.gltf dosyaları zararli script icerebilir — sandbox'ta yukleyin, dosya boyutunu sinirlayin
  • WebGL context loss: GPU kaynak yetersizliginde context kaybolabilir — renderer.domElement.addEventListener('webglcontextlost', handler) ile yakalayip kullaniciya bildirin
  • Bellek sizintisi: dispose() cagirmazsaniz bellek surekli artar — sayfa degisimlerinde (React useEffect cleanup) mutlaka temizleyin
  • Cross-origin: Texture ve modelleri farkli domain'den yuklerken CORS ayarlarina dikkat edin

İpuçları (Tips)

  • dispose() her seyi temizle: Geometry, material, texture — ozellikle SPA'larda sayfa degisiminde
  • Texture compression: KTX2 format GPU'da acilir, daha az bellek tuketir
  • LOD kullan: THREE.LOD ile uzaktaki nesneler için düşük poly versiyon
  • InstancedMesh: 100+ ayni obje varsa kesinlikle kullanin (1000x performans farki)
  • Offscreen Canvas: Worker thread'de render — ana thread'i bloklamaz
  • requestAnimationFrame: setInterval/setTimeout yerine her zaman bunu kullanin
  • Stats.js: FPS, MS, MB monitor — geliştirme sırasında performans takibi
  • Pixel ratio sinirla: renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) — 4K ekranlarda gereksiz render onleme
  • Blender export: Ctrl+A > All Transforms uygula, sonra glTF/GLB export
  • React projede: R3F + drei kullanin — vanilla Three.js yerine cok daha temiz kod

Ilgili Rehberler

Frontend

Diger Kategoriler

Developer Guides & Technical References