1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0030700: Visualization, TKOpenGl - support PBR Metallic-Roughness shading model

Metallic-Roughness shading model Graphic3d_TOSM_PBR has been implemented.
New materials descriptors Graphic3d_PBRMaterial have been added to Graphic3d_MaterialAspect.
PBR shading model requires OpenGL 3.0+ or OpenGL ES 3.0+ hardware.
Environment cubemap is expected to be provided for realistic look of metallic materials.

occLight_IsHeadlight() now returns bool instead of int.
Avoid using lowp for enumerations to workaround occLight_IsHeadlight()
ignorance on Adreno 308 caused by some GLSL optimizator bugs.

OpenGl_Texture::EstimatedDataSize() - fixed estimation for Cubemap textures.
OpenGl_Sampler::applySamplerParams() - fixed uninitialized GL_TEXTURE_WRAP_R in case of GL_TEXTURE_CUBE_MAP target.
This commit is contained in:
iko
2019-06-20 09:53:20 +03:00
committed by apn
parent f4a7308f61
commit 67312b7991
75 changed files with 7204 additions and 272 deletions

View File

@@ -110,6 +110,8 @@ Graphic3d_NameOfTexture2D.hxx
Graphic3d_NameOfTextureEnv.hxx
Graphic3d_NameOfTexturePlane.hxx
Graphic3d_NMapOfTransient.hxx
Graphic3d_PBRMaterial.cxx
Graphic3d_PBRMaterial.hxx
Graphic3d_PolygonOffset.cxx
Graphic3d_PolygonOffset.hxx
Graphic3d_PriorityDefinitionError.hxx

View File

@@ -15,6 +15,8 @@
#include <Graphic3d_BSDF.hxx>
#include <Graphic3d_PBRMaterial.hxx>
#include <algorithm>
// =======================================================================
@@ -63,6 +65,7 @@ Graphic3d_Fresnel Graphic3d_Fresnel::CreateConductor (const Graphic3d_Vec3& theR
// purpose :
// =======================================================================
Graphic3d_BSDF::Graphic3d_BSDF()
: Ks (Graphic3d_Vec3 (0.f), 1.f)
{
FresnelCoat = Graphic3d_Fresnel::CreateConstant (0.f);
FresnelBase = Graphic3d_Fresnel::CreateConstant (1.f);
@@ -189,4 +192,21 @@ Graphic3d_BSDF Graphic3d_BSDF::CreateGlass (const Graphic3d_Vec3& theWeight,
theAbsorptionCoeff);
return aBSDF;
}
}
// =======================================================================
// function : CreateMetallicRoughness
// purpose :
// =======================================================================
Graphic3d_BSDF Graphic3d_BSDF::CreateMetallicRoughness (const Graphic3d_PBRMaterial& thePbr)
{
const Graphic3d_Vec3 aDiff = (Graphic3d_Vec3 )thePbr.Color().GetRGB() * thePbr.Alpha();
const Standard_ShortReal aRougness2 = thePbr.NormalizedRoughness() * thePbr.NormalizedRoughness();
Graphic3d_BSDF aBsdf;
aBsdf.FresnelBase = Graphic3d_Fresnel::CreateSchlick (aDiff * thePbr.Metallic());
aBsdf.Ks.SetValues (Graphic3d_Vec3 (thePbr.Alpha()), aRougness2);
aBsdf.Kt = Graphic3d_Vec3 (1.0f - thePbr.Alpha());
aBsdf.Kd = aDiff * (1.0f - thePbr.Metallic());
return aBsdf;
}

View File

@@ -19,6 +19,8 @@
#include <Graphic3d_Vec3.hxx>
#include <Graphic3d_Vec4.hxx>
class Graphic3d_PBRMaterial;
//! Type of the Fresnel model.
enum Graphic3d_FresnelModel
{
@@ -169,6 +171,9 @@ public:
const Standard_ShortReal theAbsorptionCoeff,
const Standard_ShortReal theRefractionIndex);
//! Creates BSDF from PBR metallic-roughness material.
static Standard_EXPORT Graphic3d_BSDF CreateMetallicRoughness (const Graphic3d_PBRMaterial& thePbr);
public:
//! Creates uninitialized BSDF.

View File

@@ -378,7 +378,23 @@ public:
virtual Handle(Graphic3d_CubeMap) BackgroundCubeMap() const = 0;
//! Sets environment cubemap as background.
virtual void SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap) = 0;
//! @param theCubeMap cubemap source to be set as background
//! @param theToUpdatePBREnv defines whether IBL maps will be generated or not (see 'GeneratePBREnvironment')
virtual void SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap,
Standard_Boolean theToUpdatePBREnv = Standard_True) = 0;
//! Generates PBR specular probe and irradiance map
//! in order to provide environment indirect illumination in PBR shading model (Image Based Lighting).
//! The source of environment data is background cubemap.
//! If PBR is unavailable it does nothing.
//! If PBR is available but there is no cubemap being set to background it clears all IBL maps (see 'ClearPBREnvironment').
virtual void GeneratePBREnvironment() = 0;
//! Fills PBR specular probe and irradiance map with white color.
//! So that environment indirect illumination will be constant
//! and will be fully controlled by ambient light sources.
//! If PBR is unavailable it does nothing.
virtual void ClearPBREnvironment() = 0;
//! Returns environment texture set for the view.
virtual Handle(Graphic3d_TextureEnv) TextureEnv() const = 0;

