LightsprintSDK 2021.08.08
rr::RRMaterial Struct Reference

#include <RRMaterial.h>

Inheritance diagram for rr::RRMaterial:
rr::RRUniformlyAllocatedNonCopyable rr::RRUniformlyAllocated rr::RRPointMaterial

Classes

struct  Property
 
struct  Response
 

Public Types

enum  UniformTextureAction {
  UTA_KEEP ,
  UTA_DELETE ,
  UTA_NULL
}
 
enum  SpecularModel {
  PHONG = 0 ,
  BLINN_PHONG = 1 ,
  TORRANCE_SPARROW = 2 ,
  BLINN_TORRANCE_SPARROW = 3
}
 
enum  BrdfType {
  BRDF_NONE = 0 ,
  BRDF_DIFFUSE = 1 ,
  BRDF_SPECULAR = 2 ,
  BRDF_TRANSMIT = 4 ,
  BRDF_ALL = 7 ,
  NUM_BRDFS = 3
}
 

Public Member Functions

 RRMaterial ()
 
void copyFrom (const RRMaterial &from)
 
bool operator== (const RRMaterial &a) const
 
void reset (bool twoSided)
 
void updateColorsFromTextures (const RRColorSpace *colorSpace, UniformTextureAction uniformTextureAction, bool updateEvenFromStubs)
 
unsigned createTexturesFromColors ()
 
void updateKeyingFromTransmittance ()
 
void updateSideBitsFromColors ()
 
void updateBumpMapType ()
 
bool validate (RRReal redistributedPhotonsLimit=0.98f)
 
void convertFromLinear (const RRColorSpace *colorSpace)
 
void convertToLinear (const RRColorSpace *colorSpace)
 
bool needsBlending () const
 
 ~RRMaterial ()
 
void getResponse (Response &response, BrdfType type=BRDF_ALL) const
 
void sampleResponse (Response &response, const RRVec3 &randomness, BrdfType type=BRDF_ALL) const
 
bool load (const RRString &filename, RRFileLocator *textureLocator)
 
bool save (const RRString &filename) const
 
- Public Member Functions inherited from rr::RRUniformlyAllocated
void * operator new (std::size_t n)
 
void * operator new[] (std::size_t n)
 
void operator delete (void *p, std::size_t n)
 
void operator delete[] (void *p, std::size_t n)
 

Public Attributes

RRSideBits sideBits [2]
 
Property diffuseReflectance
 
Property diffuseEmittance
 
Property specularReflectance
 
SpecularModel specularModel
 
RRReal specularShininess
 
Property specularTransmittance
 
bool specularTransmittanceInAlpha
 
bool specularTransmittanceKeyed
 
RRReal specularTransmittanceThreshold
 
bool specularTransmittanceMapInverted
 
bool specularTransmittanceBackground
 
RRReal refractionIndex
 
Property bumpMap
 
bool bumpMapTypeHeight
 
Property lightmap
 
unsigned minimalQualityForPointMaterials
 
RRString name
 
RRBufferpreview
 

Additional Inherited Members

- Protected Member Functions inherited from rr::RRUniformlyAllocatedNonCopyable
 RRUniformlyAllocatedNonCopyable ()
 
 ~RRUniformlyAllocatedNonCopyable ()
 

Detailed Description

Description of material properties of a surface.

It is a set of common material properties relevant for global illumination solver. It is not necessarily complete material description, custom renderers can use additional custom information stored elsewhere.

Textures are owned and deleted by material. To change texture on the fly, delete old one before assigning new one.

Member Enumeration Documentation

◆ UniformTextureAction

What to do with completely uniform textures (single color).

Enumerator
UTA_KEEP 

Keep uniform texture.

UTA_DELETE 

Delete uniform texture.

UTA_NULL 

nullptr pointer to uniform texture, but don't delete it.

◆ SpecularModel

Enumerator
PHONG 

as in http://en.wikipedia.org/wiki/Phong_shading (shininess in 1..inf)

BLINN_PHONG 

as in http://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model (shininess in 1..inf)

TORRANCE_SPARROW 

as in Zara J.: Pocitacova grafika (1992) (roughness in 0..1)

BLINN_TORRANCE_SPARROW 

as in http://www.siggraph.org/education/materials/HyperGraph/illumin/specular_highlights/blinn_model_for_specular_reflect_1.htm (roughness in 0..1)

◆ BrdfType

Enumerator
BRDF_NONE 
BRDF_DIFFUSE 
BRDF_SPECULAR 
BRDF_TRANSMIT 
BRDF_ALL 
NUM_BRDFS 

