npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

r3f-gltf-area-lights

v1.0.0

Published

Shape-aware area lighting for GLTF models in React Three Fiber - realistic light emission from object surfaces

Readme

r3f-gltf-area-lights

Shape-aware area lighting for GLTF models in React Three Fiber. This package enables GLTF/GLB objects to emit realistic lighting that follows their geometry, creating natural light emission from entire surfaces rather than point sources.

Features

  • 🌟 Geometry-Based Emission: Light radiates from the entire surface of objects
  • 🎨 Shape-Aware: Lighting follows object contours and complex geometries
  • 🚀 Performance Optimized: Efficient GPU-based calculations
  • 🎭 Material Compatible: Works with standard Three.js materials
  • 🎮 Easy Integration: Simple React components for r3f projects
  • 📦 GLTF Support: Designed specifically for GLTF/GLB models
  • Dynamic Updates: Supports animated models with real-time light updates
  • 🔧 TypeScript Ready: Full TypeScript support with type definitions

Installation

npm install r3f-gltf-area-lights
# or
yarn add r3f-gltf-area-lights
# or
pnpm add r3f-gltf-area-lights

Quick Start

import { Canvas } from '@react-three/fiber'
import { useGLTF } from '@react-three/drei'
import { AreaLightEmitter, AreaLightProvider, useAreaLightManager } from 'r3f-gltf-area-lights'

function Scene() {
  const { scene } = useGLTF('/models/neon-sign.glb')
  const lightManager = useAreaLightManager()

  return (
    <AreaLightProvider manager={lightManager}>
      <AreaLightEmitter intensity={2} samples={32}>
        <primitive object={scene} />
      </AreaLightEmitter>
      
      {/* Objects in the scene will receive realistic lighting */}
      <mesh>
        <sphereGeometry />
        <meshStandardMaterial />
      </mesh>
    </AreaLightProvider>
  )
}

export default function App() {
  return (
    <Canvas>
      <Scene />
    </Canvas>
  )
}

Complete Guide for GLB Objects

Basic GLB Setup

import { Canvas } from '@react-three/fiber'
import { useGLTF, OrbitControls } from '@react-three/drei'
import { AreaLightEmitter, AreaLightProvider, useAreaLightManager } from 'r3f-gltf-area-lights'

function GLBModel({ url }) {
  const { scene } = useGLTF(url)
  
  return (
    <AreaLightEmitter intensity={3} samples={32}>
      <primitive object={scene} />
    </AreaLightEmitter>
  )
}

function Scene() {
  const lightManager = useAreaLightManager()
  
  return (
    <AreaLightProvider manager={lightManager}>
      {/* Your glowing GLB model */}
      <GLBModel url="/models/neon-sign.glb" />
      
      {/* Environment that receives light */}
      <mesh position={[0, -2, 0]} rotation={[-Math.PI / 2, 0, 0]}>
        <planeGeometry args={[10, 10]} />
        <meshStandardMaterial color="#1a1a1a" />
      </mesh>
    </AreaLightProvider>
  )
}

export default function App() {
  return (
    <Canvas camera={{ position: [5, 5, 5] }}>
      <OrbitControls />
      <Scene />
    </Canvas>
  )
}

Preparing Your GLB Models

For best results with area lighting, your GLB models should:

  1. Have Emissive Materials: Set emissive color and intensity in your 3D software
  2. Use Standard Materials: Works with MeshStandardMaterial or MeshPhysicalMaterial
  3. Optimize Geometry: Fewer polygons = better performance
  4. Bake Textures: Emissive textures are fully supported

Advanced GLB Example with Multiple Emitters

function ComplexGLBScene() {
  const { nodes, materials } = useGLTF('/models/cyberpunk-scene.glb')
  const lightManager = useAreaLightManager()
  
  return (
    <AreaLightProvider manager={lightManager}>
      {/* Neon signs with high intensity */}
      <AreaLightEmitter intensity={5} samples={64} color="#ff00ff">
        <mesh geometry={nodes.NeonSign.geometry} material={materials.Neon} />
      </AreaLightEmitter>
      
      {/* Computer screens with lower intensity */}
      <AreaLightEmitter intensity={1} samples={16} range={3}>
        <mesh geometry={nodes.Monitor.geometry} material={materials.Screen} />
      </AreaLightEmitter>
      
      {/* Animated hologram */}
      <AreaLightEmitter intensity={3} samples={32} updateFrequency={30}>
        <mesh geometry={nodes.Hologram.geometry} material={materials.Hologram}>
          <meshStandardMaterial
            {...materials.Hologram}
            emissive="#00ffff"
            emissiveIntensity={2}
          />
        </mesh>
      </AreaLightEmitter>
    </AreaLightProvider>
  )
}

