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-fake-lighting

v1.1.2

Published

A fake lighting system for React Three Fiber that allows GLTF models to emit and receive custom lighting

Downloads

4

Readme

r3f-fake-lighting

A fake lighting system for React Three Fiber that allows GLTF models to emit and receive custom lighting without using Three.js built-in lights. Features realistic shape-aware area lighting where light follows the actual geometry of emissive objects.

Features

  • 🔦 Custom shader-based lighting system
  • 🎨 GLTF models can emit fake light
  • 🎭 GLTF models can receive fake light with proper shading
  • ⚡ Supports up to 32 point lights or 8 area lights
  • 🎬 Full animation support for both emitters and receivers
  • 🎯 Efficient performance with custom shaders
  • 🔧 Easy to integrate with existing R3F projects
  • NEW: Shape-aware area lighting - light emission follows object geometry

Installation

npm install r3f-fake-lighting
# or
yarn add r3f-fake-lighting
# or
pnpm add r3f-fake-lighting

Quick Start

import React, { Suspense } from 'react'
import { Canvas } from '@react-three/fiber'
import { OrbitControls } from '@react-three/drei'
import {
  useLightManager,
  LightManagerUpdater,
  GLTFLightEmitter,
  GLTFLightReceiver
} from 'r3f-fake-lighting'

function Scene() {
  const lightManager = useLightManager()

  return (
    <>
      {/* Required: Updates all materials each frame */}
      <LightManagerUpdater lightManager={lightManager} />
      
      <OrbitControls />
      
      {/* GLTF model that emits light */}
      <Suspense fallback={null}>
        <GLTFLightEmitter 
          url="/models/light-source.glb"
          position={[0, 2, 0]}
          color="#ff0000"
          intensity={3}
          range={10}
          lightManager={lightManager}
          useAreaLight={true} // Enable shape-aware lighting
        />
      </Suspense>
      
      {/* GLTF model that receives light */}
      <Suspense fallback={null}>
        <GLTFLightReceiver 
          url="/models/scene.glb"
          position={[0, 0, 0]}
          lightManager={lightManager}
        />
      </Suspense>
    </>
  )
}

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

Shape-Aware Area Lighting

The library now supports realistic area lighting where light emission follows the actual shape of objects:

<GLTFLightEmitter
  url="/models/neon-sign.glb"
  lightManager={lightManager}
  useAreaLight={true}      // Enable area lighting (default: true)
  sampleCount={16}         // Number of surface samples (default: 16)
  useLegacyPointLight={false} // Force point light mode if needed
/>

How It Works

  • Surface Sampling: The system samples multiple points across the emissive surface
  • Geometry-Aware: Light emission follows the object's actual shape, not just a point
  • Realistic Falloff: Uses proper area light calculations for natural light distribution
  • Dynamic Updates: Supports animated objects with real-time surface updates

Area Light Benefits

  1. Realistic Emission: Light wraps around object contours naturally
  2. No Hotspots: Even distribution across flat surfaces like screens
  3. Shape Preservation: Long or curved objects emit light along their entire surface
  4. Soft Shadows: Natural light gradients based on surface proximity

API Reference

useLightManager()

Hook that creates and returns a light manager instance. Use this once at the top level of your scene.

const lightManager = useLightManager()

<LightManagerUpdater>

Required component that updates all registered materials with light data each frame. Must be placed inside the Canvas.

Props:

  • lightManager (required): The light manager instance

<GLTFLightEmitter>

Component for GLTF models that emit fake light.

Props:

  • url (required): Path to the GLTF file
  • position: Position in 3D space (default: [0, 0, 0])
  • color: Light color (default: '#ffffff')
  • intensity: Light intensity (default: 1)
  • range: Light range/falloff distance (default: 10)
  • lightManager (required): The light manager instance
  • animationIndex: Which animation to play (default: 0)
  • fallbackComponent: Component to render if GLTF fails to load
  • useAreaLight: Enable shape-aware area lighting (default: true)
  • sampleCount: Number of surface samples for area lights (default: 16)
  • useLegacyPointLight: Force point light mode (default: false)