Constructor & Destructor Documentation

◆ RRMaterial()

rr::RRMaterial::RRMaterial ( )

Default constructor, initializes only pointers in material, call reset() to initialize the rest of data.

◆ ~RRMaterial()

rr::RRMaterial::~RRMaterial ( )

Deletes textures (yes, textures are owned by RRMaterial).

Member Function Documentation

◆ copyFrom()

void rr::RRMaterial::copyFrom ( const RRMaterial from)

Copies given material to this material.

Don't call it from multiple threads at the same time, it is thread unsafe under very rare circumstances (that's why we didn't make it "operator =", people expect safety in assignment).

◆ operator==()

bool rr::RRMaterial::operator== ( const RRMaterial a) const

Returns true if both materials look the same (and use the same textures).

◆ reset()

void rr::RRMaterial::reset ( bool  twoSided)

Resets material to fully diffuse gray (50% reflected, 50% absorbed).

Also behaviour of both front and back side (sideBits) is reset to defaults.

  • Back side of 1-sided material is not rendered and it does not emit or reflect light.
  • Back side of 1-sided material stops light: Imagine interior with 1-sided walls. Skylight should not get in through back sides od walls. Photons that hit back side are removed from simulation.
  • However, back side of 1-sided material allows transmittance and refraction: Imagine previous example with alpha-keyed window in 1-sided wall. Skylight should get through window in both directions. It gets through according to material transmittance and refraction index.
  • Back side of 1-sided material does not emit or reflect light.
  • Sides of 2-sided material behave nearly identically, only back side doesn't have diffuse reflection.

Sidedness of the most common materials:

  • glass sphere or any other closed object should be 1-sided, light refracts differently when front and back sides are hit
  • glass window should be made of single 2-sided face, we simulate multiple bounces between virtual front and back sides, light refracts identically from both sides