View File

@@ -26,21 +26,25 @@ class Graphic3d_CubeMap : public Graphic3d_TextureMap
public:
//! Constructor defining loading cubemap from file.
Graphic3d_CubeMap (const TCollection_AsciiString& theFileName) :
Graphic3d_CubeMap (const TCollection_AsciiString& theFileName,
Standard_Boolean theToGenerateMipmaps = Standard_False) :
Graphic3d_TextureMap (theFileName, Graphic3d_TOT_CUBEMAP),
myCurrentSide (Graphic3d_CMS_POS_X),
myEndIsReached (false),
myIsTopDown (true),
myZIsInverted (false)
myZIsInverted (false),
myHasMipmaps (theToGenerateMipmaps)
{}
//! Constructor defining direct cubemap initialization from PixMap.
Graphic3d_CubeMap (const Handle(Image_PixMap)& thePixmap = Handle(Image_PixMap)()) :
Graphic3d_CubeMap (const Handle(Image_PixMap)& thePixmap = Handle(Image_PixMap)(),
Standard_Boolean theToGenerateMipmaps = Standard_False) :
Graphic3d_TextureMap (thePixmap, Graphic3d_TOT_CUBEMAP),
myCurrentSide (Graphic3d_CMS_POS_X),
myEndIsReached (false),
myIsTopDown (true),
myZIsInverted (false)
myZIsInverted (false),
myHasMipmaps (theToGenerateMipmaps)
{}
//! Returns whether the iterator has reached the end (true if it hasn't).
@@ -81,6 +85,12 @@ public:
return myZIsInverted;
}
//! Returns whether mipmaps of cubemap will be generated or not.
Standard_Boolean HasMipmaps() const { return myHasMipmaps; }
//! Sets whether to generate mipmaps of cubemap or not.
void SetMipmapsGeneration (Standard_Boolean theToGenerateMipmaps) { myHasMipmaps = theToGenerateMipmaps; }
//! Returns PixMap containing current side of cubemap.
//! Returns null handle if current side is invalid.
virtual Handle(Image_PixMap) Value() = 0;
@@ -102,6 +112,7 @@ protected:
Standard_Boolean myEndIsReached; //!< Indicates whether end of iteration has been reached or hasn't
Standard_Boolean myIsTopDown; //!< Stores rows's memory layout
Standard_Boolean myZIsInverted; //!< Indicates whether Z axis is inverted that allows to synchronize vertical flip of cubemap
Standard_Boolean myHasMipmaps; //!< Indicates whether mipmaps of cubemap will be generated or not
};

View File