<GLTFLightReceiver>

Component for GLTF models that receive fake light.

Props:

  • url (required): Path to the GLTF file
  • position: Position in 3D space (default: [0, 0, 0])
  • lightManager (required): The light manager instance
  • animationIndex: Which animation to play (default: 0)
  • fallbackComponent: Component to render if GLTF fails to load

<MockLight>

Invisible light source without any visual representation.

Props:

  • position (required): Position in 3D space
  • color (required): Light color
  • intensity (required): Light intensity
  • range (required): Light range
  • lightManager (required): The light manager instance

<FakeLightReceiverMaterialWrapper>

A React component wrapper that simplifies using the fake light receiver material with automatic prop handling and ref management.

Props:

  • color: Material color (string or THREE.Color, default: '#ffffff')
  • roughness: Surface roughness (0-1, default: 0.5)
  • metalness: Metallic appearance (0-1, default: 0.0)
  • map: Diffuse texture (THREE.Texture, optional)
  • normalMap: Normal texture (THREE.Texture, optional)
  • roughnessMap: Roughness texture (THREE.Texture, optional)
  • metalnessMap: Metalness texture (THREE.Texture, optional)
  • ref: Ref callback or object to access the material instance
import { FakeLightReceiverMaterialWrapper } from 'r3f-fake-lighting'

<Box>
  <FakeLightReceiverMaterialWrapper
    color="#cccccc"
    roughness={0.3}
    metalness={0.1}
    ref={(mat) => mat && lightManager.registerMaterial(mat)}
  />
</Box>

<fakeLightReceiverMaterial>

The raw shader material that can be used directly in JSX (requires manual uniform setting).

<Box>
  <fakeLightReceiverMaterial 
    ref={(mat) => {
      if (mat) {
        mat.uniforms.color.value = new THREE.Color('#ffffff')
        mat.uniforms.roughness.value = 0.5
        mat.uniforms.metalness.value = 0.0
        lightManager.registerMaterial(mat)
      }
    }}
  />
</Box>

Note: For most use cases, prefer FakeLightReceiverMaterialWrapper as it handles prop updates automatically.

Advanced Usage

Manual Light Management

You can also manually control lights using the light manager API:

// Add a point light
lightManager.addLight(id, position, color, intensity, range)

// Add an area light
lightManager.addAreaLight(id, surfaceSamples, color, intensity, range)

// Update a light
lightManager.updateLight(id, { position, color, intensity, range })

// Remove a light
lightManager.removeLight(id)

// Register a material to receive lighting
lightManager.registerMaterial(material)

// Unregister a material
lightManager.unregisterMaterial(material)

Custom Materials

The package exports FakeLightReceiverMaterial which you can extend or modify:

import { FakeLightReceiverMaterial } from 'r3f-fake-lighting'

// Create a custom version
const CustomMaterial = shaderMaterial(
  { ...FakeLightReceiverMaterial.uniforms },
  // Your vertex shader
  // Your fragment shader
)

Geometry Sampling Utilities

For custom implementations:

import { sampleMeshSurface, extractEmissiveMeshes } from 'r3f-fake-lighting'

// Sample points on a mesh surface
const samples = sampleMeshSurface(mesh, 16)

// Extract all emissive meshes from a scene
const emissiveMeshes = extractEmissiveMeshes(scene)

Performance Considerations

  • Area Lights: Limited to 8 simultaneous area lights for performance
  • Point Lights: Supports up to 32 point lights
  • Surface Samples: More samples = better quality but higher GPU cost
  • Materials automatically clean up when disposed
  • Use Suspense boundaries for GLTF loading
  • Area lights update every frame for animated objects

Examples & Recipes

  • Check the /examples directory for complete working examples
  • See RECIPES.md for common patterns and solutions
  • Try the area-lighting example to see shape-aware lighting in action

TypeScript

This package includes TypeScript definitions. Import types directly:

import type { 
  LightManager, 
  Light, 
  AreaLight, 
  SurfaceSample,
  GLTFLightReceiverProps 
} from 'r3f-fake-lighting'

License

MIT