1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-03 14:10:33 +03:00

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

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

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

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

View File

@@ -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;
}