mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +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:
parent
f4a7308f61
commit
67312b7991
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@ -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;
|
||||
|
351
src/Graphic3d/Graphic3d_PBRMaterial.cxx
Normal file
351
src/Graphic3d/Graphic3d_PBRMaterial.cxx
Normal 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;
|
||||
}
|
198
src/Graphic3d/Graphic3d_PBRMaterial.hxx
Normal file
198
src/Graphic3d/Graphic3d_PBRMaterial.hxx
Normal 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
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -266,6 +266,31 @@ public:
|
||||
|
||||
};
|
||||
|
||||
//! POD structure for packed float RG color value (2 floats)
|
||||
struct Image_ColorRGF
|
||||
{
|
||||
//! Component type.
|
||||
typedef Standard_ShortReal ComponentType_t;
|
||||
|
||||
//! Returns the number of components.
|
||||
static Standard_Integer Length() { return 2; }
|
||||
|
||||
//! Alias to 1st component (red intensity).
|
||||
Standard_ShortReal r() const { return v[0]; }
|
||||
|
||||
//! Alias to 2nd component (green intensity).
|
||||
Standard_ShortReal g() const { return v[1]; }
|
||||
|
||||
//! Alias to 1st component (red intensity).
|
||||
Standard_ShortReal& r() { return v[0]; }
|
||||
|
||||
//! Alias to 2nd component (green intensity).
|
||||
Standard_ShortReal& g() { return v[1]; }
|
||||
|
||||
public:
|
||||
Standard_ShortReal v[2];
|
||||
};
|
||||
|
||||
//! POD structure for packed float RGB color value (3 floats)
|
||||
struct Image_ColorRGBF
|
||||
{
|
||||
|
@ -28,6 +28,7 @@ enum Image_Format
|
||||
Image_Format_BGRA, //!< same as RGBA but with different components order
|
||||
Image_Format_GrayF, //!< 1 float (4-bytes) per pixel (1-component plane), intensity of the color
|
||||
Image_Format_AlphaF, //!< 1 float (4-bytes) per pixel (1-component plane), transparency
|
||||
Image_Format_RGF, //!< 2 floats (8-bytes) RG image plane
|
||||
Image_Format_RGBF, //!< 3 floats (12-bytes) RGB image plane
|
||||
Image_Format_BGRF, //!< same as RGBF but with different components order
|
||||
Image_Format_RGBAF, //!< 4 floats (16-bytes) RGBA image plane
|
||||
|
@ -47,6 +47,8 @@ Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat)
|
||||
case Image_Format_GrayF:
|
||||
case Image_Format_AlphaF:
|
||||
return sizeof(float);
|
||||
case Image_Format_RGF:
|
||||
return sizeof(float) * 2;
|
||||
case Image_Format_RGBAF:
|
||||
case Image_Format_BGRAF:
|
||||
return sizeof(float) * 4;
|
||||
@ -214,6 +216,11 @@ Quantity_ColorRGBA Image_PixMap::PixelColor (const Standard_Integer theX,
|
||||
const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX);
|
||||
return Quantity_ColorRGBA (NCollection_Vec4<float> (1.0f, 1.0f, 1.0f, aPixel));
|
||||
}
|
||||
case Image_Format_RGF:
|
||||
{
|
||||
const Image_ColorRGF& aPixel = Value<Image_ColorRGF> (theY, theX);
|
||||
return Quantity_ColorRGBA (NCollection_Vec4<float> (aPixel.r(), aPixel.g(), 0.0f, 1.0f));
|
||||
}
|
||||
case Image_Format_RGBAF:
|
||||
{
|
||||
const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX);
|
||||
@ -339,6 +346,13 @@ void Image_PixMap::SetPixelColor (const Standard_Integer theX,
|
||||
ChangeValue<Standard_ShortReal> (theY, theX) = aColor.a();
|
||||
return;
|
||||
}
|
||||
case Image_Format_RGF:
|
||||
{
|
||||
Image_ColorRGF& aPixel = ChangeValue<Image_ColorRGF> (theY, theX);
|
||||
aPixel.r() = aColor.r();
|
||||
aPixel.g() = aColor.g();
|
||||
return;
|
||||
}
|
||||
case Image_Format_RGBAF:
|
||||
{
|
||||
Image_ColorRGBAF& aPixel = ChangeValue<Image_ColorRGBAF> (theY, theX);
|
||||
|
@ -92,6 +92,7 @@ int Media_Frame::FormatOcct2FFmpeg (Image_Format theFormat)
|
||||
return AV_PIX_FMT_GRAY8;
|
||||
case Image_Format_GrayF:
|
||||
case Image_Format_AlphaF:
|
||||
case Image_Format_RGF:
|
||||
case Image_Format_RGBAF:
|
||||
case Image_Format_RGBF:
|
||||
case Image_Format_BGRAF:
|
||||
|
@ -105,6 +105,8 @@ OpenGl_GraphicDriver.hxx
|
||||
OpenGl_IndexBuffer.cxx
|
||||
OpenGl_IndexBuffer.hxx
|
||||
OpenGl_Layer.hxx
|
||||
OpenGl_PBREnvironment.cxx
|
||||
OpenGl_PBREnvironment.hxx
|
||||
OpenGl_RenderFilter.hxx
|
||||
OpenGl_Sampler.cxx
|
||||
OpenGl_Sampler.hxx
|
||||
|
@ -144,6 +144,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
|
||||
hasUintIndex(Standard_True),
|
||||
hasTexRGBA8(Standard_True),
|
||||
#endif
|
||||
hasTexFloatLinear (Standard_False),
|
||||
hasTexSRGB (Standard_False),
|
||||
hasFboSRGB (Standard_False),
|
||||
hasSRGBControl (Standard_False),
|
||||
@ -208,6 +209,10 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
|
||||
myHasRayTracingTextures (Standard_False),
|
||||
myHasRayTracingAdaptiveSampling (Standard_False),
|
||||
myHasRayTracingAdaptiveSamplingAtomic (Standard_False),
|
||||
myHasPBR (Standard_False),
|
||||
myPBREnvLUTTexUnit (Graphic3d_TextureUnit_0),
|
||||
myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_0),
|
||||
myPBRSpecIBLMapTexUnit (Graphic3d_TextureUnit_0),
|
||||
myFrameStats (new OpenGl_FrameStats()),
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
myPointSpriteOrig (GL_UPPER_LEFT),
|
||||
@ -1485,6 +1490,8 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
|
||||
|
||||
arbTexFloat = IsGlGreaterEqual (3, 0)
|
||||
&& FindProcShort (glTexImage3D);
|
||||
hasTexFloatLinear = arbTexFloat
|
||||
&& CheckExtension ("GL_OES_texture_float_linear");
|
||||
|
||||
const Standard_Boolean hasTexBuffer32 = IsGlGreaterEqual (3, 2) && FindProcShort (glTexBuffer);
|
||||
const Standard_Boolean hasExtTexBuffer = CheckExtension ("GL_EXT_texture_buffer") && FindProc ("glTexBufferEXT", myFuncs->glTexBuffer);
|
||||
@ -1581,6 +1588,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
|
||||
arbNPTW = CheckExtension ("GL_ARB_texture_non_power_of_two");
|
||||
arbTexFloat = IsGlGreaterEqual (3, 0)
|
||||
|| CheckExtension ("GL_ARB_texture_float");
|
||||
hasTexFloatLinear = arbTexFloat;
|
||||
arbSampleShading = CheckExtension ("GL_ARB_sample_shading");
|
||||
extBgra = CheckExtension ("GL_EXT_bgra");
|
||||
extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
|
||||
@ -2933,6 +2941,23 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
|
||||
"Check OpenGL window creation parameters for optimal performance.", Message_Trace);
|
||||
}
|
||||
}
|
||||
|
||||
// check whether PBR shading model is supported
|
||||
myHasPBR = arbFBO != NULL
|
||||
&& myMaxTexCombined >= 4
|
||||
&& arbTexRG
|
||||
&& arbTexFloat
|
||||
&& (IsGlGreaterEqual (3, 0)
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
|| (IsGlGreaterEqual (2, 1) && CheckExtension ("GL_EXT_gpu_shader4"))
|
||||
#endif
|
||||
);
|
||||
if (myHasPBR)
|
||||
{
|
||||
myPBREnvLUTTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined - 3);
|
||||
myPBRDiffIBLMapSHTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined - 2);
|
||||
myPBRSpecIBLMapTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -3547,8 +3572,11 @@ void OpenGl_Context::SetShadingMaterial (const OpenGl_Aspects* theAspect,
|
||||
Standard_ShortReal anAlphaBack = 1.0f;
|
||||
if (CheckIsTransparent (theAspect, theHighlight, anAlphaFront, anAlphaBack))
|
||||
{
|
||||
myMatFront.Diffuse.a() = anAlphaFront;
|
||||
myMatBack .Diffuse.a() = anAlphaBack;
|
||||
myMatFront.Common.Diffuse.a() = anAlphaFront;
|
||||
myMatBack .Common.Diffuse.a() = anAlphaBack;
|
||||
|
||||
myMatFront.Pbr.BaseColor.a() = anAlphaFront;
|
||||
myMatBack .Pbr.BaseColor.a() = anAlphaBack;
|
||||
}
|
||||
|
||||
// do not update material properties in case of zero reflection mode,
|
||||
|
@ -587,6 +587,25 @@ public:
|
||||
return Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB (theColor);
|
||||
}
|
||||
|
||||
//! Returns TRUE if PBR shading model is supported.
|
||||
//! Basically, feature requires OpenGL 3.0+ / OpenGL ES 3.0+ hardware; more precisely:
|
||||
//! - Graphics hardware with moderate capabilities for compiling long enough GLSL program.
|
||||
//! - FBO (e.g. for baking environment).
|
||||
//! - Multi-texturing with >= 4 units (LUT and IBL textures).
|
||||
//! - GL_RG32F texture format (arbTexRG + arbTexFloat)
|
||||
//! - Cubemap texture lookup textureCubeLod()/textureLod() with LOD index within Fragment Shader,
|
||||
//! which requires GLSL OpenGL 3.0+ / OpenGL ES 3.0+ or OpenGL 2.1 + GL_EXT_gpu_shader4 extension.
|
||||
Standard_Boolean HasPBR() const { return myHasPBR; }
|
||||
|
||||
//! Returns texture unit where Environment Lookup Table is expected to be bound, or 0 if PBR is unavailable.
|
||||
Graphic3d_TextureUnit PBREnvLUTTexUnit() const { return myPBREnvLUTTexUnit; }
|
||||
|
||||
//! Returns texture unit where Diffuse (irradiance) IBL map's spherical harmonics coefficients is expected to be bound, or 0 if PBR is unavailable.
|
||||
Graphic3d_TextureUnit PBRDiffIBLMapSHTexUnit() const { return myPBRDiffIBLMapSHTexUnit; }
|
||||
|
||||
//! Returns texture unit where Specular IBL map is expected to be bound, or 0 if PBR is unavailable.
|
||||
Graphic3d_TextureUnit PBRSpecIBLMapTexUnit() const { return myPBRSpecIBLMapTexUnit; }
|
||||
|
||||
//! Returns true if VBO is supported and permitted.
|
||||
inline bool ToUseVbo() const
|
||||
{
|
||||
@ -956,6 +975,7 @@ public: //! @name extensions
|
||||
Standard_Boolean hasHighp; //!< highp in GLSL ES fragment shader is supported
|
||||
Standard_Boolean hasUintIndex; //!< GLuint for index buffer is supported (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_element_index_uint)
|
||||
Standard_Boolean hasTexRGBA8; //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8
|
||||
Standard_Boolean hasTexFloatLinear; //!< texture-filterable state for 32-bit floating texture formats (always on desktop, GL_OES_texture_float_linear within OpenGL ES)
|
||||
Standard_Boolean hasTexSRGB; //!< sRGB texture formats (desktop OpenGL 2.0, OpenGL ES 3.0 or GL_EXT_texture_sRGB)
|
||||
Standard_Boolean hasFboSRGB; //!< sRGB FBO render targets (desktop OpenGL 2.1, OpenGL ES 3.0)
|
||||
Standard_Boolean hasSRGBControl; //!< sRGB write control (any desktop OpenGL, OpenGL ES + GL_EXT_sRGB_write_control extension)
|
||||
@ -969,7 +989,7 @@ public: //! @name extensions
|
||||
Standard_Boolean arbDrawBuffers; //!< GL_ARB_draw_buffers
|
||||
Standard_Boolean arbNPTW; //!< GL_ARB_texture_non_power_of_two
|
||||
Standard_Boolean arbTexRG; //!< GL_ARB_texture_rg
|
||||
Standard_Boolean arbTexFloat; //!< GL_ARB_texture_float (on desktop OpenGL - since 3.0 or as extension GL_ARB_texture_float; on OpenGL ES - since 3.0)
|
||||
Standard_Boolean arbTexFloat; //!< GL_ARB_texture_float (on desktop OpenGL - since 3.0 or as extension GL_ARB_texture_float; on OpenGL ES - since 3.0); @sa hasTexFloatLinear for linear filtering support
|
||||
OpenGl_ArbSamplerObject* arbSamplerObject; //!< GL_ARB_sampler_objects (on desktop OpenGL - since 3.3 or as extension GL_ARB_sampler_objects; on OpenGL ES - since 3.0)
|
||||
OpenGl_ArbTexBindless* arbTexBindless; //!< GL_ARB_bindless_texture
|
||||
OpenGl_ArbTBO* arbTBO; //!< GL_ARB_texture_buffer_object
|
||||
@ -1056,6 +1076,12 @@ private: // context info
|
||||
Standard_Boolean myHasRayTracingAdaptiveSampling; //! indicates whether adaptive screen sampling in ray tracing mode is supported
|
||||
Standard_Boolean myHasRayTracingAdaptiveSamplingAtomic; //! indicates whether atomic adaptive screen sampling in ray tracing mode is supported
|
||||
|
||||
Standard_Boolean myHasPBR; //!< indicates whether PBR shading model is supported
|
||||
Graphic3d_TextureUnit myPBREnvLUTTexUnit; //!< texture unit where environment lookup table is expected to be binded (0 if PBR is not supported)
|
||||
Graphic3d_TextureUnit myPBRDiffIBLMapSHTexUnit; //!< texture unit where diffuse (irradiance) IBL map's spherical harmonics coefficients is expected to be binded
|
||||
//! (0 if PBR is not supported)
|
||||
Graphic3d_TextureUnit myPBRSpecIBLMapTexUnit; //!< texture unit where specular IBL map is expected to be binded (0 if PBR is not supported)
|
||||
|
||||
Handle(OpenGl_ShaderManager) myShaderManager; //! support object for managing shader programs
|
||||
|
||||
private: //! @name fields tracking current state
|
||||
|
@ -786,6 +786,10 @@ Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& t
|
||||
aFormat = GL_DEPTH_COMPONENT;
|
||||
aType = GL_FLOAT;
|
||||
break;
|
||||
case Image_Format_RGF:
|
||||
aFormat = GL_RG;
|
||||
aType = GL_FLOAT;
|
||||
break;
|
||||
case Image_Format_RGB:
|
||||
aFormat = GL_RGB;
|
||||
aType = GL_UNSIGNED_BYTE;
|
||||
@ -812,6 +816,7 @@ Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& t
|
||||
case Image_Format_GrayF:
|
||||
case Image_Format_BGRF:
|
||||
case Image_Format_BGRAF:
|
||||
case Image_Format_RGF:
|
||||
return Standard_False;
|
||||
case Image_Format_BGRA:
|
||||
case Image_Format_BGR32:
|
||||
|
@ -80,6 +80,9 @@
|
||||
// adds GL_FRAMEBUFFER_SRGB_EXT flag as on desktop OpenGL
|
||||
#define GL_FRAMEBUFFER_SRGB 0x8DB9
|
||||
|
||||
#define GL_TEXTURE_BASE_LEVEL 0x813C
|
||||
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
||||
|
||||
// OpenGL ES 3.1+
|
||||
#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
|
||||
#define GL_MAX_SAMPLES 0x8D57
|
||||
|
@ -400,6 +400,8 @@ Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit
|
||||
return !aCtx.IsNull() ? aCtx->MaxDumpSizeX() : 1024;
|
||||
case Graphic3d_TypeOfLimit_MaxViewDumpSizeY:
|
||||
return !aCtx.IsNull() ? aCtx->MaxDumpSizeY() : 1024;
|
||||
case Graphic3d_TypeOfLimit_HasPBR:
|
||||
return (!aCtx.IsNull() && aCtx->HasPBR()) ? 1 : 0;
|
||||
case Graphic3d_TypeOfLimit_HasRayTracing:
|
||||
return (!aCtx.IsNull() && aCtx->HasRayTracing()) ? 1 : 0;
|
||||
case Graphic3d_TypeOfLimit_HasRayTracingTextures:
|
||||
|
@ -594,7 +594,7 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
|
||||
if (hasOwnLights)
|
||||
{
|
||||
aLayerSettings.Lights()->UpdateRevision();
|
||||
aManager->UpdateLightSourceStateTo (aLayerSettings.Lights());
|
||||
aManager->UpdateLightSourceStateTo (aLayerSettings.Lights(), theWorkspace->View()->SpecIBLMapLevels());
|
||||
}
|
||||
|
||||
const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera();
|
||||
@ -665,7 +665,7 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
|
||||
|
||||
if (hasOwnLights)
|
||||
{
|
||||
aManager->UpdateLightSourceStateTo (aLightsBack);
|
||||
aManager->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels());
|
||||
}
|
||||
if (hasLocalCS)
|
||||
{
|
||||
@ -732,7 +732,7 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
|
||||
if (aPassIter == 0)
|
||||
{
|
||||
aCtx->SetColorMask (false);
|
||||
aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)());
|
||||
aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)(), theWorkspace->View()->SpecIBLMapLevels());
|
||||
aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
|
||||
aDefaultSettings.DepthMask = GL_TRUE;
|
||||
}
|
||||
@ -743,13 +743,13 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
|
||||
continue;
|
||||
}
|
||||
aCtx->SetColorMask (true);
|
||||
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
|
||||
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels());
|
||||
aDefaultSettings = aPrevSettings;
|
||||
}
|
||||
else if (aPassIter == 2)
|
||||
{
|
||||
aCtx->SetColorMask (true);
|
||||
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack);
|
||||
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels());
|
||||
if (toPerformDepthPrepass)
|
||||
{
|
||||
aDefaultSettings.DepthFunc = GL_EQUAL;
|
||||
|
@ -22,7 +22,7 @@
|
||||
class OpenGl_Context;
|
||||
|
||||
//! OpenGL material definition
|
||||
struct OpenGl_Material
|
||||
struct OpenGl_MaterialCommon
|
||||
{
|
||||
|
||||
OpenGl_Vec4 Ambient; //!< ambient reflection coefficient
|
||||
@ -37,31 +37,58 @@ struct OpenGl_Material
|
||||
float Transparency() const { return Params.y(); }
|
||||
float& ChangeTransparency() { return Params.y(); }
|
||||
|
||||
//! Empty constructor.
|
||||
OpenGl_MaterialCommon() : Ambient (1.0f), Diffuse (1.0f), Specular (1.0f), Emission (1.0f), Params (1.0f, 0.0f, 0.0f, 0.0f) {}
|
||||
|
||||
//! Returns packed (serialized) representation of material properties
|
||||
const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
|
||||
static Standard_Integer NbOfVec4() { return 5; }
|
||||
|
||||
};
|
||||
|
||||
//! OpenGL material definition
|
||||
struct OpenGl_MaterialPBR
|
||||
{
|
||||
|
||||
OpenGl_Vec4 BaseColor; //!< base color of PBR material with alpha component
|
||||
OpenGl_Vec4 EmissionIOR; //!< light intensity which is emitted by PBR material and index of refraction
|
||||
OpenGl_Vec4 Params; //!< extra packed parameters
|
||||
|
||||
float Metallic() const { return Params.b(); }
|
||||
float& ChangeMetallic() { return Params.b(); }
|
||||
|
||||
float Roughness() const { return Params.g(); }
|
||||
float& ChangeRoughness() { return Params.g(); }
|
||||
|
||||
//! Empty constructor.
|
||||
OpenGl_MaterialPBR() : BaseColor (1.0f), EmissionIOR (1.0f), Params (1.0f, 1.0f, 1.0f, 1.0f) {}
|
||||
|
||||
//! Returns packed (serialized) representation of material properties
|
||||
const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
|
||||
static Standard_Integer NbOfVec4() { return 3; }
|
||||
|
||||
};
|
||||
|
||||
//! OpenGL material definition
|
||||
struct OpenGl_Material
|
||||
{
|
||||
OpenGl_MaterialCommon Common;
|
||||
OpenGl_MaterialPBR Pbr;
|
||||
|
||||
//! Set material color.
|
||||
void SetColor (const OpenGl_Vec4& theColor)
|
||||
{
|
||||
// apply the same formula as in Graphic3d_MaterialAspect::SetColor()
|
||||
Ambient.SetValues (theColor.rgb() * 0.25f, Ambient.a());
|
||||
Diffuse.SetValues (theColor.rgb(), Diffuse.a());
|
||||
Common.Ambient.SetValues (theColor.rgb() * 0.25f, Common.Ambient.a());
|
||||
Common.Diffuse.SetValues (theColor.rgb(), Common.Diffuse.a());
|
||||
Pbr .BaseColor.SetValues (theColor.rgb(), Pbr.BaseColor.a());
|
||||
}
|
||||
|
||||
//! Empty constructor.
|
||||
OpenGl_Material()
|
||||
: Ambient (1.0f),
|
||||
Diffuse (1.0f),
|
||||
Specular(1.0f),
|
||||
Emission(1.0f),
|
||||
Params (1.0f, 0.0f, 0.0f, 0.0f) {}
|
||||
|
||||
//! Initialize material
|
||||
void Init (const OpenGl_Context& theCtx,
|
||||
const Graphic3d_MaterialAspect& theProp,
|
||||
const Quantity_Color& theInteriorColor);
|
||||
|
||||
//! Returns packed (serialized) representation of material properties
|
||||
const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
|
||||
static Standard_Integer NbOfVec4() { return 5; }
|
||||
|
||||
//! Check this material for equality with another material (without tolerance!).
|
||||
bool IsEqual (const OpenGl_Material& theOther) const
|
||||
{
|
||||
|
487
src/OpenGl/OpenGl_PBREnvironment.cxx
Normal file
487
src/OpenGl/OpenGl_PBREnvironment.cxx
Normal file
@ -0,0 +1,487 @@
|
||||
// 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 <OpenGl_PBREnvironment.hxx>
|
||||
|
||||
#include <Graphic3d_PBRMaterial.hxx>
|
||||
#include <OpenGl_ArbFBO.hxx>
|
||||
#include <OpenGl_FrameBuffer.hxx>
|
||||
#include <OpenGl_ShaderManager.hxx>
|
||||
#include <OSD_Timer.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_PBREnvironment, OpenGl_NamedResource)
|
||||
|
||||
//! Constructor of this class saves necessary OpenGL states components which can be changed by OpenGl_PBREnvironment.
|
||||
//! Destructor restores state back.
|
||||
class OpenGl_PBREnvironmentSentry
|
||||
{
|
||||
public:
|
||||
|
||||
OpenGl_PBREnvironmentSentry (const Handle(OpenGl_Context)& theCtx)
|
||||
: myContext (theCtx)
|
||||
{
|
||||
backup();
|
||||
prepare();
|
||||
}
|
||||
|
||||
~OpenGl_PBREnvironmentSentry()
|
||||
{
|
||||
restore();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void backup()
|
||||
{
|
||||
myContext->core11fwd->glGetIntegerv (GL_FRAMEBUFFER_BINDING, &myFBO);
|
||||
myShaderProgram = myContext->ActiveProgram();
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
myViewport[i] = myContext->Viewport()[i];
|
||||
}
|
||||
myContext->core11fwd->glGetFloatv (GL_COLOR_CLEAR_VALUE, myClearColor);
|
||||
|
||||
GLboolean aStatus = GL_TRUE;
|
||||
myContext->core11fwd->glGetBooleanv (GL_DEPTH_TEST, &aStatus);
|
||||
myDepthTestWasEnabled = aStatus ? Standard_True : Standard_False;
|
||||
myContext->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aStatus);
|
||||
myDepthWrirtingWasEnablig = aStatus ? Standard_True : Standard_False;
|
||||
myContext->core11fwd->glGetBooleanv (GL_SCISSOR_TEST, &aStatus);
|
||||
myScissorTestWasEnabled = aStatus ? Standard_True : Standard_False;
|
||||
myContext->core11fwd->glGetIntegerv (GL_SCISSOR_BOX, myScissorBox);
|
||||
}
|
||||
|
||||
void prepare()
|
||||
{
|
||||
myContext->BindDefaultVao();
|
||||
myContext->core11fwd->glDisable (GL_DEPTH_TEST);
|
||||
myContext->core11fwd->glDepthMask (GL_FALSE);
|
||||
myContext->core11fwd->glDisable (GL_BLEND);
|
||||
myContext->core11fwd->glDisable (GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void restore()
|
||||
{
|
||||
myContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myFBO);
|
||||
myContext->BindProgram (myShaderProgram);
|
||||
myContext->ResizeViewport (myViewport);
|
||||
myContext->core11fwd->glClearColor (myClearColor.r(), myClearColor.g(), myClearColor.b(), myClearColor.a());
|
||||
if (myDepthTestWasEnabled)
|
||||
{
|
||||
myContext->core11fwd->glEnable (GL_DEPTH_TEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
myContext->core11fwd->glDisable (GL_DEPTH_TEST);
|
||||
}
|
||||
myContext->core11fwd->glDepthMask (myDepthWrirtingWasEnablig ? GL_TRUE : GL_FALSE);
|
||||
if (myScissorTestWasEnabled)
|
||||
{
|
||||
myContext->core11fwd->glEnable (GL_SCISSOR_TEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
myContext->core11fwd->glDisable (GL_SCISSOR_TEST);
|
||||
}
|
||||
myContext->core11fwd->glScissor (myScissorBox[0], myScissorBox[1], myScissorBox[2], myScissorBox[3]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
OpenGl_PBREnvironmentSentry (const OpenGl_PBREnvironmentSentry& );
|
||||
OpenGl_PBREnvironmentSentry& operator= (const OpenGl_PBREnvironmentSentry& );
|
||||
|
||||
private:
|
||||
|
||||
const Handle(OpenGl_Context) myContext;
|
||||
GLint myFBO;
|
||||
Handle(OpenGl_ShaderProgram) myShaderProgram;
|
||||
Standard_Boolean myDepthTestWasEnabled;
|
||||
Standard_Boolean myDepthWrirtingWasEnablig;
|
||||
Standard_Boolean myScissorTestWasEnabled;
|
||||
Standard_Integer myScissorBox[4];
|
||||
Standard_Integer myViewport[4];
|
||||
Graphic3d_Vec4 myClearColor;
|
||||
|
||||
};
|
||||
|
||||
// =======================================================================
|
||||
// function : Create
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Handle(OpenGl_PBREnvironment) OpenGl_PBREnvironment::Create (const Handle(OpenGl_Context)& theCtx,
|
||||
unsigned int thePow2Size,
|
||||
unsigned int theLevelsNumber,
|
||||
const TCollection_AsciiString& theId)
|
||||
{
|
||||
if (theCtx->arbFBO == NULL)
|
||||
{
|
||||
return Handle(OpenGl_PBREnvironment)();
|
||||
}
|
||||
|
||||
Handle(OpenGl_PBREnvironment) anEnvironment = new OpenGl_PBREnvironment (theCtx, thePow2Size, theLevelsNumber, theId);
|
||||
if (!anEnvironment->IsComplete())
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
|
||||
"Warning: PBR environment is not created. PBR material system will be ignored.");
|
||||
anEnvironment->Release (theCtx.get());
|
||||
anEnvironment.Nullify();
|
||||
}
|
||||
|
||||
return anEnvironment;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OpenGl_PBREnvironment
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
OpenGl_PBREnvironment::OpenGl_PBREnvironment (const Handle(OpenGl_Context)& theCtx,
|
||||
unsigned int thePowOf2Size,
|
||||
unsigned int theSpecMapLevelsNumber,
|
||||
const TCollection_AsciiString& theId)
|
||||
: OpenGl_NamedResource (theId),
|
||||
myPow2Size (std::max (1u, thePowOf2Size)),
|
||||
mySpecMapLevelsNumber (std::max (2u, std::min (theSpecMapLevelsNumber, std::max (1u, thePowOf2Size) + 1))),
|
||||
myFBO (OpenGl_FrameBuffer::NO_FRAMEBUFFER),
|
||||
myIsComplete (Standard_False),
|
||||
myIsNeededToBeBound (Standard_True)
|
||||
{
|
||||
OpenGl_PBREnvironmentSentry aSentry (theCtx);
|
||||
|
||||
myIsComplete = initVAO (theCtx)
|
||||
&& initTextures (theCtx)
|
||||
&& initFBO (theCtx);
|
||||
|
||||
if (myIsComplete)
|
||||
{
|
||||
clear (theCtx);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Bind
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_PBREnvironment::Bind (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].Bind (theCtx);
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular] .Bind (theCtx);
|
||||
myIsNeededToBeBound = Standard_False;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Unbind
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_PBREnvironment::Unbind (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].Unbind (theCtx);
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular] .Unbind (theCtx);
|
||||
myIsNeededToBeBound = Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Clear
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_PBREnvironment::Clear (const Handle(OpenGl_Context)& theCtx,
|
||||
const Graphic3d_Vec3& theColor)
|
||||
{
|
||||
OpenGl_PBREnvironmentSentry aSentry (theCtx);
|
||||
clear (theCtx, theColor);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Bake
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_PBREnvironment::Bake (const Handle(OpenGl_Context)& theCtx,
|
||||
const Handle(OpenGl_Texture)& theEnvMap,
|
||||
Standard_Boolean theZIsInverted,
|
||||
Standard_Boolean theIsTopDown,
|
||||
Standard_Size theDiffMapNbSamples,
|
||||
Standard_Size theSpecMapNbSamples,
|
||||
Standard_ShortReal theProbability)
|
||||
{
|
||||
Standard_ProgramError_Raise_if (theEnvMap.IsNull(), "'Bake' function of 'OpenGl_PBREnvironment' can't work without source environment map")
|
||||
Standard_RangeError_Raise_if (theProbability > 1.f || theProbability < 0.f, "'probability' parameter in 'Bake' function of 'OpenGl_PBREnvironment' must be in range [0, 1]")
|
||||
Unbind (theCtx);
|
||||
OpenGl_PBREnvironmentSentry aSentry (theCtx);
|
||||
bake (theCtx, theEnvMap, theZIsInverted, theIsTopDown, theDiffMapNbSamples, theSpecMapNbSamples, theProbability);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SizesAreDifferent
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_PBREnvironment::SizesAreDifferent (unsigned int thePow2Size,
|
||||
unsigned int theSpecMapLevelsNumber) const
|
||||
{
|
||||
thePow2Size = std::max (1u, thePow2Size);
|
||||
theSpecMapLevelsNumber = std::max (2u, std::min (theSpecMapLevelsNumber, std::max (1u, thePow2Size) + 1));
|
||||
return myPow2Size != thePow2Size
|
||||
|| mySpecMapLevelsNumber != theSpecMapLevelsNumber;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Release
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_PBREnvironment::Release (OpenGl_Context* theCtx)
|
||||
{
|
||||
if (myFBO != OpenGl_FrameBuffer::NO_FRAMEBUFFER)
|
||||
{
|
||||
if (theCtx != NULL
|
||||
&& theCtx->IsValid())
|
||||
{
|
||||
theCtx->arbFBO->glDeleteFramebuffers (1, &myFBO);
|
||||
}
|
||||
myFBO = OpenGl_FrameBuffer::NO_FRAMEBUFFER;
|
||||
}
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].Release(theCtx);
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular] .Release (theCtx);
|
||||
myVBO.Release (theCtx);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~OpenGl_PBREnvironment
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
OpenGl_PBREnvironment::~OpenGl_PBREnvironment()
|
||||
{
|
||||
Release (NULL);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : initTextures
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_PBREnvironment::initTextures (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular] .Sampler()->Parameters()->SetTextureUnit (theCtx->PBRSpecIBLMapTexUnit());
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].Sampler()->Parameters()->SetTextureUnit (theCtx->PBRDiffIBLMapSHTexUnit());
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular] .Sampler()->Parameters()->SetFilter (Graphic3d_TOTF_TRILINEAR);
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].Sampler()->Parameters()->SetFilter(Graphic3d_TOTF_NEAREST);
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular] .Sampler()->Parameters()->SetLevelsRange (mySpecMapLevelsNumber - 1);
|
||||
|
||||
// NVIDIA's driver didn't work properly with 3 channel texture for diffuse SH coefficients so that alpha channel has been added
|
||||
return myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].Init (theCtx,
|
||||
OpenGl_TextureFormat::FindFormat (theCtx, Image_Format_RGBAF, false),
|
||||
Graphic3d_Vec2i (9, 1),
|
||||
Graphic3d_TOT_2D)
|
||||
&& myIBLMaps[OpenGl_TypeOfIBLMap_Specular].InitCubeMap (theCtx, Handle(Graphic3d_CubeMap)(),
|
||||
Standard_Size(1) << myPow2Size, Image_Format_RGB, true, false);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : initVAO
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_PBREnvironment::initVAO (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
const float aVertexPos[] =
|
||||
{
|
||||
-1.f, -1.f, 0.f, 0.f,
|
||||
1.f, -1.f, 0.f, 0.f,
|
||||
-1.f, 1.f, 0.f, 0.f,
|
||||
1.f, 1.f, 0.f, 0.f
|
||||
};
|
||||
return myVBO.Init (theCtx, 4, 4, aVertexPos);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : initFBO
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_PBREnvironment::initFBO (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
theCtx->arbFBO->glGenFramebuffers (1, &myFBO);
|
||||
return checkFBOComplentess (theCtx);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : processDiffIBLMap
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_PBREnvironment::processDiffIBLMap (const Handle(OpenGl_Context)& theCtx,
|
||||
Standard_Boolean theIsDrawAction,
|
||||
Standard_Size theNbSamples)
|
||||
{
|
||||
theCtx->arbFBO->glFramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].TextureId(), 0);
|
||||
const Standard_Integer aViewport[4] = { 0, 0, 9, 1 };
|
||||
theCtx->ResizeViewport(aViewport);
|
||||
if (theIsDrawAction)
|
||||
{
|
||||
theCtx->ActiveProgram()->SetUniform(theCtx, "occNbSpecIBLLevels", 0);
|
||||
theCtx->ActiveProgram()->SetUniform(theCtx, "uSamplesNum", static_cast<Standard_Integer>(theNbSamples));
|
||||
|
||||
theCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
theCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
theCtx->core11fwd->glEnable (GL_SCISSOR_TEST);
|
||||
theCtx->core11fwd->glClearColor (0.f, 0.f, 0.f, 1.f);
|
||||
theCtx->core11fwd->glScissor (1, 0, 8, 1);
|
||||
theCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : processSpecIBLMap
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_PBREnvironment::processSpecIBLMap (const Handle(OpenGl_Context)& theCtx,
|
||||
Standard_Boolean theIsDrawAction,
|
||||
Standard_Integer theEnvMapSize,
|
||||
Standard_Size theNbSamples,
|
||||
Standard_ShortReal theProbability)
|
||||
{
|
||||
if (theIsDrawAction)
|
||||
{
|
||||
theCtx->ActiveProgram()->SetUniform (theCtx, "occNbSpecIBLLevels", Standard_Integer(mySpecMapLevelsNumber));
|
||||
theCtx->ActiveProgram()->SetUniform (theCtx, "uEnvMapSize", theEnvMapSize);
|
||||
}
|
||||
|
||||
for (int aLevelIter = mySpecMapLevelsNumber - 1;; --aLevelIter)
|
||||
{
|
||||
const Standard_Integer aSize = 1 << (myPow2Size - aLevelIter);
|
||||
const Standard_Integer aViewport[4] = { 0, 0, aSize, aSize };
|
||||
theCtx->ResizeViewport (aViewport);
|
||||
if (theIsDrawAction)
|
||||
{
|
||||
Standard_Integer aNbSamples = static_cast<Standard_Integer>(Graphic3d_PBRMaterial::SpecIBLMapSamplesFactor (theProbability, aLevelIter / float (mySpecMapLevelsNumber - 1)) * theNbSamples);
|
||||
theCtx->ActiveProgram()->SetUniform (theCtx, "uSamplesNum", static_cast<Standard_Integer>(aNbSamples));
|
||||
theCtx->ActiveProgram()->SetUniform (theCtx, "uCurrentLevel", aLevelIter);
|
||||
}
|
||||
|
||||
for (Standard_Integer aSideIter = 0; aSideIter < 6; ++aSideIter)
|
||||
{
|
||||
theCtx->arbFBO->glFramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + aSideIter,
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular].TextureId(), aLevelIter);
|
||||
if (theIsDrawAction)
|
||||
{
|
||||
theCtx->ActiveProgram()->SetUniform(theCtx, "uCurrentSide", aSideIter);
|
||||
theCtx->core11fwd->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
theCtx->core11fwd->glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
if (aLevelIter == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : checkFBOCompletness
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_PBREnvironment::checkFBOComplentess (const Handle(OpenGl_Context)& theCtx) const
|
||||
{
|
||||
theCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myFBO);
|
||||
theCtx->arbFBO->glFramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_DiffuseSH].TextureId(), 0);
|
||||
if (theCtx->arbFBO->glCheckFramebufferStatus (GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (Standard_Integer aSideIter = 0; aSideIter < 6; ++aSideIter)
|
||||
{
|
||||
for (unsigned int aLevel = 0; aLevel < mySpecMapLevelsNumber; ++aLevel)
|
||||
{
|
||||
theCtx->arbFBO->glFramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + aSideIter,
|
||||
myIBLMaps[OpenGl_TypeOfIBLMap_Specular].TextureId(), aLevel);
|
||||
if (theCtx->arbFBO->glCheckFramebufferStatus (GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : bake
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_PBREnvironment::bake (const Handle(OpenGl_Context)& theCtx,
|
||||
const Handle(OpenGl_Texture)& theEnvMap,
|
||||
Standard_Boolean theZIsInverted,
|
||||
Standard_Boolean theIsTopDown,
|
||||
Standard_Size theDiffNbSamples,
|
||||
Standard_Size theSpecNbSamples,
|
||||
Standard_ShortReal theProbability)
|
||||
{
|
||||
myIsNeededToBeBound = Standard_True;
|
||||
if (!theCtx->ShaderManager()->BindPBREnvBakingProgram())
|
||||
{
|
||||
return;
|
||||
}
|
||||
theEnvMap->Bind (theCtx, theCtx->PBRSpecIBLMapTexUnit());
|
||||
theCtx->ActiveProgram()->SetSampler (theCtx, "uEnvMap", theCtx->PBRSpecIBLMapTexUnit());
|
||||
theCtx->ActiveProgram()->SetUniform (theCtx, "uZCoeff", theZIsInverted ? -1 : 1);
|
||||
theCtx->ActiveProgram()->SetUniform (theCtx, "uYCoeff", theIsTopDown ? 1 : -1);
|
||||
theCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myFBO);
|
||||
myVBO.BindAttribute (theCtx, Graphic3d_TOA_POS);
|
||||
|
||||
OSD_Timer aTimer;
|
||||
aTimer.Start();
|
||||
if (processSpecIBLMap (theCtx, true, theEnvMap->SizeX(), theSpecNbSamples, theProbability)
|
||||
&& processDiffIBLMap (theCtx, true, theDiffNbSamples))
|
||||
{
|
||||
Message::DefaultMessenger()->Send(TCollection_AsciiString()
|
||||
+ "IBL " + myIBLMaps[OpenGl_TypeOfIBLMap_Specular].SizeX() + "x" + myIBLMaps[OpenGl_TypeOfIBLMap_Specular].SizeY()
|
||||
+ " is baked in " + aTimer.ElapsedTime() + " s", Message_Trace);
|
||||
}
|
||||
else
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
TCollection_AsciiString("Error: baking PBR environment ") + myIBLMaps[OpenGl_TypeOfIBLMap_Specular].SizeX()
|
||||
+ "x" + myIBLMaps[OpenGl_TypeOfIBLMap_Specular].SizeY() + " takes too much time!.");
|
||||
clear (theCtx, Graphic3d_Vec3(1.0f));
|
||||
}
|
||||
|
||||
myVBO.UnbindAttribute (theCtx, Graphic3d_TOA_POS);
|
||||
theEnvMap->Unbind (theCtx, theCtx->PBREnvLUTTexUnit());
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : clear
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_PBREnvironment::clear (const Handle(OpenGl_Context)& theCtx,
|
||||
const Graphic3d_Vec3& theColor)
|
||||
{
|
||||
myIsNeededToBeBound = Standard_True;
|
||||
theCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myFBO);
|
||||
theCtx->core11fwd->glClearColor (theColor.r(), theColor.g(), theColor.b(), 1.f);
|
||||
|
||||
processSpecIBLMap (theCtx, false);
|
||||
processDiffIBLMap (theCtx, false);
|
||||
}
|
206
src/OpenGl/OpenGl_PBREnvironment.hxx
Normal file
206
src/OpenGl/OpenGl_PBREnvironment.hxx
Normal file
@ -0,0 +1,206 @@
|
||||
// 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 _OpenGl_PBREnvironment_HeaderFile
|
||||
#define _OpenGl_PBREnvironment_HeaderFile
|
||||
|
||||
#include <OpenGl_Texture.hxx>
|
||||
#include <OpenGl_VertexBuffer.hxx>
|
||||
|
||||
//! This class contains specular and diffuse maps required for Image Base Lighting (IBL) in PBR shading model with it's generation methods.
|
||||
class OpenGl_PBREnvironment : public OpenGl_NamedResource
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(OpenGl_PBREnvironment, OpenGl_NamedResource)
|
||||
public:
|
||||
|
||||
//! Creates and initializes new PBR environment. It is the only way to create OpenGl_PBREnvironment.
|
||||
//! @param theCtx OpenGL context where environment will be created
|
||||
//! @param thePow2Size final size of texture's sides can be calculated as 2^thePow2Size;
|
||||
//! if thePow2Size less than 1 it will be set to 1
|
||||
//! @param theSpecMapLevelsNum number of mipmap levels used in specular IBL map;
|
||||
//! if theSpecMapLevelsNum less than 2 or less than Pow2Size + 1 it will be set to the corresponding values.
|
||||
//! @param theId OpenGl_Resource name
|
||||
//! @return handle to created PBR environment or NULL handle in case of fail
|
||||
Standard_EXPORT static Handle(OpenGl_PBREnvironment) Create (const Handle(OpenGl_Context)& theCtx,
|
||||
unsigned int thePow2Size = 9,
|
||||
unsigned int theSpecMapLevelsNum = 6,
|
||||
const TCollection_AsciiString& theId = "PBREnvironment");
|
||||
|
||||
public:
|
||||
|
||||
//! Binds diffuse and specular IBL maps to the corresponding texture units.
|
||||
Standard_EXPORT void Bind (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Unbinds diffuse and specular IBL maps.
|
||||
Standard_EXPORT void Unbind (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Fills all mipmaps of specular IBL map and diffuse IBL map with one color.
|
||||
//! So that environment illumination will be constant.
|
||||
Standard_EXPORT void Clear (const Handle(OpenGl_Context)& theCtx,
|
||||
const Graphic3d_Vec3& theColor = Graphic3d_Vec3 (1.f));
|
||||
|
||||
//! Generates specular and diffuse (irradiance) IBL maps.
|
||||
//! @param theCtx OpenGL context
|
||||
//! @param theEnvMap source environment map
|
||||
//! @param theZIsInverted flags indicates whether environment cubemap has inverted Z axis or not
|
||||
//! @param theIsTopDown flags indicates whether environment cubemap has top-down memory layout or not
|
||||
//! @param theDiffMapNbSamples number of samples in Monte-Carlo integration for diffuse IBL spherical harmonics calculation
|
||||
//! @param theSpecMapNbSamples number of samples in Monte-Carlo integration for specular IBL map generation
|
||||
//! @param theProbability controls strength of samples number reducing strategy during specular IBL map baking (see 'SpecIBLMapSamplesFactor' for details)
|
||||
//! theZIsInverted and theIsTopDown can be taken from Graphic3d_CubeMap source of environment cubemap.
|
||||
//! theDiffMapNbSamples and theSpecMapNbSamples is the main parameter directly affected to performance.
|
||||
Standard_EXPORT void Bake (const Handle(OpenGl_Context)& theCtx,
|
||||
const Handle(OpenGl_Texture)& theEnvMap,
|
||||
Standard_Boolean theZIsInverted = Standard_False,
|
||||
Standard_Boolean theIsTopDown = Standard_True,
|
||||
Standard_Size theDiffMapNbSamples = 1024,
|
||||
Standard_Size theSpecMapNbSamples = 256,
|
||||
Standard_ShortReal theProbability = 0.99f);
|
||||
|
||||
//! Returns number of mipmap levels used in specular IBL map.
|
||||
//! It can be different from value passed to creation method.
|
||||
unsigned int SpecMapLevelsNumber() const { return mySpecMapLevelsNumber; }
|
||||
|
||||
//! Returns size of IBL maps sides as power of 2.
|
||||
//! So that the real size can be calculated as 2^Pow2Size()
|
||||
unsigned int Pow2Size() const { return myPow2Size; }
|
||||
|
||||
//! Checks whether the given sizes affects to the current ones.
|
||||
//! It can be imagined as creation of new PBR environment.
|
||||
//! If creation method with this values returns the PBR environment having real sizes which are equals to current ones
|
||||
//! then this method will return false.
|
||||
//! It is handful when sizes are required to be changed.
|
||||
//! If this method returns false there is no reason to recreate PBR environment in order to change sizes.
|
||||
Standard_EXPORT bool SizesAreDifferent (unsigned int thePow2Size,
|
||||
unsigned int theSpecMapLevelsNumber) const;
|
||||
|
||||
//! Indicates whether IBL map's textures have to be bound or it is not obligate.
|
||||
bool IsNeededToBeBound() const
|
||||
{
|
||||
return myIsNeededToBeBound;
|
||||
}
|
||||
|
||||
//! Releases all OpenGL resources.
|
||||
//! It must be called before destruction.
|
||||
Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
|
||||
|
||||
//! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
|
||||
virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE
|
||||
{
|
||||
unsigned int aDiffIBLMapSidePixelsCount = 1 << myPow2Size;
|
||||
aDiffIBLMapSidePixelsCount *= aDiffIBLMapSidePixelsCount;
|
||||
Standard_Size anEstimatedDataSize = aDiffIBLMapSidePixelsCount;
|
||||
for (unsigned int i = 0; i < mySpecMapLevelsNumber; ++i)
|
||||
{
|
||||
anEstimatedDataSize += aDiffIBLMapSidePixelsCount >> (2 * i);
|
||||
}
|
||||
anEstimatedDataSize *= 6; // cubemap sides
|
||||
anEstimatedDataSize *= 3; // channels
|
||||
return anEstimatedDataSize;
|
||||
}
|
||||
|
||||
//! Checks completeness of PBR environment.
|
||||
//! Creation method returns only completed objects or null handles otherwise.
|
||||
Standard_Boolean IsComplete() const { return myIsComplete; }
|
||||
|
||||
//! Destructor.
|
||||
//! Warning! 'Release' method must be called before destruction.
|
||||
//! Otherwise unhandled critical error will be generated.
|
||||
Standard_EXPORT virtual ~OpenGl_PBREnvironment();
|
||||
|
||||
private:
|
||||
|
||||
//! Creates new PBR environment.
|
||||
//! Parameters and logic are described in 'Create' method documentation.
|
||||
Standard_EXPORT OpenGl_PBREnvironment (const Handle(OpenGl_Context)& theCtx,
|
||||
unsigned int thePowOf2Size = 9,
|
||||
unsigned int theSpecMapLevelsNumber = 6,
|
||||
const TCollection_AsciiString& theId = "PBREnvironment");
|
||||
|
||||
private:
|
||||
|
||||
//! Enum classified the type of IBL map
|
||||
enum OpenGl_TypeOfIBLMap
|
||||
{
|
||||
OpenGl_TypeOfIBLMap_DiffuseSH,
|
||||
OpenGl_TypeOfIBLMap_Specular
|
||||
};
|
||||
|
||||
//! Initializes all textures.
|
||||
//! @return false in case of failed texture initialization
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
bool initTextures (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Creates frame buffer object for IBL maps generation.
|
||||
//! @return false in case of failed FBO initialization
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
bool initFBO (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Initializes vertex buffer object of screen rectangle.
|
||||
//! @return false in case of failed creation
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
bool initVAO (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Responses for diffuse (irradiance) IBL map processing.
|
||||
//! @return false in case of failed baking or clearing
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
bool processDiffIBLMap (const Handle(OpenGl_Context)& theCtx,
|
||||
Standard_Boolean theIsDrawAction,
|
||||
Standard_Size theNbSamples = 0);
|
||||
|
||||
//! Responses for specular IBL map processing.
|
||||
//! @return false in case of failed baking or clearing
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
bool processSpecIBLMap (const Handle(OpenGl_Context)& theCtx,
|
||||
Standard_Boolean theIsDrawAction,
|
||||
Standard_Integer theEnvMapSize = 1024,
|
||||
Standard_Size theNbSamples = 0,
|
||||
Standard_ShortReal theProbability = 1.f);
|
||||
|
||||
//! Checks completeness of frame buffer object for all targets
|
||||
//! (all cube map sides and levels of IBL maps).
|
||||
//! @return false in case of uncompleted frame buffer object.
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
bool checkFBOComplentess (const Handle(OpenGl_Context)& theCtx) const;
|
||||
|
||||
//! Version of 'Bake' without OpenGl_PBREnvironmentSetnry.
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
void bake (const Handle(OpenGl_Context)& theCtx,
|
||||
const Handle(OpenGl_Texture)& theEnvMap,
|
||||
Standard_Boolean theZIsInverted = Standard_False,
|
||||
Standard_Boolean theIsTopDown = Standard_True,
|
||||
Standard_Size theDiffMapNbSamples = 1024,
|
||||
Standard_Size theSpecMapNbSamples = 256,
|
||||
Standard_ShortReal theProbability = 1.f);
|
||||
|
||||
//! Version of 'Clear' without OpenGl_PBREnvironmentSetnry.
|
||||
//! Warning! Requires using of OpenGl_PBREnvironmentSentry.
|
||||
void clear (const Handle(OpenGl_Context)& theCtx,
|
||||
const Graphic3d_Vec3& theColor = Graphic3d_Vec3 (1.f));
|
||||
|
||||
private:
|
||||
|
||||
unsigned int myPow2Size; //!< size of IBL maps sides (real size can be calculated as 2^myPow2Size)
|
||||
unsigned int mySpecMapLevelsNumber; //!< number of mipmap levels used in specular IBL map
|
||||
|
||||
OpenGl_Texture myIBLMaps[2]; //!< IBL maps
|
||||
OpenGl_VertexBuffer myVBO; //!< vertex buffer object of screen rectangular
|
||||
GLuint myFBO; //!< frame buffer object to generate or clear IBL maps
|
||||
|
||||
Standard_Boolean myIsComplete; //!< completeness of PBR environment
|
||||
Standard_Boolean myIsNeededToBeBound; //!< indicates whether IBL map's textures have to be bound or it is not obligate
|
||||
|
||||
};
|
||||
|
||||
#endif // _OpenGl_PBREnvironment_HeaderFile
|
@ -223,7 +223,8 @@ void OpenGl_Sampler::applySamplerParams (const Handle(OpenGl_Context)& theCtx,
|
||||
}
|
||||
#endif
|
||||
setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_T, aWrapMode);
|
||||
if (theTarget == GL_TEXTURE_3D)
|
||||
if (theTarget == GL_TEXTURE_3D
|
||||
|| theTarget == GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_WRAP_R, aWrapMode);
|
||||
return;
|
||||
@ -261,6 +262,13 @@ void OpenGl_Sampler::applySamplerParams (const Handle(OpenGl_Context)& theCtx,
|
||||
|
||||
setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
|
||||
}
|
||||
|
||||
if (theCtx->IsGlGreaterEqual(1, 2) &&
|
||||
(theSampler == NULL || !theSampler->isValidSampler()))
|
||||
{
|
||||
setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_BASE_LEVEL, theParams->BaseLevel());
|
||||
setParameter (theCtx, theSampler, theTarget, GL_TEXTURE_MAX_LEVEL, theParams->MaxLevel());
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@ -19,14 +19,22 @@
|
||||
#include <OpenGl_Aspects.hxx>
|
||||
#include <OpenGl_ClippingIterator.hxx>
|
||||
#include <OpenGl_Context.hxx>
|
||||
#include <Graphic3d_CubeMapPacked.hxx>
|
||||
#include <OpenGl_ShaderManager.hxx>
|
||||
#include <OpenGl_ShaderProgram.hxx>
|
||||
#include <OpenGl_VertexBufferCompat.hxx>
|
||||
#include <OpenGl_PointSprite.hxx>
|
||||
#include <OpenGl_Workspace.hxx>
|
||||
|
||||
#include <TCollection_ExtendedString.hxx>
|
||||
|
||||
#include "../Shaders/Shaders_PBRDistribution_glsl.pxx"
|
||||
#include "../Shaders/Shaders_PBRGeometry_glsl.pxx"
|
||||
#include "../Shaders/Shaders_PBRFresnel_glsl.pxx"
|
||||
#include "../Shaders/Shaders_PBRCookTorrance_glsl.pxx"
|
||||
#include "../Shaders/Shaders_PBRIllumination_glsl.pxx"
|
||||
#include "../Shaders/Shaders_PBREnvBaking_fs.pxx"
|
||||
#include "../Shaders/Shaders_PBREnvBaking_vs.pxx"
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
|
||||
|
||||
namespace
|
||||
@ -57,8 +65,8 @@ const char THE_VARY_TexCoord_Trsf[] =
|
||||
//! Auxiliary function to flip gl_PointCoord vertically
|
||||
#define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
|
||||
|
||||
//! Auxiliary function to transform normal
|
||||
const char THE_FUNC_transformNormal[] =
|
||||
//! Auxiliary function to transform normal from model to view coordinate system.
|
||||
const char THE_FUNC_transformNormal_view[] =
|
||||
EOL"vec3 transformNormal (in vec3 theNormal)"
|
||||
EOL"{"
|
||||
EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
|
||||
@ -67,12 +75,31 @@ const char THE_FUNC_transformNormal[] =
|
||||
EOL" return normalize (aResult.xyz);"
|
||||
EOL"}";
|
||||
|
||||
//! The same function as THE_FUNC_transformNormal but is used in PBR pipeline.
|
||||
//! The normals are expected to be in world coordinate system in PBR pipeline.
|
||||
const char THE_FUNC_transformNormal_world[] =
|
||||
EOL"vec3 transformNormal (in vec3 theNormal)"
|
||||
EOL"{"
|
||||
EOL" vec4 aResult = occModelWorldMatrixInverseTranspose"
|
||||
EOL" * vec4 (theNormal, 0.0);"
|
||||
EOL" return normalize (aResult.xyz);"
|
||||
EOL"}";
|
||||
|
||||
//! Global shader variable for color definition with lighting enabled.
|
||||
const char THE_FUNC_lightDef[] =
|
||||
EOL"vec3 Ambient;" //!< Ambient contribution of light sources
|
||||
EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
|
||||
EOL"vec3 Specular;"; //!< Specular contribution of light sources
|
||||
|
||||
//! Global shader variable for color definition with lighting enabled.
|
||||
const char THE_FUNC_PBR_lightDef[] =
|
||||
EOL"vec3 DirectLighting;" //!< Accumulator of direct lighting from light sources
|
||||
EOL"vec4 BaseColor;" //!< Base color (albedo) of material for PBR
|
||||
EOL"float Metallic;" //!< Metallic coefficient of material
|
||||
EOL"float Roughness;" //!< Roughness coefficient of material
|
||||
EOL"vec3 Emission;" //!< Light intensity emitted by material
|
||||
EOL"float IOR;"; //!< Material's index of refraction
|
||||
|
||||
//! Function computes contribution of isotropic point light source
|
||||
const char THE_FUNC_pointLight[] =
|
||||
EOL"void pointLight (in int theId,"
|
||||
@ -82,7 +109,7 @@ const char THE_FUNC_pointLight[] =
|
||||
EOL" in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" vec3 aLight = occLight_Position (theId).xyz;"
|
||||
EOL" if (occLight_IsHeadlight (theId) == 0)"
|
||||
EOL" if (!occLight_IsHeadlight (theId))"
|
||||
EOL" {"
|
||||
EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
|
||||
EOL" }"
|
||||
@ -110,6 +137,38 @@ const char THE_FUNC_pointLight[] =
|
||||
EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
|
||||
EOL"}";
|
||||
|
||||
//! Function computes contribution of isotropic point light source
|
||||
const char THE_FUNC_PBR_pointLight[] =
|
||||
EOL"void pointLight (in int theId,"
|
||||
EOL" in vec3 theNormal,"
|
||||
EOL" in vec3 theView,"
|
||||
EOL" in vec3 thePoint,"
|
||||
EOL" in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" vec3 aLight = occLight_Position (theId).xyz;"
|
||||
EOL" if (occLight_IsHeadlight (theId))"
|
||||
EOL" {"
|
||||
EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
|
||||
EOL" }"
|
||||
EOL" aLight -= thePoint;"
|
||||
EOL
|
||||
EOL" float aDist = length (aLight);"
|
||||
EOL" aLight /= aDist;"
|
||||
EOL
|
||||
EOL" float anAtten = 1.0 / max (aDist * aDist, 0.01);"
|
||||
EOL
|
||||
EOL" theNormal = theIsFront ? theNormal : -theNormal;"
|
||||
EOL" DirectLighting += occPBRIllumination (theView,"
|
||||
EOL" aLight,"
|
||||
EOL" theNormal,"
|
||||
EOL" BaseColor,"
|
||||
EOL" Metallic,"
|
||||
EOL" Roughness,"
|
||||
EOL" IOR,"
|
||||
EOL" occLight_Specular(theId).rgb,"
|
||||
EOL" occLight_Intensity(theId) * anAtten);"
|
||||
EOL"}";
|
||||
|
||||
//! Function computes contribution of spotlight source
|
||||
const char THE_FUNC_spotLight[] =
|
||||
EOL"void spotLight (in int theId,"
|
||||
@ -120,7 +179,7 @@ const char THE_FUNC_spotLight[] =
|
||||
EOL"{"
|
||||
EOL" vec3 aLight = occLight_Position (theId).xyz;"
|
||||
EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
|
||||
EOL" if (occLight_IsHeadlight (theId) == 0)"
|
||||
EOL" if (!occLight_IsHeadlight (theId))"
|
||||
EOL" {"
|
||||
EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
|
||||
EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
|
||||
@ -162,6 +221,53 @@ const char THE_FUNC_spotLight[] =
|
||||
EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
|
||||
EOL"}";
|
||||
|
||||
//! Function computes contribution of spotlight source
|
||||
const char THE_FUNC_PBR_spotLight[] =
|
||||
EOL"void spotLight (in int theId,"
|
||||
EOL" in vec3 theNormal,"
|
||||
EOL" in vec3 theView,"
|
||||
EOL" in vec3 thePoint,"
|
||||
EOL" in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" vec3 aLight = occLight_Position (theId).xyz;"
|
||||
EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
|
||||
EOL" if (occLight_IsHeadlight (theId))"
|
||||
EOL" {"
|
||||
EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
|
||||
EOL" aSpotDir = vec3 (occWorldViewMatrixInverse * vec4 (aSpotDir, 0.0));"
|
||||
EOL" }"
|
||||
EOL" aLight -= thePoint;"
|
||||
EOL
|
||||
EOL" float aDist = length (aLight);"
|
||||
EOL" aLight /= aDist;"
|
||||
EOL
|
||||
EOL" aSpotDir = normalize (aSpotDir);"
|
||||
// light cone
|
||||
EOL" float aCosA = dot (aSpotDir, -aLight);"
|
||||
EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
|
||||
EOL" {"
|
||||
EOL" return;"
|
||||
EOL" }"
|
||||
EOL
|
||||
EOL" float anExponent = occLight_SpotExponent (theId);"
|
||||
EOL" float anAtten = 1.0 / max (aDist * aDist, 0.01);"
|
||||
EOL" if (anExponent > 0.0)"
|
||||
EOL" {"
|
||||
EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
|
||||
EOL" }"
|
||||
EOL
|
||||
EOL" theNormal = theIsFront ? theNormal : -theNormal;"
|
||||
EOL" DirectLighting += occPBRIllumination (theView,"
|
||||
EOL" aLight,"
|
||||
EOL" theNormal,"
|
||||
EOL" BaseColor,"
|
||||
EOL" Metallic,"
|
||||
EOL" Roughness,"
|
||||
EOL" IOR,"
|
||||
EOL" occLight_Specular(theId).rgb,"
|
||||
EOL" occLight_Intensity(theId) * anAtten);"
|
||||
EOL"}";
|
||||
|
||||
//! Function computes contribution of directional light source
|
||||
const char THE_FUNC_directionalLight[] =
|
||||
EOL"void directionalLight (in int theId,"
|
||||
@ -170,7 +276,7 @@ const char THE_FUNC_directionalLight[] =
|
||||
EOL" in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
|
||||
EOL" if (occLight_IsHeadlight (theId) == 0)"
|
||||
EOL" if (!occLight_IsHeadlight (theId))"
|
||||
EOL" {"
|
||||
EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
|
||||
EOL" }"
|
||||
@ -191,6 +297,31 @@ const char THE_FUNC_directionalLight[] =
|
||||
EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
|
||||
EOL"}";
|
||||
|
||||
//! Function computes contribution of directional light source
|
||||
const char THE_FUNC_PBR_directionalLight[] =
|
||||
EOL"void directionalLight (in int theId,"
|
||||
EOL" in vec3 theNormal,"
|
||||
EOL" in vec3 theView,"
|
||||
EOL" in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
|
||||
EOL" if (occLight_IsHeadlight (theId))"
|
||||
EOL" {"
|
||||
EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 0.0));"
|
||||
EOL" }"
|
||||
EOL
|
||||
EOL" theNormal = theIsFront ? theNormal : -theNormal;"
|
||||
EOL" DirectLighting += occPBRIllumination (theView,"
|
||||
EOL" aLight,"
|
||||
EOL" theNormal,"
|
||||
EOL" BaseColor,"
|
||||
EOL" Metallic,"
|
||||
EOL" Roughness,"
|
||||
EOL" IOR,"
|
||||
EOL" occLight_Specular(theId).rgb,"
|
||||
EOL" occLight_Intensity(theId));"
|
||||
EOL"}";
|
||||
|
||||
//! The same as THE_FUNC_directionalLight but for the light with zero index
|
||||
//! (avoids limitations on some mobile devices).
|
||||
const char THE_FUNC_directionalLightFirst[] =
|
||||
@ -199,7 +330,7 @@ const char THE_FUNC_directionalLightFirst[] =
|
||||
EOL" in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" vec3 aLight = normalize (occLightSources[1].xyz);"
|
||||
EOL" if (occLight_IsHeadlight (0) == 0)"
|
||||
EOL" if (!occLight_IsHeadlight (0))"
|
||||
EOL" {"
|
||||
EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
|
||||
EOL" }"
|
||||
@ -220,6 +351,18 @@ const char THE_FUNC_directionalLightFirst[] =
|
||||
EOL" Specular += occLightSources[0].rgb * aSpecl;"
|
||||
EOL"}";
|
||||
|
||||
//! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip.
|
||||
const char THE_FUNC_cubemap_vector_transform[] =
|
||||
EOL"vec3 cubemapVectorTransform (in vec3 theVector,"
|
||||
EOL" in int theYCoeff,"
|
||||
EOL" in int theZCoeff)"
|
||||
EOL"{"
|
||||
EOL" theVector = theVector.yzx;"
|
||||
EOL" theVector.y *= float(theYCoeff);"
|
||||
EOL" theVector.z *= float(theZCoeff);"
|
||||
EOL" return theVector;"
|
||||
EOL"}";
|
||||
|
||||
//! Process clipping planes in Fragment Shader.
|
||||
//! Should be added at the beginning of the main() function.
|
||||
const char THE_FRAG_CLIP_PLANES_N[] =
|
||||
@ -422,6 +565,10 @@ OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
|
||||
OpenGl_ShaderManager::~OpenGl_ShaderManager()
|
||||
{
|
||||
myProgramList.Clear();
|
||||
if (!myPBREnvironment.IsNull())
|
||||
{
|
||||
myPBREnvironment->Release (myContext);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -585,9 +732,11 @@ void OpenGl_ShaderManager::UpdateSRgbState()
|
||||
// function : UpdateLightSourceStateTo
|
||||
// purpose : Updates state of OCCT light sources
|
||||
// =======================================================================
|
||||
void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights)
|
||||
void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
|
||||
Standard_Integer theSpecIBLMapLevels)
|
||||
{
|
||||
myLightSourceState.Set (theLights);
|
||||
myLightSourceState.SetSpecIBLMapLevels (theSpecIBLMapLevels);
|
||||
myLightSourceState.Update();
|
||||
switchLightPrograms();
|
||||
}
|
||||
@ -768,6 +917,7 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr
|
||||
aLightType.Type = aLight.Type();
|
||||
aLightType.IsHeadlight = aLight.IsHeadlight();
|
||||
aLightParams.Color = aLight.PackedColor();
|
||||
aLightParams.Color.a() = aLight.Intensity(); // used by PBR and ignored by old shading model
|
||||
if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
|
||||
{
|
||||
aLightParams.Position = -aLight.PackedDirection();
|
||||
@ -813,6 +963,11 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr
|
||||
aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
|
||||
myLightParamsArray.First().Packed());
|
||||
}
|
||||
|
||||
if (const OpenGl_ShaderUniformLocation aLocation = theProgram->GetStateLocation (OpenGl_OCCT_NB_SPEC_IBL_LEVELS))
|
||||
{
|
||||
theProgram->SetUniform (myContext, aLocation, myLightSourceState.SpecIBLMapLevels());
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -1164,18 +1319,18 @@ void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)
|
||||
}
|
||||
|
||||
const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Ambient.GetData());
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Diffuse.GetData());
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Specular.GetData());
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Emission.GetData());
|
||||
myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Shine());
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Common.Ambient.GetData());
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Common.Diffuse.GetData());
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Common.Specular.GetData());
|
||||
myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Common.Emission.GetData());
|
||||
myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Common.Shine());
|
||||
if (myMaterialState.ToDistinguish())
|
||||
{
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Ambient.GetData());
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Diffuse.GetData());
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Specular.GetData());
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Emission.GetData());
|
||||
myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Shine());
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Common.Ambient.GetData());
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Common.Diffuse.GetData());
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Common.Specular.GetData());
|
||||
myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Common.Emission.GetData());
|
||||
myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Common.Shine());
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
@ -1191,15 +1346,25 @@ void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)
|
||||
theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
|
||||
myMaterialState.ToDistinguish() ? 1 : 0);
|
||||
|
||||
if (const OpenGl_ShaderUniformLocation aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL))
|
||||
if (const OpenGl_ShaderUniformLocation& aLocPbrFront = theProgram->GetStateLocation (OpenGl_OCCT_PBR_FRONT_MATERIAL))
|
||||
{
|
||||
theProgram->SetUniform (myContext, aLocFront, OpenGl_Material::NbOfVec4(),
|
||||
aFrontMat.Packed());
|
||||
theProgram->SetUniform (myContext, aLocPbrFront, OpenGl_MaterialPBR::NbOfVec4(),
|
||||
aFrontMat.Pbr.Packed());
|
||||
}
|
||||
if (const OpenGl_ShaderUniformLocation aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_BACK_MATERIAL))
|
||||
if (const OpenGl_ShaderUniformLocation aLocPbrBack = theProgram->GetStateLocation (OpenGl_OCCT_PBR_BACK_MATERIAL))
|
||||
{
|
||||
theProgram->SetUniform (myContext, aLocBack, OpenGl_Material::NbOfVec4(),
|
||||
aBackMat.Packed());
|
||||
theProgram->SetUniform (myContext, aLocPbrBack, OpenGl_MaterialPBR::NbOfVec4(),
|
||||
aBackMat.Pbr.Packed());
|
||||
}
|
||||
if (const OpenGl_ShaderUniformLocation aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_FRONT_MATERIAL))
|
||||
{
|
||||
theProgram->SetUniform (myContext, aLocFront, OpenGl_MaterialCommon::NbOfVec4(),
|
||||
aFrontMat.Common.Packed());
|
||||
}
|
||||
if (const OpenGl_ShaderUniformLocation aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_BACK_MATERIAL))
|
||||
{
|
||||
theProgram->SetUniform (myContext, aLocBack, OpenGl_MaterialCommon::NbOfVec4(),
|
||||
aBackMat.Common.Packed());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1614,7 +1779,8 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((theBits & OpenGl_PO_StippleLine) != 0)
|
||||
if ((theBits & OpenGl_PO_StippleLine) != 0
|
||||
|| theProgram->IsPBR())
|
||||
{
|
||||
if (myContext->IsGlGreaterEqual (3, 0))
|
||||
{
|
||||
@ -1654,6 +1820,11 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
|
||||
}
|
||||
else
|
||||
{
|
||||
if (theProgram->IsPBR()
|
||||
&& myContext->IsGlGreaterEqual (3, 0))
|
||||
{
|
||||
theProgram->SetHeader ("#version 300 es");
|
||||
}
|
||||
if ((theBits & OpenGl_PO_WriteOit) != 0
|
||||
|| (theBits & OpenGl_PO_StippleLine) != 0)
|
||||
{
|
||||
@ -1863,7 +2034,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha
|
||||
}
|
||||
else if ((theBits & OpenGl_PO_TextureEnv) != 0)
|
||||
{
|
||||
aSrcVertExtraFunc = THE_FUNC_transformNormal;
|
||||
aSrcVertExtraFunc = THE_FUNC_transformNormal_view;
|
||||
|
||||
aSrcVertExtraMain +=
|
||||
EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
|
||||
@ -2046,7 +2217,8 @@ TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TColl
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
|
||||
Standard_Boolean theHasVertColor)
|
||||
Standard_Boolean theHasVertColor,
|
||||
Standard_Boolean theIsPBR)
|
||||
{
|
||||
TCollection_AsciiString aLightsFunc, aLightsLoop;
|
||||
theNbLights = 0;
|
||||
@ -2122,8 +2294,19 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
|
||||
}
|
||||
aLightsLoop += EOL" }";
|
||||
}
|
||||
|
||||
if (theIsPBR)
|
||||
{
|
||||
aLightsFunc += Shaders_PBRDistribution_glsl;
|
||||
aLightsFunc += Shaders_PBRGeometry_glsl;
|
||||
aLightsFunc += Shaders_PBRFresnel_glsl;
|
||||
aLightsFunc += Shaders_PBRCookTorrance_glsl;
|
||||
aLightsFunc += Shaders_PBRIllumination_glsl;
|
||||
}
|
||||
|
||||
if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
|
||||
&& theNbLights == 1)
|
||||
&& theNbLights == 1
|
||||
&& !theIsPBR)
|
||||
{
|
||||
// use the version with hard-coded first index
|
||||
aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
|
||||
@ -2131,15 +2314,15 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
|
||||
}
|
||||
else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
|
||||
{
|
||||
aLightsFunc += THE_FUNC_directionalLight;
|
||||
aLightsFunc += theIsPBR ? THE_FUNC_PBR_directionalLight : THE_FUNC_directionalLight;
|
||||
}
|
||||
if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
|
||||
{
|
||||
aLightsFunc += THE_FUNC_pointLight;
|
||||
aLightsFunc += theIsPBR ? THE_FUNC_PBR_pointLight : THE_FUNC_pointLight;
|
||||
}
|
||||
if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
|
||||
{
|
||||
aLightsFunc += THE_FUNC_spotLight;
|
||||
aLightsFunc += theIsPBR ? THE_FUNC_PBR_spotLight : THE_FUNC_spotLight;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2151,7 +2334,9 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
|
||||
aGetMatDiffuse = "getVertColor();";
|
||||
}
|
||||
|
||||
return TCollection_AsciiString()
|
||||
if (!theIsPBR)
|
||||
{
|
||||
return TCollection_AsciiString()
|
||||
+ THE_FUNC_lightDef
|
||||
+ aLightsFunc
|
||||
+ EOL
|
||||
@ -2175,6 +2360,42 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
|
||||
EOL" + aMatEmission.rgb;"
|
||||
EOL" return vec4 (aColor, aMatDiffuse.a);"
|
||||
EOL"}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return TCollection_AsciiString()
|
||||
+ THE_FUNC_PBR_lightDef
|
||||
+ aLightsFunc
|
||||
+ EOL
|
||||
EOL"vec4 computeLighting (in vec3 theNormal,"
|
||||
EOL" in vec3 theView,"
|
||||
EOL" in vec4 thePoint,"
|
||||
EOL" in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" DirectLighting = vec3(0.0);"
|
||||
EOL" BaseColor = " + (theHasVertColor ? "getVertColor();" : "getBaseColor (theIsFront);")
|
||||
+ EOL" Metallic = theIsFront ? occPBRFrontMaterial_Metallic() : occPBRBackMaterial_Metallic();"
|
||||
EOL" Roughness = theIsFront ? occPBRFrontMaterial_Roughness() : occPBRBackMaterial_Roughness();"
|
||||
EOL" IOR = theIsFront ? occPBRFrontMaterial_IOR() : occPBRBackMaterial_IOR();"
|
||||
EOL" Emission = theIsFront ? occPBRFrontMaterial_Emission() : occPBRBackMaterial_Emission();"
|
||||
EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
|
||||
+ aLightsLoop
|
||||
+ EOL" vec3 aColor = DirectLighting;"
|
||||
EOL" vec3 anIndirectLightingSpec = occPBRFresnel (BaseColor.rgb, Metallic, IOR);"
|
||||
EOL" Roughness = theIsFront ? occPBRFrontMaterial_NormalizedRoughness() : occPBRBackMaterial_NormalizedRoughness();"
|
||||
EOL" vec2 aCoeff = occTexture2D (occEnvLUT, vec2(abs(dot(theView, theNormal)), Roughness)).xy;"
|
||||
EOL" anIndirectLightingSpec *= aCoeff.x;"
|
||||
EOL" anIndirectLightingSpec += aCoeff.y;"
|
||||
EOL" anIndirectLightingSpec *= occTextureCubeLod (occSpecIBLMap, -reflect (theView, theNormal), Roughness * float (occNbSpecIBLLevels - 1)).rgb;"
|
||||
EOL" vec3 aRefractionCoeff = 1.0 - occPBRFresnel (BaseColor.rgb, Metallic, Roughness, IOR, abs(dot(theView, theNormal)));"
|
||||
EOL" aRefractionCoeff *= (1.0 - Metallic);"
|
||||
EOL" vec3 anIndirectLightingDiff = aRefractionCoeff * BaseColor.rgb * BaseColor.a;"
|
||||
EOL" anIndirectLightingDiff *= occDiffIBLMap (theNormal).rgb;"
|
||||
EOL" aColor += occLightAmbient.rgb * (anIndirectLightingDiff + anIndirectLightingSpec);"
|
||||
EOL" aColor += Emission;"
|
||||
EOL" return vec4 (aColor, mix(1.0, BaseColor.a, aRefractionCoeff.x));"
|
||||
EOL"}";
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -2278,9 +2499,9 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
|
||||
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
|
||||
|
||||
Standard_Integer aNbLights = 0;
|
||||
const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty());
|
||||
const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false);
|
||||
aSrcVert = TCollection_AsciiString()
|
||||
+ THE_FUNC_transformNormal
|
||||
+ THE_FUNC_transformNormal_view
|
||||
+ EOL
|
||||
+ aSrcVertColor
|
||||
+ aLights
|
||||
@ -2334,9 +2555,12 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
|
||||
// =======================================================================
|
||||
Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
|
||||
const Standard_Integer theBits,
|
||||
const Standard_Boolean theIsFlatNormal)
|
||||
const Standard_Boolean theIsFlatNormal,
|
||||
const Standard_Boolean theIsPBR)
|
||||
{
|
||||
#define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
|
||||
TCollection_AsciiString aPosition = theIsPBR ? "PositionWorld" : "Position";
|
||||
TCollection_AsciiString aPhongCompLight = TCollection_AsciiString() +
|
||||
"computeLighting (normalize (Normal), normalize (View), " + aPosition + ", gl_FrontFacing)";
|
||||
const bool isFlatNormal = theIsFlatNormal
|
||||
&& myContext->hasFlatShading != OpenGl_FeatureNotAvailable;
|
||||
const char* aDFdxSignReversion = "";
|
||||
@ -2357,9 +2581,16 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
|
||||
}
|
||||
#endif
|
||||
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
|
||||
aProgramSrc->SetPBR (theIsPBR);
|
||||
|
||||
TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain;
|
||||
TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
|
||||
TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
|
||||
TCollection_AsciiString aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void) { return " + aPhongCompLight + "; }";
|
||||
TCollection_AsciiString aSrcFragPBRGetBaseColor = TCollection_AsciiString() +
|
||||
EOL"vec4 getBaseColor(in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" return theIsFront ? occPBRFrontMaterial_Color() : occPBRBackMaterial_Color();"
|
||||
EOL"}";
|
||||
OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
|
||||
if ((theBits & OpenGl_PO_IsPoint) != 0)
|
||||
{
|
||||
@ -2378,7 +2609,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
|
||||
#endif
|
||||
|
||||
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
|
||||
aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
|
||||
aSrcFragGetColor = pointSpriteShadingSrc (aPhongCompLight, theBits);
|
||||
}
|
||||
|
||||
if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB
|
||||
@ -2399,12 +2630,24 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
|
||||
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
|
||||
aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
|
||||
|
||||
aSrcFragGetColor =
|
||||
EOL"vec4 getColor(void)"
|
||||
EOL"{"
|
||||
EOL" vec4 aColor = " thePhongCompLight ";"
|
||||
EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
|
||||
EOL"}";
|
||||
if (!theIsPBR)
|
||||
{
|
||||
aSrcFragGetColor = TCollection_AsciiString() +
|
||||
EOL"vec4 getColor(void)"
|
||||
EOL"{"
|
||||
EOL" vec4 aColor = " + aPhongCompLight + ";"
|
||||
EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
|
||||
EOL"}";
|
||||
}
|
||||
else
|
||||
{
|
||||
aSrcFragPBRGetBaseColor = TCollection_AsciiString() +
|
||||
EOL"vec4 getBaseColor (in bool theIsFront)"
|
||||
EOL"{"
|
||||
EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) *"
|
||||
EOL" (theIsFront ? occPBRFrontMaterial_Color() : occPBRBackMaterial_Color());"
|
||||
EOL"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2448,13 +2691,13 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
|
||||
{
|
||||
aSrcFragExtraOut += EOL"vec3 Normal;";
|
||||
aSrcFragExtraMain += TCollection_AsciiString()
|
||||
+ EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));"
|
||||
+ EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (" + aPosition + ".xyz / " + aPosition + ".w), dFdy (" + aPosition + ".xyz / " + aPosition + ".w)));"
|
||||
EOL" if (!gl_FrontFacing) { Normal = -Normal; }";
|
||||
}
|
||||
else
|
||||
{
|
||||
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 Normal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
|
||||
aSrcVertExtraFunc += THE_FUNC_transformNormal;
|
||||
aSrcVertExtraFunc += theIsPBR ? THE_FUNC_transformNormal_world : THE_FUNC_transformNormal_view;
|
||||
aSrcVertExtraMain += EOL" Normal = transformNormal (occNormal);";
|
||||
}
|
||||
|
||||
@ -2468,7 +2711,15 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
|
||||
EOL"{"
|
||||
EOL" PositionWorld = occModelWorldMatrix * occVertex;"
|
||||
EOL" Position = occWorldViewMatrix * PositionWorld;"
|
||||
+ EOL" View = vec3 (0.0, 0.0, 1.0);"
|
||||
EOL" if (occProjectionMatrix[3][3] == 1.0)"
|
||||
EOL" {"
|
||||
EOL" View = vec3(0.0, 0.0, 1.0);"
|
||||
EOL" }"
|
||||
EOL" else"
|
||||
EOL" {"
|
||||
EOL" View = -Position.xyz;"
|
||||
EOL" }"
|
||||
+ (theIsPBR ? EOL" View = (occWorldViewMatrixInverse * vec4(View, 0.0)).xyz;" : "")
|
||||
+ aSrcVertExtraMain
|
||||
+ THE_VERT_gl_Position
|
||||
+ EOL"}";
|
||||
@ -2479,11 +2730,12 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
|
||||
: EOL"#define getFinalColor getColor";
|
||||
|
||||
Standard_Integer aNbLights = 0;
|
||||
const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty());
|
||||
const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR);
|
||||
aSrcFrag = TCollection_AsciiString()
|
||||
+ EOL
|
||||
+ aSrcFragExtraOut
|
||||
+ aSrcFragGetVertColor
|
||||
+ (theIsPBR ? aSrcFragPBRGetBaseColor : "")
|
||||
+ aLights
|
||||
+ aSrcFragGetColor
|
||||
+ EOL
|
||||
@ -2493,12 +2745,13 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
|
||||
+ EOL" occSetFragColor (getFinalColor());"
|
||||
+ EOL"}";
|
||||
|
||||
const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + genLightKey (myLightSourceState.LightSources()) + "-";
|
||||
const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") + genLightKey (myLightSourceState.LightSources()) + "-";
|
||||
defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal);
|
||||
aProgramSrc->SetDefaultSampler (false);
|
||||
aProgramSrc->SetNbLightsMax (aNbLights);
|
||||
aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
|
||||
aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
|
||||
|
||||
const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
|
||||
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
|
||||
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
|
||||
@ -2787,6 +3040,48 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : preparePBREnvBakingProgram
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Boolean OpenGl_ShaderManager::preparePBREnvBakingProgram()
|
||||
{
|
||||
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
|
||||
OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
|
||||
|
||||
TCollection_AsciiString aSrcVert = TCollection_AsciiString()
|
||||
+ THE_FUNC_cubemap_vector_transform
|
||||
+ Shaders_PBREnvBaking_vs;
|
||||
|
||||
TCollection_AsciiString aSrcFrag = TCollection_AsciiString()
|
||||
+ THE_FUNC_cubemap_vector_transform
|
||||
+ Shaders_PBRDistribution_glsl
|
||||
+ Shaders_PBREnvBaking_fs;
|
||||
|
||||
// constant array definition requires OpenGL 2.1+ or OpenGL ES 3.0+
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
aProgramSrc->SetHeader ("#version 300 es");
|
||||
#else
|
||||
aProgramSrc->SetHeader ("#version 120");
|
||||
#endif
|
||||
|
||||
defaultGlslVersion (aProgramSrc, "pbr_env_baking", 0);
|
||||
aProgramSrc->SetDefaultSampler (false);
|
||||
aProgramSrc->SetNbLightsMax (0);
|
||||
aProgramSrc->SetNbClipPlanesMax (0);
|
||||
aProgramSrc->SetPBR (true);
|
||||
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
|
||||
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
|
||||
TCollection_AsciiString aKey;
|
||||
if (!Create (aProgramSrc, aKey, myPBREnvBakingProgram))
|
||||
{
|
||||
myPBREnvBakingProgram = new OpenGl_ShaderProgram(); // just mark as invalid
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : GetBgCubeMapProgram
|
||||
// purpose :
|
||||
@ -2795,24 +3090,23 @@ const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram
|
||||
{
|
||||
if (myBgCubeMapProgram.IsNull())
|
||||
{
|
||||
myBgCubeMapProgram = new Graphic3d_ShaderProgram;
|
||||
myBgCubeMapProgram = new Graphic3d_ShaderProgram();
|
||||
|
||||
OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
|
||||
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable("vec3 ViewDirection", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
|
||||
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX)); // defines orientation of Z axis to make horizontal flip
|
||||
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX)); // defines orientation of Y axis to make vertical flip
|
||||
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("samplerCube occSampler0", Graphic3d_TOS_FRAGMENT));
|
||||
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX));
|
||||
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX));
|
||||
|
||||
TCollection_AsciiString aSrcVert =
|
||||
EOL"void main()"
|
||||
TCollection_AsciiString aSrcVert = TCollection_AsciiString()
|
||||
+ THE_FUNC_cubemap_vector_transform
|
||||
+ EOL"void main()"
|
||||
EOL"{"
|
||||
EOL" vec4 aViewDirection = occProjectionMatrixInverse * vec4(occVertex.xy, 0.0, 1.0);"
|
||||
EOL" aViewDirection /= aViewDirection.w;"
|
||||
EOL" aViewDirection.w = 0.0;"
|
||||
EOL" ViewDirection = normalize((occWorldViewMatrixInverse * aViewDirection).xyz);"
|
||||
EOL" ViewDirection = ViewDirection.yzx;" // is needed to sync horizon and frontal camera position
|
||||
EOL" ViewDirection.y *= uYCoeff;"
|
||||
EOL" ViewDirection.z *= uZCoeff;"
|
||||
EOL" ViewDirection = cubemapVectorTransform (ViewDirection, uYCoeff, uZCoeff);"
|
||||
EOL" gl_Position = vec4(occVertex.xy, 0.0, 1.0);"
|
||||
EOL"}";
|
||||
|
||||
@ -2820,15 +3114,15 @@ const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram
|
||||
EOL"#define occEnvCubemap occSampler0"
|
||||
EOL"void main()"
|
||||
EOL"{"
|
||||
EOL" occSetFragColor (vec4(texture(occEnvCubemap, ViewDirection).rgb, 1.0));"
|
||||
EOL" occSetFragColor (vec4(occTextureCube (occEnvCubemap, ViewDirection).rgb, 1.0));"
|
||||
EOL"}";
|
||||
|
||||
defaultGlslVersion(myBgCubeMapProgram, "background_cubemap", 0);
|
||||
myBgCubeMapProgram->SetDefaultSampler(false);
|
||||
myBgCubeMapProgram->SetNbLightsMax(0);
|
||||
myBgCubeMapProgram->SetNbClipPlanesMax(0);
|
||||
myBgCubeMapProgram->AttachShader(OpenGl_ShaderObject::CreateFromSource(aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
|
||||
myBgCubeMapProgram->AttachShader(OpenGl_ShaderObject::CreateFromSource(aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
|
||||
defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0);
|
||||
myBgCubeMapProgram->SetDefaultSampler (false);
|
||||
myBgCubeMapProgram->SetNbLightsMax (0);
|
||||
myBgCubeMapProgram->SetNbClipPlanesMax (0);
|
||||
myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
|
||||
myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
|
||||
}
|
||||
|
||||
return myBgCubeMapProgram;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
|
||||
#include <OpenGl_PBREnvironment.hxx>
|
||||
#include <OpenGl_SetOfShaderPrograms.hxx>
|
||||
#include <OpenGl_ShaderStates.hxx>
|
||||
#include <OpenGl_Aspects.hxx>
|
||||
@ -249,16 +250,44 @@ public:
|
||||
//! Returns bounding box vertex buffer.
|
||||
const Handle(OpenGl_VertexBuffer)& BoundBoxVertBuffer() const { return myBoundBoxVertBuffer; }
|
||||
|
||||
//! Bind program for IBL maps generation in PBR pipeline.
|
||||
Standard_Boolean BindPBREnvBakingProgram()
|
||||
{
|
||||
if (myPBREnvBakingProgram.IsNull())
|
||||
{
|
||||
preparePBREnvBakingProgram();
|
||||
}
|
||||
return myContext->BindProgram (myPBREnvBakingProgram);
|
||||
}
|
||||
|
||||
//! Generates shader program to render environment cubemap as background.
|
||||
Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetBgCubeMapProgram ();
|
||||
|
||||
//! Resets PBR shading models to corresponding non-PBR ones if PBR is not allowed.
|
||||
static Graphic3d_TypeOfShadingModel PBRShadingModelFallback (Graphic3d_TypeOfShadingModel theShadingModel,
|
||||
Standard_Boolean theIsPbrAllowed = Standard_False)
|
||||
{
|
||||
if (theIsPbrAllowed)
|
||||
{
|
||||
return theShadingModel;
|
||||
}
|
||||
|
||||
switch (theShadingModel)
|
||||
{
|
||||
case Graphic3d_TOSM_PBR: return Graphic3d_TOSM_FRAGMENT;
|
||||
case Graphic3d_TOSM_PBR_FACET: return Graphic3d_TOSM_FACET;
|
||||
default: return theShadingModel;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//! Returns current state of OCCT light sources.
|
||||
const OpenGl_LightSourceState& LightSourceState() const { return myLightSourceState; }
|
||||
|
||||
//! Updates state of OCCT light sources.
|
||||
Standard_EXPORT void UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights);
|
||||
Standard_EXPORT void UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
|
||||
Standard_Integer theSpecIBLMapLevels = 0);
|
||||
|
||||
//! Invalidate state of OCCT light sources.
|
||||
Standard_EXPORT void UpdateLightSourceState();
|
||||
@ -443,6 +472,7 @@ public:
|
||||
|
||||
//! Choose Shading Model for filled primitives.
|
||||
//! Fallbacks to FACET model if there are no normal attributes.
|
||||
//! Fallbacks to corresponding non-PBR models if PBR is unavailable.
|
||||
Graphic3d_TypeOfShadingModel ChooseFaceShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
|
||||
bool theHasNodalNormals) const
|
||||
{
|
||||
@ -460,12 +490,17 @@ public:
|
||||
case Graphic3d_TOSM_VERTEX:
|
||||
case Graphic3d_TOSM_FRAGMENT:
|
||||
return theHasNodalNormals ? aModel : Graphic3d_TOSM_FACET;
|
||||
case Graphic3d_TOSM_PBR:
|
||||
return PBRShadingModelFallback (theHasNodalNormals ? aModel : Graphic3d_TOSM_PBR_FACET, IsPbrAllowed());
|
||||
case Graphic3d_TOSM_PBR_FACET:
|
||||
return PBRShadingModelFallback (aModel, IsPbrAllowed());
|
||||
}
|
||||
return Graphic3d_TOSM_UNLIT;
|
||||
}
|
||||
|
||||
//! Choose Shading Model for line primitives.
|
||||
//! Fallbacks to UNLIT model if there are no normal attributes.
|
||||
//! Fallbacks to corresponding non-PBR models if PBR is unavailable.
|
||||
Graphic3d_TypeOfShadingModel ChooseLineShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
|
||||
bool theHasNodalNormals) const
|
||||
{
|
||||
@ -483,6 +518,10 @@ public:
|
||||
case Graphic3d_TOSM_VERTEX:
|
||||
case Graphic3d_TOSM_FRAGMENT:
|
||||
return theHasNodalNormals ? aModel : Graphic3d_TOSM_UNLIT;
|
||||
case Graphic3d_TOSM_PBR:
|
||||
return PBRShadingModelFallback (theHasNodalNormals ? aModel : Graphic3d_TOSM_UNLIT, IsPbrAllowed());
|
||||
case Graphic3d_TOSM_PBR_FACET:
|
||||
return Graphic3d_TOSM_UNLIT;
|
||||
}
|
||||
return Graphic3d_TOSM_UNLIT;
|
||||
}
|
||||
@ -648,11 +687,13 @@ protected:
|
||||
{
|
||||
switch (theShadingModel)
|
||||
{
|
||||
case Graphic3d_TOSM_UNLIT: return prepareStdProgramUnlit (theProgram, theBits, false);
|
||||
case Graphic3d_TOSM_FACET: return prepareStdProgramPhong (theProgram, theBits, true);
|
||||
case Graphic3d_TOSM_VERTEX: return prepareStdProgramGouraud(theProgram, theBits);
|
||||
case Graphic3d_TOSM_UNLIT: return prepareStdProgramUnlit (theProgram, theBits, false);
|
||||
case Graphic3d_TOSM_FACET: return prepareStdProgramPhong (theProgram, theBits, true);
|
||||
case Graphic3d_TOSM_VERTEX: return prepareStdProgramGouraud(theProgram, theBits);
|
||||
case Graphic3d_TOSM_DEFAULT:
|
||||
case Graphic3d_TOSM_FRAGMENT: return prepareStdProgramPhong (theProgram, theBits, false);
|
||||
case Graphic3d_TOSM_FRAGMENT: return prepareStdProgramPhong (theProgram, theBits, false);
|
||||
case Graphic3d_TOSM_PBR: return prepareStdProgramPhong (theProgram, theBits, false, true);
|
||||
case Graphic3d_TOSM_PBR_FACET: return prepareStdProgramPhong (theProgram, theBits, true, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -663,15 +704,19 @@ protected:
|
||||
|
||||
//! Prepare standard GLSL program with per-pixel lighting.
|
||||
//! @param theIsFlatNormal when TRUE, the Vertex normals will be ignored and Face normal will be computed instead
|
||||
//! @param theIsPBR when TRUE, the PBR pipeline will be activated
|
||||
Standard_EXPORT Standard_Boolean prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
|
||||
const Standard_Integer theBits,
|
||||
const Standard_Boolean theIsFlatNormal = false);
|
||||
const Standard_Boolean theIsFlatNormal = false,
|
||||
const Standard_Boolean theIsPBR = false);
|
||||
|
||||
//! Define computeLighting GLSL function depending on current lights configuration
|
||||
//! @param theNbLights [out] number of defined light sources
|
||||
//! @param theHasVertColor [in] flag to use getVertColor() instead of Ambient and Diffuse components of active material
|
||||
//! @param theIsPBR [in] flag to activate PBR pipeline
|
||||
Standard_EXPORT TCollection_AsciiString stdComputeLighting (Standard_Integer& theNbLights,
|
||||
Standard_Boolean theHasVertColor);
|
||||
Standard_Boolean theHasVertColor,
|
||||
Standard_Boolean theIsPBR);
|
||||
|
||||
//! Bind specified program to current context and apply state.
|
||||
Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram);
|
||||
@ -697,6 +742,13 @@ protected:
|
||||
OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
|
||||
Standard_Integer theBits);
|
||||
|
||||
//! Prepare GLSL source for IBL generation used in PBR pipeline.
|
||||
Standard_EXPORT Standard_Boolean preparePBREnvBakingProgram();
|
||||
|
||||
//! Checks whether one of PBR shading models is set as default model.
|
||||
Standard_Boolean IsPbrAllowed() const { return myShadingModel == Graphic3d_TOSM_PBR
|
||||
|| myShadingModel == Graphic3d_TOSM_PBR_FACET; }
|
||||
|
||||
protected:
|
||||
|
||||
//! Packed properties of light source
|
||||
@ -769,12 +821,15 @@ protected:
|
||||
Handle(OpenGl_ShaderProgram) myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and MSAA).
|
||||
OpenGl_MapOfShaderPrograms myMapOfLightPrograms; //!< map of lighting programs depending on lights configuration
|
||||
|
||||
Handle(OpenGl_ShaderProgram) myPBREnvBakingProgram;//!< program for IBL maps generation used in PBR pipeline
|
||||
Handle(Graphic3d_ShaderProgram) myBgCubeMapProgram; //!< program for background cubemap rendering
|
||||
|
||||
Handle(OpenGl_ShaderProgram) myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
|
||||
|
||||
Handle(OpenGl_VertexBuffer) myBoundBoxVertBuffer; //!< bounding box vertex buffer
|
||||
|
||||
mutable Handle(OpenGl_PBREnvironment) myPBREnvironment; //!< manager of IBL maps used in PBR pipeline
|
||||
|
||||
OpenGl_Context* myContext; //!< OpenGL context
|
||||
Standard_Boolean mySRgbState; //!< track sRGB state
|
||||
|
||||
|
@ -56,38 +56,42 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
|
||||
"occWorldViewMatrixInverseTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
|
||||
"occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
|
||||
|
||||
"occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
|
||||
"occClipPlaneChains", // OpenGl_OCC_CLIP_PLANE_CHAINS
|
||||
"occClipPlaneCount", // OpenGl_OCC_CLIP_PLANE_COUNT
|
||||
"occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
|
||||
"occClipPlaneChains", // OpenGl_OCC_CLIP_PLANE_CHAINS
|
||||
"occClipPlaneCount", // OpenGl_OCC_CLIP_PLANE_COUNT
|
||||
|
||||
"occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT
|
||||
"occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES
|
||||
"occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS
|
||||
"occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT
|
||||
"occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT
|
||||
"occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES
|
||||
"occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS
|
||||
"occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT
|
||||
|
||||
"occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE
|
||||
"occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
|
||||
"occFrontMaterial", // OpenGl_OCCT_FRONT_MATERIAL
|
||||
"occBackMaterial", // OpenGl_OCCT_BACK_MATERIAL
|
||||
"occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF
|
||||
"occColor", // OpenGl_OCCT_COLOR
|
||||
"occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE
|
||||
"occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
|
||||
"occPbrFrontMaterial", // OpenGl_OCCT_PBR_FRONT_MATERIAL
|
||||
"occPbrBackMaterial", // OpenGl_OCCT_PBR_BACK_MATERIAL
|
||||
"occFrontMaterial", // OpenGl_OCCT_COMMON_FRONT_MATERIAL
|
||||
"occBackMaterial", // OpenGl_OCCT_COMMON_BACK_MATERIAL
|
||||
"occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF
|
||||
"occColor", // OpenGl_OCCT_COLOR
|
||||
|
||||
"occOitOutput", // OpenGl_OCCT_OIT_OUTPUT
|
||||
"occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR
|
||||
"occOitOutput", // OpenGl_OCCT_OIT_OUTPUT
|
||||
"occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR
|
||||
|
||||
"occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D
|
||||
"occPointSize", // OpenGl_OCCT_POINT_SIZE
|
||||
"occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D
|
||||
"occPointSize", // OpenGl_OCCT_POINT_SIZE
|
||||
|
||||
"occViewport", // OpenGl_OCCT_VIEWPORT
|
||||
"occLineWidth", // OpenGl_OCCT_LINE_WIDTH
|
||||
"occLineFeather", // OpenGl_OCCT_LINE_FEATHER
|
||||
"occStipplePattern", // OpenGl_OCCT_LINE_STIPPLE_PATTERN
|
||||
"occStippleFactor", // OpenGl_OCCT_LINE_STIPPLE_FACTOR
|
||||
"occWireframeColor", // OpenGl_OCCT_WIREFRAME_COLOR
|
||||
"occIsQuadMode", // OpenGl_OCCT_QUAD_MODE_STATE
|
||||
"occViewport", // OpenGl_OCCT_VIEWPORT
|
||||
"occLineWidth", // OpenGl_OCCT_LINE_WIDTH
|
||||
"occLineFeather", // OpenGl_OCCT_LINE_FEATHER
|
||||
"occStipplePattern", // OpenGl_OCCT_LINE_STIPPLE_PATTERN
|
||||
"occStippleFactor", // OpenGl_OCCT_LINE_STIPPLE_FACTOR
|
||||
"occWireframeColor", // OpenGl_OCCT_WIREFRAME_COLOR
|
||||
"occIsQuadMode", // OpenGl_OCCT_QUAD_MODE_STATE
|
||||
|
||||
"occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE
|
||||
"occSilhouetteThickness" // OpenGl_OCCT_SILHOUETTE_THICKNESS
|
||||
"occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE
|
||||
"occSilhouetteThickness", // OpenGl_OCCT_SILHOUETTE_THICKNESS
|
||||
|
||||
"occNbSpecIBLLevels" // OpenGl_OCCT_NB_SPEC_IBL_LEVELS
|
||||
};
|
||||
|
||||
namespace
|
||||
@ -409,6 +413,11 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
|
||||
{
|
||||
aHeaderConstants += "#define THE_HAS_DEFAULT_SAMPLER\n";
|
||||
}
|
||||
if (!myProxy.IsNull()
|
||||
&& myProxy->IsPBR())
|
||||
{
|
||||
aHeaderConstants += "#define THE_IS_PBR\n";
|
||||
}
|
||||
|
||||
const TCollection_AsciiString aSource = aHeaderVer // #version - header defining GLSL version, should be first
|
||||
+ (!aHeaderVer.IsEmpty() ? "\n" : "")
|
||||
@ -488,6 +497,18 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
|
||||
{
|
||||
SetUniform (theCtx, aLocSampler, GLint(theCtx->SpriteTextureUnit()));
|
||||
}
|
||||
if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDiffIBLMapSHCoeffs"))
|
||||
{
|
||||
SetUniform (theCtx, aLocSampler, GLint(theCtx->PBRDiffIBLMapSHTexUnit()));
|
||||
}
|
||||
if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSpecIBLMap"))
|
||||
{
|
||||
SetUniform (theCtx, aLocSampler, GLint(theCtx->PBRSpecIBLMapTexUnit()));
|
||||
}
|
||||
if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occEnvLUT"))
|
||||
{
|
||||
SetUniform (theCtx, aLocSampler, GLint(theCtx->PBREnvLUTTexUnit()));
|
||||
}
|
||||
|
||||
const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
|
||||
const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
|
||||
|
@ -62,8 +62,10 @@ enum OpenGl_StateVariable
|
||||
// Material state
|
||||
OpenGl_OCCT_TEXTURE_ENABLE,
|
||||
OpenGl_OCCT_DISTINGUISH_MODE,
|
||||
OpenGl_OCCT_FRONT_MATERIAL,
|
||||
OpenGl_OCCT_BACK_MATERIAL,
|
||||
OpenGl_OCCT_PBR_FRONT_MATERIAL,
|
||||
OpenGl_OCCT_PBR_BACK_MATERIAL,
|
||||
OpenGl_OCCT_COMMON_FRONT_MATERIAL,
|
||||
OpenGl_OCCT_COMMON_BACK_MATERIAL,
|
||||
OpenGl_OCCT_ALPHA_CUTOFF,
|
||||
OpenGl_OCCT_COLOR,
|
||||
|
||||
@ -88,6 +90,9 @@ enum OpenGl_StateVariable
|
||||
OpenGl_OCCT_ORTHO_SCALE,
|
||||
OpenGl_OCCT_SILHOUETTE_THICKNESS,
|
||||
|
||||
// PBR state
|
||||
OpenGl_OCCT_NB_SPEC_IBL_LEVELS,
|
||||
|
||||
// DON'T MODIFY THIS ITEM (insert new items before it)
|
||||
OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES
|
||||
};
|
||||
|
@ -122,7 +122,7 @@ class OpenGl_LightSourceState : public OpenGl_StateInterface
|
||||
public:
|
||||
|
||||
//! Creates uninitialized state of light sources.
|
||||
OpenGl_LightSourceState() {}
|
||||
OpenGl_LightSourceState() : mySpecIBLMapLevels (0) {}
|
||||
|
||||
//! Sets new light sources.
|
||||
void Set (const Handle(Graphic3d_LightSet)& theLightSources) { myLightSources = theLightSources; }
|
||||
@ -130,9 +130,17 @@ public:
|
||||
//! Returns current list of light sources.
|
||||
const Handle(Graphic3d_LightSet)& LightSources() const { return myLightSources; }
|
||||
|
||||
//! Returns number of mipmap levels used in specular IBL map.
|
||||
//! 0 by default or in case of using non-PBR shading model.
|
||||
Standard_Integer SpecIBLMapLevels() const { return mySpecIBLMapLevels; }
|
||||
|
||||
//! Sets number of mipmap levels used in specular IBL map.
|
||||
void SetSpecIBLMapLevels(Standard_Integer theSpecIBLMapLevels) { mySpecIBLMapLevels = theSpecIBLMapLevels; }
|
||||
|
||||
private:
|
||||
|
||||
Handle(Graphic3d_LightSet) myLightSources; //!< List of OCCT light sources
|
||||
Handle(Graphic3d_LightSet) myLightSources; //!< List of OCCT light sources
|
||||
Standard_Integer mySpecIBLMapLevels; //!< Number of mipmap levels used in specular IBL map (0 by default or in case of using non-PBR shading model)
|
||||
|
||||
};
|
||||
|
||||
|
@ -563,7 +563,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
{
|
||||
case Graphic3d_TOT_CUBEMAP:
|
||||
{
|
||||
return initCubeMap (theCtx, Handle(Graphic3d_CubeMap)::DownCast(theTextureMap),
|
||||
return InitCubeMap (theCtx, Handle(Graphic3d_CubeMap)::DownCast(theTextureMap),
|
||||
0, Image_Format_RGB, false, theTextureMap->IsColorMap());
|
||||
}
|
||||
default:
|
||||
@ -793,10 +793,10 @@ bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : initCubeMap
|
||||
// function : InitCubeMap
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_Texture::initCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
const Handle(Graphic3d_CubeMap)& theCubeMap,
|
||||
Standard_Size theSize,
|
||||
Image_Format theFormat,
|
||||
@ -811,6 +811,7 @@ bool OpenGl_Texture::initCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
|
||||
if (!theCubeMap.IsNull())
|
||||
{
|
||||
theToGenMipmap = theCubeMap->HasMipmaps();
|
||||
if (Handle(Image_PixMap) anImage = theCubeMap->Reset().Value())
|
||||
{
|
||||
theSize = anImage->SizeX();
|
||||
@ -836,6 +837,8 @@ bool OpenGl_Texture::initCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
myTarget = GL_TEXTURE_CUBE_MAP;
|
||||
myHasMipmaps = theToGenMipmap;
|
||||
myNbSamples = 1;
|
||||
mySizeX = (GLsizei )theSize;
|
||||
mySizeY = (GLsizei )theSize;
|
||||
Bind (theCtx);
|
||||
applyDefaultSamplerParams (theCtx);
|
||||
|
||||
@ -991,6 +994,10 @@ Standard_Size OpenGl_Texture::EstimatedDataSize() const
|
||||
{
|
||||
aSize *= Standard_Size(mySizeZ);
|
||||
}
|
||||
if (myTarget == GL_TEXTURE_CUBE_MAP)
|
||||
{
|
||||
aSize *= 6; // cube sides
|
||||
}
|
||||
if (myHasMipmaps)
|
||||
{
|
||||
aSize = aSize + aSize / 3;
|
||||
|
@ -245,11 +245,6 @@ public:
|
||||
return Init3D (theCtx, aFormat, Graphic3d_Vec3i (theSizeX, theSizeY, theSizeZ), thePixels);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Apply default sampler parameters after texture creation.
|
||||
Standard_EXPORT void applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Initializes 6 sides of cubemap.
|
||||
//! If theCubeMap is not NULL then size and format will be taken from it and corresponding arguments will be ignored.
|
||||
//! Otherwise this parametres will be taken from arguments.
|
||||
@ -259,13 +254,18 @@ protected:
|
||||
//! @param theFormat [in] image format
|
||||
//! @param theToGenMipmap [in] flag to generate mipmaped cubemap
|
||||
//! @param theIsColorMap [in] flag indicating cubemap storing color values
|
||||
Standard_EXPORT bool initCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
Standard_EXPORT bool InitCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
const Handle(Graphic3d_CubeMap)& theCubeMap,
|
||||
Standard_Size theSize,
|
||||
Image_Format theFormat,
|
||||
Standard_Boolean theToGenMipmap,
|
||||
Standard_Boolean theIsColorMap);
|
||||
|
||||
protected:
|
||||
|
||||
//! Apply default sampler parameters after texture creation.
|
||||
Standard_EXPORT void applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
protected:
|
||||
|
||||
Handle(OpenGl_Sampler) mySampler; //!< texture sampler
|
||||
|
@ -31,7 +31,7 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte
|
||||
aFormat.SetNbComponents (1);
|
||||
if (theCtx->core11 == NULL)
|
||||
{
|
||||
aFormat.SetInternalFormat (GL_R8); // GL_R32F
|
||||
aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_R32F : GL_R8);
|
||||
aFormat.SetPixelFormat (GL_RED);
|
||||
}
|
||||
else
|
||||
@ -51,7 +51,7 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte
|
||||
aFormat.SetNbComponents (1);
|
||||
if (theCtx->core11 == NULL)
|
||||
{
|
||||
aFormat.SetInternalFormat (GL_R8); // GL_R32F
|
||||
aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_R32F : GL_R8);
|
||||
aFormat.SetPixelFormat (GL_RED);
|
||||
}
|
||||
else
|
||||
@ -66,10 +66,22 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte
|
||||
aFormat.SetDataType (GL_FLOAT);
|
||||
return aFormat;
|
||||
}
|
||||
case Image_Format_RGF:
|
||||
{
|
||||
if (!theCtx->arbTexRG)
|
||||
{
|
||||
return OpenGl_TextureFormat();
|
||||
}
|
||||
aFormat.SetNbComponents (2);
|
||||
aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RG32F : GL_RG8);
|
||||
aFormat.SetPixelFormat (GL_RG);
|
||||
aFormat.SetDataType (GL_FLOAT);
|
||||
return aFormat;
|
||||
}
|
||||
case Image_Format_RGBAF:
|
||||
{
|
||||
aFormat.SetNbComponents (4);
|
||||
aFormat.SetInternalFormat (GL_RGBA8); // GL_RGBA32F
|
||||
aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGBA32F : GL_RGBA8);
|
||||
aFormat.SetPixelFormat (GL_RGBA);
|
||||
aFormat.SetDataType (GL_FLOAT);
|
||||
return aFormat;
|
||||
@ -81,7 +93,7 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte
|
||||
return OpenGl_TextureFormat();
|
||||
}
|
||||
aFormat.SetNbComponents (4);
|
||||
aFormat.SetInternalFormat (GL_RGBA8); // GL_RGBA32F
|
||||
aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGBA32F : GL_RGBA8);
|
||||
aFormat.SetPixelFormat (GL_BGRA_EXT); // equals to GL_BGRA
|
||||
aFormat.SetDataType (GL_FLOAT);
|
||||
return aFormat;
|
||||
@ -89,7 +101,7 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte
|
||||
case Image_Format_RGBF:
|
||||
{
|
||||
aFormat.SetNbComponents (3);
|
||||
aFormat.SetInternalFormat (GL_RGB8); // GL_RGB32F
|
||||
aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGB32F : GL_RGB8);
|
||||
aFormat.SetPixelFormat (GL_RGB);
|
||||
aFormat.SetDataType (GL_FLOAT);
|
||||
return aFormat;
|
||||
@ -98,7 +110,7 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte
|
||||
{
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
aFormat.SetNbComponents (3);
|
||||
aFormat.SetInternalFormat (GL_RGB8); // GL_RGB32F
|
||||
aFormat.SetInternalFormat (theCtx->arbTexFloat ? GL_RGB32F : GL_RGB8);
|
||||
aFormat.SetPixelFormat (GL_BGR); // equals to GL_BGR_EXT
|
||||
aFormat.SetDataType (GL_FLOAT);
|
||||
return aFormat;
|
||||
|
@ -72,6 +72,8 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
|
||||
myTextureParams (new OpenGl_Aspects()),
|
||||
myCubeMapParams (new OpenGl_Aspects()),
|
||||
myBackgroundType (Graphic3d_TOB_NONE),
|
||||
myPBREnvState (OpenGl_PBREnvState_NONEXISTENT),
|
||||
myPBREnvRequest (OpenGl_PBREnvRequest_NONE),
|
||||
// ray-tracing fields initialization
|
||||
myRaytraceInitStatus (OpenGl_RT_NONE),
|
||||
myIsRaytraceDataValid (Standard_False),
|
||||
@ -202,6 +204,11 @@ void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
|
||||
releaseSrgbResources (theCtx);
|
||||
|
||||
releaseRaytraceResources (theCtx);
|
||||
|
||||
if (!myPBREnvironment.IsNull())
|
||||
{
|
||||
myPBREnvironment->Release (theCtx.get());
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -530,37 +537,56 @@ Handle(Graphic3d_CubeMap) OpenGl_View::BackgroundCubeMap() const
|
||||
{
|
||||
return myBackgroundCubeMap;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SpecIBLMapLevels
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
unsigned int OpenGl_View::SpecIBLMapLevels() const
|
||||
{
|
||||
return myPBREnvironment.IsNull() ? 0 : myPBREnvironment->SpecMapLevelsNumber();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetBackgroundCubeMap
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_View::SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap)
|
||||
void OpenGl_View::SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap,
|
||||
Standard_Boolean theToUpdatePBREnv)
|
||||
{
|
||||
myBackgroundCubeMap = theCubeMap;
|
||||
Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d;
|
||||
Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (myBackgroundCubeMap);
|
||||
if (theCubeMap.IsNull())
|
||||
{
|
||||
if (theToUpdatePBREnv)
|
||||
{
|
||||
myPBREnvRequest = OpenGl_PBREnvRequest_CLEAR;
|
||||
}
|
||||
if (myBackgroundType == Graphic3d_TOB_CUBEMAP)
|
||||
{
|
||||
myBackgroundType = Graphic3d_TOB_NONE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
anAspect->SetInteriorStyle(Aspect_IS_SOLID);
|
||||
anAspect->SetSuppressBackFaces(false);
|
||||
anAspect->SetTextureSet(aTextureSet);
|
||||
theCubeMap ->SetMipmapsGeneration (Standard_True);
|
||||
Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
|
||||
Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (myBackgroundCubeMap);
|
||||
anAspect->SetInteriorStyle (Aspect_IS_SOLID);
|
||||
anAspect->SetSuppressBackFaces (false);
|
||||
anAspect->SetTextureSet (aTextureSet);
|
||||
|
||||
const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
|
||||
if (!aCtx.IsNull())
|
||||
{
|
||||
anAspect->SetShaderProgram (aCtx->ShaderManager()->GetBgCubeMapProgram());
|
||||
}
|
||||
anAspect->SetTextureMapOn (theCubeMap->IsDone());
|
||||
myCubeMapParams->SetAspect (anAspect);
|
||||
|
||||
if (theCubeMap->IsDone())
|
||||
if (theToUpdatePBREnv)
|
||||
{
|
||||
anAspect->SetTextureMapOn();
|
||||
myPBREnvRequest = OpenGl_PBREnvRequest_BAKE;
|
||||
}
|
||||
else
|
||||
{
|
||||
anAspect->SetTextureMapOff();
|
||||
}
|
||||
|
||||
myCubeMapParams->SetAspect(anAspect);
|
||||
const OpenGl_Aspects* anAspectsBackup = myWorkspace->SetAspects (myCubeMapParams);
|
||||
myWorkspace->ApplyAspects();
|
||||
myWorkspace->SetAspects (anAspectsBackup);
|
||||
|
@ -57,6 +57,7 @@ struct OpenGl_Matrix;
|
||||
|
||||
class Graphic3d_StructureManager;
|
||||
class OpenGl_GraphicDriver;
|
||||
class OpenGl_PBREnvironment;
|
||||
class OpenGl_StateCounter;
|
||||
class OpenGl_TriangleSet;
|
||||
class OpenGl_Workspace;
|
||||
@ -226,7 +227,27 @@ public:
|
||||
Standard_EXPORT Handle(Graphic3d_CubeMap) BackgroundCubeMap() const Standard_OVERRIDE;
|
||||
|
||||
//! Sets environment cubemap as background.
|
||||
Standard_EXPORT virtual void SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap) Standard_OVERRIDE;
|
||||
//! @param theCubeMap cubemap source to be set as background
|
||||
//! @param theToUpdatePBREnv defines whether IBL maps will be generated or not (see 'GeneratePBREnvironment')
|
||||
Standard_EXPORT virtual void SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap,
|
||||
Standard_Boolean theToUpdatePBREnv = Standard_True) Standard_OVERRIDE;
|
||||
|
||||
//! 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() Standard_OVERRIDE { myPBREnvRequest = OpenGl_PBREnvRequest_BAKE; }
|
||||
|
||||
//! 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() Standard_OVERRIDE { myPBREnvRequest = OpenGl_PBREnvRequest_CLEAR; }
|
||||
|
||||
//! Returns number of mipmap levels used in specular IBL map.
|
||||
//! 0 if PBR environment is not created.
|
||||
Standard_EXPORT unsigned int SpecIBLMapLevels() const;
|
||||
|
||||
//! Returns environment texture set for the view.
|
||||
virtual Handle(Graphic3d_TextureEnv) TextureEnv() const Standard_OVERRIDE { return myTextureEnvData; }
|
||||
@ -518,10 +539,48 @@ protected: //! @name Background parameters
|
||||
|
||||
OpenGl_Aspects* myTextureParams; //!< Stores texture and its parameters for textured background
|
||||
OpenGl_Aspects* myCubeMapParams; //!< Stores cubemap and its parameters for cubemap background
|
||||
Handle(Graphic3d_CubeMap) myBackgroundCubeMap; //!< Cubemap has been setted as background
|
||||
Graphic3d_TypeOfBackground myBackgroundType; //!< Current typy of background
|
||||
Handle(Graphic3d_CubeMap) myBackgroundCubeMap; //!< Cubemap has been set as background
|
||||
Graphic3d_TypeOfBackground myBackgroundType; //!< Current type of background
|
||||
OpenGl_BackgroundArray* myBackgrounds[Graphic3d_TypeOfBackground_NB]; //!< Array of primitive arrays of different background types
|
||||
|
||||
protected: //! @name methods related to PBR
|
||||
|
||||
//! Checks whether PBR is available.
|
||||
Standard_EXPORT Standard_Boolean checkPBRAvailability() const;
|
||||
|
||||
//! Generates IBL maps used in PBR pipeline.
|
||||
//! If background cubemap is not set clears all IBL maps.
|
||||
Standard_EXPORT void bakePBREnvironment (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Fills all IBL maps with white color.
|
||||
//! So that environment lighting is considered to be constant and is completely controls by ambient light sources.
|
||||
Standard_EXPORT void clearPBREnvironment (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
//! Process requests to generate or to clear PBR environment.
|
||||
Standard_EXPORT void processPBREnvRequest (const Handle(OpenGl_Context)& theCtx);
|
||||
|
||||
protected: //! @name fields and types related to PBR
|
||||
|
||||
//! State of PBR environment.
|
||||
enum PBREnvironmentState
|
||||
{
|
||||
OpenGl_PBREnvState_NONEXISTENT,
|
||||
OpenGl_PBREnvState_UNAVAILABLE, // indicates failed try to create PBR environment
|
||||
OpenGl_PBREnvState_CREATED
|
||||
};
|
||||
|
||||
//! Type of action which can be done with PBR environment.
|
||||
enum PBREnvironmentRequest
|
||||
{
|
||||
OpenGl_PBREnvRequest_NONE,
|
||||
OpenGl_PBREnvRequest_BAKE,
|
||||
OpenGl_PBREnvRequest_CLEAR
|
||||
};
|
||||
|
||||
Handle(OpenGl_PBREnvironment) myPBREnvironment; //!< manager of IBL maps used in PBR pipeline
|
||||
PBREnvironmentState myPBREnvState; //!< state of PBR environment
|
||||
PBREnvironmentRequest myPBREnvRequest; //!< type of action is requested to be done with PBR environment
|
||||
|
||||
protected: //! @name data types related to ray-tracing
|
||||
|
||||
//! Result of OpenGL shaders initialization.
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include <OpenGl_Structure.hxx>
|
||||
#include <OpenGl_ArbFBO.hxx>
|
||||
|
||||
#include "../Textures/Textures_EnvLUT.pxx"
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Format Frame Buffer format for logging messages.
|
||||
@ -344,6 +346,65 @@ void OpenGl_View::Redraw()
|
||||
}
|
||||
}
|
||||
|
||||
// process PBR environment
|
||||
if (myShadingModel == Graphic3d_TOSM_PBR
|
||||
|| myShadingModel == Graphic3d_TOSM_PBR_FACET)
|
||||
{
|
||||
if (!myPBREnvironment.IsNull()
|
||||
&& myPBREnvironment->SizesAreDifferent (myRenderParams.PbrEnvPow2Size,
|
||||
myRenderParams.PbrEnvSpecMapNbLevels))
|
||||
{
|
||||
myPBREnvironment->Release (aCtx.get());
|
||||
myPBREnvironment.Nullify();
|
||||
myPBREnvState = OpenGl_PBREnvState_NONEXISTENT;
|
||||
myPBREnvRequest = OpenGl_PBREnvRequest_BAKE;
|
||||
++myLightsRevision;
|
||||
}
|
||||
|
||||
if (myPBREnvState == OpenGl_PBREnvState_NONEXISTENT
|
||||
&& aCtx->HasPBR())
|
||||
{
|
||||
myPBREnvironment = OpenGl_PBREnvironment::Create (aCtx, myRenderParams.PbrEnvPow2Size, myRenderParams.PbrEnvSpecMapNbLevels);
|
||||
myPBREnvState = myPBREnvironment.IsNull() ? OpenGl_PBREnvState_UNAVAILABLE : OpenGl_PBREnvState_CREATED;
|
||||
if (myPBREnvState == OpenGl_PBREnvState_CREATED)
|
||||
{
|
||||
Handle(OpenGl_Texture) anEnvLUT;
|
||||
static const TCollection_AsciiString THE_SHARED_ENV_LUT_KEY("EnvLUT");
|
||||
if (!aCtx->GetResource (THE_SHARED_ENV_LUT_KEY, anEnvLUT))
|
||||
{
|
||||
Handle(Graphic3d_TextureParams) aParams = new Graphic3d_TextureParams();
|
||||
aParams->SetFilter (Graphic3d_TOTF_BILINEAR);
|
||||
aParams->SetRepeat (Standard_False);
|
||||
aParams->SetTextureUnit (aCtx->PBREnvLUTTexUnit());
|
||||
anEnvLUT = new OpenGl_Texture(THE_SHARED_ENV_LUT_KEY, aParams);
|
||||
Handle(Image_PixMap) aPixMap = new Image_PixMap();
|
||||
aPixMap->InitWrapper (Image_Format_RGF, (Standard_Byte*)Textures_EnvLUT, Textures_EnvLUTSize, Textures_EnvLUTSize);
|
||||
OpenGl_TextureFormat aTexFormat = OpenGl_TextureFormat::FindFormat (aCtx, aPixMap->Format(), false);
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
// GL_RG32F is not texture-filterable format on OpenGL ES without OES_texture_float_linear extension.
|
||||
// GL_RG16F is texture-filterable since OpenGL ES 3.0 and can be initialized from 32-bit floats.
|
||||
// Note that it is expected that GL_RG16F has enough precision for this table, so that it can be used also on desktop OpenGL.
|
||||
//if (!aCtx->hasTexFloatLinear)
|
||||
aTexFormat.SetInternalFormat (GL_RG16F);
|
||||
#endif
|
||||
if (!aTexFormat.IsValid()
|
||||
|| !anEnvLUT->Init (aCtx, aTexFormat, Graphic3d_Vec2i((Standard_Integer)Textures_EnvLUTSize), Graphic3d_TOT_2D, aPixMap.get()))
|
||||
{
|
||||
aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Failed allocation of LUT for PBR");
|
||||
anEnvLUT.Nullify();
|
||||
}
|
||||
aCtx->ShareResource (THE_SHARED_ENV_LUT_KEY, anEnvLUT);
|
||||
}
|
||||
if (!anEnvLUT.IsNull())
|
||||
{
|
||||
anEnvLUT->Bind (aCtx);
|
||||
}
|
||||
myWorkspace->ApplyAspects();
|
||||
}
|
||||
}
|
||||
processPBREnvRequest (aCtx);
|
||||
}
|
||||
|
||||
// create color and coverage accumulation buffers required for OIT algorithm
|
||||
if (toUseOit)
|
||||
{
|
||||
@ -938,7 +999,7 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
|
||||
|| aLightsRevision != myLightsRevision)
|
||||
{
|
||||
myLightsRevision = aLightsRevision;
|
||||
aManager->UpdateLightSourceStateTo (aLights);
|
||||
aManager->UpdateLightSourceStateTo (aLights, SpecIBLMapLevels());
|
||||
myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
|
||||
}
|
||||
|
||||
@ -1020,7 +1081,7 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
|
||||
}
|
||||
#endif
|
||||
|
||||
aManager->SetShadingModel (myShadingModel);
|
||||
aManager->SetShadingModel (OpenGl_ShaderManager::PBRShadingModelFallback (myShadingModel, checkPBRAvailability()));
|
||||
|
||||
// Redraw 3d scene
|
||||
if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye)
|
||||
@ -1848,3 +1909,64 @@ bool OpenGl_View::chooseOitColorConfiguration (const Handle(OpenGl_Context)& the
|
||||
}
|
||||
return false; // color combination does not exist
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : checkPBRAvailability
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Boolean OpenGl_View::checkPBRAvailability() const
|
||||
{
|
||||
return myWorkspace->GetGlContext()->HasPBR()
|
||||
&& !myPBREnvironment.IsNull();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : bakePBREnvironment
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_View::bakePBREnvironment (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
const Handle(OpenGl_TextureSet)& aTextureSet = myCubeMapParams->TextureSet (theCtx);
|
||||
if (!aTextureSet.IsNull()
|
||||
&& !aTextureSet->IsEmpty())
|
||||
{
|
||||
myPBREnvironment->Bake (theCtx,
|
||||
aTextureSet->First(),
|
||||
myBackgroundCubeMap->ZIsInverted(),
|
||||
myBackgroundCubeMap->IsTopDown(),
|
||||
myRenderParams.PbrEnvBakingDiffNbSamples,
|
||||
myRenderParams.PbrEnvBakingSpecNbSamples,
|
||||
myRenderParams.PbrEnvBakingProbability);
|
||||
}
|
||||
else
|
||||
{
|
||||
myPBREnvironment->Clear (theCtx);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : clearPBREnvironment
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_View::clearPBREnvironment (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
myPBREnvironment->Clear (theCtx);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : clearPBREnvironment
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void OpenGl_View::processPBREnvRequest (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
if (myPBREnvState == OpenGl_PBREnvState_CREATED)
|
||||
{
|
||||
switch (myPBREnvRequest)
|
||||
{
|
||||
case OpenGl_PBREnvRequest_NONE: return;
|
||||
case OpenGl_PBREnvRequest_BAKE: bakePBREnvironment (theCtx); break;
|
||||
case OpenGl_PBREnvRequest_CLEAR: clearPBREnvironment (theCtx); break;
|
||||
}
|
||||
}
|
||||
myPBREnvRequest = OpenGl_PBREnvRequest_NONE;
|
||||
}
|
||||
|
@ -58,36 +58,42 @@ void OpenGl_Material::Init (const OpenGl_Context& theCtx,
|
||||
const Graphic3d_MaterialAspect& theMat,
|
||||
const Quantity_Color& theInteriorColor)
|
||||
{
|
||||
ChangeShine() = 128.0f * theMat.Shininess();
|
||||
ChangeTransparency() = theMat.Alpha();
|
||||
Common.ChangeShine() = 128.0f * theMat.Shininess();
|
||||
Common.ChangeTransparency() = theMat.Alpha();
|
||||
|
||||
Pbr.ChangeMetallic() = theMat.PBRMaterial().Metallic();
|
||||
Pbr.ChangeRoughness() = theMat.PBRMaterial().NormalizedRoughness();
|
||||
Pbr.EmissionIOR = Graphic3d_Vec4 (theMat.PBRMaterial().Emission(), theMat.PBRMaterial().IOR());
|
||||
|
||||
const OpenGl_Vec3& aSrcAmb = theMat.AmbientColor();
|
||||
const OpenGl_Vec3& aSrcDif = theMat.DiffuseColor();
|
||||
const OpenGl_Vec3& aSrcSpe = theMat.SpecularColor();
|
||||
const OpenGl_Vec3& aSrcEms = theMat.EmissiveColor();
|
||||
Specular.SetValues (aSrcSpe, 1.0f); // interior color is ignored for Specular
|
||||
Common.Specular.SetValues (aSrcSpe, 1.0f); // interior color is ignored for Specular
|
||||
switch (theMat.MaterialType())
|
||||
{
|
||||
case Graphic3d_MATERIAL_ASPECT:
|
||||
{
|
||||
Ambient .SetValues (aSrcAmb * theInteriorColor, 1.0f);
|
||||
Diffuse .SetValues (aSrcDif * theInteriorColor, 1.0f);
|
||||
Emission.SetValues (aSrcEms * theInteriorColor, 1.0f);
|
||||
Common.Ambient .SetValues (aSrcAmb * theInteriorColor, 1.0f);
|
||||
Common.Diffuse .SetValues (aSrcDif * theInteriorColor, 1.0f);
|
||||
Common.Emission.SetValues (aSrcEms * theInteriorColor, 1.0f);
|
||||
Pbr .BaseColor.SetValues (theInteriorColor, theMat.Alpha());
|
||||
break;
|
||||
}
|
||||
case Graphic3d_MATERIAL_PHYSIC:
|
||||
{
|
||||
Ambient .SetValues (aSrcAmb, 1.0f);
|
||||
Diffuse .SetValues (aSrcDif, 1.0f);
|
||||
Emission.SetValues (aSrcEms, 1.0f);
|
||||
Common.Ambient .SetValues (aSrcAmb, 1.0f);
|
||||
Common.Diffuse .SetValues (aSrcDif, 1.0f);
|
||||
Common.Emission.SetValues (aSrcEms, 1.0f);
|
||||
Pbr.BaseColor = theMat.PBRMaterial().Color();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ambient = theCtx.Vec4FromQuantityColor (Ambient);
|
||||
Diffuse = theCtx.Vec4FromQuantityColor (Diffuse);
|
||||
Specular = theCtx.Vec4FromQuantityColor (Specular);
|
||||
Emission = theCtx.Vec4FromQuantityColor (Emission);
|
||||
Common.Ambient = theCtx.Vec4FromQuantityColor (Common.Ambient);
|
||||
Common.Diffuse = theCtx.Vec4FromQuantityColor (Common.Diffuse);
|
||||
Common.Specular = theCtx.Vec4FromQuantityColor (Common.Specular);
|
||||
Common.Emission = theCtx.Vec4FromQuantityColor (Common.Emission);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -310,6 +316,14 @@ const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects()
|
||||
myGlContext->BindTextures (myEnvironmentTexture);
|
||||
}
|
||||
|
||||
if ((myView->myShadingModel == Graphic3d_TOSM_PBR
|
||||
|| myView->myShadingModel == Graphic3d_TOSM_PBR_FACET)
|
||||
&& !myView->myPBREnvironment.IsNull()
|
||||
&& myView->myPBREnvironment->IsNeededToBeBound())
|
||||
{
|
||||
myView->myPBREnvironment->Bind (myGlContext);
|
||||
}
|
||||
|
||||
myAspectsApplied = myAspectsSet->Aspect();
|
||||
return myAspectsSet;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
#define occTexture1D texture
|
||||
#define occTexture2D texture
|
||||
#define occTexture3D texture
|
||||
#define occTextureCube texture
|
||||
#define occTextureCubeLod textureLod
|
||||
#else
|
||||
#define THE_ATTRIBUTE attribute
|
||||
#define THE_SHADER_IN varying
|
||||
@ -29,10 +31,16 @@
|
||||
#define occTexture1D texture1D
|
||||
#define occTexture2D texture2D
|
||||
#define occTexture3D texture3D
|
||||
#define occTextureCube textureCube
|
||||
#define occTextureCubeLod textureCubeLod
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
#define THE_PREC_ENUM lowp // enumerations should fit into lowp range
|
||||
#if (__VERSION__ >= 300)
|
||||
#define THE_PREC_ENUM highp // lowp should be enough for enums but triggers driver bugs
|
||||
#else
|
||||
#define THE_PREC_ENUM lowp
|
||||
#endif
|
||||
#else
|
||||
#define THE_PREC_ENUM
|
||||
#endif
|
||||
@ -85,6 +93,15 @@
|
||||
void occSetFragColor (in vec4 theColor);
|
||||
#endif
|
||||
|
||||
// Pi number definitions
|
||||
#define PI 3.141592654
|
||||
#define PI_2 6.283185307
|
||||
#define PI_DIV_2 1.570796327
|
||||
#define PI_DIV_3 1.047197551
|
||||
#define PI_DIV_4 0.785398163
|
||||
#define INV_PI 0.318309886
|
||||
#define INV_PI_2 0.159154943
|
||||
|
||||
// Matrix state
|
||||
uniform mat4 occWorldViewMatrix; //!< World-view matrix
|
||||
uniform mat4 occProjectionMatrix; //!< Projection matrix
|
||||
@ -102,6 +119,15 @@ uniform mat4 occWorldViewMatrixInverseTranspose; //!< Transpose of the inverse
|
||||
uniform mat4 occProjectionMatrixInverseTranspose; //!< Transpose of the inverse of the projection matrix
|
||||
uniform mat4 occModelWorldMatrixInverseTranspose; //!< Transpose of the inverse of the model-world matrix
|
||||
|
||||
#if defined(THE_IS_PBR)
|
||||
uniform sampler2D occEnvLUT; //!< Environment Lookup Table
|
||||
uniform sampler2D occDiffIBLMapSHCoeffs; //!< Packed diffuse (irradiance) IBL map's spherical harmonics coefficients
|
||||
uniform samplerCube occSpecIBLMap; //!< Specular IBL map
|
||||
uniform int occNbSpecIBLLevels; //!< Number of mipmap levels used in occSpecIBLMap to store different roughness values maps
|
||||
|
||||
vec3 occDiffIBLMap (in vec3 theNormal); //!< Unpacks spherical harmonics coefficients to diffuse IBL map's values
|
||||
#endif
|
||||
|
||||
// light type enumeration (same as Graphic3d_TypeOfLightSource)
|
||||
const int OccLightType_Direct = 1; //!< directional light source
|
||||
const int OccLightType_Point = 2; //!< isotropic point light source
|
||||
@ -116,7 +142,7 @@ uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sour
|
||||
#define occLight_Type(theId) occLightSourcesTypes[theId].x
|
||||
|
||||
//! Is light a headlight, int?
|
||||
#define occLight_IsHeadlight(theId) occLightSourcesTypes[theId].y
|
||||
#define occLight_IsHeadlight(theId) (occLightSourcesTypes[theId].y != 0)
|
||||
|
||||
//! Specular intensity (equals to diffuse), vec4.
|
||||
#define occLight_Specular(theId) occLightSources[theId * 4 + 0]
|
||||
@ -133,6 +159,11 @@ uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sour
|
||||
//! Attenuation of the spot light intensity (from 0 to 1), float.
|
||||
#define occLight_SpotExponent(theId) occLightSources[theId * 4 + 3].w
|
||||
|
||||
#if defined(THE_IS_PBR)
|
||||
//! Intensity of light source (>= 0), float.
|
||||
#define occLight_Intensity(theId) occLightSources[theId * 4 + 0].a
|
||||
#else
|
||||
|
||||
//! Diffuse intensity (equals to Specular), vec4.
|
||||
#define occLight_Diffuse(theId) occLightSources[theId * 4 + 0]
|
||||
|
||||
@ -142,22 +173,44 @@ uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sour
|
||||
//! Linear attenuation factor of positional light source, float.
|
||||
#define occLight_LinearAttenuation(theId) occLightSources[theId * 4 + 3].y
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Converts roughness value from range [0, 1] to real value for calculations
|
||||
float occRoughness (in float theNormalizedRoughness);
|
||||
|
||||
// Front material properties accessors
|
||||
vec4 occFrontMaterial_Emission(void); //!< Emission color
|
||||
vec4 occFrontMaterial_Ambient(void); //!< Ambient reflection
|
||||
vec4 occFrontMaterial_Diffuse(void); //!< Diffuse reflection
|
||||
vec4 occFrontMaterial_Specular(void); //!< Specular reflection
|
||||
float occFrontMaterial_Shininess(void); //!< Specular exponent
|
||||
float occFrontMaterial_Transparency(void); //!< Transparency coefficient
|
||||
#if !defined(THE_IS_PBR)
|
||||
vec4 occFrontMaterial_Emission(void); //!< Emission color
|
||||
vec4 occFrontMaterial_Ambient(void); //!< Ambient reflection
|
||||
vec4 occFrontMaterial_Diffuse(void); //!< Diffuse reflection
|
||||
vec4 occFrontMaterial_Specular(void); //!< Specular reflection
|
||||
float occFrontMaterial_Shininess(void); //!< Specular exponent
|
||||
float occFrontMaterial_Transparency(void); //!< Transparency coefficient
|
||||
#else
|
||||
vec4 occPBRFrontMaterial_Color(void); //!< Base color of PBR material
|
||||
float occPBRFrontMaterial_Metallic(void); //!< Metallic coefficient
|
||||
float occPBRFrontMaterial_Roughness(void); //!< Roughness coefficient
|
||||
float occPBRFrontMaterial_NormalizedRoughness(void); //!< Normalized roughness coefficient
|
||||
vec3 occPBRFrontMaterial_Emission(void); //!< Light intensity emitted by material
|
||||
float occPBRFrontMaterial_IOR(void); //!< Index of refraction
|
||||
#endif
|
||||
|
||||
// Back material properties accessors
|
||||
vec4 occBackMaterial_Emission(void); //!< Emission color
|
||||
vec4 occBackMaterial_Ambient(void); //!< Ambient reflection
|
||||
vec4 occBackMaterial_Diffuse(void); //!< Diffuse reflection
|
||||
vec4 occBackMaterial_Specular(void); //!< Specular reflection
|
||||
float occBackMaterial_Shininess(void); //!< Specular exponent
|
||||
float occBackMaterial_Transparency(void); //!< Transparency coefficient
|
||||
#if !defined(THE_IS_PBR)
|
||||
vec4 occBackMaterial_Emission(void); //!< Emission color
|
||||
vec4 occBackMaterial_Ambient(void); //!< Ambient reflection
|
||||
vec4 occBackMaterial_Diffuse(void); //!< Diffuse reflection
|
||||
vec4 occBackMaterial_Specular(void); //!< Specular reflection
|
||||
float occBackMaterial_Shininess(void); //!< Specular exponent
|
||||
float occBackMaterial_Transparency(void); //!< Transparency coefficient
|
||||
#else
|
||||
vec4 occPBRBackMaterial_Color(void); //!< Base color of PBR material
|
||||
float occPBRBackMaterial_Metallic(void); //!< Metallic coefficient
|
||||
float occPBRBackMaterial_Roughness(void); //!< Roughness coefficient
|
||||
float occPBRBackMaterial_NormalizedRoughness(void); //!< Normalized roughness coefficient
|
||||
vec3 occPBRBackMaterial_Emission(void); //!< Light intensity emitted by material
|
||||
float occPBRBackMaterial_IOR(void); //!< Index of refraction
|
||||
#endif
|
||||
|
||||
#ifdef THE_HAS_DEFAULT_SAMPLER
|
||||
#define occActiveSampler occSampler0 //!< alias for backward compatibility
|
||||
|
@ -19,15 +19,59 @@ void occSetFragColor (in vec4 theColor)
|
||||
|
||||
#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)
|
||||
// arrays of light sources
|
||||
uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types
|
||||
uniform vec4 occLightSources[THE_MAX_LIGHTS * 4]; //!< packed light sources parameters
|
||||
uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types
|
||||
#endif
|
||||
|
||||
// material state
|
||||
#if defined(THE_IS_PBR)
|
||||
vec3 occDiffIBLMap (in vec3 theNormal)
|
||||
{
|
||||
vec3 aSHCoeffs[9];
|
||||
for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
aSHCoeffs[i] = occTexture2D (occDiffIBLMapSHCoeffs, vec2 ((float(i) + 0.5) / 9.0, 0.0)).rgb;
|
||||
}
|
||||
return aSHCoeffs[0]
|
||||
|
||||
+ aSHCoeffs[1] * theNormal.x
|
||||
+ aSHCoeffs[2] * theNormal.y
|
||||
+ aSHCoeffs[3] * theNormal.z
|
||||
|
||||
+ aSHCoeffs[4] * theNormal.x * theNormal.z
|
||||
+ aSHCoeffs[5] * theNormal.y * theNormal.z
|
||||
+ aSHCoeffs[6] * theNormal.x * theNormal.y
|
||||
|
||||
+ aSHCoeffs[7] * (3.0 * theNormal.z * theNormal.z - 1.0)
|
||||
+ aSHCoeffs[8] * (theNormal.x * theNormal.x - theNormal.y * theNormal.y);
|
||||
}
|
||||
#endif
|
||||
|
||||
// front and back material properties accessors
|
||||
#if defined(THE_IS_PBR)
|
||||
uniform vec4 occPbrFrontMaterial[3];
|
||||
uniform vec4 occPbrBackMaterial[3];
|
||||
|
||||
#define MIN_ROUGHNESS 0.01
|
||||
// Converts roughness value from range [0, 1] to real value for calculations
|
||||
float occRoughness (in float theNormalizedRoughness) { return theNormalizedRoughness * (1.0 - MIN_ROUGHNESS) + MIN_ROUGHNESS; }
|
||||
|
||||
vec4 occPBRFrontMaterial_Color(void) { return occPbrFrontMaterial[0]; }
|
||||
vec3 occPBRFrontMaterial_Emission(void) { return occPbrFrontMaterial[1].rgb; }
|
||||
float occPBRFrontMaterial_IOR(void) { return occPbrFrontMaterial[1].w; }
|
||||
float occPBRFrontMaterial_Metallic(void) { return occPbrFrontMaterial[2].b; }
|
||||
float occPBRFrontMaterial_Roughness(void) { return occRoughness (occPbrFrontMaterial[2].g); }
|
||||
float occPBRFrontMaterial_NormalizedRoughness(void) { return occPbrFrontMaterial[2].g; }
|
||||
|
||||
vec4 occPBRBackMaterial_Color(void) { return occPbrBackMaterial[0]; }
|
||||
vec3 occPBRBackMaterial_Emission(void) { return occPbrBackMaterial[1].rgb; }
|
||||
float occPBRBackMaterial_IOR(void) { return occPbrBackMaterial[1].w; }
|
||||
float occPBRBackMaterial_Metallic(void) { return occPbrBackMaterial[2].b; }
|
||||
float occPBRBackMaterial_Roughness(void) { return occRoughness (occPbrBackMaterial[2].g); }
|
||||
float occPBRBackMaterial_NormalizedRoughness(void) { return occPbrBackMaterial[2].g; }
|
||||
#else
|
||||
uniform vec4 occFrontMaterial[5];
|
||||
uniform vec4 occBackMaterial[5];
|
||||
|
||||
// front material properties accessors
|
||||
vec4 occFrontMaterial_Ambient(void) { return occFrontMaterial[0]; }
|
||||
vec4 occFrontMaterial_Diffuse(void) { return occFrontMaterial[1]; }
|
||||
vec4 occFrontMaterial_Specular(void) { return occFrontMaterial[2]; }
|
||||
@ -35,13 +79,13 @@ vec4 occFrontMaterial_Emission(void) { return occFrontMaterial[3]; }
|
||||
float occFrontMaterial_Shininess(void) { return occFrontMaterial[4].x; }
|
||||
float occFrontMaterial_Transparency(void) { return occFrontMaterial[4].y; }
|
||||
|
||||
// back material properties accessors
|
||||
vec4 occBackMaterial_Ambient(void) { return occBackMaterial[0]; }
|
||||
vec4 occBackMaterial_Diffuse(void) { return occBackMaterial[1]; }
|
||||
vec4 occBackMaterial_Specular(void) { return occBackMaterial[2]; }
|
||||
vec4 occBackMaterial_Emission(void) { return occBackMaterial[3]; }
|
||||
float occBackMaterial_Shininess(void) { return occBackMaterial[4].x; }
|
||||
float occBackMaterial_Transparency(void) { return occBackMaterial[4].y; }
|
||||
#endif
|
||||
|
||||
// 2D texture coordinates transformation
|
||||
vec2 occTextureTrsf_Translation(void) { return occTexTrsf2d[0].xy; }
|
||||
|
@ -1,5 +1,12 @@
|
||||
srcinc:::Declarations.glsl
|
||||
srcinc:::DeclarationsImpl.glsl
|
||||
srcinc:::PBRCookTorrance.glsl
|
||||
srcinc:::PBRDistribution.glsl
|
||||
srcinc:::PBREnvBaking.fs
|
||||
srcinc:::PBREnvBaking.vs
|
||||
srcinc:::PBRFresnel.glsl
|
||||
srcinc:::PBRGeometry.glsl
|
||||
srcinc:::PBRIllumination.glsl
|
||||
srcinc:::PhongShading.fs
|
||||
srcinc:::PhongShading.vs
|
||||
srcinc:::Display.fs
|
||||
@ -11,6 +18,13 @@ srcinc:::RaytraceSmooth.fs
|
||||
Shaders_Declarations_glsl.pxx
|
||||
Shaders_DeclarationsImpl_glsl.pxx
|
||||
Shaders_Display_fs.pxx
|
||||
Shaders_PBRCookTorrance_glsl.pxx
|
||||
Shaders_PBRDistribution_glsl.pxx
|
||||
Shaders_PBREnvBaking_fs.pxx
|
||||
Shaders_PBREnvBaking_vs.pxx
|
||||
Shaders_PBRFresnel_glsl.pxx
|
||||
Shaders_PBRGeometry_glsl.pxx
|
||||
Shaders_PBRIllumination_glsl.pxx
|
||||
Shaders_RaytraceBase_fs.pxx
|
||||
Shaders_RaytraceRender_fs.pxx
|
||||
Shaders_PathtraceBase_fs.pxx
|
||||
|
20
src/Shaders/PBRCookTorrance.glsl
Normal file
20
src/Shaders/PBRCookTorrance.glsl
Normal file
@ -0,0 +1,20 @@
|
||||
//! Calculates Cook-Torrance BRDF.
|
||||
vec3 occPBRCookTorrance (in vec3 theView,
|
||||
in vec3 theLight,
|
||||
in vec3 theNormal,
|
||||
in vec3 theBaseColor,
|
||||
in float theMetallic,
|
||||
in float theRoughness,
|
||||
in float theIOR)
|
||||
{
|
||||
vec3 aHalf = normalize (theView + theLight);
|
||||
float aCosV = max(dot(theView, theNormal), 0.0);
|
||||
float aCosL = max(dot(theLight, theNormal), 0.0);
|
||||
float aCosH = max(dot(aHalf, theNormal), 0.0);
|
||||
float aCosVH = max(dot(aHalf, theView), 0.0);
|
||||
vec3 aCookTorrance = occPBRDistribution (aCosH, theRoughness)
|
||||
* occPBRGeometry (aCosV, aCosL, theRoughness)
|
||||
* occPBRFresnel (theBaseColor, theMetallic, theIOR, aCosVH);
|
||||
aCookTorrance /= 4.0;
|
||||
return aCookTorrance;
|
||||
}
|
9
src/Shaders/PBRDistribution.glsl
Normal file
9
src/Shaders/PBRDistribution.glsl
Normal file
@ -0,0 +1,9 @@
|
||||
//! Calculates micro facet normals distribution.
|
||||
float occPBRDistribution (in float theCosH,
|
||||
in float theRoughness)
|
||||
{
|
||||
float aDistribution = theRoughness * theRoughness;
|
||||
aDistribution = aDistribution / (theCosH * theCosH * (aDistribution * aDistribution - 1.0) + 1.0);
|
||||
aDistribution = INV_PI * aDistribution * aDistribution;
|
||||
return aDistribution;
|
||||
}
|
162
src/Shaders/PBREnvBaking.fs
Normal file
162
src/Shaders/PBREnvBaking.fs
Normal file
@ -0,0 +1,162 @@
|
||||
THE_SHADER_IN vec3 ViewDirection; //!< direction of fetching from environment cubemap
|
||||
|
||||
uniform int uSamplesNum; //!< number of samples in Monte-Carlo integration
|
||||
uniform int uCurrentLevel; //!< current level of specular IBL map (ignored in case of diffuse map's processing)
|
||||
uniform int uEnvMapSize; //!< one edge's size of source environtment map's zero mipmap level
|
||||
uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap
|
||||
uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap
|
||||
uniform samplerCube uEnvMap; //!< source of baking (environment cubemap)
|
||||
|
||||
//! Returns coordinates of point theNumber from Hammersley point set having size theSize.
|
||||
vec2 hammersley (in int theNumber,
|
||||
in int theSize)
|
||||
{
|
||||
int aDenominator = 2;
|
||||
int aNumber = theNumber;
|
||||
float aVanDerCorput = 0.0;
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
if (aNumber > 0)
|
||||
{
|
||||
aVanDerCorput += float(aNumber % 2) / float(aDenominator);
|
||||
aNumber /= 2;
|
||||
aDenominator *= 2;
|
||||
}
|
||||
}
|
||||
return vec2(float(theNumber) / float(theSize), aVanDerCorput);
|
||||
}
|
||||
|
||||
//! This function does importance sampling on hemisphere surface using GGX normal distribution function
|
||||
//! in tangent space (positive z axis is surface normal direction).
|
||||
vec3 importanceSample (in vec2 theHammersleyPoint,
|
||||
in float theRoughness)
|
||||
{
|
||||
float aPhi = PI_2 * theHammersleyPoint.x;
|
||||
theRoughness *= theRoughness;
|
||||
theRoughness *= theRoughness;
|
||||
float aCosTheta = sqrt((1.0 - theHammersleyPoint.y) / (1.0 + (theRoughness - 1.0) * theHammersleyPoint.y));
|
||||
float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);
|
||||
return vec3(aSinTheta * cos(aPhi),
|
||||
aSinTheta * sin(aPhi),
|
||||
aCosTheta);
|
||||
}
|
||||
|
||||
//! This function uniformly generates samples on whole sphere.
|
||||
vec3 sphereUniformSample (in vec2 theHammersleyPoint)
|
||||
{
|
||||
float aPhi = PI_2 * theHammersleyPoint.x;
|
||||
float aCosTheta = 2.0 * theHammersleyPoint.y - 1.0;
|
||||
float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);
|
||||
return vec3(aSinTheta * cos(aPhi),
|
||||
aSinTheta * sin(aPhi),
|
||||
aCosTheta);
|
||||
}
|
||||
|
||||
//! Transforms resulted sampled direction from tangent space to world space considering the surface normal.
|
||||
vec3 fromTangentSpace (in vec3 theVector,
|
||||
in vec3 theNormal)
|
||||
{
|
||||
vec3 anUp = (abs(theNormal.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 anX = normalize(cross(anUp, theNormal));
|
||||
vec3 anY = cross(theNormal, anX);
|
||||
return anX * theVector.x + anY * theVector.y + theNormal * theVector.z;
|
||||
}
|
||||
|
||||
const float aSHBasisFuncCoeffs[9] = float[9]
|
||||
(
|
||||
0.282095 * 0.282095,
|
||||
0.488603 * 0.488603,
|
||||
0.488603 * 0.488603,
|
||||
0.488603 * 0.488603,
|
||||
1.092548 * 1.092548,
|
||||
1.092548 * 1.092548,
|
||||
1.092548 * 1.092548,
|
||||
0.315392 * 0.315392,
|
||||
0.546274 * 0.546274
|
||||
);
|
||||
|
||||
const float aSHCosCoeffs[9] = float[9]
|
||||
(
|
||||
3.141593,
|
||||
2.094395,
|
||||
2.094395,
|
||||
2.094395,
|
||||
0.785398,
|
||||
0.785398,
|
||||
0.785398,
|
||||
0.785398,
|
||||
0.785398
|
||||
);
|
||||
|
||||
//! Bakes diffuse IBL map's spherical harmonics coefficients.
|
||||
vec3 bakeDiffuseSH()
|
||||
{
|
||||
int anIndex = int(gl_FragCoord.x);
|
||||
vec3 aResult = vec3 (0.0);
|
||||
for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)
|
||||
{
|
||||
vec2 aHammersleyPoint = hammersley (aSampleIter, uSamplesNum);
|
||||
vec3 aDirection = sphereUniformSample (aHammersleyPoint);
|
||||
|
||||
vec3 aValue = occTextureCube (uEnvMap, cubemapVectorTransform (aDirection, uYCoeff, uZCoeff)).rgb;
|
||||
|
||||
float aBasisFunc[9];
|
||||
aBasisFunc[0] = 1.0;
|
||||
|
||||
aBasisFunc[1] = aDirection.x;
|
||||
aBasisFunc[2] = aDirection.y;
|
||||
aBasisFunc[3] = aDirection.z;
|
||||
|
||||
aBasisFunc[4] = aDirection.x * aDirection.z;
|
||||
aBasisFunc[5] = aDirection.y * aDirection.z;
|
||||
aBasisFunc[6] = aDirection.x * aDirection.y;
|
||||
|
||||
aBasisFunc[7] = 3.0 * aDirection.z * aDirection.z - 1.0;
|
||||
aBasisFunc[8] = aDirection.x * aDirection.x - aDirection.y * aDirection.y;
|
||||
|
||||
aResult += aValue * aBasisFunc[anIndex];
|
||||
}
|
||||
|
||||
aResult *= 4.0 * aSHCosCoeffs[anIndex] * aSHBasisFuncCoeffs[anIndex] / float(uSamplesNum);
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//! Bakes specular IBL map.
|
||||
vec3 bakeSpecularMap (in vec3 theNormal,
|
||||
in float theRoughness)
|
||||
{
|
||||
vec3 aResult = vec3(0.0);
|
||||
float aWeightSum = 0.0;
|
||||
int aSamplesNum = (theRoughness == 0.0) ? 1 : uSamplesNum;
|
||||
float aSolidAngleSource = 4.0 * PI / (6.0 * float(uEnvMapSize * uEnvMapSize));
|
||||
for (int aSampleIter = 0; aSampleIter < aSamplesNum; ++aSampleIter)
|
||||
{
|
||||
vec2 aHammersleyPoint = hammersley (aSampleIter, aSamplesNum);
|
||||
vec3 aHalf = importanceSample (aHammersleyPoint, occRoughness (theRoughness));
|
||||
float aHdotV = aHalf.z;
|
||||
aHalf = fromTangentSpace (aHalf, theNormal);
|
||||
vec3 aLight = -reflect (theNormal, aHalf);
|
||||
float aNdotL = dot (aLight, theNormal);
|
||||
if (aNdotL > 0.0)
|
||||
{
|
||||
float aSolidAngleSample = 1.0 / (float(aSamplesNum) * (occPBRDistribution (aHdotV, theRoughness) * 0.25 + 0.0001) + 0.0001);
|
||||
float aLod = (theRoughness == 0.0) ? 0.0 : 0.5 * log2 (aSolidAngleSample / aSolidAngleSource);
|
||||
aResult += occTextureCubeLod (uEnvMap, aLight, aLod).rgb * aNdotL;
|
||||
aWeightSum += aNdotL;
|
||||
}
|
||||
}
|
||||
return aResult / aWeightSum;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 aViewDirection = normalize (ViewDirection);
|
||||
if (occNbSpecIBLLevels == 0)
|
||||
{
|
||||
occSetFragColor (vec4 (bakeDiffuseSH (), 1.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
occSetFragColor (vec4 (bakeSpecularMap (aViewDirection, float(uCurrentLevel) / float(occNbSpecIBLLevels - 1)), 1.0));
|
||||
}
|
||||
}
|
35
src/Shaders/PBREnvBaking.vs
Normal file
35
src/Shaders/PBREnvBaking.vs
Normal file
@ -0,0 +1,35 @@
|
||||
THE_SHADER_OUT vec3 ViewDirection; //!< direction of fetching from environment cubemap
|
||||
|
||||
uniform int uCurrentSide; //!< current side of cubemap
|
||||
uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap
|
||||
uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap
|
||||
|
||||
const mat2 cubemapDirectionMatrices[6] = mat2[]
|
||||
(
|
||||
mat2 ( 0, -1, -1, 0),
|
||||
mat2 ( 0, 1, -1, 0),
|
||||
mat2 ( 0, 1, 1, 0),
|
||||
mat2 ( 0, 1, -1, 0),
|
||||
mat2 ( 1, 0, 0, -1),
|
||||
mat2 (-1, 0, 0, -1)
|
||||
);
|
||||
|
||||
//! Generates environment map fetching direction considering current index of side.
|
||||
vec3 cubemapBakingViewDirection (in int theSide,
|
||||
in vec2 theScreenCoord)
|
||||
{
|
||||
int anAxis = theSide / 2;
|
||||
vec3 aDirection = vec3(0.0);
|
||||
aDirection[anAxis] = float(-(int(theSide) % 2) * 2 + 1);
|
||||
theScreenCoord = cubemapDirectionMatrices[theSide] * theScreenCoord;
|
||||
aDirection[(anAxis + 1) % 3] = theScreenCoord.x;
|
||||
aDirection[(anAxis + 2) % 3] = theScreenCoord.y;
|
||||
return aDirection;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ViewDirection = cubemapBakingViewDirection (uCurrentSide, occVertex.xy);
|
||||
ViewDirection = cubemapVectorTransform (ViewDirection, uYCoeff, uZCoeff);
|
||||
gl_Position = vec4 (occVertex.xy, 0.0, 1.0);
|
||||
}
|
36
src/Shaders/PBRFresnel.glsl
Normal file
36
src/Shaders/PBRFresnel.glsl
Normal file
@ -0,0 +1,36 @@
|
||||
//! Functions to calculate fresnel coefficient and approximate zero fresnel value.
|
||||
vec3 occPBRFresnel (in vec3 theBaseColor,
|
||||
in float theMetallic,
|
||||
in float theIOR)
|
||||
{
|
||||
theIOR = (1.0 - theIOR) / (1.0 + theIOR);
|
||||
theIOR *= theIOR;
|
||||
vec3 f0 = vec3(theIOR);
|
||||
f0 = mix (f0, theBaseColor.rgb, theMetallic);
|
||||
return f0;
|
||||
}
|
||||
|
||||
vec3 occPBRFresnel (in vec3 theBaseColor,
|
||||
in float theMetallic,
|
||||
in float theIOR,
|
||||
in float theCosVH)
|
||||
{
|
||||
vec3 f0 = occPBRFresnel (theBaseColor, theMetallic, theIOR);
|
||||
theCosVH = 1.0 - theCosVH;
|
||||
theCosVH *= theCosVH;
|
||||
theCosVH *= theCosVH * theCosVH * theCosVH * theCosVH;
|
||||
return f0 + (vec3 (1.0) - f0) * theCosVH;
|
||||
}
|
||||
|
||||
vec3 occPBRFresnel (in vec3 theBaseColor,
|
||||
in float theMetallic,
|
||||
in float theRoughness,
|
||||
in float theIOR,
|
||||
in float theCosV)
|
||||
{
|
||||
vec3 f0 = occPBRFresnel (theBaseColor, theMetallic, theIOR);
|
||||
theCosV = 1.0 - theCosV;
|
||||
theCosV *= theCosV;
|
||||
theCosV *= theCosV * theCosV * theCosV * theCosV;
|
||||
return f0 + (max(vec3(1.0 - theRoughness), f0) - f0) * theCosV;
|
||||
}
|
13
src/Shaders/PBRGeometry.glsl
Normal file
13
src/Shaders/PBRGeometry.glsl
Normal file
@ -0,0 +1,13 @@
|
||||
//! Calculates geometry factor for Cook-Torrance BRDF.
|
||||
float occPBRGeometry (in float theCosV,
|
||||
in float theCosL,
|
||||
in float theRoughness)
|
||||
{
|
||||
float k = theRoughness + 1.0;
|
||||
k *= 0.125 * k;
|
||||
float g1 = 1.0;
|
||||
g1 /= theCosV * (1.0 - k) + k;
|
||||
float g2 = 1.0;
|
||||
g2 /= theCosL * (1.0 - k) + k;
|
||||
return g1 * g2;
|
||||
}
|
28
src/Shaders/PBRIllumination.glsl
Normal file
28
src/Shaders/PBRIllumination.glsl
Normal file
@ -0,0 +1,28 @@
|
||||
//! Calculates direct illumination using Cook-Torrance BRDF.
|
||||
vec3 occPBRIllumination (in vec3 theView,
|
||||
in vec3 theLight,
|
||||
in vec3 theNormal,
|
||||
in vec4 theBaseColor,
|
||||
in float theMetallic,
|
||||
in float theRoughness,
|
||||
in float theIOR,
|
||||
in vec3 theLightColor,
|
||||
in float theLightIntensity)
|
||||
{
|
||||
vec3 aHalf = normalize (theView + theLight);
|
||||
float aCosVH = max(dot(theView, aHalf), 0.0);
|
||||
vec3 aFresnel = occPBRFresnel (theBaseColor.rgb, theMetallic, theIOR, aCosVH);
|
||||
vec3 aSpecular = occPBRCookTorrance (theView,
|
||||
theLight,
|
||||
theNormal,
|
||||
theBaseColor.rgb,
|
||||
theMetallic,
|
||||
theRoughness,
|
||||
theIOR);
|
||||
vec3 aDiffuse = vec3(1.0) - aFresnel;
|
||||
aDiffuse *= 1.0 - theMetallic;
|
||||
aDiffuse *= INV_PI;
|
||||
aDiffuse *= theBaseColor.rgb;
|
||||
aDiffuse = mix (vec3(0.0), aDiffuse, theBaseColor.a);
|
||||
return (aDiffuse + aSpecular) * theLightColor * theLightIntensity * max(0.0, dot(theLight, theNormal));
|
||||
}
|
@ -29,7 +29,7 @@ void pointLight (in int theId,
|
||||
in vec3 thePoint)
|
||||
{
|
||||
vec3 aLight = occLight_Position (theId).xyz;
|
||||
if (occLight_IsHeadlight (theId) == 0)
|
||||
if (!occLight_IsHeadlight (theId))
|
||||
{
|
||||
aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));
|
||||
}
|
||||
|
@ -22,15 +22,59 @@ static const char Shaders_DeclarationsImpl_glsl[] =
|
||||
"\n"
|
||||
"#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)\n"
|
||||
"// arrays of light sources\n"
|
||||
"uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types\n"
|
||||
"uniform vec4 occLightSources[THE_MAX_LIGHTS * 4]; //!< packed light sources parameters\n"
|
||||
"uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// material state\n"
|
||||
"#if defined(THE_IS_PBR)\n"
|
||||
"vec3 occDiffIBLMap (in vec3 theNormal)\n"
|
||||
"{\n"
|
||||
" vec3 aSHCoeffs[9];\n"
|
||||
" for (int i = 0; i < 9; ++i)\n"
|
||||
" {\n"
|
||||
" aSHCoeffs[i] = occTexture2D (occDiffIBLMapSHCoeffs, vec2 ((float(i) + 0.5) / 9.0, 0.0)).rgb;\n"
|
||||
" }\n"
|
||||
" return aSHCoeffs[0]\n"
|
||||
"\n"
|
||||
" + aSHCoeffs[1] * theNormal.x\n"
|
||||
" + aSHCoeffs[2] * theNormal.y\n"
|
||||
" + aSHCoeffs[3] * theNormal.z\n"
|
||||
"\n"
|
||||
" + aSHCoeffs[4] * theNormal.x * theNormal.z\n"
|
||||
" + aSHCoeffs[5] * theNormal.y * theNormal.z\n"
|
||||
" + aSHCoeffs[6] * theNormal.x * theNormal.y\n"
|
||||
"\n"
|
||||
" + aSHCoeffs[7] * (3.0 * theNormal.z * theNormal.z - 1.0)\n"
|
||||
" + aSHCoeffs[8] * (theNormal.x * theNormal.x - theNormal.y * theNormal.y);\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// front and back material properties accessors\n"
|
||||
"#if defined(THE_IS_PBR)\n"
|
||||
"uniform vec4 occPbrFrontMaterial[3];\n"
|
||||
"uniform vec4 occPbrBackMaterial[3];\n"
|
||||
"\n"
|
||||
"#define MIN_ROUGHNESS 0.01\n"
|
||||
"// Converts roughness value from range [0, 1] to real value for calculations\n"
|
||||
"float occRoughness (in float theNormalizedRoughness) { return theNormalizedRoughness * (1.0 - MIN_ROUGHNESS) + MIN_ROUGHNESS; }\n"
|
||||
"\n"
|
||||
"vec4 occPBRFrontMaterial_Color(void) { return occPbrFrontMaterial[0]; }\n"
|
||||
"vec3 occPBRFrontMaterial_Emission(void) { return occPbrFrontMaterial[1].rgb; }\n"
|
||||
"float occPBRFrontMaterial_IOR(void) { return occPbrFrontMaterial[1].w; }\n"
|
||||
"float occPBRFrontMaterial_Metallic(void) { return occPbrFrontMaterial[2].b; }\n"
|
||||
"float occPBRFrontMaterial_Roughness(void) { return occRoughness (occPbrFrontMaterial[2].g); }\n"
|
||||
"float occPBRFrontMaterial_NormalizedRoughness(void) { return occPbrFrontMaterial[2].g; }\n"
|
||||
"\n"
|
||||
"vec4 occPBRBackMaterial_Color(void) { return occPbrBackMaterial[0]; }\n"
|
||||
"vec3 occPBRBackMaterial_Emission(void) { return occPbrBackMaterial[1].rgb; }\n"
|
||||
"float occPBRBackMaterial_IOR(void) { return occPbrBackMaterial[1].w; }\n"
|
||||
"float occPBRBackMaterial_Metallic(void) { return occPbrBackMaterial[2].b; }\n"
|
||||
"float occPBRBackMaterial_Roughness(void) { return occRoughness (occPbrBackMaterial[2].g); }\n"
|
||||
"float occPBRBackMaterial_NormalizedRoughness(void) { return occPbrBackMaterial[2].g; }\n"
|
||||
"#else\n"
|
||||
"uniform vec4 occFrontMaterial[5];\n"
|
||||
"uniform vec4 occBackMaterial[5];\n"
|
||||
"\n"
|
||||
"// front material properties accessors\n"
|
||||
"vec4 occFrontMaterial_Ambient(void) { return occFrontMaterial[0]; }\n"
|
||||
"vec4 occFrontMaterial_Diffuse(void) { return occFrontMaterial[1]; }\n"
|
||||
"vec4 occFrontMaterial_Specular(void) { return occFrontMaterial[2]; }\n"
|
||||
@ -38,13 +82,13 @@ static const char Shaders_DeclarationsImpl_glsl[] =
|
||||
"float occFrontMaterial_Shininess(void) { return occFrontMaterial[4].x; }\n"
|
||||
"float occFrontMaterial_Transparency(void) { return occFrontMaterial[4].y; }\n"
|
||||
"\n"
|
||||
"// back material properties accessors\n"
|
||||
"vec4 occBackMaterial_Ambient(void) { return occBackMaterial[0]; }\n"
|
||||
"vec4 occBackMaterial_Diffuse(void) { return occBackMaterial[1]; }\n"
|
||||
"vec4 occBackMaterial_Specular(void) { return occBackMaterial[2]; }\n"
|
||||
"vec4 occBackMaterial_Emission(void) { return occBackMaterial[3]; }\n"
|
||||
"float occBackMaterial_Shininess(void) { return occBackMaterial[4].x; }\n"
|
||||
"float occBackMaterial_Transparency(void) { return occBackMaterial[4].y; }\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// 2D texture coordinates transformation\n"
|
||||
"vec2 occTextureTrsf_Translation(void) { return occTexTrsf2d[0].xy; }\n"
|
||||
|
@ -24,6 +24,8 @@ static const char Shaders_Declarations_glsl[] =
|
||||
" #define occTexture1D texture\n"
|
||||
" #define occTexture2D texture\n"
|
||||
" #define occTexture3D texture\n"
|
||||
" #define occTextureCube texture\n"
|
||||
" #define occTextureCubeLod textureLod\n"
|
||||
"#else\n"
|
||||
" #define THE_ATTRIBUTE attribute\n"
|
||||
" #define THE_SHADER_IN varying\n"
|
||||
@ -32,10 +34,16 @@ static const char Shaders_Declarations_glsl[] =
|
||||
" #define occTexture1D texture1D\n"
|
||||
" #define occTexture2D texture2D\n"
|
||||
" #define occTexture3D texture3D\n"
|
||||
" #define occTextureCube textureCube\n"
|
||||
" #define occTextureCubeLod textureCubeLod\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#ifdef GL_ES\n"
|
||||
" #define THE_PREC_ENUM lowp // enumerations should fit into lowp range\n"
|
||||
"#if (__VERSION__ >= 300)\n"
|
||||
" #define THE_PREC_ENUM highp // lowp should be enough for enums but triggers driver bugs\n"
|
||||
"#else\n"
|
||||
" #define THE_PREC_ENUM lowp\n"
|
||||
"#endif\n"
|
||||
"#else\n"
|
||||
" #define THE_PREC_ENUM\n"
|
||||
"#endif\n"
|
||||
@ -88,6 +96,15 @@ static const char Shaders_Declarations_glsl[] =
|
||||
" void occSetFragColor (in vec4 theColor);\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// Pi number definitions\n"
|
||||
"#define PI 3.141592654\n"
|
||||
"#define PI_2 6.283185307\n"
|
||||
"#define PI_DIV_2 1.570796327\n"
|
||||
"#define PI_DIV_3 1.047197551\n"
|
||||
"#define PI_DIV_4 0.785398163\n"
|
||||
"#define INV_PI 0.318309886\n"
|
||||
"#define INV_PI_2 0.159154943\n"
|
||||
"\n"
|
||||
"// Matrix state\n"
|
||||
"uniform mat4 occWorldViewMatrix; //!< World-view matrix\n"
|
||||
"uniform mat4 occProjectionMatrix; //!< Projection matrix\n"
|
||||
@ -105,6 +122,15 @@ static const char Shaders_Declarations_glsl[] =
|
||||
"uniform mat4 occProjectionMatrixInverseTranspose; //!< Transpose of the inverse of the projection matrix\n"
|
||||
"uniform mat4 occModelWorldMatrixInverseTranspose; //!< Transpose of the inverse of the model-world matrix\n"
|
||||
"\n"
|
||||
"#if defined(THE_IS_PBR)\n"
|
||||
"uniform sampler2D occEnvLUT; //!< Environment Lookup Table\n"
|
||||
"uniform sampler2D occDiffIBLMapSHCoeffs; //!< Packed diffuse (irradiance) IBL map's spherical harmonics coefficients\n"
|
||||
"uniform samplerCube occSpecIBLMap; //!< Specular IBL map\n"
|
||||
"uniform int occNbSpecIBLLevels; //!< Number of mipmap levels used in occSpecIBLMap to store different roughness values maps\n"
|
||||
"\n"
|
||||
"vec3 occDiffIBLMap (in vec3 theNormal); //!< Unpacks spherical harmonics coefficients to diffuse IBL map's values\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// light type enumeration (same as Graphic3d_TypeOfLightSource)\n"
|
||||
"const int OccLightType_Direct = 1; //!< directional light source\n"
|
||||
"const int OccLightType_Point = 2; //!< isotropic point light source\n"
|
||||
@ -119,7 +145,7 @@ static const char Shaders_Declarations_glsl[] =
|
||||
"#define occLight_Type(theId) occLightSourcesTypes[theId].x\n"
|
||||
"\n"
|
||||
"//! Is light a headlight, int?\n"
|
||||
"#define occLight_IsHeadlight(theId) occLightSourcesTypes[theId].y\n"
|
||||
"#define occLight_IsHeadlight(theId) (occLightSourcesTypes[theId].y != 0)\n"
|
||||
"\n"
|
||||
"//! Specular intensity (equals to diffuse), vec4.\n"
|
||||
"#define occLight_Specular(theId) occLightSources[theId * 4 + 0]\n"
|
||||
@ -136,6 +162,11 @@ static const char Shaders_Declarations_glsl[] =
|
||||
"//! Attenuation of the spot light intensity (from 0 to 1), float.\n"
|
||||
"#define occLight_SpotExponent(theId) occLightSources[theId * 4 + 3].w\n"
|
||||
"\n"
|
||||
"#if defined(THE_IS_PBR)\n"
|
||||
"//! Intensity of light source (>= 0), float.\n"
|
||||
"#define occLight_Intensity(theId) occLightSources[theId * 4 + 0].a\n"
|
||||
"#else\n"
|
||||
"\n"
|
||||
"//! Diffuse intensity (equals to Specular), vec4.\n"
|
||||
"#define occLight_Diffuse(theId) occLightSources[theId * 4 + 0]\n"
|
||||
"\n"
|
||||
@ -145,22 +176,44 @@ static const char Shaders_Declarations_glsl[] =
|
||||
"//! Linear attenuation factor of positional light source, float.\n"
|
||||
"#define occLight_LinearAttenuation(theId) occLightSources[theId * 4 + 3].y\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// Converts roughness value from range [0, 1] to real value for calculations\n"
|
||||
"float occRoughness (in float theNormalizedRoughness);\n"
|
||||
"\n"
|
||||
"// Front material properties accessors\n"
|
||||
"vec4 occFrontMaterial_Emission(void); //!< Emission color\n"
|
||||
"vec4 occFrontMaterial_Ambient(void); //!< Ambient reflection\n"
|
||||
"vec4 occFrontMaterial_Diffuse(void); //!< Diffuse reflection\n"
|
||||
"vec4 occFrontMaterial_Specular(void); //!< Specular reflection\n"
|
||||
"float occFrontMaterial_Shininess(void); //!< Specular exponent\n"
|
||||
"float occFrontMaterial_Transparency(void); //!< Transparency coefficient\n"
|
||||
"#if !defined(THE_IS_PBR)\n"
|
||||
"vec4 occFrontMaterial_Emission(void); //!< Emission color\n"
|
||||
"vec4 occFrontMaterial_Ambient(void); //!< Ambient reflection\n"
|
||||
"vec4 occFrontMaterial_Diffuse(void); //!< Diffuse reflection\n"
|
||||
"vec4 occFrontMaterial_Specular(void); //!< Specular reflection\n"
|
||||
"float occFrontMaterial_Shininess(void); //!< Specular exponent\n"
|
||||
"float occFrontMaterial_Transparency(void); //!< Transparency coefficient\n"
|
||||
"#else\n"
|
||||
"vec4 occPBRFrontMaterial_Color(void); //!< Base color of PBR material\n"
|
||||
"float occPBRFrontMaterial_Metallic(void); //!< Metallic coefficient\n"
|
||||
"float occPBRFrontMaterial_Roughness(void); //!< Roughness coefficient\n"
|
||||
"float occPBRFrontMaterial_NormalizedRoughness(void); //!< Normalized roughness coefficient\n"
|
||||
"vec3 occPBRFrontMaterial_Emission(void); //!< Light intensity emitted by material\n"
|
||||
"float occPBRFrontMaterial_IOR(void); //!< Index of refraction\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"// Back material properties accessors\n"
|
||||
"vec4 occBackMaterial_Emission(void); //!< Emission color\n"
|
||||
"vec4 occBackMaterial_Ambient(void); //!< Ambient reflection\n"
|
||||
"vec4 occBackMaterial_Diffuse(void); //!< Diffuse reflection\n"
|
||||
"vec4 occBackMaterial_Specular(void); //!< Specular reflection\n"
|
||||
"float occBackMaterial_Shininess(void); //!< Specular exponent\n"
|
||||
"float occBackMaterial_Transparency(void); //!< Transparency coefficient\n"
|
||||
"#if !defined(THE_IS_PBR)\n"
|
||||
"vec4 occBackMaterial_Emission(void); //!< Emission color\n"
|
||||
"vec4 occBackMaterial_Ambient(void); //!< Ambient reflection\n"
|
||||
"vec4 occBackMaterial_Diffuse(void); //!< Diffuse reflection\n"
|
||||
"vec4 occBackMaterial_Specular(void); //!< Specular reflection\n"
|
||||
"float occBackMaterial_Shininess(void); //!< Specular exponent\n"
|
||||
"float occBackMaterial_Transparency(void); //!< Transparency coefficient\n"
|
||||
"#else\n"
|
||||
"vec4 occPBRBackMaterial_Color(void); //!< Base color of PBR material\n"
|
||||
"float occPBRBackMaterial_Metallic(void); //!< Metallic coefficient\n"
|
||||
"float occPBRBackMaterial_Roughness(void); //!< Roughness coefficient\n"
|
||||
"float occPBRBackMaterial_NormalizedRoughness(void); //!< Normalized roughness coefficient\n"
|
||||
"vec3 occPBRBackMaterial_Emission(void); //!< Light intensity emitted by material\n"
|
||||
"float occPBRBackMaterial_IOR(void); //!< Index of refraction\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#ifdef THE_HAS_DEFAULT_SAMPLER\n"
|
||||
"#define occActiveSampler occSampler0 //!< alias for backward compatibility\n"
|
||||
|
23
src/Shaders/Shaders_PBRCookTorrance_glsl.pxx
Normal file
23
src/Shaders/Shaders_PBRCookTorrance_glsl.pxx
Normal file
@ -0,0 +1,23 @@
|
||||
// This file has been automatically generated from resource file src/Shaders/PBRCookTorrance.glsl
|
||||
|
||||
static const char Shaders_PBRCookTorrance_glsl[] =
|
||||
"//! Calculates Cook-Torrance BRDF.\n"
|
||||
"vec3 occPBRCookTorrance (in vec3 theView,\n"
|
||||
" in vec3 theLight,\n"
|
||||
" in vec3 theNormal,\n"
|
||||
" in vec3 theBaseColor,\n"
|
||||
" in float theMetallic,\n"
|
||||
" in float theRoughness,\n"
|
||||
" in float theIOR)\n"
|
||||
"{\n"
|
||||
" vec3 aHalf = normalize (theView + theLight);\n"
|
||||
" float aCosV = max(dot(theView, theNormal), 0.0);\n"
|
||||
" float aCosL = max(dot(theLight, theNormal), 0.0);\n"
|
||||
" float aCosH = max(dot(aHalf, theNormal), 0.0);\n"
|
||||
" float aCosVH = max(dot(aHalf, theView), 0.0);\n"
|
||||
" vec3 aCookTorrance = occPBRDistribution (aCosH, theRoughness)\n"
|
||||
" * occPBRGeometry (aCosV, aCosL, theRoughness)\n"
|
||||
" * occPBRFresnel (theBaseColor, theMetallic, theIOR, aCosVH);\n"
|
||||
" aCookTorrance /= 4.0;\n"
|
||||
" return aCookTorrance;\n"
|
||||
"}\n";
|
12
src/Shaders/Shaders_PBRDistribution_glsl.pxx
Normal file
12
src/Shaders/Shaders_PBRDistribution_glsl.pxx
Normal file
@ -0,0 +1,12 @@
|
||||
// This file has been automatically generated from resource file src/Shaders/PBRDistribution.glsl
|
||||
|
||||
static const char Shaders_PBRDistribution_glsl[] =
|
||||
"//! Calculates micro facet normals distribution.\n"
|
||||
"float occPBRDistribution (in float theCosH,\n"
|
||||
" in float theRoughness)\n"
|
||||
"{\n"
|
||||
" float aDistribution = theRoughness * theRoughness;\n"
|
||||
" aDistribution = aDistribution / (theCosH * theCosH * (aDistribution * aDistribution - 1.0) + 1.0);\n"
|
||||
" aDistribution = INV_PI * aDistribution * aDistribution;\n"
|
||||
" return aDistribution;\n"
|
||||
"}\n";
|
165
src/Shaders/Shaders_PBREnvBaking_fs.pxx
Normal file
165
src/Shaders/Shaders_PBREnvBaking_fs.pxx
Normal file
@ -0,0 +1,165 @@
|
||||
// This file has been automatically generated from resource file src/Shaders/PBREnvBaking.fs
|
||||
|
||||
static const char Shaders_PBREnvBaking_fs[] =
|
||||
"THE_SHADER_IN vec3 ViewDirection; //!< direction of fetching from environment cubemap\n"
|
||||
"\n"
|
||||
"uniform int uSamplesNum; //!< number of samples in Monte-Carlo integration\n"
|
||||
"uniform int uCurrentLevel; //!< current level of specular IBL map (ignored in case of diffuse map's processing)\n"
|
||||
"uniform int uEnvMapSize; //!< one edge's size of source environtment map's zero mipmap level\n"
|
||||
"uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap\n"
|
||||
"uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap\n"
|
||||
"uniform samplerCube uEnvMap; //!< source of baking (environment cubemap)\n"
|
||||
"\n"
|
||||
"//! Returns coordinates of point theNumber from Hammersley point set having size theSize.\n"
|
||||
"vec2 hammersley (in int theNumber,\n"
|
||||
" in int theSize)\n"
|
||||
"{\n"
|
||||
" int aDenominator = 2;\n"
|
||||
" int aNumber = theNumber;\n"
|
||||
" float aVanDerCorput = 0.0;\n"
|
||||
" for (int i = 0; i < 32; ++i)\n"
|
||||
" {\n"
|
||||
" if (aNumber > 0)\n"
|
||||
" {\n"
|
||||
" aVanDerCorput += float(aNumber % 2) / float(aDenominator);\n"
|
||||
" aNumber /= 2;\n"
|
||||
" aDenominator *= 2;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return vec2(float(theNumber) / float(theSize), aVanDerCorput);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"//! This function does importance sampling on hemisphere surface using GGX normal distribution function\n"
|
||||
"//! in tangent space (positive z axis is surface normal direction).\n"
|
||||
"vec3 importanceSample (in vec2 theHammersleyPoint,\n"
|
||||
" in float theRoughness)\n"
|
||||
"{\n"
|
||||
" float aPhi = PI_2 * theHammersleyPoint.x;\n"
|
||||
" theRoughness *= theRoughness;\n"
|
||||
" theRoughness *= theRoughness;\n"
|
||||
" float aCosTheta = sqrt((1.0 - theHammersleyPoint.y) / (1.0 + (theRoughness - 1.0) * theHammersleyPoint.y));\n"
|
||||
" float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);\n"
|
||||
" return vec3(aSinTheta * cos(aPhi),\n"
|
||||
" aSinTheta * sin(aPhi),\n"
|
||||
" aCosTheta);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"//! This function uniformly generates samples on whole sphere.\n"
|
||||
"vec3 sphereUniformSample (in vec2 theHammersleyPoint)\n"
|
||||
"{\n"
|
||||
" float aPhi = PI_2 * theHammersleyPoint.x;\n"
|
||||
" float aCosTheta = 2.0 * theHammersleyPoint.y - 1.0;\n"
|
||||
" float aSinTheta = sqrt(1.0 - aCosTheta * aCosTheta);\n"
|
||||
" return vec3(aSinTheta * cos(aPhi),\n"
|
||||
" aSinTheta * sin(aPhi),\n"
|
||||
" aCosTheta);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"//! Transforms resulted sampled direction from tangent space to world space considering the surface normal.\n"
|
||||
"vec3 fromTangentSpace (in vec3 theVector,\n"
|
||||
" in vec3 theNormal)\n"
|
||||
"{\n"
|
||||
" vec3 anUp = (abs(theNormal.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n"
|
||||
" vec3 anX = normalize(cross(anUp, theNormal));\n"
|
||||
" vec3 anY = cross(theNormal, anX);\n"
|
||||
" return anX * theVector.x + anY * theVector.y + theNormal * theVector.z;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"const float aSHBasisFuncCoeffs[9] = float[9]\n"
|
||||
"(\n"
|
||||
" 0.282095 * 0.282095,\n"
|
||||
" 0.488603 * 0.488603,\n"
|
||||
" 0.488603 * 0.488603,\n"
|
||||
" 0.488603 * 0.488603,\n"
|
||||
" 1.092548 * 1.092548,\n"
|
||||
" 1.092548 * 1.092548,\n"
|
||||
" 1.092548 * 1.092548,\n"
|
||||
" 0.315392 * 0.315392,\n"
|
||||
" 0.546274 * 0.546274\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"const float aSHCosCoeffs[9] = float[9]\n"
|
||||
"(\n"
|
||||
" 3.141593,\n"
|
||||
" 2.094395,\n"
|
||||
" 2.094395,\n"
|
||||
" 2.094395,\n"
|
||||
" 0.785398,\n"
|
||||
" 0.785398,\n"
|
||||
" 0.785398,\n"
|
||||
" 0.785398,\n"
|
||||
" 0.785398\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"//! Bakes diffuse IBL map's spherical harmonics coefficients.\n"
|
||||
"vec3 bakeDiffuseSH()\n"
|
||||
"{\n"
|
||||
" int anIndex = int(gl_FragCoord.x);\n"
|
||||
" vec3 aResult = vec3 (0.0);\n"
|
||||
" for (int aSampleIter = 0; aSampleIter < uSamplesNum; ++aSampleIter)\n"
|
||||
" {\n"
|
||||
" vec2 aHammersleyPoint = hammersley (aSampleIter, uSamplesNum);\n"
|
||||
" vec3 aDirection = sphereUniformSample (aHammersleyPoint);\n"
|
||||
"\n"
|
||||
" vec3 aValue = occTextureCube (uEnvMap, cubemapVectorTransform (aDirection, uYCoeff, uZCoeff)).rgb;\n"
|
||||
"\n"
|
||||
" float aBasisFunc[9];\n"
|
||||
" aBasisFunc[0] = 1.0;\n"
|
||||
"\n"
|
||||
" aBasisFunc[1] = aDirection.x;\n"
|
||||
" aBasisFunc[2] = aDirection.y;\n"
|
||||
" aBasisFunc[3] = aDirection.z;\n"
|
||||
"\n"
|
||||
" aBasisFunc[4] = aDirection.x * aDirection.z;\n"
|
||||
" aBasisFunc[5] = aDirection.y * aDirection.z;\n"
|
||||
" aBasisFunc[6] = aDirection.x * aDirection.y;\n"
|
||||
"\n"
|
||||
" aBasisFunc[7] = 3.0 * aDirection.z * aDirection.z - 1.0;\n"
|
||||
" aBasisFunc[8] = aDirection.x * aDirection.x - aDirection.y * aDirection.y;\n"
|
||||
"\n"
|
||||
" aResult += aValue * aBasisFunc[anIndex];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" aResult *= 4.0 * aSHCosCoeffs[anIndex] * aSHBasisFuncCoeffs[anIndex] / float(uSamplesNum);\n"
|
||||
" return aResult;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"//! Bakes specular IBL map.\n"
|
||||
"vec3 bakeSpecularMap (in vec3 theNormal,\n"
|
||||
" in float theRoughness)\n"
|
||||
"{\n"
|
||||
" vec3 aResult = vec3(0.0);\n"
|
||||
" float aWeightSum = 0.0;\n"
|
||||
" int aSamplesNum = (theRoughness == 0.0) ? 1 : uSamplesNum;\n"
|
||||
" float aSolidAngleSource = 4.0 * PI / (6.0 * float(uEnvMapSize * uEnvMapSize));\n"
|
||||
" for (int aSampleIter = 0; aSampleIter < aSamplesNum; ++aSampleIter)\n"
|
||||
" {\n"
|
||||
" vec2 aHammersleyPoint = hammersley (aSampleIter, aSamplesNum);\n"
|
||||
" vec3 aHalf = importanceSample (aHammersleyPoint, occRoughness (theRoughness));\n"
|
||||
" float aHdotV = aHalf.z;\n"
|
||||
" aHalf = fromTangentSpace (aHalf, theNormal);\n"
|
||||
" vec3 aLight = -reflect (theNormal, aHalf);\n"
|
||||
" float aNdotL = dot (aLight, theNormal);\n"
|
||||
" if (aNdotL > 0.0)\n"
|
||||
" {\n"
|
||||
" float aSolidAngleSample = 1.0 / (float(aSamplesNum) * (occPBRDistribution (aHdotV, theRoughness) * 0.25 + 0.0001) + 0.0001);\n"
|
||||
" float aLod = (theRoughness == 0.0) ? 0.0 : 0.5 * log2 (aSolidAngleSample / aSolidAngleSource);\n"
|
||||
" aResult += occTextureCubeLod (uEnvMap, aLight, aLod).rgb * aNdotL;\n"
|
||||
" aWeightSum += aNdotL;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return aResult / aWeightSum;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec3 aViewDirection = normalize (ViewDirection);\n"
|
||||
" if (occNbSpecIBLLevels == 0)\n"
|
||||
" {\n"
|
||||
" occSetFragColor (vec4 (bakeDiffuseSH (), 1.0));\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" occSetFragColor (vec4 (bakeSpecularMap (aViewDirection, float(uCurrentLevel) / float(occNbSpecIBLLevels - 1)), 1.0));\n"
|
||||
" }\n"
|
||||
"}\n";
|
38
src/Shaders/Shaders_PBREnvBaking_vs.pxx
Normal file
38
src/Shaders/Shaders_PBREnvBaking_vs.pxx
Normal file
@ -0,0 +1,38 @@
|
||||
// This file has been automatically generated from resource file src/Shaders/PBREnvBaking.vs
|
||||
|
||||
static const char Shaders_PBREnvBaking_vs[] =
|
||||
"THE_SHADER_OUT vec3 ViewDirection; //!< direction of fetching from environment cubemap\n"
|
||||
"\n"
|
||||
"uniform int uCurrentSide; //!< current side of cubemap\n"
|
||||
"uniform int uYCoeff; //!< coefficient of Y controlling horizontal flip of cubemap\n"
|
||||
"uniform int uZCoeff; //!< coefficient of Z controlling vertical flip of cubemap\n"
|
||||
"\n"
|
||||
"const mat2 cubemapDirectionMatrices[6] = mat2[]\n"
|
||||
"(\n"
|
||||
" mat2 ( 0, -1, -1, 0),\n"
|
||||
" mat2 ( 0, 1, -1, 0),\n"
|
||||
" mat2 ( 0, 1, 1, 0),\n"
|
||||
" mat2 ( 0, 1, -1, 0),\n"
|
||||
" mat2 ( 1, 0, 0, -1),\n"
|
||||
" mat2 (-1, 0, 0, -1)\n"
|
||||
");\n"
|
||||
"\n"
|
||||
"//! Generates environment map fetching direction considering current index of side.\n"
|
||||
"vec3 cubemapBakingViewDirection (in int theSide,\n"
|
||||
" in vec2 theScreenCoord)\n"
|
||||
"{\n"
|
||||
" int anAxis = theSide / 2;\n"
|
||||
" vec3 aDirection = vec3(0.0);\n"
|
||||
" aDirection[anAxis] = float(-(int(theSide) % 2) * 2 + 1);\n"
|
||||
" theScreenCoord = cubemapDirectionMatrices[theSide] * theScreenCoord;\n"
|
||||
" aDirection[(anAxis + 1) % 3] = theScreenCoord.x;\n"
|
||||
" aDirection[(anAxis + 2) % 3] = theScreenCoord.y;\n"
|
||||
" return aDirection;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ViewDirection = cubemapBakingViewDirection (uCurrentSide, occVertex.xy);\n"
|
||||
" ViewDirection = cubemapVectorTransform (ViewDirection, uYCoeff, uZCoeff);\n"
|
||||
" gl_Position = vec4 (occVertex.xy, 0.0, 1.0);\n"
|
||||
"}\n";
|
39
src/Shaders/Shaders_PBRFresnel_glsl.pxx
Normal file
39
src/Shaders/Shaders_PBRFresnel_glsl.pxx
Normal file
@ -0,0 +1,39 @@
|
||||
// This file has been automatically generated from resource file src/Shaders/PBRFresnel.glsl
|
||||
|
||||
static const char Shaders_PBRFresnel_glsl[] =
|
||||
"//! Functions to calculate fresnel coefficient and approximate zero fresnel value.\n"
|
||||
"vec3 occPBRFresnel (in vec3 theBaseColor,\n"
|
||||
" in float theMetallic,\n"
|
||||
" in float theIOR)\n"
|
||||
"{\n"
|
||||
" theIOR = (1.0 - theIOR) / (1.0 + theIOR);\n"
|
||||
" theIOR *= theIOR;\n"
|
||||
" vec3 f0 = vec3(theIOR);\n"
|
||||
" f0 = mix (f0, theBaseColor.rgb, theMetallic);\n"
|
||||
" return f0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec3 occPBRFresnel (in vec3 theBaseColor,\n"
|
||||
" in float theMetallic,\n"
|
||||
" in float theIOR,\n"
|
||||
" in float theCosVH)\n"
|
||||
"{\n"
|
||||
" vec3 f0 = occPBRFresnel (theBaseColor, theMetallic, theIOR);\n"
|
||||
" theCosVH = 1.0 - theCosVH;\n"
|
||||
" theCosVH *= theCosVH;\n"
|
||||
" theCosVH *= theCosVH * theCosVH * theCosVH * theCosVH;\n"
|
||||
" return f0 + (vec3 (1.0) - f0) * theCosVH;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec3 occPBRFresnel (in vec3 theBaseColor,\n"
|
||||
" in float theMetallic,\n"
|
||||
" in float theRoughness,\n"
|
||||
" in float theIOR,\n"
|
||||
" in float theCosV)\n"
|
||||
"{\n"
|
||||
" vec3 f0 = occPBRFresnel (theBaseColor, theMetallic, theIOR);\n"
|
||||
" theCosV = 1.0 - theCosV;\n"
|
||||
" theCosV *= theCosV;\n"
|
||||
" theCosV *= theCosV * theCosV * theCosV * theCosV;\n"
|
||||
" return f0 + (max(vec3(1.0 - theRoughness), f0) - f0) * theCosV;\n"
|
||||
"}\n";
|
16
src/Shaders/Shaders_PBRGeometry_glsl.pxx
Normal file
16
src/Shaders/Shaders_PBRGeometry_glsl.pxx
Normal file
@ -0,0 +1,16 @@
|
||||
// This file has been automatically generated from resource file src/Shaders/PBRGeometry.glsl
|
||||
|
||||
static const char Shaders_PBRGeometry_glsl[] =
|
||||
"//! Calculates geometry factor for Cook-Torrance BRDF.\n"
|
||||
"float occPBRGeometry (in float theCosV,\n"
|
||||
" in float theCosL,\n"
|
||||
" in float theRoughness)\n"
|
||||
"{\n"
|
||||
" float k = theRoughness + 1.0;\n"
|
||||
" k *= 0.125 * k;\n"
|
||||
" float g1 = 1.0;\n"
|
||||
" g1 /= theCosV * (1.0 - k) + k;\n"
|
||||
" float g2 = 1.0;\n"
|
||||
" g2 /= theCosL * (1.0 - k) + k;\n"
|
||||
" return g1 * g2;\n"
|
||||
"}\n";
|
31
src/Shaders/Shaders_PBRIllumination_glsl.pxx
Normal file
31
src/Shaders/Shaders_PBRIllumination_glsl.pxx
Normal file
@ -0,0 +1,31 @@
|
||||
// This file has been automatically generated from resource file src/Shaders/PBRIllumination.glsl
|
||||
|
||||
static const char Shaders_PBRIllumination_glsl[] =
|
||||
"//! Calculates direct illumination using Cook-Torrance BRDF.\n"
|
||||
"vec3 occPBRIllumination (in vec3 theView,\n"
|
||||
" in vec3 theLight,\n"
|
||||
" in vec3 theNormal,\n"
|
||||
" in vec4 theBaseColor,\n"
|
||||
" in float theMetallic,\n"
|
||||
" in float theRoughness,\n"
|
||||
" in float theIOR,\n"
|
||||
" in vec3 theLightColor,\n"
|
||||
" in float theLightIntensity)\n"
|
||||
"{\n"
|
||||
" vec3 aHalf = normalize (theView + theLight);\n"
|
||||
" float aCosVH = max(dot(theView, aHalf), 0.0);\n"
|
||||
" vec3 aFresnel = occPBRFresnel (theBaseColor.rgb, theMetallic, theIOR, aCosVH);\n"
|
||||
" vec3 aSpecular = occPBRCookTorrance (theView,\n"
|
||||
" theLight,\n"
|
||||
" theNormal,\n"
|
||||
" theBaseColor.rgb,\n"
|
||||
" theMetallic,\n"
|
||||
" theRoughness,\n"
|
||||
" theIOR);\n"
|
||||
" vec3 aDiffuse = vec3(1.0) - aFresnel;\n"
|
||||
" aDiffuse *= 1.0 - theMetallic;\n"
|
||||
" aDiffuse *= INV_PI;\n"
|
||||
" aDiffuse *= theBaseColor.rgb;\n"
|
||||
" aDiffuse = mix (vec3(0.0), aDiffuse, theBaseColor.a);\n"
|
||||
" return (aDiffuse + aSpecular) * theLightColor * theLightIntensity * max(0.0, dot(theLight, theNormal));\n"
|
||||
"}\n";
|
@ -29,3 +29,4 @@ icon:::env_pearl.rgb
|
||||
icon:::env_road.rgb
|
||||
icon:::env_sky1.rgb
|
||||
icon:::env_sky2.rgb
|
||||
Textures_EnvLUT.pxx
|
||||
|
3461
src/Textures/Textures_EnvLUT.pxx
Normal file
3461
src/Textures/Textures_EnvLUT.pxx
Normal file
File diff suppressed because it is too large
Load Diff
@ -506,10 +506,36 @@ void V3d_View::SetBgImageStyle (const Aspect_FillMethod theFillStyle, const Stan
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void V3d_View::SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap,
|
||||
Standard_Boolean theToUpdatePBREnv,
|
||||
Standard_Boolean theToUpdate)
|
||||
{
|
||||
myView->SetBackgroundCubeMap (theCubeMap);
|
||||
myView->SetBackgroundCubeMap (theCubeMap, theToUpdatePBREnv);
|
||||
if (myImmediateUpdate || theToUpdate)
|
||||
{
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//function : GeneratePBREnvironment
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void V3d_View::GeneratePBREnvironment (Standard_Boolean theToUpdate)
|
||||
{
|
||||
myView->GeneratePBREnvironment();
|
||||
if (myImmediateUpdate || theToUpdate)
|
||||
{
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//function : ClearPBREnvironment
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
void V3d_View::ClearPBREnvironment (Standard_Boolean theToUpdate)
|
||||
{
|
||||
myView->ClearPBREnvironment();
|
||||
if (myImmediateUpdate || theToUpdate)
|
||||
{
|
||||
Redraw();
|
||||
|
@ -228,10 +228,25 @@ public:
|
||||
Standard_EXPORT void SetBgImageStyle (const Aspect_FillMethod theFillStyle,
|
||||
const Standard_Boolean theToUpdate = Standard_False);
|
||||
|
||||
//! Sets environment cubemap as interactive background.
|
||||
//! Sets environment cubemap as background.
|
||||
//! @param theCubeMap cubemap source to be set as background
|
||||
//! @param theToUpdatePBREnv defines whether IBL maps will be generated or not (see 'GeneratePBREnvironment')
|
||||
Standard_EXPORT void SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap,
|
||||
Standard_Boolean theToUpdatePBREnv = Standard_True,
|
||||
Standard_Boolean theToUpdate = Standard_False);
|
||||
|
||||
//! 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').
|
||||
Standard_EXPORT void GeneratePBREnvironment (Standard_Boolean theToUpdate = Standard_False);
|
||||
|
||||
//! 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.
|
||||
Standard_EXPORT void ClearPBREnvironment (Standard_Boolean theToUpdate = Standard_False);
|
||||
|
||||
//! Definition of an axis from its origin and
|
||||
//! its orientation .
|
||||
//! This will be the current axis for rotations and movements.
|
||||
|
@ -517,6 +517,14 @@ Standard_Boolean ViewerTest::ParseShadingModel (Standard_CString th
|
||||
{
|
||||
theModel = Graphic3d_TOSM_FRAGMENT;
|
||||
}
|
||||
else if (aTypeStr == "pbr")
|
||||
{
|
||||
theModel = Graphic3d_TOSM_PBR;
|
||||
}
|
||||
else if (aTypeStr == "pbr_facet")
|
||||
{
|
||||
theModel = Graphic3d_TOSM_PBR_FACET;
|
||||
}
|
||||
else if (aTypeStr == "default"
|
||||
|| aTypeStr == "def")
|
||||
{
|
||||
@ -1982,7 +1990,7 @@ struct ViewerTest_AspectsChangeSet
|
||||
isOk = Standard_False;
|
||||
}
|
||||
if (ToSetShadingModel == 1
|
||||
&& (ShadingModel < Graphic3d_TOSM_DEFAULT || ShadingModel > Graphic3d_TOSM_FRAGMENT))
|
||||
&& (ShadingModel < Graphic3d_TOSM_DEFAULT || ShadingModel > Graphic3d_TOSM_PBR_FACET))
|
||||
{
|
||||
std::cout << "Error: unknown shading model " << ShadingModelName << ".\n";
|
||||
isOk = Standard_False;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <OpenGl_Workspace.hxx>
|
||||
#include <OSD_Environment.hxx>
|
||||
#include <OSD_File.hxx>
|
||||
#include <OSD_OpenFile.hxx>
|
||||
#include <Prs3d_Drawer.hxx>
|
||||
#include <Prs3d_Presentation.hxx>
|
||||
#include <Prs3d_Root.hxx>
|
||||
@ -1037,17 +1038,24 @@ static Standard_Integer VListMaterials (Draw_Interpretor& theDI,
|
||||
"ASPECT material does not define final colors, it is taken from Internal Color instead.\n"
|
||||
"See also Graphic3d_TypeOfMaterial enumeration'>"
|
||||
"Type</div></th>\n"
|
||||
"<th colspan='5'><div title='Common material definition for Phong shading model'>"
|
||||
"Common</div></th>\n"
|
||||
"<th rowspan='2'>Transparency</th>\n"
|
||||
"<th rowspan='2'>Refraction Index</th>\n"
|
||||
"<th colspan='9'><div title='BSDF (Bidirectional Scattering Distribution Function).\n"
|
||||
"<th colspan='5'><div title='PBR Metallic-Roughness'>"
|
||||
"PBR Metallic-Roughness</div></th>\n"
|
||||
"<th colspan='5'><div title='Common material definition for Phong shading model'>"
|
||||
"Common (Blinn-Phong)</div></th>\n"
|
||||
"<th colspan='10'><div title='BSDF (Bidirectional Scattering Distribution Function).\n"
|
||||
"Used for physically-based rendering (in path tracing engine).\n"
|
||||
"BSDF is represented as weighted mixture of basic BRDFs/BTDFs (Bidirectional Reflectance (Transmittance) Distribution Functions).\n"
|
||||
"See also Graphic3d_BSDF structure.'>"
|
||||
"BSDF</div></th>\n"
|
||||
"BSDF (Bidirectional Scattering Distribution Function)</div></th>\n"
|
||||
"</tr>\n"
|
||||
"<tr>\n"
|
||||
"<th>Color</th>\n"
|
||||
"<th>Metallic</th>\n"
|
||||
"<th>Roughness</th>\n"
|
||||
"<th>Emission</th>\n"
|
||||
"<th><div title='Index of refraction'>"
|
||||
"IOR</div></th>\n"
|
||||
"<th>Ambient</th>\n"
|
||||
"<th>Diffuse</th>\n"
|
||||
"<th>Specular</th>\n"
|
||||
@ -1069,6 +1077,7 @@ static Standard_Integer VListMaterials (Draw_Interpretor& theDI,
|
||||
"FresnelCoat</div></th>\n"
|
||||
"<th><div title='Parameters of Fresnel reflectance of base layer'>"
|
||||
"FresnelBase</div></th>\n"
|
||||
"<th>Refraction Index</th>\n"
|
||||
"</tr>\n";
|
||||
}
|
||||
else if (!aDumpFile.IsEmpty())
|
||||
@ -1105,13 +1114,17 @@ static Standard_Integer VListMaterials (Draw_Interpretor& theDI,
|
||||
anHtmlFile << "<tr>\n";
|
||||
anHtmlFile << "<td>" << aMat.StringName() << "</td>\n";
|
||||
anHtmlFile << "<td>" << (aMat.MaterialType() == Graphic3d_MATERIAL_PHYSIC ? "PHYSIC" : "ASPECT") << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.Transparency() << "</td>\n";
|
||||
anHtmlFile << "<td>" << formatSvgColoredRect (aMat.PBRMaterial().Color().GetRGB()) << (Graphic3d_Vec3 )aMat.PBRMaterial().Color().GetRGB() << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.PBRMaterial().Metallic() << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.PBRMaterial().NormalizedRoughness() << "</td>\n";
|
||||
anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aMat.PBRMaterial().Emission())) << aMat.PBRMaterial().Emission() << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.PBRMaterial().IOR() << "</td>\n";
|
||||
anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (anAmbient)) << anAmbient << "</td>\n";
|
||||
anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aDiffuse)) << aDiffuse << "</td>\n";
|
||||
anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (aSpecular)) << aSpecular << "</td>\n";
|
||||
anHtmlFile << "<td>" << formatSvgColoredRect (Quantity_Color (anEmission)) << anEmission << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.Shininess() << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.Transparency() << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.RefractionIndex() << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.BSDF().Kc << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.BSDF().Kd << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.BSDF().Ks << "</td>\n";
|
||||
@ -1120,18 +1133,23 @@ static Standard_Integer VListMaterials (Draw_Interpretor& theDI,
|
||||
anHtmlFile << "<td>" << aMat.BSDF().Absorption << "</td>\n";
|
||||
anHtmlFile << "<td>" << fresnelModelString (aMat.BSDF().FresnelCoat.FresnelType()) << "</td>\n";
|
||||
anHtmlFile << "<td>" << fresnelModelString (aMat.BSDF().FresnelBase.FresnelType()) << "</td>\n";
|
||||
anHtmlFile << "<td>" << aMat.RefractionIndex() << "</td>\n";
|
||||
anHtmlFile << "</tr>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
theDI << aMat.StringName() << "\n";
|
||||
theDI << " Transparency: " << aMat.Transparency() << "\n";
|
||||
theDI << " PBR.BaseColor: " << (Graphic3d_Vec3 )aMat.PBRMaterial().Color().GetRGB() << "\n";
|
||||
theDI << " PBR.Metallic: " << aMat.PBRMaterial().Metallic() << "\n";
|
||||
theDI << " PBR.Roughness: " << aMat.PBRMaterial().NormalizedRoughness() << "\n";
|
||||
theDI << " PBR.Emission: " << aMat.PBRMaterial().Emission() << "\n";
|
||||
theDI << " PBR.IOR: " << aMat.PBRMaterial().IOR() << "\n";
|
||||
theDI << " Common.Ambient: " << anAmbient << "\n";
|
||||
theDI << " Common.Diffuse: " << aDiffuse << "\n";
|
||||
theDI << " Common.Specular: " << aSpecular << "\n";
|
||||
theDI << " Common.Emissive: " << anEmission << "\n";
|
||||
theDI << " Common.Shiness: " << aMat.Shininess() << "\n";
|
||||
theDI << " Common.Transparency: " << aMat.Transparency() << "\n";
|
||||
theDI << " RefractionIndex: " << aMat.RefractionIndex() << "\n";
|
||||
theDI << " BSDF.Kc: " << aMat.BSDF().Kc << "\n";
|
||||
theDI << " BSDF.Kd: " << aMat.BSDF().Kd << "\n";
|
||||
theDI << " BSDF.Ks: " << aMat.BSDF().Ks << "\n";
|
||||
@ -1140,6 +1158,7 @@ static Standard_Integer VListMaterials (Draw_Interpretor& theDI,
|
||||
theDI << " BSDF.Absorption: " << aMat.BSDF().Absorption << "\n";
|
||||
theDI << " BSDF.FresnelCoat: " << fresnelModelString (aMat.BSDF().FresnelCoat.FresnelType()) << "\n";
|
||||
theDI << " BSDF.FresnelBase: " << fresnelModelString (aMat.BSDF().FresnelBase.FresnelType()) << "\n";
|
||||
theDI << " RefractionIndex: " << aMat.RefractionIndex() << "\n";
|
||||
}
|
||||
|
||||
if (anObjFile.is_open())
|
||||
@ -1335,6 +1354,159 @@ static Standard_Integer VListColors (Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : envlutWriteToFile
|
||||
//purpose :
|
||||
//==============================================================================
|
||||
static std::string envLutWriteToFile (Standard_ShortReal theValue)
|
||||
{
|
||||
std::stringstream aStream;
|
||||
aStream << theValue;
|
||||
if (aStream.str().length() == 1)
|
||||
{
|
||||
aStream << '.';
|
||||
}
|
||||
aStream << 'f';
|
||||
return aStream.str();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//function : VGenEnvLUT
|
||||
//purpose :
|
||||
//==============================================================================
|
||||
static Standard_Integer VGenEnvLUT (Draw_Interpretor&,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
Standard_Integer aTableSize = -1;
|
||||
Standard_Integer aNbSamples = -1;
|
||||
TCollection_AsciiString aFilePath = Graphic3d_TextureRoot::TexturesFolder() + "/Textures_EnvLUT.pxx";
|
||||
|
||||
for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
|
||||
{
|
||||
TCollection_AsciiString anArg(theArgVec[anArgIter]);
|
||||
anArg.LowerCase();
|
||||
|
||||
if (anArg == "-size"
|
||||
|| anArg == "-s")
|
||||
{
|
||||
if (anArgIter + 1 >= theArgNb)
|
||||
{
|
||||
std::cerr << "Syntax error: size of PBR environment look up table is undefined" << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
aTableSize = Draw::Atoi(theArgVec[++anArgIter]);
|
||||
|
||||
if (aTableSize < 16)
|
||||
{
|
||||
std::cerr << "Error: size of PBR environment look up table must be greater or equal 16\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (anArg == "-nbsamples"
|
||||
|| anArg == "-samples")
|
||||
{
|
||||
if (anArgIter + 1 >= theArgNb)
|
||||
{
|
||||
std::cerr << "Syntax error: number of samples to generate PBR environment look up table is undefined" << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
aNbSamples = Draw::Atoi(theArgVec[++anArgIter]);
|
||||
|
||||
if (aNbSamples < 1)
|
||||
{
|
||||
std::cerr << "Syntax error: number of samples to generate PBR environment look up table must be greater than 1\n" << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Syntax error: unknown argument " << anArg << ";\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (aTableSize < 0)
|
||||
{
|
||||
aTableSize = 128;
|
||||
}
|
||||
|
||||
if (aNbSamples < 0)
|
||||
{
|
||||
aNbSamples = 1024;
|
||||
}
|
||||
|
||||
std::ofstream aFile;
|
||||
|
||||
OSD_OpenStream (aFile, aFilePath, std::ios::out | std::ios::binary);
|
||||
|
||||
if (!aFile.good())
|
||||
{
|
||||
std::cerr << "Error: unable to write to " << aFilePath << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
aFile << "//this file has been generated by vgenenvlut draw command\n";
|
||||
aFile << "static unsigned int Textures_EnvLUTSize = " << aTableSize << ";\n\n";
|
||||
aFile << "static float Textures_EnvLUT[] =\n";
|
||||
aFile << "{\n";
|
||||
|
||||
Handle(Image_PixMap) aPixMap = new Image_PixMap();
|
||||
aPixMap->InitZero (Image_Format_RGF, aTableSize, aTableSize);
|
||||
Graphic3d_PBRMaterial::GenerateEnvLUT (aPixMap, aNbSamples);
|
||||
|
||||
const Standard_Integer aNumbersInRow = 5;
|
||||
Standard_Integer aCounter = 0;
|
||||
|
||||
for (int y = 0; y < aTableSize - 1; ++y)
|
||||
{
|
||||
aCounter = 0;
|
||||
for (int x = 0; x < aTableSize; ++x)
|
||||
{
|
||||
aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(aTableSize - 1 - y, x).x()) << ",";
|
||||
aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(aTableSize - 1 - y, x).y()) << ",";
|
||||
if (++aCounter % aNumbersInRow == 0)
|
||||
{
|
||||
aFile << "\n";
|
||||
}
|
||||
else if (x != aTableSize - 1)
|
||||
{
|
||||
aFile << " ";
|
||||
}
|
||||
}
|
||||
aFile << "\n";
|
||||
if (aTableSize % aNumbersInRow != 0)
|
||||
{
|
||||
aFile << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
aCounter = 0;
|
||||
for (int x = 0; x < aTableSize - 1; ++x)
|
||||
{
|
||||
aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, x).x()) << ",";
|
||||
aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, x).y()) << ",";
|
||||
if (++aCounter % aNumbersInRow == 0)
|
||||
{
|
||||
aFile << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
aFile << " ";
|
||||
}
|
||||
}
|
||||
|
||||
aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, aTableSize - 1).x()) << ",";
|
||||
aFile << envLutWriteToFile (aPixMap->Value<Graphic3d_Vec3>(0, aTableSize - 1).y()) << "\n";
|
||||
|
||||
aFile << "};";
|
||||
aFile.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : OpenGlCommands
|
||||
//purpose :
|
||||
@ -1386,4 +1558,12 @@ void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands)
|
||||
"\n\t\t: or dumped into specified file."
|
||||
"\n\t\t: * can be used to refer to complete list of standard colors.",
|
||||
__FILE__, VListColors, aGroup);
|
||||
theCommands.Add("vgenenvlut",
|
||||
"vgenenvlut [-size size = 128] [-nbsamples nbsamples = 1024]"
|
||||
"\n\t\t: Generates PBR environment look up table."
|
||||
"\n\t\t: Saves it as C++ source file which is expected to be included in code."
|
||||
"\n\t\t: The path where result will be located is 'Graphic3d_TextureRoot::TexturesFolder()'."
|
||||
"\n\t\t: -size size of one side of resulted square table"
|
||||
"\n\t\t: -nbsamples number of samples used in Monte-Carlo integration",
|
||||
__FILE__, VGenEnvLUT, aGroup);
|
||||
}
|
||||
|
@ -416,6 +416,9 @@ namespace
|
||||
//! the option key for the command that sets inversion of Z axis for background cubemap
|
||||
ViewerTest_CommandOptionKey myCubeMapInvertedZOptionKey;
|
||||
|
||||
//! the option key for the command that allows skip IBL map generation
|
||||
ViewerTest_CommandOptionKey myCubeMapDoNotGenPBREnvOptionKey;
|
||||
|
||||
//! the variable set of options that are allowed for the old scenario (without any option passed)
|
||||
CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
|
||||
|
||||
@ -466,6 +469,7 @@ namespace
|
||||
myCubeMapOrderOptionKey = myCommandParser.AddOption ("order|o", "order of sides in one image packed cubemap");
|
||||
myCubeMapInvertedZOptionKey = myCommandParser.AddOption (
|
||||
"invertedz|invz|iz", "whether Z axis is inverted or not during background cubemap rendering");
|
||||
myCubeMapDoNotGenPBREnvOptionKey = myCommandParser.AddOption ("nopbrenv", "whether IBL map generation should be skipped");
|
||||
}
|
||||
|
||||
//! Creates option sets used to determine if a passed option set is valid or not
|
||||
@ -479,6 +483,7 @@ namespace
|
||||
aCubeMapOptionSet.insert (myCubeMapOptionKey);
|
||||
ViewerTest_CommandOptionKeySet aCubeMapAdditionalOptionKeySet;
|
||||
aCubeMapAdditionalOptionKeySet.insert (myCubeMapInvertedZOptionKey);
|
||||
aCubeMapAdditionalOptionKeySet.insert (myCubeMapDoNotGenPBREnvOptionKey);
|
||||
aCubeMapAdditionalOptionKeySet.insert (myCubeMapOrderOptionKey);
|
||||
myCubeMapOptionVariableSet = CommandOptionKeyVariableSet (aCubeMapOptionSet, aCubeMapAdditionalOptionKeySet);
|
||||
|
||||
@ -852,7 +857,17 @@ namespace
|
||||
aZIsInverted = true;
|
||||
}
|
||||
|
||||
setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted);
|
||||
bool aToGenPBREnv = true;
|
||||
if (myCommandParser.HasOption (myCubeMapDoNotGenPBREnvOptionKey))
|
||||
{
|
||||
if (!processCubeMapDoNotGenPBREnvOptionSet())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
aToGenPBREnv = false;
|
||||
}
|
||||
|
||||
setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted, aToGenPBREnv);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1017,8 +1032,7 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Processes the cubemap option
|
||||
//! @param theIsNeededToRedraw defines need of redraw after option's processing
|
||||
//! Processes the inverted z cubemap option
|
||||
//! @return true if processing was successful, or false otherwise
|
||||
bool processCubeMapInvertedZOptionSet () const
|
||||
{
|
||||
@ -1033,6 +1047,21 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Processes the option allowing to skip IBM maps generation
|
||||
//! @return true if processing was successful, or false otherwise
|
||||
bool processCubeMapDoNotGenPBREnvOptionSet() const
|
||||
{
|
||||
const Standard_Integer aNumberOfCubeMapDoNotGenPBREnvOptionArguments =
|
||||
myCommandParser.GetNumberOfOptionArguments(myCubeMapDoNotGenPBREnvOptionKey);
|
||||
|
||||
if (aNumberOfCubeMapDoNotGenPBREnvOptionArguments != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Processes the tiles order option
|
||||
//! @param theOrder the array of indexes if cubemap sides in tile grid
|
||||
//! @return true if processing was successful, or false otherwise
|
||||
@ -1221,7 +1250,8 @@ namespace
|
||||
//! @param theOrder array of cubemap sides indexes mapping them from tiles in packed cubemap
|
||||
static void setCubeMap (const NCollection_Array1<TCollection_AsciiString>& theFileNames,
|
||||
const Graphic3d_ValidatedCubeMapOrder theOrder = Graphic3d_CubeMapOrder::Default(),
|
||||
bool theZIsInverted = false)
|
||||
bool theZIsInverted = false,
|
||||
bool theToGenPBREnv = true)
|
||||
{
|
||||
const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
|
||||
Handle(Graphic3d_CubeMap) aCubeMap;
|
||||
@ -1237,7 +1267,7 @@ namespace
|
||||
aCubeMap->GetParams()->SetRepeat(Standard_False);
|
||||
aCubeMap->GetParams()->SetTextureUnit(Graphic3d_TextureUnit_EnvMap);
|
||||
|
||||
aCurrentView->SetBackgroundCubeMap (aCubeMap, Standard_True);
|
||||
aCurrentView->SetBackgroundCubeMap (aCubeMap, theToGenPBREnv, Standard_True);
|
||||
}
|
||||
|
||||
//! Sets the image as a background
|
||||
@ -11185,6 +11215,48 @@ static int VLight (Draw_Interpretor& theDi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===============================================================================================
|
||||
//function : VPBREnvironment
|
||||
//purpose :
|
||||
//===============================================================================================
|
||||
static int VPBREnvironment (Draw_Interpretor&,
|
||||
Standard_Integer theArgsNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
if (theArgsNb > 2)
|
||||
{
|
||||
std::cerr << "Error: 'vpbrenv' command has only one argument\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Handle(V3d_View) aView = ViewerTest::CurrentView();
|
||||
if (aView.IsNull())
|
||||
{
|
||||
std::cerr << "Error: no active viewer!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
TCollection_AsciiString anArg = TCollection_AsciiString (theArgVec[1]);
|
||||
anArg.LowerCase();
|
||||
|
||||
if (anArg == "-generate"
|
||||
|| anArg == "-gen")
|
||||
{
|
||||
aView->GeneratePBREnvironment (Standard_True);
|
||||
}
|
||||
else if (anArg == "-clear")
|
||||
{
|
||||
aView->ClearPBREnvironment (Standard_True);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: unknown argument [" << theArgVec[1] << "] for 'vpbrenv' command\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Read Graphic3d_RenderingParams::PerfCounters flag.
|
||||
static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
|
||||
Standard_Boolean& theToReset,
|
||||
@ -11391,11 +11463,13 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
||||
theDI << "shadingModel: ";
|
||||
switch (aView->ShadingModel())
|
||||
{
|
||||
case Graphic3d_TOSM_DEFAULT: theDI << "default"; break;
|
||||
case Graphic3d_TOSM_UNLIT: theDI << "unlit"; break;
|
||||
case Graphic3d_TOSM_FACET: theDI << "flat"; break;
|
||||
case Graphic3d_TOSM_VERTEX: theDI << "gouraud"; break;
|
||||
case Graphic3d_TOSM_FRAGMENT: theDI << "phong"; break;
|
||||
case Graphic3d_TOSM_DEFAULT: theDI << "default"; break;
|
||||
case Graphic3d_TOSM_UNLIT: theDI << "unlit"; break;
|
||||
case Graphic3d_TOSM_FACET: theDI << "flat"; break;
|
||||
case Graphic3d_TOSM_VERTEX: theDI << "gouraud"; break;
|
||||
case Graphic3d_TOSM_FRAGMENT: theDI << "phong"; break;
|
||||
case Graphic3d_TOSM_PBR: theDI << "pbr"; break;
|
||||
case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
|
||||
}
|
||||
{
|
||||
theDI << "perfCounters:";
|
||||
@ -11957,11 +12031,13 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
||||
{
|
||||
switch (aView->ShadingModel())
|
||||
{
|
||||
case Graphic3d_TOSM_DEFAULT: theDI << "default"; break;
|
||||
case Graphic3d_TOSM_UNLIT: theDI << "unlit "; break;
|
||||
case Graphic3d_TOSM_FACET: theDI << "flat "; break;
|
||||
case Graphic3d_TOSM_VERTEX: theDI << "gouraud "; break;
|
||||
case Graphic3d_TOSM_FRAGMENT: theDI << "phong "; break;
|
||||
case Graphic3d_TOSM_DEFAULT: theDI << "default"; break;
|
||||
case Graphic3d_TOSM_UNLIT: theDI << "unlit "; break;
|
||||
case Graphic3d_TOSM_FACET: theDI << "flat "; break;
|
||||
case Graphic3d_TOSM_VERTEX: theDI << "gouraud "; break;
|
||||
case Graphic3d_TOSM_FRAGMENT: theDI << "phong "; break;
|
||||
case Graphic3d_TOSM_PBR: theDI << "pbr"; break;
|
||||
case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -11983,6 +12059,97 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (aFlag == "-pbrenvpow2size"
|
||||
|| aFlag == "-pbrenvp2s"
|
||||
|| aFlag == "-pep2s")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Standard_Integer aPbrEnvPow2Size = Draw::Atoi (theArgVec[anArgIter]);
|
||||
if (aPbrEnvPow2Size < 1)
|
||||
{
|
||||
std::cout << "Error: 'Pow2Size' of PBR Environment has to be greater or equal 1\n";
|
||||
return 1;
|
||||
}
|
||||
aParams.PbrEnvPow2Size = aPbrEnvPow2Size;
|
||||
}
|
||||
else if (aFlag == "-pbrenvspecmaplevelsnumber"
|
||||
|| aFlag == "-pbrenvspecmapnblevels"
|
||||
|| aFlag == "-pbrenvspecmaplevels"
|
||||
|| aFlag == "-pbrenvsmln"
|
||||
|| aFlag == "-pesmln")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Standard_Integer aPbrEnvSpecMapNbLevels = Draw::Atoi (theArgVec[anArgIter]);
|
||||
if (aPbrEnvSpecMapNbLevels < 2)
|
||||
{
|
||||
std::cout << "Error: 'SpecMapLevelsNumber' of PBR Environment has to be greater or equal 2\n";
|
||||
return 1;
|
||||
}
|
||||
aParams.PbrEnvSpecMapNbLevels = aPbrEnvSpecMapNbLevels;
|
||||
}
|
||||
else if (aFlag == "-pbrenvbakngdiffsamplesnumber"
|
||||
|| aFlag == "-pbrenvbakingdiffsamples"
|
||||
|| aFlag == "-pbrenvbdsn")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Standard_Integer aPbrEnvBakingDiffNbSamples = Draw::Atoi (theArgVec[anArgIter]);
|
||||
if (aPbrEnvBakingDiffNbSamples < 1)
|
||||
{
|
||||
std::cout << "Error: 'BakingDiffSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
|
||||
return 1;
|
||||
}
|
||||
aParams.PbrEnvBakingDiffNbSamples = aPbrEnvBakingDiffNbSamples;
|
||||
}
|
||||
else if (aFlag == "-pbrenvbakngspecsamplesnumber"
|
||||
|| aFlag == "-pbrenvbakingspecsamples"
|
||||
|| aFlag == "-pbrenvbssn")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Standard_Integer aPbrEnvBakingSpecNbSamples = Draw::Atoi(theArgVec[anArgIter]);
|
||||
if (aPbrEnvBakingSpecNbSamples < 1)
|
||||
{
|
||||
std::cout << "Error: 'BakingSpecSamplesNumber' of PBR Environtment has to be greater or equal 1\n";
|
||||
return 1;
|
||||
}
|
||||
aParams.PbrEnvBakingSpecNbSamples = aPbrEnvBakingSpecNbSamples;
|
||||
}
|
||||
else if (aFlag == "-pbrenvbakingprobability"
|
||||
|| aFlag == "-pbrenvbp")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
{
|
||||
std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
|
||||
return 1;
|
||||
}
|
||||
const Standard_ShortReal aPbrEnvBakingProbability = static_cast<Standard_ShortReal>(Draw::Atof (theArgVec[anArgIter]));
|
||||
if (aPbrEnvBakingProbability < 0.f
|
||||
|| aPbrEnvBakingProbability > 1.f)
|
||||
{
|
||||
std::cout << "Error: 'BakingProbability' of PBR Environtment has to be in range of [0, 1]\n";
|
||||
return 1;
|
||||
}
|
||||
aParams.PbrEnvBakingProbability = aPbrEnvBakingProbability;
|
||||
}
|
||||
else if (aFlag == "-resolution")
|
||||
{
|
||||
if (++anArgIter >= theArgNb)
|
||||
@ -14205,6 +14372,12 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
|
||||
"\n\n example: vlight -add positional -head 1 -pos 0 1 1 -color red"
|
||||
"\n example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
|
||||
__FILE__, VLight, group);
|
||||
theCommands.Add("vpbrenv",
|
||||
"vpbrenv -clear|-generate"
|
||||
"\n\t\t: Clears or generates PBR environment map of active view."
|
||||
"\n\t\t: -clear clears PBR environment (fills by white color)"
|
||||
"\n\t\t: -generate generates PBR environment from current background cubemap",
|
||||
__FILE__, VPBREnvironment, group);
|
||||
theCommands.Add("vraytrace",
|
||||
"vraytrace [0|1]"
|
||||
"\n\t\t: Turns on/off ray-tracing renderer."
|
||||
@ -14238,6 +14411,11 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
|
||||
"\n '-rebuildGlsl on|off' Rebuild Ray-Tracing GLSL programs (for debugging)"
|
||||
"\n '-shadingModel model' Controls shading model from enumeration"
|
||||
"\n unlit, flat, gouraud, phong"
|
||||
"\n '-pbrEnvPow2size > 0' Controls size of IBL maps (real size can be calculates as 2^pbrenvpow2size)"
|
||||
"\n '-pbrEnvSMLN > 1' Controls number of mipmap levels used in specular IBL map"
|
||||
"\n '-pbrEnvBDSN > 0' Controls number of samples in Monte-Carlo integration during diffuse IBL map's sherical harmonics calculation"
|
||||
"\n '-pbrEnvBSSN > 0' Controls maximum number of samples per mipmap level in Monte-Carlo integration during specular IBL maps generation"
|
||||
"\n '-pbrEnvBP [0, 1]' Controls strength of samples number reducing during specular IBL maps generation (1 disables reducing)"
|
||||
"\n '-resolution value' Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
|
||||
"\n '-aperture >= 0.0' Aperture size of perspective camera for depth-of-field effect (0 disables DOF)"
|
||||
"\n '-focal >= 0.0' Focal distance of perspective camera for depth-of-field effect"
|
||||
|
@ -166,22 +166,6 @@ XCAFDoc_VisMaterialCommon XCAFDoc_VisMaterial::ConvertToCommonMaterial()
|
||||
return aComMat;
|
||||
}
|
||||
|
||||
//! Compute material roughness from common material.
|
||||
static Standard_ShortReal roughnessFromCommon (const XCAFDoc_VisMaterialCommon& theMat)
|
||||
{
|
||||
Standard_Real aRoughnessFactor = 1.0 - theMat.Shininess;
|
||||
//Standard_Real aSpecIntens = theMat.SpecularColor.Light() * theMat.SpecularColor;
|
||||
const Standard_Real aSpecIntens = theMat.SpecularColor.Red() * 0.2125
|
||||
+ theMat.SpecularColor.Green() * 0.7154
|
||||
+ theMat.SpecularColor.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 : ConvertToPbrMaterial
|
||||
//purpose :
|
||||
@ -201,9 +185,8 @@ XCAFDoc_VisMaterialPBR XCAFDoc_VisMaterial::ConvertToPbrMaterial()
|
||||
aPbrMat.IsDefined = true;
|
||||
aPbrMat.BaseColor.SetRGB (myCommonMat.DiffuseColor);
|
||||
aPbrMat.BaseColor.SetAlpha (1.0f - myCommonMat.Transparency);
|
||||
// we allow to save any number in range [0, 1] but logically metallicity can be either 0 or 1
|
||||
aPbrMat.Metallic = ((Graphic3d_Vec3 )myCommonMat.SpecularColor).maxComp(); // > 0.1f ? 1.0 : 0.0;
|
||||
aPbrMat.Roughness = roughnessFromCommon (myCommonMat);
|
||||
aPbrMat.Metallic = Graphic3d_PBRMaterial::MetallicFromSpecular (myCommonMat.SpecularColor);
|
||||
aPbrMat.Roughness = Graphic3d_PBRMaterial::RoughnessFromSpecular (myCommonMat.SpecularColor, myCommonMat.Shininess);
|
||||
return aPbrMat;
|
||||
}
|
||||
|
||||
@ -226,13 +209,12 @@ void XCAFDoc_VisMaterial::FillMaterialAspect (Graphic3d_MaterialAspect& theAspec
|
||||
// convert common into metal-roughness
|
||||
if (!myPbrMat.IsDefined)
|
||||
{
|
||||
#ifdef _Graphic3d_PBRMaterial_HeaderFile
|
||||
Graphic3d_PBRMaterial aPbr;
|
||||
aPbr.SetColor (myCommonMat.DiffuseColor);
|
||||
aPbr.SetMetallic (((Graphic3d_Vec3 )myCommonMat.SpecularColor).maxComp());
|
||||
aPbr.SetRoughness (roughnessFromCommon (myCommonMat));
|
||||
aPbr.SetMetallic (Graphic3d_PBRMaterial::MetallicFromSpecular (myCommonMat.SpecularColor));
|
||||
aPbr.SetRoughness (Graphic3d_PBRMaterial::RoughnessFromSpecular (myCommonMat.SpecularColor, myCommonMat.Shininess));
|
||||
theAspect.SetPBRMaterial (aPbr);
|
||||
#endif
|
||||
theAspect.SetBSDF (Graphic3d_BSDF::CreateMetallicRoughness (aPbr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,14 +230,16 @@ void XCAFDoc_VisMaterial::FillMaterialAspect (Graphic3d_MaterialAspect& theAspec
|
||||
theAspect.SetShininess (1.0f - myPbrMat.Roughness);
|
||||
}
|
||||
|
||||
#ifdef _Graphic3d_PBRMaterial_HeaderFile
|
||||
Graphic3d_PBRMaterial aPbr;
|
||||
aPbr.SetColor (myPbrMat.BaseColor);
|
||||
aPbr.SetMetallic (myPbrMat.Metallic);
|
||||
aPbr.SetRoughness(myPbrMat.Roughness);
|
||||
aPbr.SetEmission (myPbrMat.EmissiveFactor);
|
||||
if (myPbrMat.EmissiveTexture.IsNull()) // TODO Temporal measure until emissive map will be implemented
|
||||
{
|
||||
aPbr.SetEmission(myPbrMat.EmissiveFactor);
|
||||
}
|
||||
theAspect.SetPBRMaterial (aPbr);
|
||||
#endif
|
||||
theAspect.SetBSDF (Graphic3d_BSDF::CreateMetallicRoughness (aPbr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,4 +3,18 @@ vinit View1
|
||||
XDisplay -dispMode 1 D
|
||||
vaxo
|
||||
vfit
|
||||
|
||||
vrenderparams -shadingModel PHONG
|
||||
vlight -change 0 -intensity 2.5
|
||||
vlight -change 1 -intensity 0.3
|
||||
vcamera -orthographic
|
||||
vdump ${imagedir}/${casename}.png
|
||||
vdump ${imagedir}/${casename}_ortho_phong.png
|
||||
vcamera -persp
|
||||
vdump ${imagedir}/${casename}_persp_phong.png
|
||||
|
||||
vrenderparams -shadingModel PBR
|
||||
vcamera -orthographic
|
||||
vdump ${imagedir}/${casename}_ortho_pbr.png
|
||||
vcamera -persp
|
||||
vdump ${imagedir}/${casename}_persp_pbr.png
|
||||
|
@ -3,4 +3,18 @@ vinit View1
|
||||
XDisplay -dispMode 1 D -explore
|
||||
vaxo
|
||||
vfit
|
||||
|
||||
vrenderparams -shadingModel PHONG
|
||||
vlight -change 0 -intensity 2.5
|
||||
vlight -change 1 -intensity 0.3
|
||||
vcamera -orthographic
|
||||
vdump ${imagedir}/${casename}.png
|
||||
vdump ${imagedir}/${casename}_ortho_phong.png
|
||||
vcamera -persp
|
||||
vdump ${imagedir}/${casename}_persp_phong.png
|
||||
|
||||
vrenderparams -shadingModel PBR
|
||||
vcamera -orthographic
|
||||
vdump ${imagedir}/${casename}_ortho_pbr.png
|
||||
vcamera -persp
|
||||
vdump ${imagedir}/${casename}_persp_pbr.png
|
||||
|
74
tests/v3d/glsl/pbr_spheres
Normal file
74
tests/v3d/glsl/pbr_spheres
Normal file
@ -0,0 +1,74 @@
|
||||
puts "========"
|
||||
puts "0030700: Visualization, TKOpenGl - support PBR Metallic-Roughness shading model"
|
||||
puts "Spheres grid with different roughness values"
|
||||
puts "========"
|
||||
|
||||
pload XDE OCAF MODELING VISUALIZATION
|
||||
psphere s 0.35
|
||||
|
||||
catch { Close D }
|
||||
XNewDoc D
|
||||
|
||||
# grid of spheres
|
||||
set THE_UPPER 6
|
||||
foreach i [list 0 3] {
|
||||
set aPrefix ""
|
||||
set aColor "GRAY80"
|
||||
if { $i != 0 } {
|
||||
set aPrefix "g_";
|
||||
set aColor "CCB11D"
|
||||
}
|
||||
for { set m 0 } { $m <= $THE_UPPER } { incr m } {
|
||||
for { set r 0 } { $r <= $THE_UPPER } { incr r } {
|
||||
set aName ${aPrefix}m${m}r${r}
|
||||
copy s $aName
|
||||
ttranslate $aName ${r} ${i} ${m}
|
||||
set aLab [XAddShape D $aName]
|
||||
SetName D $aLab $aName
|
||||
XAddVisMaterial D $aName -baseColor $aColor -metallic ${m}/$THE_UPPER -roughness ${r}/$THE_UPPER
|
||||
XSetVisMaterial D $aLab $aName
|
||||
}
|
||||
}
|
||||
}
|
||||
XGetAllVisMaterials D
|
||||
|
||||
# labels
|
||||
text2brep tm "Metal" -plane 0 -1 0 0 0 -1 -height 0.5 -pos -0.5 0 6.5 -halign left -valign top -font monospace
|
||||
text2brep tnm "Non-metal" -plane 0 -1 0 0 0 -1 -height 0.5 -pos -0.5 0 -0.5 -halign right -valign top -font monospace
|
||||
text2brep ts "Smooth" -plane 0 -1 0 1 0 0 -height 0.5 -pos -0.5 0 -0.5 -halign left -valign top -font monospace
|
||||
text2brep tr "Rough" -plane 0 -1 0 1 0 0 -height 0.5 -pos 6.5 0 -0.5 -halign right -valign top -font monospace
|
||||
set aLab [XAddShape D tm]
|
||||
SetName D $aLab "Metal"
|
||||
set aLab [XAddShape D tnm]
|
||||
SetName D $aLab "Non-metal"
|
||||
set aLab [XAddShape D ts]
|
||||
SetName D $aLab "Smooth"
|
||||
set aLab [XAddShape D tr]
|
||||
SetName D $aLab "Rough"
|
||||
|
||||
vclear
|
||||
vinit View1 -width 768 -height 768
|
||||
vfront
|
||||
vrenderparams -shadingModel PBR
|
||||
vlight -change 0 -intensity 2.5
|
||||
XDisplay -dispMode 1 D
|
||||
vcamera -ortho
|
||||
vfit
|
||||
vlight -change 1 -intensity 0.0001
|
||||
vdump $::imagedir/${::casename}_ortho0.png
|
||||
vlight -change 1 -intensity 0.3
|
||||
vdump $::imagedir/${::casename}_ortho30.png
|
||||
vcamera -persp
|
||||
vfit
|
||||
vlight -change 1 -intensity 0.0001
|
||||
vdump $::imagedir/${::casename}_persp0.png
|
||||
vlight -change 1 -intensity 0.3
|
||||
vdump $::imagedir/${::casename}_persp30.png
|
||||
|
||||
set aCubeMap [locate_data_file Circus_CubeMap_V.png]
|
||||
vlight -change 1 -intensity 1
|
||||
vbackground -cubemap $aCubeMap
|
||||
vcamera -ortho
|
||||
vdump $::imagedir/${::casename}_orthoenv.png
|
||||
vcamera -persp
|
||||
vdump $::imagedir/${::casename}_perspenv.png
|
11
tests/v3d/materials/pbr1
Normal file
11
tests/v3d/materials/pbr1
Normal file
@ -0,0 +1,11 @@
|
||||
source $env(CSF_OCCTSamplesPath)/tcl/materials.tcl
|
||||
vlight -change 0 -intensity 5
|
||||
vrenderparams -shadingModel PBR -msaa 0
|
||||
vdump $imagedir/${casename}_default.png
|
||||
|
||||
set aCubeMap [locate_data_file Circus_CubeMap_V.png]
|
||||
vbackground -cubemap $aCubeMap
|
||||
vdump $imagedir/${casename}_env.png
|
||||
|
||||
vbackground -cubemap $aCubeMap -invertedz
|
||||
vdump $imagedir/${casename}_env_iz.png
|
Loading…
x
Reference in New Issue
Block a user