Working with Animated GLB Models

import { useAnimations } from '@react-three/drei'

function AnimatedGLB({ url }) {
  const { scene, animations } = useGLTF(url)
  const { actions } = useAnimations(animations, scene)
  
  useEffect(() => {
    // Play animation
    actions.Animation?.play()
  }, [actions])
  
  return (
    <AreaLightEmitter 
      intensity={3} 
      samples={32} 
      updateFrequency={30} // Important for animated models
    >
      <primitive object={scene} />
    </AreaLightEmitter>
  )
}

How It Works

The package analyzes GLTF models with emissive materials and creates area lights that:

  1. Sample the Surface: Distributes light emission points across the mesh surface
  2. Follow Geometry: Each point emits light based on surface normals and area
  3. Calculate Realistically: Uses physically-based calculations for natural falloff
  4. Update Dynamically: Supports animated models with real-time updates

API Reference

<AreaLightEmitter>

Wraps GLTF objects to make them emit area lights.

<AreaLightEmitter
  intensity={2}          // Light intensity multiplier
  samples={32}           // Number of surface samples (higher = better quality)
  range={10}            // Maximum light range
  color="#ffffff"       // Override emission color
  updateFrequency={60}  // Updates per second for animated models
  enabled={true}        // Enable/disable the light
>
  <primitive object={gltfScene} />
</AreaLightEmitter>

Props:

  • intensity (number): Multiplier for light brightness. Default: 1
  • samples (number): Number of surface samples. Range: 4-64. Default: 32
  • range (number): Maximum light influence distance. Default: 10
  • color (string | THREE.Color): Override emissive color. Default: uses material emission
  • updateFrequency (number): Updates per second for animations. Default: 60
  • enabled (boolean): Toggle light on/off. Default: true

<AreaLightProvider>

Context provider that manages all area lights in the scene.

<AreaLightProvider manager={lightManager}>
  {/* Your scene with area lights */}
</AreaLightProvider>

useAreaLightManager()

Hook that creates and provides the area light manager.

const lightManager = useAreaLightManager()

// Access properties
lightManager.getLightCount() // Number of active lights
lightManager.getDataTexture() // GPU data texture
lightManager.update() // Manual update (called automatically)

// Listen to updates
useEffect(() => {
  return lightManager.onUpdate(() => {
    console.log('Lights updated')
  })
}, [lightManager])

useAreaLight()

Hook for creating area lights from mesh references (advanced usage).

const meshRef = useRef()
const lightManager = useAreaLightManager()
const areaLight = useAreaLight(meshRef, lightManager, {
  intensity: 2,
  samples: 16,
  enabled: true,
  updateFrequency: 30
})

Best Practices

Performance Optimization

  1. Sample Count: Balance quality vs performance

    • Low (4-16): Fast, good for small/distant objects
    • Medium (16-32): Default, good balance
    • High (32-64): Best quality, for hero objects
  2. Update Frequency: Reduce for static or slowly moving objects

    // Static objects
    <AreaLightEmitter updateFrequency={0} samples={32}>
       
    // Animated objects
    <AreaLightEmitter updateFrequency={30} samples={16}>
  3. Light Range: Smaller ranges improve performance

    <AreaLightEmitter range={5} intensity={2}>
  4. Light Count: Maximum 16 area lights per scene

Material Setup

For best visual results:

// Good material for receiving light
<meshStandardMaterial
  color="#ffffff"
  roughness={0.5}
  metalness={0}
/>

// Good emissive material
<meshStandardMaterial
  color="#ff0000"
  emissive="#ff0000"
  emissiveIntensity={2}
/>

Common Patterns

Multiple Light Sources in One Model

function MultiLightGLB() {
  const { nodes } = useGLTF('/model.glb')
  
  return (
    <>
      <AreaLightEmitter intensity={2} color="#ff0000">
        <mesh geometry={nodes.RedLight.geometry} />
      </AreaLightEmitter>
      
      <AreaLightEmitter intensity={3} color="#00ff00">
        <mesh geometry={nodes.GreenLight.geometry} />
      </AreaLightEmitter>
    </>
  )
}

Conditional Lighting