@@ -25,6 +25,7 @@ namespace
{
const char* StringName;
Graphic3d_BSDF BSDF;
Graphic3d_PBRMaterial PBRMaterial;
Quantity_Color Colors[Graphic3d_TypeOfReflection_NB];
Standard_ShortReal TransparencyCoef;
Standard_ShortReal RefractionIndex;
@@ -99,6 +100,7 @@ RawMaterial::RawMaterial (Graphic3d_NameOfMaterial theName, const char* theStrin
BSDF.Kd = Graphic3d_Vec3 (0.2f);
BSDF.Ks = Graphic3d_Vec4 (0.00784314f, 0.00784314f, 0.00784314f, 0.25f);
BSDF.Normalize();
break;
case Graphic3d_NOM_SHINY_PLASTIC:
MaterialType = Graphic3d_MATERIAL_ASPECT;
@@ -124,6 +126,7 @@ RawMaterial::RawMaterial (Graphic3d_NameOfMaterial theName, const char* theStrin
BSDF.Kd = Graphic3d_Vec3 (0.2f);
BSDF.Ks = Graphic3d_Vec4 (0.6f);
break;
case Graphic3d_NOM_NEON_GNC:
MaterialType = Graphic3d_MATERIAL_ASPECT;
@@ -221,6 +224,7 @@ RawMaterial::RawMaterial (Graphic3d_NameOfMaterial theName, const char* theStrin
Colors[Graphic3d_TOR_EMISSION] = Quantity_Color (Graphic3d_Vec3 (0.0f));
BSDF.Kd = Graphic3d_Vec3 (0.482353f, 0.482353f, 0.482353f);
break;
case Graphic3d_NOM_SILVER:
MaterialType = Graphic3d_MATERIAL_PHYSIC;
@@ -261,6 +265,7 @@ RawMaterial::RawMaterial (Graphic3d_NameOfMaterial theName, const char* theStrin
BSDF.Kd = Graphic3d_Vec3 (0.243137f, 0.243137f, 0.243137f);
BSDF.Ks = Graphic3d_Vec4 (0.00392157f, 0.00392157f, 0.00392157f, 0.5f);
break;
case Graphic3d_NOM_CHROME:
MaterialType = Graphic3d_MATERIAL_PHYSIC;
@@ -418,6 +423,7 @@ RawMaterial::RawMaterial (Graphic3d_NameOfMaterial theName, const char* theStrin
Colors[Graphic3d_TOR_EMISSION] = Quantity_Color (Graphic3d_Vec3 (0.0f));
break;
}
PBRMaterial.SetBSDF (BSDF);
}
// =======================================================================
@@ -447,8 +453,9 @@ Graphic3d_MaterialAspect::Graphic3d_MaterialAspect (const Graphic3d_NameOfMateri
void Graphic3d_MaterialAspect::init (const Graphic3d_NameOfMaterial theName)
{
const RawMaterial& aMat = THE_MATERIALS[theName];
myBSDF = aMat.BSDF;
myStringName = aMat.StringName;
myBSDF = aMat.BSDF;
myPBRMaterial = aMat.PBRMaterial;
myStringName = aMat.StringName;
myColors[Graphic3d_TOR_AMBIENT] = aMat.Colors[Graphic3d_TOR_AMBIENT];
myColors[Graphic3d_TOR_DIFFUSE] = aMat.Colors[Graphic3d_TOR_DIFFUSE];
myColors[Graphic3d_TOR_SPECULAR] = aMat.Colors[Graphic3d_TOR_SPECULAR];
@@ -499,6 +506,8 @@ void Graphic3d_MaterialAspect::SetColor (const Quantity_Color& theColor)
return;
}
myPBRMaterial.SetColor (theColor);
const RawMaterial& aSrcMat = THE_MATERIALS[myRequestedMaterialName];
const Quantity_Color anAmbient((Graphic3d_Vec3 )theColor * aSrcMat.AmbientCoef);
const Quantity_Color aDiffuse ((Graphic3d_Vec3 )theColor * aSrcMat.DiffuseCoef);
@@ -585,6 +594,7 @@ void Graphic3d_MaterialAspect::SetTransparency (const Standard_ShortReal theValu
}
myTransparencyCoef = theValue;
myPBRMaterial.SetAlpha (1.0f - theValue);
}
// =======================================================================

View File

@@ -17,6 +17,7 @@
#define _Graphic3d_MaterialAspect_HeaderFile
#include <Graphic3d_BSDF.hxx>
#include <Graphic3d_PBRMaterial.hxx>
#include <Graphic3d_NameOfMaterial.hxx>
#include <Graphic3d_TypeOfMaterial.hxx>
#include <Graphic3d_TypeOfReflection.hxx>
@@ -170,6 +171,12 @@ public:
//! Modifies the BSDF (bidirectional scattering distribution function).
void SetBSDF (const Graphic3d_BSDF& theBSDF) { myBSDF = theBSDF; }
//! Returns physically based representation of material
const Graphic3d_PBRMaterial& PBRMaterial () const { return myPBRMaterial; }
//! Modifies the physically based representation of material
void SetPBRMaterial (const Graphic3d_PBRMaterial& thePBRMaterial) { myPBRMaterial = thePBRMaterial; }
//! Returns TRUE if the reflection mode is active, FALSE otherwise.
Standard_Boolean ReflectionMode (const Graphic3d_TypeOfReflection theType) const
{
@@ -197,6 +204,7 @@ public:
return myTransparencyCoef == theOther.myTransparencyCoef
&& myRefractionIndex == theOther.myRefractionIndex
&& myBSDF == theOther.myBSDF
&& myPBRMaterial == theOther.myPBRMaterial
&& myShininess == theOther.myShininess
&& myColors[Graphic3d_TOR_AMBIENT] == theOther.myColors[Graphic3d_TOR_AMBIENT]
&& myColors[Graphic3d_TOR_DIFFUSE] == theOther.myColors[Graphic3d_TOR_DIFFUSE]
@@ -247,6 +255,7 @@ private:
private:
Graphic3d_BSDF myBSDF;
Graphic3d_PBRMaterial myPBRMaterial;
TCollection_AsciiString myStringName;
Quantity_Color myColors[Graphic3d_TypeOfReflection_NB];
Standard_ShortReal myTransparencyCoef;

View File

@@ -0,0 +1,351 @@
// Author: Ilya Khramov
// Copyright (c) 2019 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Graphic3d_PBRMaterial.hxx>
#include <Graphic3d_MaterialDefinitionError.hxx>
#include <limits>
// =======================================================================
// function : RoughnessFromSpecular
// purpose :
// =======================================================================
Standard_ShortReal Graphic3d_PBRMaterial::RoughnessFromSpecular (const Quantity_Color& theSpecular,
const Standard_Real theShiness)
{
Standard_Real aRoughnessFactor = 1.0 - theShiness;
//Standard_Real aSpecIntens = theSpecular.Light() * theSpecular;
const Standard_Real aSpecIntens = theSpecular.Red() * 0.2125
+ theSpecular.Green() * 0.7154
+ theSpecular.Blue() * 0.0721;
if (aSpecIntens < 0.1)
{
// low specular intensity should produce a rough material even if shininess is high
aRoughnessFactor *= (1.0 - aSpecIntens);
}
return (Standard_ShortReal )aRoughnessFactor;
}
// =======================================================================
// function : Constructor
// purpose :
// =======================================================================
Graphic3d_PBRMaterial::Graphic3d_PBRMaterial ()
: myColor (0.f, 0.f, 0.f, 1.f),
myMetallic (0.f),
myRoughness (1.f),
myEmission (0.f),
myIOR (1.5f)
{}
// =======================================================================
// function : Constructor
// purpose :
// =======================================================================
Graphic3d_PBRMaterial::Graphic3d_PBRMaterial (const Graphic3d_BSDF& theBSDF)
{
SetBSDF (theBSDF);
}
// =======================================================================
// function : SetMetallic
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetMetallic (Standard_ShortReal theMetallic)
{
Graphic3d_MaterialDefinitionError_Raise_if (theMetallic < 0.f || theMetallic > 1.f,
"'metallic' parameter of PBR material must be in range [0, 1]")
myMetallic = theMetallic;
}
// =======================================================================
// function : Roughness
// purpose :
// =======================================================================
Standard_ShortReal Graphic3d_PBRMaterial::Roughness (Standard_ShortReal theNormalizedRoughness)
{
return theNormalizedRoughness * (1.f - MinRoughness()) + MinRoughness();
}
// =======================================================================
// function : SetRoughness
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetRoughness (Standard_ShortReal theRoughness)
{
Graphic3d_MaterialDefinitionError_Raise_if (theRoughness < 0.f || theRoughness > 1.f,
"'roughness' parameter of PBR material must be in range [0, 1]")
myRoughness = theRoughness;
}
// =======================================================================
// function : SetIOR
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetIOR (Standard_ShortReal theIOR)
{
Graphic3d_MaterialDefinitionError_Raise_if (theIOR < 1.f || theIOR > 3.f,
"'IOR' parameter of PBR material must be in range [1, 3]")
myIOR = theIOR;
}
// =======================================================================
// function : SetColor
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetColor (const Quantity_ColorRGBA& theColor)
{
myColor.SetRGB (theColor.GetRGB());
SetAlpha (theColor.Alpha());
}
// =======================================================================
// function : SetColor
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetColor (const Quantity_Color& theColor)
{
myColor.SetRGB (theColor);
}
// =======================================================================
// function : SetAlpha
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetAlpha (Standard_ShortReal theAlpha)
{
Graphic3d_MaterialDefinitionError_Raise_if (theAlpha < 0.f || theAlpha > 1.f,
"'alpha' parameter of PBR material must be in range [0, 1]")
myColor.SetAlpha (theAlpha);
}
// =======================================================================
// function : SetEmission
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetEmission (const Graphic3d_Vec3& theEmission)
{
Graphic3d_MaterialDefinitionError_Raise_if (theEmission.r() < 0.f
|| theEmission.g() < 0.f
|| theEmission.b() < 0.f,
"all components of 'emission' parameter of PBR material must be greater than 0")
myEmission = theEmission;
}
// =======================================================================
// function : SetBSDF
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::SetBSDF (const Graphic3d_BSDF& theBSDF)
{
SetEmission (theBSDF.Le);
if (theBSDF.Absorption != Graphic3d_Vec4(0.f))
{
SetMetallic (0.f);
SetColor (Quantity_Color (theBSDF.Absorption.rgb()));
if (theBSDF.FresnelCoat.FresnelType() == Graphic3d_FM_DIELECTRIC)
{
SetIOR (theBSDF.FresnelCoat.Serialize().y());
SetRoughness (0.f);
SetAlpha (theBSDF.Absorption.a() * 4.f);
}
return;
}
if (theBSDF.FresnelBase.FresnelType() == Graphic3d_FM_CONSTANT
&& theBSDF.Kt != Graphic3d_Vec3(0.f))
{
SetIOR (1.f);
SetRoughness (1.f);
SetMetallic (0.f);
SetColor (Quantity_Color (theBSDF.Kt));
SetAlpha (1.f - (theBSDF.Kt.r() + theBSDF.Kt.g() + theBSDF.Kt.b()) / 3.f);
return;
}
SetRoughness(sqrtf (theBSDF.Ks.w()));
if (theBSDF.FresnelBase.FresnelType() == Graphic3d_FM_DIELECTRIC
|| theBSDF.FresnelBase.FresnelType() == Graphic3d_FM_CONSTANT)
{
SetIOR (1.5f);
SetColor (Quantity_Color (theBSDF.Kd));
SetMetallic (0.f);
}
else if (theBSDF.FresnelBase.FresnelType() == Graphic3d_FM_SCHLICK)
{
SetColor (Quantity_Color (theBSDF.FresnelBase.Serialize().rgb()));
SetMetallic (1.f);
}
else
{
SetColor (Quantity_Color (theBSDF.Ks.rgb()));
SetMetallic (1.f);
}
}
// =======================================================================
// function : GenerateEnvLUT
// purpose :
// =======================================================================
void Graphic3d_PBRMaterial::GenerateEnvLUT (const Handle(Image_PixMap)& theLUT,
unsigned int theNbIntegralSamples)
{
if (theLUT->Format() != Image_Format_RGF)
{
throw Standard_ProgramError("LUT pix map format for PBR LUT generation must be Image_Format_RGF");
}
for (unsigned int y = 0; y < theLUT->SizeY(); ++y)
{
Standard_ShortReal aRoughness = Roughness(y / Standard_ShortReal(theLUT->SizeY() - 1));
for (unsigned int x = 0; x < theLUT->SizeX(); ++x)
{
Standard_ShortReal aCosV = x / Standard_ShortReal(theLUT->SizeX() - 1);
Graphic3d_Vec3 aView = lutGenView (aCosV);
unsigned int aCount = 0;
Graphic3d_Vec2 aResult = Graphic3d_Vec2 (0.f);
for (unsigned int i = 0; i < theNbIntegralSamples; ++i)
{
Graphic3d_Vec2 aHammersleyPoint = lutGenHammersley (i, theNbIntegralSamples);
Graphic3d_Vec3 aHalf = lutGenImportanceSample (aHammersleyPoint, aRoughness);
Graphic3d_Vec3 aLight = lutGenReflect (aView, aHalf);
if (aLight.z() >= 0.f)
{
++aCount;
Standard_ShortReal aCosVH = aView.Dot (aHalf);
Standard_ShortReal aGeometryFactor = lutGenGeometryFactor (aLight.z(),
aCosV,
aRoughness);
Standard_ShortReal anIntermediateResult = 1.f - aCosVH;
anIntermediateResult *= anIntermediateResult;
anIntermediateResult *= anIntermediateResult;
anIntermediateResult *= 1.f - aCosVH;
aResult.x() += aGeometryFactor * (aCosVH / aHalf.z()) * (1.f - anIntermediateResult);
aResult.y() += aGeometryFactor * (aCosVH / aHalf.z()) * anIntermediateResult;
}
}
aResult = aResult / Standard_ShortReal(theNbIntegralSamples);
theLUT->ChangeValue<Graphic3d_Vec2> (theLUT->SizeY() - 1 - y, x) = aResult;
}
}
}
// =======================================================================
// function : SpecIBLMapSamplesFactor
// purpose :
// =======================================================================
Standard_ShortReal Graphic3d_PBRMaterial::SpecIBLMapSamplesFactor (Standard_ShortReal theProbability,
Standard_ShortReal theRoughness)
{
return acosf (lutGenImportanceSampleCosTheta (theProbability, theRoughness)) * 2.f / Standard_ShortReal(M_PI);
}
// =======================================================================
// function : lutGenGeometryFactor
// purpose :
// =======================================================================
Standard_ShortReal Graphic3d_PBRMaterial::lutGenGeometryFactor (Standard_ShortReal theCosL,
Standard_ShortReal theCosV,
Standard_ShortReal theRoughness)
{
Standard_ShortReal aK = theRoughness * theRoughness * 0.5f;
Standard_ShortReal aGeometryFactor = theCosL;
aGeometryFactor /= theCosL * (1.f - aK) + aK;
aGeometryFactor /= theCosV * (1.f - aK) + aK;
return aGeometryFactor;
}
// =======================================================================
// function : lutGenHammersley
// purpose :
// =======================================================================
Graphic3d_Vec2 Graphic3d_PBRMaterial::lutGenHammersley (unsigned int theNumber, unsigned int theCount)
{
Standard_ShortReal aPhi2 = 0.f;
for (unsigned int i = 0; i < sizeof(unsigned int) * 8; ++i)
{
if ((theNumber >> i) == 0)
{
break;
}
aPhi2 += ((theNumber >> i) & 1) / Standard_ShortReal(1 << (i + 1));
}
return Graphic3d_Vec2(theNumber / Standard_ShortReal(theCount), aPhi2);
}
// =======================================================================
// function : lutGenImportanceSampleCosTheta
// purpose :
// =======================================================================
Standard_ShortReal Graphic3d_PBRMaterial::lutGenImportanceSampleCosTheta (Standard_ShortReal theHammersleyPointComponent,
Standard_ShortReal theRoughness)
{
Standard_ShortReal aQuadRoughness = theRoughness * theRoughness;
aQuadRoughness *= aQuadRoughness;
Standard_ShortReal aTmp = 1.f + (aQuadRoughness - 1.f) * theHammersleyPointComponent;
if (aTmp != 0.f)
{
return sqrtf ((1.f - theHammersleyPointComponent) / aTmp);
}
else
{
return 0.f;
}
}
// =======================================================================
// function : lutGenImportanceSample
// purpose :
// =======================================================================
Graphic3d_Vec3 Graphic3d_PBRMaterial::lutGenImportanceSample (const Graphic3d_Vec2 &theHammerslayPoint,
Standard_ShortReal theRoughness)
{
Standard_ShortReal aPhi = 2.f * Standard_ShortReal(M_PI) * theHammerslayPoint.y();
Standard_ShortReal aCosTheta = lutGenImportanceSampleCosTheta (theHammerslayPoint.x(), theRoughness);
Standard_ShortReal aSinTheta = sqrtf (1.f - aCosTheta * aCosTheta);
return Graphic3d_Vec3(aSinTheta * cosf (aPhi),
aSinTheta * sinf (aPhi),
aCosTheta);
}
// =======================================================================
// function : lutGenView
// purpose :
// =======================================================================
Graphic3d_Vec3 Graphic3d_PBRMaterial::lutGenView (Standard_ShortReal theCosV)
{
return Graphic3d_Vec3(0.f, sqrtf(1.f - theCosV * theCosV), theCosV);
}
// =======================================================================
// function : lutGenReflect
// purpose :
// =======================================================================
Graphic3d_Vec3 Graphic3d_PBRMaterial::lutGenReflect (const Graphic3d_Vec3 &theVector,
const Graphic3d_Vec3 &theAxis)
{
return theAxis * theAxis.Dot(theVector) * 2.f - theVector;
}

View File

@@ -0,0 +1,198 @@
// Author: Ilya Khramov
// Copyright (c) 2019 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _Graphic3d_PBRMaterial_HeaderFile
#define _Graphic3d_PBRMaterial_HeaderFile
#include <Image_PixMap.hxx>
#include <Graphic3d_BSDF.hxx>
#include <Graphic3d_Vec2.hxx>
#include <Graphic3d_Vec3.hxx>
#include <Graphic3d_Vec4.hxx>
#include <Quantity_Color.hxx>
//! Class implementing Metallic-Roughness physically based material definition
class Graphic3d_PBRMaterial
{
public:
//! Creates new physically based material in Metallic-Roughness system.
//! 'metallic' parameter is 0 by default.
//! 'roughness' parameter is 1 by default.
//! 'color' parameter is (0, 0, 0) by default.
//! 'alpha' parameter is 1 by default.
//! 'IOR' parameter is 1.5 by default.
//! 'emission' parameter is (0, 0, 0) by default.
Standard_EXPORT Graphic3d_PBRMaterial();
//! Creates new physically based material in Metallic-Roughness system from Graphic3d_BSDF.
Standard_EXPORT Graphic3d_PBRMaterial (const Graphic3d_BSDF& theBSDF);
//! Returns material's metallic coefficient in [0, 1] range.
//! 1 for metals and 0 for dielectrics.
//! It is preferable to be exactly 0 or 1. Average values are needed for textures mixing in shader.
Standard_ShortReal Metallic() const { return myMetallic; }
//! Modifies metallic coefficient of material in [0, 1] range.
Standard_EXPORT void SetMetallic (Standard_ShortReal theMetallic);
//! Maps roughness from [0, 1] to [MinRoughness, 1] for calculations.
Standard_EXPORT static Standard_ShortReal Roughness(Standard_ShortReal theNormalizedRoughness);
//! Returns real value of roughness in [MinRoughness, 1] range for calculations.
Standard_ShortReal Roughness() const { return Roughness(myRoughness); }
//! Returns roughness mapping parameter in [0, 1] range.
//! Roughness is defined in [0, 1] for handful material settings
//! and is mapped to [MinRoughness, 1] for calculations.
Standard_ShortReal NormalizedRoughness() const { return myRoughness; }
//! Modifies roughness coefficient of material in [0, 1] range.
Standard_EXPORT void SetRoughness (Standard_ShortReal theRoughness);
//! Returns index of refraction in [1, 3] range.
Standard_ShortReal IOR() const { return myIOR; }
//! Modifies index of refraction in [1, 3] range.
//! In practice affects only on non-metal materials reflection possibilities.
Standard_EXPORT void SetIOR (Standard_ShortReal theIOR);
//! Returns albedo color with alpha component of material.
const Quantity_ColorRGBA& Color() const { return myColor; }
//! Modifies albedo color with alpha component.
Standard_EXPORT void SetColor (const Quantity_ColorRGBA& theColor);
//! Modifies only albedo color.
Standard_EXPORT void SetColor (const Quantity_Color& theColor);
//! Returns alpha component in range [0, 1].
Standard_ShortReal Alpha() const { return myColor.Alpha(); };
//! Modifies alpha component.
Standard_EXPORT void SetAlpha (Standard_ShortReal theAlpha);
//! Returns light intensity emitted by material.
//! Values are greater or equal 0.
Graphic3d_Vec3 Emission() const { return myEmission; }
//! Modifies light intensity emitted by material.
Standard_EXPORT void SetEmission (const Graphic3d_Vec3& theEmission);
//! Generates material in Metallic-Roughness system from Graphic3d_BSDF.
Standard_EXPORT void SetBSDF (const Graphic3d_BSDF& theBSDF);
public:
//! PBR materials comparison operator.
Standard_Boolean operator== (const Graphic3d_PBRMaterial& theOther) const
{
return (myMetallic == theOther.myMetallic)
&& (myRoughness == theOther.myRoughness)
&& (myIOR == theOther.myIOR)
&& (myColor == theOther.myColor)
&& (myEmission == theOther.myEmission);
}
public:
//! Generates 2D look up table of scale and bias for fresnell zero coefficient.
//! It is needed for calculation reflectance part of environment lighting.
//! @param [out] theLUT table storage (must be Image_Format_RGF).
//! @param [in] theIntegralSamplesCount number of importance samples in hemisphere integral calculation for every table item.
Standard_EXPORT static void GenerateEnvLUT (const Handle(Image_PixMap)& theLUT,
unsigned int theNbIntegralSamples = 1024);
//! Compute material roughness from common material (specular color + shininess).
//! @param theSpecular [in] specular color
//! @param theShiness [in] normalized shininess coefficient within [0..1] range
//! @return roughness within [0..1] range
Standard_EXPORT static Standard_ShortReal RoughnessFromSpecular (const Quantity_Color& theSpecular,
const Standard_Real theShiness);
//! Compute material metallicity from common material (specular color).
//! @param theSpecular [in] specular color
//! @return metallicity within [0..1] range
static Standard_ShortReal MetallicFromSpecular (const Quantity_Color& theSpecular)
{
return ((Graphic3d_Vec3 )theSpecular).maxComp();
}
public:
//! Roughness cannot be 0 in real calculations, so it returns minimal achievable level of roughness in practice
static Standard_ShortReal MinRoughness() { return 0.01f; }
public:
//! Shows how much times less samples can be used in certain roughness value specular IBL map generation
//! in compare with samples number for map with roughness of 1.
//! Specular IBL maps with less roughness values have higher resolution but require less samples for the same quality of baking.
//! So that reducing samples number is good strategy to improve performance of baking.
//! The samples number for specular IBL map with roughness of 1 (the maximum possible samples number) is expected to be defined as baking parameter.
//! Samples number for other roughness values can be calculated by multiplication origin samples number by this factor.
//! @param theProbability value from 0 to 1 controlling strength of samples reducing.
//! Bigger values result in slower reduction to provide better quality but worse performance.
//! Value of 1 doesn't affect at all so that 1 will be returned (it can be used to disable reduction strategy).
//! @param theRoughness roughness value of current generated specular IBL map (from 0 to 1).
//! @return factor to calculate number of samples for current specular IBL map baking.
//! Be aware! It has no obligation to return 1 in case of roughness of 1.
//! Be aware! It produces poor quality with small number of origin samples. In that case it is recommended to be disabled.
Standard_EXPORT static Standard_ShortReal SpecIBLMapSamplesFactor (Standard_ShortReal theProbability,
Standard_ShortReal theRoughness);
private:
//! Calculates geometry factor of Cook-Torrance BRDF using Smith formula.
static Standard_ShortReal lutGenGeometryFactor (Standard_ShortReal theCosL,
Standard_ShortReal theCosV,
Standard_ShortReal theRoughness);
//! Generates quasi-random point from Hammersley set.
//! @param theNumber number of point
//! @param theCount size of Hammersley set
static Graphic3d_Vec2 lutGenHammersley (unsigned int theNumber, unsigned int theCount);
//! Generates only cosine theta of direction in spherical coordinates system
//! according to micro facet distribution function from Cook-Torrance BRDF.
static Standard_ShortReal lutGenImportanceSampleCosTheta (Standard_ShortReal theHammerslayPointComponent,
Standard_ShortReal theRoughness);
//! Generates direction using point from Hammersley set
//! according to micro facet distribution function from Cook-Torrance BRDF.
static Graphic3d_Vec3 lutGenImportanceSample (const Graphic3d_Vec2 &theHammerslayPoint,
Standard_ShortReal theRoughness);
//! Generates vector using cosine of angle between up vector (normal in hemisphere)
//! and desired vector.
//! x component for resulting vector will be zero.
static Graphic3d_Vec3 lutGenView (Standard_ShortReal theCosV);
//! Returns reflected vector according axis.
//! @param theVector vector is needed to be reflected.
//! @param theAxis axis of reflection.
static Graphic3d_Vec3 lutGenReflect (const Graphic3d_Vec3 &theVector,
const Graphic3d_Vec3 &theAxis);
private:
Quantity_ColorRGBA myColor; //!< albedo color with alpha component [0, 1]
Standard_ShortReal myMetallic; //!< metallic coefficient of material [0, 1]
Standard_ShortReal myRoughness; //!< roughness coefficient of material [0, 1]
Graphic3d_Vec3 myEmission; //!< light intensity emitted by material [>= 0]
Standard_ShortReal myIOR; //!< index of refraction [1, 3]
};
#endif // _Graphic3d_PBRMaterial_HeaderFile

View File

@@ -95,6 +95,13 @@ public:
: Method (Graphic3d_RM_RASTERIZATION),
TransparencyMethod (Graphic3d_RTM_BLEND_UNORDERED),
LineFeather (1.0f),
// PBR parameters
PbrEnvPow2Size (9),
PbrEnvSpecMapNbLevels (6),
PbrEnvBakingDiffNbSamples (1024),
PbrEnvBakingSpecNbSamples (256),
PbrEnvBakingProbability (0.99f),
//
OitDepthFactor (0.0f),
NbMsaaSamples (0),
RenderResolutionScale (1.0f),
@@ -171,6 +178,15 @@ public:
Graphic3d_RenderTransparentMethod TransparencyMethod; //!< specifies rendering method for transparent graphics
Standard_ShortReal LineFeather; //!< line feater width in pixels (> 0.0), 1.0 by default;
//! high values produce blurred results, small values produce sharp (aliased) edges
Standard_Integer PbrEnvPow2Size; //!< size of IBL maps side can be calculated as 2^PbrEnvPow2Size (> 0), 9 by default
Standard_Integer PbrEnvSpecMapNbLevels; //!< number of levels used in specular IBL map (> 1), 6 by default
Standard_Integer PbrEnvBakingDiffNbSamples; //!< number of samples used in Monte-Carlo integration during diffuse IBL map's
//! spherical harmonics coefficients generation (> 0), 1024 by default
Standard_Integer PbrEnvBakingSpecNbSamples; //!< number of samples used in Monte-Carlo integration during specular IBL map's generation (> 0), 256 by default
Standard_ShortReal PbrEnvBakingProbability; //!< controls strength of samples reducing strategy during specular IBL map's generation
//! (see 'SpecIBLMapSamplesFactor' function for detail explanation) [0.0, 1.0], 0.99 by default
Standard_ShortReal OitDepthFactor; //!< scalar factor [0-1] controlling influence of depth of a fragment to its final coverage
Standard_Integer NbMsaaSamples; //!< number of MSAA samples (should be within 0..GL_MAX_SAMPLES, power-of-two number), 0 by default
Standard_ShortReal RenderResolutionScale; //!< rendering resolution scale factor, 1 by default;

View File

@@ -82,7 +82,8 @@ Graphic3d_ShaderProgram::Graphic3d_ShaderProgram()
myNbFragOutputs (THE_NB_FRAG_OUTPUTS),
myHasDefSampler (true),
myHasAlphaTest (false),
myHasWeightOitOutput (false)
myHasWeightOitOutput (false),
myIsPBR (false)
{
myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_")
+ TCollection_AsciiString (Standard_Atomic_Increment (&THE_PROGRAM_OBJECT_COUNTER));

View File

@@ -151,6 +151,13 @@ public:
//! Note that weighted OIT also requires at least 2 Fragment Outputs (color + coverage).
void SetWeightOitOutput (Standard_Boolean theOutput) { myHasWeightOitOutput = theOutput; }
//! Return TRUE if standard program header should define functions and variables used in PBR pipeline.
//! FALSE by default
Standard_Boolean IsPBR() const { return myIsPBR; }
//! Sets whether standard program header should define functions and variables used in PBR pipeline.
void SetPBR (Standard_Boolean theIsPBR) { myIsPBR = theIsPBR; }
//! Pushes custom uniform variable to the program.
//! The list of pushed variables is automatically cleared after applying to GLSL program.
//! Thus after program recreation even unchanged uniforms should be pushed anew.
@@ -204,6 +211,7 @@ private:
Standard_Boolean myHasDefSampler; //!< flag indicating that program defines default texture sampler occSampler0
Standard_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader performs alpha test
Standard_Boolean myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage
Standard_Boolean myIsPBR; //!< flag indicating that program defines functions and variables used in PBR pipeline
};

View File

@@ -29,6 +29,8 @@ Graphic3d_TextureParams::Graphic3d_TextureParams()
myFilter (Graphic3d_TOTF_NEAREST),
myAnisoLevel (Graphic3d_LOTA_OFF),
myGenMode (Graphic3d_TOTM_MANUAL),
myBaseLevel (0),
myMaxLevel (1000),
myRotAngle (0.0f),
myToModulate (Standard_False),
myToRepeat (Standard_False)

View File

@@ -106,6 +106,21 @@ public:
//! Setup texture coordinates generation mode.
Standard_EXPORT void SetGenMode (const Graphic3d_TypeOfTextureMode theMode, const Graphic3d_Vec4 thePlaneS, const Graphic3d_Vec4 thePlaneT);
//! @return base texture mipmap level; 0 by default.
Standard_Integer BaseLevel() const { return myBaseLevel; }
//! @return maximum texture mipmap array level; 1000 by default.
Standard_Integer MaxLevel() const { return myMaxLevel; }
//! Setups texture mipmap array levels range.
//! The lowest value will be the base level.
//! The remaining one will be the maximum level.
void SetLevelsRange (Standard_Integer theFirstLevel, Standard_Integer theSecondLevel = 0)
{
myMaxLevel = theFirstLevel > theSecondLevel ? theFirstLevel : theSecondLevel;
myBaseLevel = theFirstLevel > theSecondLevel ? theSecondLevel : theFirstLevel;
}
//! Return modification counter of parameters related to sampler state.
unsigned int SamplerRevision() const { return mySamplerRevision; }
@@ -125,6 +140,8 @@ private:
Graphic3d_TypeOfTextureFilter myFilter; //!< texture filter, Graphic3d_TOTF_NEAREST by default
Graphic3d_LevelOfTextureAnisotropy myAnisoLevel; //!< level of anisotropy filter, Graphic3d_LOTA_OFF by default
Graphic3d_TypeOfTextureMode myGenMode; //!< texture coordinates generation mode, Graphic3d_TOTM_MANUAL by default
Standard_Integer myBaseLevel; //!< base texture mipmap level (0 by default)
Standard_Integer myMaxLevel; //!< maximum texture mipmap array level (1000 by default)
Standard_ShortReal myRotAngle; //!< texture coordinates rotation angle in degrees, 0 by default
Standard_Boolean myToModulate; //!< flag to modulate texture with material color, FALSE by default
Standard_Boolean myToRepeat; //!< flag to repeat (true) or wrap (false) texture coordinates out of [0,1] range

View File

@@ -25,6 +25,7 @@ enum Graphic3d_TypeOfLimit
Graphic3d_TypeOfLimit_MaxViewDumpSizeY, //!< maximum height for image dump
Graphic3d_TypeOfLimit_MaxCombinedTextureUnits, //!< maximum number of combined texture units for multitexturing
Graphic3d_TypeOfLimit_MaxMsaa, //!< maximum number of MSAA samples
Graphic3d_TypeOfLimit_HasPBR, //!< indicates whether PBR metallic-roughness shading model is supported
Graphic3d_TypeOfLimit_HasRayTracing, //!< indicates whether ray tracing is supported
Graphic3d_TypeOfLimit_HasRayTracingTextures, //!< indicates whether ray tracing textures are supported
Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSampling, //!< indicates whether adaptive screen sampling is supported

View File

@@ -46,6 +46,12 @@ enum Graphic3d_TypeOfShadingModel
//! Shading model requires normals to be defined within vertex attributes.
Graphic3d_TOSM_FRAGMENT,
//! Metallic-roughness physically based (PBR) illumination system.
Graphic3d_TOSM_PBR,
//! Same as Graphic3d_TOSM_PBR but using flat per-triangle normal.
Graphic3d_TOSM_PBR_FACET,
// obsolete aliases
Graphic3d_TOSM_NONE = Graphic3d_TOSM_UNLIT,
V3d_COLOR = Graphic3d_TOSM_NONE,
@@ -57,7 +63,7 @@ enum Graphic3d_TypeOfShadingModel
enum
{
//! Auxiliary value defining the overall number of values in enumeration Graphic3d_TypeOfShadingModel
Graphic3d_TypeOfShadingModel_NB = Graphic3d_TOSM_FRAGMENT + 1
Graphic3d_TypeOfShadingModel_NB = Graphic3d_TOSM_PBR_FACET + 1
};
#endif // _Graphic3d_TypeOfShadingModel_HeaderFile