tinyusdz icon indicating copy to clipboard operation
tinyusdz copied to clipboard

[Proposal] Spectral color support

Open syoyo opened this issue 2 years ago • 0 comments

USD itself does not support native spectral color type.

It'd be nice to have spectral color(and also other color value encoding(e.g. XYZ)) for physcally-based spectral rendering.

There are some directions to support spectral color

  • Use namespace: Backward compatible way ⭐
  • Introduce dedicated type for spectral color
  • Define spectral color as customData or introduce SpectralColorAPI Prim API schema
  • Use external file(e.g. JSON) and reference it

Backward compatible way(preferred way at the moment)

Use namespace(suffix) spectrum and wavelength.

color3f[] myred = (1.0, 0.0, 0.0) # Use this for existing RGB-based renderer and preview color for spectral renderer 
float[] myred:spectrum = [0.1, 0.2, 0.8]
float[] myred:wavelength = [550, 600, 700]

default unit in wavelegnth is [nm](nanometer), since most computer graphics tool with spectral color support uses nanometer(e.g. PBRT). On the contrary, most(?) optical software uses [um](micrometer) by default .

Unit can be specified in Stage metadatum or Attiribute's metadata

#usda 1.0
( wavelengthUnitPerNanometer = 1000 # for [um] )

float[] myred:wavelength = [0.55, 0.6, 0.7] ( wavelengthUnitPerNanometer = 1000 )

native support with new syntax

We can reuse TimeSamples syntax describe spectral value.

It'd be something like...

double spectral:myred = {550: 0.1, 600: 0.4, 700: 1.0}
double spectral:myred.timeSamples = {0: {550: 0.1, 600: 0.4, 700: 1.0}, 1: {...}}

Disadvantace: Need a custom support in DCC tool(e.g. Blender)

as CustomData

color3f myred = (1.0, 0.3, 0.1) ( customData = { dictionary spectral = { double[] wavelengths = [...], double[] values = [...] } } )

Advantage: its backward compatible. we can use native color3f value as an preview RGB color in spectral rendering. Disadvantace: A bit tricky

as new API Schema

def Material ( prepend apiSchemas = ["SpectralColorAPI"] ) {
  double[] spectral:myred:wavelengths = [550, 600, 700]
  double[] spectral:myred:values = [0.1, 0.4, 1.0]
  color3f spectal:myred:displayColor = (1.0, 0.4, 0.1)
}

Advantage: its backward compatible. we can use :displayColor suffix variable as an preview RGB color in spectral rendering. Disadvantage: Still a bit tricky?

Use external file

def Material () {
  asset spectral:myred:file = @blackbody.spd@
  token spectral:myred:sourceColorSpace = "spectral"
}

Advantage: Simple

TODO

  • [ ] Spectral texture map asset support(e.g. EXR multichannel), sequence of images(wavelength in its filename)
    • EXR for spectral format: https://jcgt.org/published/0010/03/01/
    • TIFF multichannel?
  • [ ] Text wavelength data file format
    • [x] CSV: This should be simple. wavelength, value per line
    • [ ] JSON

syoyo avatar Dec 10 '22 13:12 syoyo