function ToggleableLight({ isOn }) {
  const { scene } = useGLTF('/lamp.glb')
  
  return (
    <AreaLightEmitter enabled={isOn} intensity={2}>
      <primitive object={scene} />
    </AreaLightEmitter>
  )
}

Light Color Animation

function AnimatedColorLight() {
  const { scene } = useGLTF('/model.glb')
  const [hue, setHue] = useState(0)
  
  useFrame((state) => {
    setHue(state.clock.elapsedTime * 50 % 360)
  })
  
  return (
    <AreaLightEmitter 
      color={`hsl(${hue}, 100%, 50%)`} 
      intensity={3}
    >
      <primitive object={scene} />
    </AreaLightEmitter>
  )
}

Troubleshooting

Common Issues

Lights Not Showing

// ❌ Wrong - Missing AreaLightProvider
<AreaLightEmitter intensity={3}>
  <primitive object={scene} />
</AreaLightEmitter>

// ✅ Correct - With AreaLightProvider
<AreaLightProvider manager={lightManager}>
  <AreaLightEmitter intensity={3}>
    <primitive object={scene} />
  </AreaLightEmitter>
</AreaLightProvider>

Performance Issues

// ❌ Too many samples for multiple lights
{lights.map(light => (
  <AreaLightEmitter samples={64} key={light.id}>
    {/* ... */}
  </AreaLightEmitter>
))}

// ✅ Balanced sample count
{lights.map(light => (
  <AreaLightEmitter samples={16} key={light.id}>
    {/* ... */}
  </AreaLightEmitter>
))}

Materials Not Receiving Light

// ❌ Using unsupported material
<meshBasicMaterial />

// ✅ Using standard material
<meshStandardMaterial />
// or
<meshPhysicalMaterial />

Debug Tips

  1. Check Light Count:

    console.log('Active lights:', lightManager.getLightCount())
  2. Verify Material Emissive:

    // Ensure your GLB has emissive materials
    const { materials } = useGLTF('/model.glb')
    console.log('Emissive:', materials.Light.emissive)
  3. Monitor Performance:

    import { Stats } from '@react-three/drei'
       
    <Canvas>
      <Stats />
      {/* Your scene */}
    </Canvas>

Technical Details

Architecture Overview

The package uses a sophisticated GPU-based lighting system:

  1. Geometry Sampling: Extracts representative points from mesh surfaces
  2. Data Texture: Packs light data into a 256x128 RGBA float texture
  3. Shader Integration: Custom GLSL chunks integrate with Three.js materials
  4. Real-time Updates: Supports dynamic meshes with configurable update rates

Limitations

  • Maximum 16 area lights per scene (GPU shader limit)
  • WebGL 2.0 recommended for best performance
  • Large meshes with many samples can impact performance
  • Only works with MeshStandardMaterial and MeshPhysicalMaterial

Performance Benchmarks

Typical performance on modern hardware:

  • 8 area lights @ 32 samples each: 60+ FPS
  • 16 area lights @ 16 samples each: 60+ FPS
  • Single light @ 64 samples: 120+ FPS

Migration Guide

From Point Lights

// Before - Three.js point light
<pointLight position={[0, 5, 0]} intensity={1} color="white" />

// After - Area light from geometry
<AreaLightEmitter intensity={1} samples={32}>
  <Box position={[0, 5, 0]} args={[2, 0.1, 2]}>
    <meshStandardMaterial emissive="white" emissiveIntensity={1} />
  </Box>
</AreaLightEmitter>

From Emissive Materials Only

// Before - Just emissive material
<mesh>
  <boxGeometry />
  <meshStandardMaterial emissive="#ff0000" emissiveIntensity={2} />
</mesh>

// After - Emissive material that casts light
<AreaLightEmitter intensity={2}>
  <mesh>
    <boxGeometry />
    <meshStandardMaterial emissive="#ff0000" emissiveIntensity={2} />
  </mesh>
</AreaLightEmitter>

Examples

Check out the /examples directory for complete working examples:

  • basic/ - Simple scene with area lights
  • More examples coming soon!

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Setup

# Clone the repo
git clone https://github.com/yourusername/r3f-gltf-area-lights.git

# Install dependencies
npm install

# Start development build
npm run dev

# Run tests
npm test

# Build for production
npm run build

Browser Support

  • ✅ Chrome/Edge 90+
  • ✅ Firefox 85+
  • ✅ Safari 14+
  • ✅ Mobile browsers with WebGL 2.0
  • ⚠️ WebGL 1.0 (limited features)

License

MIT © Vincent Duchateau