# generate-spherical-harmonics

[![npm version](https://badge.fury.io/js/generate-spherical-harmonics.svg)](https://badge.fury.io/js/generate-spherical-harmonics)
[![dependencies](https://david-dm.org/timvanscherpenzeel/generate-spherical-harmonics.svg)](https://david-dm.org/timvanscherpenzeel/generate-spherical-harmonics)
[![devDependencies](https://david-dm.org/timvanscherpenzeel/generate-spherical-harmonics/dev-status.svg)](https://david-dm.org/timvanscherpenzeel/generate-spherical-harmonics#info=devDependencies)

Generate spherical harmonics and octahedral environment maps for HDR image based lighting.

![Russel 16 | Jeff Russel: HDR Image-Based Lighting on the Web. WebGL Insights Chapter 16, https://webglinsights.github.io/downloads/WebGL-Insights-Chapter-16.pdf](/docs/octahedral.jpg?raw=true)

The library ships two binaries: [cmft](https://github.com/dariomanesku/cmft) by [Dario Manesku](https://github.com/dariomanesku) (a CLI cubemap filtering tool) and [hdr2png](https://github.com/plepers/hdr2png) by [Pierre Lepers](https://github.com/plepers) (conversion tool for radiance .hdr to png). It requires [montage](http://brewformulas.org/Montage) (toolkit for assembling images into custom mosaics) to be installed. `generate-spherical-harmonics` is almost a direct copy of the bash script shipped along [nanogl-pbr/bin/nanoglibl](https://github.com/plepers/nanogl-pbr/blob/master/bin/nanoglibl) by [Pierre Lepers](https://github.com/plepers) but implemented in Node.js.

The tool outputs multiple files though only 3 files are relevant for the end user: `env_hi.png`, `env.png` and `sh.bin`. `env_hi.png` is a high quality octant texture that serves as the main octahedral environment map. The tool generates several versions of octant textures (`level0.hdr` to `level7.hdr`) with different gloss intensity and assembles them in one single strip texture `env.png` using `montage`. `sh.bin` is constructed from the outputted spherical harmonics coefficients in `sh.c` and exports as a `UInt8Array` in order to be quickly decoded in the browser.

For details regarding the implementation of spherical harmonics for ambient lighting and interpreting the octant textures in `env.png` as a cubemap please refer to the shaders in [nanogl-pbr/glsl/includes](https://github.com/plepers/nanogl-pbr/tree/master/glsl/includes), [octahedral.shader](https://gist.github.com/pyalot/cc7c3e5f144fb825d626) and [pex-gl/pex-renderer](https://github.com/pex-gl/pex-renderer/blob/v2/glsl/OctMapUVToDir.glsl).

## Demo

[Decoding sh.bin](https://timvanscherpenzeel.github.io/generate-spherical-harmonics/)

In the `docs` folder one can find an implementation of a parser for `sh.bin` that is constructed from the `IBL.convert` implementation in [ibl.js](https://github.com/plepers/nanogl-pbr/blob/master/ibl.js) of [nanogl-pbr](https://github.com/plepers/nanogl-pbr/blob/master/bin/nanoglibl).

![Spherical harmonics visualized](/docs/spherical-harmonics.png?raw=true)

[Visualizing spherical harmonics](http://requirebin.com/?gist=plepers/79c127dcd9bd33f50ffa350afcd0cf58)

## Support

Currently the tool only works out-of-the-box on MacOS but there is no reason why it wouldn't be able to be extended to work on Linux and Windows.

## Installation

Make sure you have [Node.js](http://nodejs.org/) installed.

```sh
  npm install
```

```sh
  node ./bin/generate-spherical-harmonics.js -i ./input/studio022-1024x512.hdr -o ./output
```

## Development

```sh
  npm start

  npm run lint

  npm run deploy
```

## Flags

### Required

	-i, --input [example: ./input/studio022-1024x512.hdr] [required]
	-o, --output [example: ./output] [required]

## Resources
- [HDR Image-Based Lighting on the Web](https://webglinsights.github.io/downloads/WebGL-Insights-Chapter-16.pdf)
- [Image-Based Lighting](http://ict.usc.edu/pubs/Image-Based%20Lighting.pdf)
- [RGBM color encoding](https://graphicrants.blogspot.nl/2009/04/rgbm-color-encoding.html)
- [Pragmatic PBR HDR](http://marcinignac.com/blog/pragmatic-pbr-hdr)
- [An Efficient Representation for Irradiance Environment Maps](http://graphics.stanford.edu/papers/envmap/)
- [A Survey of Efficient Representations for Independent Unit Vectors](http://jcgt.org/published/0003/02/01/paper.pdf)
- [WebGL-based Prefiltered Mipmaped Radiance Environment Map (PMREM) generator](https://github.com/mrdoob/three.js/issues/7402)
- [Advanced WebGL - Part 3: Irradiance Environment Map](http://codeflow.org/entries/2011/apr/18/advanced-webgl-part-3-irradiance-environment-map/)
- [Real-Time Computation of Dynamic Irradiance Environment Maps](https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter10.html)

A very good resource to find free HDRI's is [https://hdrihaven.com/](https://hdrihaven.com/).

## Licence

My work is released under the [GPL-2.0 licence](https://raw.githubusercontent.com/TimvanScherpenzeel/generate-spherical-harmonics/master/LICENSE) in order to be in line with the licence agreement of [nanogl-pbr](https://github.com/plepers/nanogl-pbr/blob/master/package.json).

This repository distributes multiple binary tools for Mac.

- [cmft](https://raw.githubusercontent.com/dariomanesku/cmft/master/LICENSE)
- [hdr2png](https://github.com/plepers/hdr2png)