Illumination produced by updateLightmap[s]() for faces with 2-sided material depends on solver. Realtime solvers sum illumination of both sides, offline solver outputs front side illumination. (Changing offline solver to work like realtime one would probably create more confusion than it would fix, it's not clear how directional lightmaps would look etc.)

◆ updateColorsFromTextures()

void rr::RRMaterial::updateColorsFromTextures ( const RRColorSpace colorSpace,
UniformTextureAction  uniformTextureAction,
bool  updateEvenFromStubs 
)

Gathers information from textures, updates color for all Properties with texture. Updates also minimalQualityForPointMaterials.

Parameters
colorSpaceTextures are expected in custom scale of this colorSpace. Average colors are computed in the same scale. Function would work even with colorSpace=nullptr, and it would be faster, but computed averages would be slightly incorrect, and minimalQualityForPointMaterials would be much lower, slowing down lightmap baking with unnecessary texture lookups.
uniformTextureActionWhat to do with textures of constant color. Removing them may make rendering/calculations faster.
updateEvenFromStubsTrue=updates color even if texture is a stub. Pass true if you don't know color; stub texture is also wrong, but at least they will match. Pass false if you know color and don't want it to be overwritten by stub.

◆ createTexturesFromColors()

unsigned rr::RRMaterial::createTexturesFromColors ( )

Creates stub 1x1 textures for properties without texture.

LightsprintCore fully supports materials without textures, and working with flat colors instead of textures is faster. But in case of need, this function would create 1x1 textures out of material colors. Don't call it unless you know what you are doing, risk of reduced performance.

Returns
Number of textures created.

◆ updateKeyingFromTransmittance()

void rr::RRMaterial::updateKeyingFromTransmittance ( )

Updates specularTransmittanceKeyed.

Looks at specularTransmittance and tries to guess what user expects when realtime rendering, 1-bit keying or smooth blending. If you know what user prefers, set or clear specularTransmittanceKeyed yourself instead of calling this function.

◆ updateSideBitsFromColors()

void rr::RRMaterial::updateSideBitsFromColors ( )

Updates sideBits, clears bits with relevant color black. This may make rendering faster.

◆ updateBumpMapType()

void rr::RRMaterial::updateBumpMapType ( )

Updates bumpMapTypeHeight, tries to guess what type it is by looking at contents of bumpMap.texture.

◆ validate()

bool rr::RRMaterial::validate ( RRReal  redistributedPhotonsLimit = 0.98f)

Changes material's colorLinear values to closest physically valid ones. Returns whether changes were made.

In physical scale, diffuse+specular+transmission must be below 1 (real world materials are below 0.98) and this function enforces it. We call it automatically from solver. In custom scale, real world materials have diffuse+specular+transmission higher (up to roughly 1.7), but we don't enforce this at all, color stays unchanged.

◆ convertFromLinear()

void rr::RRMaterial::convertFromLinear ( const RRColorSpace colorSpace)

Converts material properties from physical to custom scale (colorLinear -> color).

◆ convertToLinear()

void rr::RRMaterial::convertToLinear ( const RRColorSpace colorSpace)

Converts material properties from custom to physical scale (color -> colorLinear).

◆ needsBlending()

bool rr::RRMaterial::needsBlending ( ) const

True if renderer needs blending to render the material.

◆ getResponse()

void rr::RRMaterial::getResponse ( Response response,
BrdfType  type = BRDF_ALL 
) const

Calculates color of light exiting surface in response to incoming white light (dirIn, dirNormal, dirOut -> colorOut)

◆ sampleResponse()

void rr::RRMaterial::sampleResponse ( Response response,
const RRVec3 randomness,
BrdfType  type = BRDF_ALL 
) const

Calculates direction and color of light exiting surface in response to incoming white light (dirNormal, dirOut -> dirIn, colorOut, pdf, brdfType.

◆ load()

bool rr::RRMaterial::load ( const RRString filename,
RRFileLocator textureLocator 
)

Loads first material from file, returns true on success.

◆ save()

bool rr::RRMaterial::save ( const RRString filename) const

Saves material to file, returns true on success.

Member Data Documentation

◆ sideBits

RRSideBits rr::RRMaterial::sideBits[2]

Defines material behaviour for front (sideBits[0]) and back (sideBits[1]) side.

◆ diffuseReflectance

Property rr::RRMaterial::diffuseReflectance

Fraction of energy that is reflected in diffuse reflection (each channel separately).

◆ diffuseEmittance

Property rr::RRMaterial::diffuseEmittance

Radiant emittance in watts per square meter (each channel separately). (Adapters usually create materials in sRGB scale, so that this is screen color.)

◆ specularReflectance

Property rr::RRMaterial::specularReflectance

Fraction of energy that is reflected in specular reflection (each channel separately).

When texture is set, its color is used as a specular reflectance color, and its alpha is used to modulate material's specularShininess/roughness. For alpha=1 there is no change in shininess/roughness. As alpha goes down to 0, shininess/roughness also goes down to its minimal value (1 or 0). Whether it is rough or shiny depends on specularModel. So in case of need, you can invert effect of alpha channel by changing specularModel.

◆ specularModel

SpecularModel rr::RRMaterial::specularModel

Selects what model / distribution function to use for specular reflectance.

◆ specularShininess

RRReal rr::RRMaterial::specularShininess

Interpreted as shininess (0..inf) or roughness (0..1), according to specularModel.

◆ specularTransmittance

Property rr::RRMaterial::specularTransmittance

Fraction of energy that continues through surface (with direction possibly changed by refraction).

Whether light gets through translucent object, e.g. sphere, it depends on material sphere is made of

  • standard 2sided material -> ray gets through interacting with both front and back faces, creating correct caustics
  • standard 1sided material -> ray is deleted when it hits back side of 1sided face
  • 1sided material with sideBits[1].catchFrom=1 -> ray gets through, interacting with front face, skipping back face, creating incorrect caustics

Note that higher transmittance does not decrease reflectance and emittance, they are independent properties. There's single exception to this rule: [#39] when reading transmittance from texture, diffuseReflectance is reduced on the fly (multiplied by 1-specularTransmittance), because existing datasets expect it. So e.g. billboard cloud material has cloud shape controlled only by transparency texture, diffuse color can be uniform white.

Material with transparency stored in alpha of diffuse texture is initialized like

virtual RRBuffer * createReference()=0
Creates reference to the same buffer. Both buffer and reference must be deleted (in any order).
static RRBuffer * load(const RRString &filename, const char *cubeSideName[6]=nullptr, const RRFileLocator *fileLocator=nullptr)
Loads buffer from disk to system memory.
RRBuffer * texture
Material property expressed as a texture or video.
Definition RRMaterial.h:108
Property specularTransmittance
Fraction of energy that continues through surface (with direction possibly changed by refraction).
Definition RRMaterial.h:253
bool specularTransmittanceInAlpha
Whether specular transmittance is in specularTransmittance.texture's Alpha (0=transparent) or in RGB ...
Definition RRMaterial.h:255
Property diffuseReflectance
Fraction of energy that is reflected in diffuse reflection (each channel separately).
Definition RRMaterial.h:216

◆ specularTransmittanceInAlpha

bool rr::RRMaterial::specularTransmittanceInAlpha

Whether specular transmittance is in specularTransmittance.texture's Alpha (0=transparent) or in RGB (1,1,1=transparent). It is irrelevant when specularTransmittance.texture==nullptr.

◆ specularTransmittanceKeyed

bool rr::RRMaterial::specularTransmittanceKeyed

Whether 1-bit alpha keying is used instead of smooth alpha blending in realtime render. 1-bit alpha keying is faster but removes semi-translucency. Smooth alpha blend renders semi-translucency, but artifacts appear on meshes where semi-translucent faces overlap.

◆ specularTransmittanceThreshold

RRReal rr::RRMaterial::specularTransmittanceThreshold

If specularTransmittanceKeyed, transmittance in 0..1 range is tested against this threshold. Values above threshold are rounded to 1 (transparent), values below threshold are rounded to 0 (opaque).

◆ specularTransmittanceMapInverted

bool rr::RRMaterial::specularTransmittanceMapInverted

Whether specular transmittance map is inverted. True = values read from map should be inverted before use. This inversion is implemented in getPointMaterial() and in shaders.

◆ specularTransmittanceBackground

bool rr::RRMaterial::specularTransmittanceBackground

If set, pathtracer renders material with color of environment, so it becomes kind of invisible, yet still receiving illumination and shadows. It's typically used on a plane under pathtraced car, surrounded only by environment map; results look like car casting shadows on environment.

◆ refractionIndex

RRReal rr::RRMaterial::refractionIndex

For 1-sided faces, it is refractive index of matter behind surface divided by refractive index of matter in front of surface (1-sided surfaces are treated as volume boundaries, this index tells what happens when light leaves matter in front of boundary and enters matter behind). For 2-sided faces, it is refractive index of matter inside thin layer divided by refractive index of matter around (2-sided surfaces are treated as thin layers made of different matter, renderer accounts for multiple front/back interreflection). Real world surfaces have index from 0.25 to 4. Examples.

◆ bumpMap

Property rr::RRMaterial::bumpMap

Optional bump map modulates surface normals.

RGB maps are interpreted as normal maps, grayscale maps (or the same map as diffuseReflectance.texture, or c@pture) as heightmaps. bumpMap.color.x is used as a multiplier of normal steepness, y multiplies height in parallax mapping, defaults are 1, negative values are legal.

◆ bumpMapTypeHeight

bool rr::RRMaterial::bumpMapTypeHeight

True = bump map is height/displacement map, false = bump map is normal map.

◆ lightmap

Property rr::RRMaterial::lightmap

Optional lightmaps/ambient maps.

lightmap.texcoord

  • Texcoord channel with unwrap for lightmaps/ambient maps. To be used in RRMesh::getTriangleMapping().
  • Note that for proper lighting, unwrap must have all coordinates in <0..1> range and triangles must not overlap. Unwrap can be imported or automatically generated by RRObjects::buildUnwrap().

lightmap.color

  • Not used. Keep it set to 0.5.

lightmap.texture

  • Secondary location, it is usually nullptr, because we store lightmaps and ambient maps in separated layers in RRObjectIllumination. However, some fileformats store them in ambient or lightmap slot in material. We use lightmap.texture only for smoother import from / export to such fileformats. After import, we move lightmaps from RRMaterial to lightmap layer in RRObjectIllumination.

◆ minimalQualityForPointMaterials

unsigned rr::RRMaterial::minimalQualityForPointMaterials

Hint/optimization for offline solver, material tells solver to use RRObject::getPointMaterial() if desired lighting quality is equal or higher than this number. Inited to UINT_MAX (=never use point materials), automatically adjusted by updateColorsFromTextures().

Warning: If you don't call updateColorsFromTextures(), make sure you adjust minimalQualityForPointMaterials on per-material basis. Keeping UINT_MAX would make keyed objects cast solid shadows to lightmaps. Setting always 0 would make lightmap build very slow.

Not used by realtime solver; you don't have to update it each time your realtime app changes texture.

◆ name

RRString rr::RRMaterial::name

Optional name of material.

If name starts with "water" and static normal map is set, realtime renderer animates mapping to simulate flow of waves.

◆ preview

RRBuffer* rr::RRMaterial::preview

Optional image of material, for use e.g. by material library. It is owned by material, deleted in dtor. Not saved to .rrmaterial.