diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 7fe5539a1b..31ac882481 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -164,6 +164,7 @@ Graphic3d_TextureRoot.hxx Graphic3d_TextureUnit.hxx Graphic3d_TextureSet.cxx Graphic3d_TextureSet.hxx +Graphic3d_TextureSetBits.hxx Graphic3d_ToneMappingMethod.hxx Graphic3d_TransformError.hxx Graphic3d_TransformPers.hxx diff --git a/src/Graphic3d/Graphic3d_BSDF.cxx b/src/Graphic3d/Graphic3d_BSDF.cxx index f3e67108dc..81d53fb9c1 100644 --- a/src/Graphic3d/Graphic3d_BSDF.cxx +++ b/src/Graphic3d/Graphic3d_BSDF.cxx @@ -208,5 +208,6 @@ Graphic3d_BSDF Graphic3d_BSDF::CreateMetallicRoughness (const Graphic3d_PBRMater aBsdf.Ks.SetValues (Graphic3d_Vec3 (thePbr.Alpha()), aRougness2); aBsdf.Kt = Graphic3d_Vec3 (1.0f - thePbr.Alpha()); aBsdf.Kd = aDiff * (1.0f - thePbr.Metallic()); + aBsdf.Le = thePbr.Emission(); return aBsdf; } diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.cxx b/src/Graphic3d/Graphic3d_ShaderProgram.cxx index e08774d954..aef9958a8b 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.cxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.cxx @@ -80,6 +80,7 @@ Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() : myNbLightsMax (THE_MAX_LIGHTS_DEFAULT), myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT), myNbFragOutputs (THE_NB_FRAG_OUTPUTS), + myTextureSetBits (Graphic3d_TextureSetBits_NONE), myHasDefSampler (true), myHasAlphaTest (false), myHasWeightOitOutput (false), diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index 2aa7f19bb7..b039067329 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -20,6 +20,7 @@ #include #include #include +#include #include //! List of shader objects. @@ -152,12 +153,18 @@ public: 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 + //! 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; } + //! Return texture units declared within the program, @sa Graphic3d_TextureSetBits. + Standard_Integer TextureSetBits() const { return myTextureSetBits; } + + //! Set texture units declared within the program. + void SetTextureSetBits (Standard_Integer theBits) { myTextureSetBits = theBits; } + //! 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. @@ -208,6 +215,7 @@ private: Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES) Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) + Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits 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 diff --git a/src/Graphic3d/Graphic3d_TextureSetBits.hxx b/src/Graphic3d/Graphic3d_TextureSetBits.hxx new file mode 100644 index 0000000000..3a7e96de80 --- /dev/null +++ b/src/Graphic3d/Graphic3d_TextureSetBits.hxx @@ -0,0 +1,30 @@ +// 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_TextureSetBits_HeaderFile +#define _Graphic3d_TextureSetBits_HeaderFile + +#include + +//! Standard texture units combination bits. +enum Graphic3d_TextureSetBits +{ + Graphic3d_TextureSetBits_NONE = 0, + Graphic3d_TextureSetBits_BaseColor = (unsigned int )(1 << int(Graphic3d_TextureUnit_BaseColor)), + Graphic3d_TextureSetBits_Emissive = (unsigned int )(1 << int(Graphic3d_TextureUnit_Emissive)), + Graphic3d_TextureSetBits_Occlusion = (unsigned int )(1 << int(Graphic3d_TextureUnit_Occlusion)), + Graphic3d_TextureSetBits_Normal = (unsigned int )(1 << int(Graphic3d_TextureUnit_Normal)), + Graphic3d_TextureSetBits_MetallicRoughness = (unsigned int )(1 << int(Graphic3d_TextureUnit_MetallicRoughness)), +}; + +#endif // _Graphic3d_TextureSetBits_HeaderFile diff --git a/src/Graphic3d/Graphic3d_TextureUnit.hxx b/src/Graphic3d/Graphic3d_TextureUnit.hxx index 477147b641..f554b8efc4 100644 --- a/src/Graphic3d/Graphic3d_TextureUnit.hxx +++ b/src/Graphic3d/Graphic3d_TextureUnit.hxx @@ -35,17 +35,54 @@ enum Graphic3d_TextureUnit Graphic3d_TextureUnit_14, Graphic3d_TextureUnit_15, - Graphic3d_TextureUnit_BaseColor = Graphic3d_TextureUnit_0, //!< base color of the material - //Graphic3d_TextureUnit_Normal = Graphic3d_TextureUnit_1, //!< tangent space normal map - //Graphic3d_TextureUnit_MetallicRoughness = Graphic3d_TextureUnit_2, //!< metalness+roughness of the material - //Graphic3d_TextureUnit_Emissive = Graphic3d_TextureUnit_3, //!< emissive map controls the color and intensity of the light being emitted by the material - //Graphic3d_TextureUnit_Occlusion = Graphic3d_TextureUnit_4, //!< occlusion map indicating areas of indirect lighting + // aliases - Graphic3d_TextureUnit_EnvMap = Graphic3d_TextureUnit_0 //!< environment cubemap for background + //! sampler2D occSamplerBaseColor. + //! RGB(A) base color of the material and alpha mask/opacity. + Graphic3d_TextureUnit_BaseColor = Graphic3d_TextureUnit_0, + //! sampler2D occSamplerEmissive. + //! RGB emissive map controls the color and intensity of the light being emitted by the material. + Graphic3d_TextureUnit_Emissive = Graphic3d_TextureUnit_1, + //! sampler2D occSamplerOcclusion. + //! Occlusion map indicating areas of indirect lighting. + //! Encoded into RED channel, with 1.0 meaning no occlusion (full color intensity) and 0.0 complete occlusion (black). + Graphic3d_TextureUnit_Occlusion = Graphic3d_TextureUnit_2, + //! sampler2D occSamplerNormal. + //! XYZ tangent space normal map. + Graphic3d_TextureUnit_Normal = Graphic3d_TextureUnit_3, + //! sampler2D occSamplerMetallicRoughness. + //! Metalness + roughness of the material. + //! Encoded into GREEN (roughness) + BLUE (metallic) channels, + //! so that it can be optionally combined with occlusion texture (RED channel). + Graphic3d_TextureUnit_MetallicRoughness = Graphic3d_TextureUnit_4, + + //! samplerCube occSampler0. + //! Environment cubemap for background. Rendered by dedicated program and normally occupies first texture unit. + Graphic3d_TextureUnit_EnvMap = Graphic3d_TextureUnit_0, + + //! sampler2D occSamplerPointSprite. + //! Sprite alpha-mask or RGBA image mapped using point UV, additional to BaseColor (mapping using vertex UV). + //! This texture unit is set Graphic3d_TextureUnit_1, so that it can be combined with Graphic3d_TextureUnit_BaseColor, + //! while other texture maps (normal map and others) are unexpected and unsupported for points. + //! Note that it can be overridden to Graphic3d_TextureUnit_0 for FFP fallback on hardware without multi-texturing. + Graphic3d_TextureUnit_PointSprite = Graphic3d_TextureUnit_1, + + //! sampler2D occEnvLUT. + //! Lookup table for approximated PBR environment lighting. + //! Configured as index at the end of available texture units - 3. + Graphic3d_TextureUnit_PbrEnvironmentLUT = -3, + //! sampler2D occDiffIBLMapSHCoeffs. + //! Diffuse (irradiance) IBL map's spherical harmonics coefficients baked for PBR from environment cubemap image. + //! Configured as index at the end of available texture units - 2. + Graphic3d_TextureUnit_PbrIblDiffuseSH = -2, + //! samplerCube occSpecIBLMap. + //! Specular IBL (Image-Based Lighting) environment map baked for PBR from environment cubemap image. + //! Configured as index at the end of available texture units - 1. + Graphic3d_TextureUnit_PbrIblSpecular = -1, }; enum { - Graphic3d_TextureUnit_NB = Graphic3d_TextureUnit_15 + 1 + Graphic3d_TextureUnit_NB = Graphic3d_TextureUnit_15 + 1, }; #endif // _Graphic3d_TextureUnit_HeaderFile diff --git a/src/OpenGl/OpenGl_AspectsTextureSet.cxx b/src/OpenGl/OpenGl_AspectsTextureSet.cxx index 2ad97297bc..150361b30d 100644 --- a/src/OpenGl/OpenGl_AspectsTextureSet.cxx +++ b/src/OpenGl/OpenGl_AspectsTextureSet.cxx @@ -131,6 +131,7 @@ void OpenGl_AspectsTextureSet::UpdateRediness (const Handle(Graphic3d_Aspects)& { // just invalidate texture parameters aResource->Sampler()->SetParameters (aTexture->GetParams()); + aResIter.ChangeUnit() = aResource->Sampler()->Parameters()->TextureUnit(); } } } @@ -192,6 +193,8 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, } } + Standard_Integer& aTextureSetBits = myTextures[0]->ChangeTextureSetBits(); + aTextureSetBits = Graphic3d_TextureSetBits_NONE; if (theAspect->ToMapTexture()) { Graphic3d_TextureSet::Iterator aTextureIter (aNewTextureSet); @@ -208,6 +211,7 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, { if (aResource->Init(theCtx, aTexture)) { + aResIter0.ChangeUnit() = aResource->Sampler()->Parameters()->TextureUnit(); aResource->Sampler()->SetParameters(aTexture->GetParams()); aResource->SetRevision (aTexture->Revision()); } @@ -254,6 +258,14 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, } aResource->Sampler()->SetParameters (aTexture->GetParams()); } + + // update occupation of texture units + const Graphic3d_TextureUnit aTexUnit = aResource->Sampler()->Parameters()->TextureUnit(); + aResIter0.ChangeUnit() = aTexUnit; + if (aTexUnit >= Graphic3d_TextureUnit_0 && aTexUnit <= Graphic3d_TextureUnit_5) + { + aTextureSetBits |= (1 << int(aTexUnit)); + } } } } @@ -261,6 +273,8 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, if (hasSprite) { myTextures[0]->ChangeLast() = theSprite; + myTextures[0]->ChangeLastUnit() = theCtx->SpriteTextureUnit(); + // Graphic3d_TextureUnit_PointSprite if (!theSprite.IsNull()) { theSprite ->Sampler()->Parameters()->SetTextureUnit (theCtx->SpriteTextureUnit()); @@ -275,12 +289,15 @@ void OpenGl_AspectsTextureSet::build (const Handle(OpenGl_Context)& theCtx, return; } + myTextures[1]->ChangeTextureSetBits() = aTextureSetBits; for (OpenGl_TextureSet::Iterator aResIter0 (myTextures[0]), aResIter1 (myTextures[1]); aResIter0.More(); aResIter0.Next(), aResIter1.Next()) { aResIter1.ChangeValue() = aResIter0.Value(); + aResIter1.ChangeUnit() = aResIter0.Unit(); } if (hasSprite) { myTextures[1]->ChangeLast() = theSpriteA; + myTextures[1]->ChangeLastUnit() = theCtx->SpriteTextureUnit(); } } diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index d61be5be62..a84e125b9c 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -204,16 +204,17 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myIsInitialized (Standard_False), myIsStereoBuffers (Standard_False), myIsGlNormalizeEnabled (Standard_False), - mySpriteTexUnit (Graphic3d_TextureUnit_0), + mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite), myHasRayTracing (Standard_False), myHasRayTracingTextures (Standard_False), myHasRayTracingAdaptiveSampling (Standard_False), myHasRayTracingAdaptiveSamplingAtomic (Standard_False), myHasPBR (Standard_False), - myPBREnvLUTTexUnit (Graphic3d_TextureUnit_0), - myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_0), - myPBRSpecIBLMapTexUnit (Graphic3d_TextureUnit_0), + myPBREnvLUTTexUnit (Graphic3d_TextureUnit_PbrEnvironmentLUT), + myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH), + myPBRSpecIBLMapTexUnit (Graphic3d_TextureUnit_PbrIblSpecular), myFrameStats (new OpenGl_FrameStats()), + myActiveMockTextures (0), #if !defined(GL_ES_VERSION_2_0) myPointSpriteOrig (GL_UPPER_LEFT), myRenderMode (GL_RENDER), @@ -307,6 +308,18 @@ OpenGl_Context::~OpenGl_Context() myDefaultVao = 0; #endif + // release mock textures + if (!myTextureRgbaBlack.IsNull()) + { + myTextureRgbaBlack->Release (this); + myTextureRgbaBlack.Nullify(); + } + if (!myTextureRgbaWhite.IsNull()) + { + myTextureRgbaWhite->Release (this); + myTextureRgbaWhite.Nullify(); + } + // release default FBO if (!myDefaultFbo.IsNull()) { @@ -1651,7 +1664,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined); } mySpriteTexUnit = myMaxTexCombined >= 2 - ? Graphic3d_TextureUnit_1 + ? Graphic3d_TextureUnit_PointSprite : Graphic3d_TextureUnit_0; GLint aMaxVPortSize[2] = {0, 0}; @@ -2954,9 +2967,9 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) ); if (myHasPBR) { - myPBREnvLUTTexUnit = static_cast(myMaxTexCombined - 3); - myPBRDiffIBLMapSHTexUnit = static_cast(myMaxTexCombined - 2); - myPBRSpecIBLMapTexUnit = static_cast(myMaxTexCombined - 1); + myPBREnvLUTTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT); + myPBRDiffIBLMapSHTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH); + myPBRSpecIBLMapTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular); } } @@ -3369,104 +3382,149 @@ void OpenGl_Context::ReleaseDelayed() // function : BindTextures // purpose : // ======================================================================= -Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures) +Handle(OpenGl_TextureSet) OpenGl_Context::BindTextures (const Handle(OpenGl_TextureSet)& theTextures, + const Handle(OpenGl_ShaderProgram)& theProgram) { - if (myActiveTextures == theTextures) + const Standard_Integer aTextureSetBits = !theTextures.IsNull() ? theTextures->TextureSetBits() : 0; + const Standard_Integer aProgramBits = !theProgram.IsNull() ? theProgram->TextureSetBits() : 0; + Standard_Integer aMissingBits = aProgramBits & ~aTextureSetBits; + if (aMissingBits != 0 + && myTextureRgbaBlack.IsNull()) { - return myActiveTextures; - } - - Handle(OpenGl_Context) aThisCtx (this); - OpenGl_TextureSet::Iterator aTextureIterOld (myActiveTextures), aTextureIterNew (theTextures); - for (;;) - { - if (!aTextureIterNew.More()) + // allocate mock textures + myTextureRgbaBlack = new OpenGl_Texture(); + myTextureRgbaWhite = new OpenGl_Texture(); + Image_PixMap anImage; + anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )0); + if (!myTextureRgbaBlack->Init (this, OpenGl_TextureFormat::Create(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage)) { - for (; aTextureIterOld.More(); aTextureIterOld.Next()) - { - if (const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value()) - { - aTextureOld->Unbind(aThisCtx); - #if !defined(GL_ES_VERSION_2_0) - if (core11 != NULL) - { - OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); - } - #endif - } - } - break; + PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, + "Error: unable to create unit mock PBR texture map."); } - - const Handle(OpenGl_Texture)& aTextureNew = aTextureIterNew.Value(); - if (aTextureIterOld.More()) + anImage.InitZero (Image_Format_RGBA, 2, 2, 0, (Standard_Byte )255); + if (!myTextureRgbaWhite->Init (this, OpenGl_TextureFormat::Create(), Graphic3d_Vec2i (2, 2), Graphic3d_TOT_2D, &anImage)) { - const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value(); - if (aTextureNew == aTextureOld) - { - aTextureIterNew.Next(); - aTextureIterOld.Next(); - continue; - } - else if (aTextureNew.IsNull() - || !aTextureNew->IsValid()) - { - if (!aTextureOld.IsNull()) - { - aTextureOld->Unbind(aThisCtx); - #if !defined(GL_ES_VERSION_2_0) - if (core11 != NULL) - { - OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); - } - #endif - } - - aTextureIterNew.Next(); - aTextureIterOld.Next(); - continue; - } - - aTextureIterOld.Next(); + PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, + "Error: unable to create normal mock PBR texture map."); } - if (aTextureNew.IsNull()) - { - aTextureIterNew.Next(); - continue; - } - - const Graphic3d_TextureUnit aTexUnit = aTextureNew->Sampler()->Parameters()->TextureUnit(); - if (aTexUnit >= myMaxTexCombined) - { - PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, - TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined); - aTextureIterNew.Next(); - continue; - } - - aTextureNew->Bind (aThisCtx); - if (aTextureNew->Sampler()->ToUpdateParameters()) - { - if (aTextureNew->Sampler()->IsImmutable()) - { - aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew); - } - else - { - OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->HasMipmaps()); - } - } - #if !defined(GL_ES_VERSION_2_0) - if (core11 != NULL) - { - OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters()); - } - #endif - aTextureIterNew.Next(); } Handle(OpenGl_TextureSet) anOldTextures = myActiveTextures; - myActiveTextures = theTextures; + if (myActiveTextures != theTextures) + { + Handle(OpenGl_Context) aThisCtx (this); + OpenGl_TextureSet::Iterator aTextureIterOld (myActiveTextures), aTextureIterNew (theTextures); + for (;;) + { + if (!aTextureIterNew.More()) + { + for (; aTextureIterOld.More(); aTextureIterOld.Next()) + { + if (const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value()) + { + aTextureOld->Unbind (aThisCtx, aTextureIterOld.Unit()); + #if !defined(GL_ES_VERSION_2_0) + if (core11 != NULL) + { + OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); + } + #endif + } + } + break; + } + + const Handle(OpenGl_Texture)& aTextureNew = aTextureIterNew.Value(); + if (aTextureIterOld.More()) + { + const Handle(OpenGl_Texture)& aTextureOld = aTextureIterOld.Value(); + if (aTextureNew == aTextureOld + && aTextureIterNew.Unit() == aTextureIterOld.Unit()) + { + aTextureIterNew.Next(); + aTextureIterOld.Next(); + continue; + } + else if (aTextureNew.IsNull() + || !aTextureNew->IsValid()) + { + if (!aTextureOld.IsNull()) + { + aTextureOld->Unbind (aThisCtx, aTextureIterOld.Unit()); + #if !defined(GL_ES_VERSION_2_0) + if (core11 != NULL) + { + OpenGl_Sampler::resetGlobalTextureParams (aThisCtx, *aTextureOld, aTextureOld->Sampler()->Parameters()); + } + #endif + } + + aTextureIterNew.Next(); + aTextureIterOld.Next(); + continue; + } + + aTextureIterOld.Next(); + } + if (aTextureNew.IsNull()) + { + aTextureIterNew.Next(); + continue; + } + + const Graphic3d_TextureUnit aTexUnit = aTextureIterNew.Unit(); + if (aTexUnit >= myMaxTexCombined) + { + PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString("Texture unit ") + aTexUnit + " for " + aTextureNew->ResourceId() + " exceeds hardware limit " + myMaxTexCombined); + aTextureIterNew.Next(); + continue; + } + + aTextureNew->Bind (aThisCtx, aTexUnit); + if (aTextureNew->Sampler()->ToUpdateParameters()) + { + if (aTextureNew->Sampler()->IsImmutable()) + { + aTextureNew->Sampler()->Init (aThisCtx, *aTextureNew); + } + else + { + OpenGl_Sampler::applySamplerParams (aThisCtx, aTextureNew->Sampler()->Parameters(), aTextureNew->Sampler().get(), aTextureNew->GetTarget(), aTextureNew->HasMipmaps()); + } + } + #if !defined(GL_ES_VERSION_2_0) + if (core11 != NULL) + { + OpenGl_Sampler::applyGlobalTextureParams (aThisCtx, *aTextureNew, aTextureNew->Sampler()->Parameters()); + } + #endif + aTextureIterNew.Next(); + } + myActiveTextures = theTextures; + } + + if (myActiveMockTextures != aMissingBits) + { + myActiveMockTextures = aMissingBits; + for (Standard_Integer aBitIter = 0; aMissingBits != 0; ++aBitIter) + { + Standard_Integer aUnitMask = 1 << aBitIter; + if ((aUnitMask & aMissingBits) != 0) + { + aMissingBits = aMissingBits & ~aUnitMask; + if (aBitIter == Graphic3d_TextureUnit_Normal) + { + myTextureRgbaBlack->Bind (this, static_cast(aBitIter)); + } + else + { + myTextureRgbaWhite->Bind (this, static_cast(aBitIter)); + } + } + } + } + return anOldTextures; } diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index a7c4215fae..e7575266f1 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -502,7 +502,7 @@ public: //! @return value for GL_MAX_TEXTURE_UNITS Standard_Integer MaxTextureUnitsFFP() const { return myMaxTexUnitsFFP; } - //! @return texture unit to be used for sprites + //! Return texture unit to be used for sprites (Graphic3d_TextureUnit_PointSprite by default). Graphic3d_TextureUnit SpriteTextureUnit() const { return mySpriteTexUnit; } //! @return value for GL_MAX_SAMPLES @@ -803,9 +803,20 @@ public: //! @name methods to alter or retrieve current state //! @return active textures const Handle(OpenGl_TextureSet)& ActiveTextures() const { return myActiveTextures; } - //! Bind specified texture set to current context, - //! or unbind previous one when NULL specified. - Standard_EXPORT Handle(OpenGl_TextureSet) BindTextures (const Handle(OpenGl_TextureSet)& theTextures); + //! Bind specified texture set to current context taking into account active GLSL program. + Standard_DEPRECATED("BindTextures() with explicit GLSL program should be used instead") + Handle(OpenGl_TextureSet) BindTextures (const Handle(OpenGl_TextureSet)& theTextures) + { + return BindTextures (theTextures, myActiveProgram); + } + + //! Bind specified texture set to current context, or unbind previous one when NULL specified. + //! @param theTextures [in] texture set to bind + //! @param theProgram [in] program attributes; when not NULL, + //! mock textures will be bound to texture units expected by GLSL program, but undefined by texture set + //! @return previous texture set + Standard_EXPORT Handle(OpenGl_TextureSet) BindTextures (const Handle(OpenGl_TextureSet)& theTextures, + const Handle(OpenGl_ShaderProgram)& theProgram); //! @return active GLSL program const Handle(OpenGl_ShaderProgram)& ActiveProgram() const @@ -1076,7 +1087,7 @@ private: // context info Standard_Boolean myIsStereoBuffers; //!< context supports stereo buffering Standard_Boolean myIsGlNormalizeEnabled; //!< GL_NORMALIZE flag //!< Used to tell OpenGl that normals should be normalized - Graphic3d_TextureUnit mySpriteTexUnit; //!< texture unit for point sprite texture + Graphic3d_TextureUnit mySpriteTexUnit; //!< sampler2D occSamplerPointSprite, texture unit for point sprite texture Standard_Boolean myHasRayTracing; //! indicates whether ray tracing mode is supported Standard_Boolean myHasRayTracingTextures; //! indicates whether textures in ray tracing mode are supported @@ -1084,10 +1095,10 @@ private: // context info 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 + Graphic3d_TextureUnit myPBREnvLUTTexUnit; //!< sampler2D occEnvLUT, texture unit where environment lookup table is expected to be binded (0 if PBR is not supported) + Graphic3d_TextureUnit myPBRDiffIBLMapSHTexUnit; //!< sampler2D occDiffIBLMapSHCoeffs, 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) + Graphic3d_TextureUnit myPBRSpecIBLMapTexUnit; //!< samplerCube occSpecIBLMap, 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 @@ -1097,8 +1108,11 @@ private: //! @name fields tracking current state Handle(OpenGl_ShaderProgram) myActiveProgram; //!< currently active GLSL program Handle(OpenGl_TextureSet) myActiveTextures; //!< currently bound textures //!< currently active sampler objects + Standard_Integer myActiveMockTextures; //!< currently active mock sampler objects Handle(OpenGl_FrameBuffer) myDefaultFbo; //!< default Frame Buffer Object Handle(OpenGl_LineAttributes) myHatchStyles; //!< resource holding predefined hatch styles patterns + Handle(OpenGl_Texture) myTextureRgbaBlack;//!< mock black texture returning (0, 0, 0, 0) + Handle(OpenGl_Texture) myTextureRgbaWhite;//!< mock white texture returning (1, 1, 1, 1) Standard_Integer myViewport[4]; //!< current viewport Standard_Integer myViewportVirt[4]; //!< virtual viewport Standard_Integer myPointSpriteOrig; //!< GL_POINT_SPRITE_COORD_ORIGIN state (GL_UPPER_LEFT by default) diff --git a/src/OpenGl/OpenGl_LayerList.cxx b/src/OpenGl/OpenGl_LayerList.cxx index b3126445df..f639a5840d 100644 --- a/src/OpenGl/OpenGl_LayerList.cxx +++ b/src/OpenGl/OpenGl_LayerList.cxx @@ -932,7 +932,7 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theW // Bind full screen quad buffer and framebuffer resources. aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS); - const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)()); + const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0); theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1); @@ -949,7 +949,7 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theW if (!aTextureBack.IsNull()) { - aCtx->BindTextures (aTextureBack); + aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)()); } } else diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 97a6f39c30..9bb3274c77 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -769,12 +769,10 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace return; } - const OpenGl_Aspects* anAspectFace = theWorkspace->ApplyAspects(); + const OpenGl_Aspects* anAspectFace = theWorkspace->Aspects(); const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); - const bool toEnableEnvMap = !aCtx->ActiveTextures().IsNull() - && aCtx->ActiveTextures() == theWorkspace->EnvironmentTexture(); - bool toDrawArray = true; + bool toDrawArray = true, toSetLinePolygMode = false; int toDrawInteriorEdges = 0; // 0 - no edges, 1 - glsl edges, 2 - polygonMode if (myIsFillType) { @@ -797,7 +795,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace } else { - aCtx->SetPolygonMode (GL_LINE); + toSetLinePolygMode = true; } } } @@ -843,6 +841,10 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace } Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TOSM_UNLIT; + anAspectFace = theWorkspace->ApplyAspects (false); // do not bind textures before binding the program + const Handle(OpenGl_TextureSet)& aTextureSet = theWorkspace->TextureSet(); + const bool toEnableEnvMap = !aTextureSet.IsNull() + && aTextureSet == theWorkspace->EnvironmentTexture(); if (toDrawArray) { const bool hasColorAttrib = !myVboAttribs.IsNull() @@ -855,7 +857,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace case GL_POINTS: { aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm); - aCtx->ShaderManager()->BindMarkerProgram (aCtx->ActiveTextures(), + aCtx->ShaderManager()->BindMarkerProgram (aTextureSet, aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectFace->ShaderProgramRes (aCtx)); break; @@ -875,7 +877,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace default: { aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm); - aCtx->ShaderManager()->BindFaceProgram (aCtx->ActiveTextures(), + aCtx->ShaderManager()->BindFaceProgram (aTextureSet, aShadingModel, aCtx->ShaderManager()->MaterialState().HasAlphaCutoff() ? Graphic3d_AlphaMode_Mask : Graphic3d_AlphaMode_Opaque, toDrawInteriorEdges == 1 ? anAspectFace->Aspect()->InteriorStyle() : Aspect_IS_SOLID, @@ -887,6 +889,14 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace { aCtx->ShaderManager()->PushInteriorState (aCtx->ActiveProgram(), anAspectFace->Aspect()); } + #if !defined (GL_ES_VERSION_2_0) + else if (toSetLinePolygMode) + { + aCtx->SetPolygonMode (GL_LINE); + } + #else + (void )toSetLinePolygMode; + #endif break; } } @@ -907,12 +917,16 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace } #endif - if (!aCtx->ActiveTextures().IsNull() - && !aCtx->ActiveTextures()->IsEmpty() - && !aCtx->ActiveTextures()->First().IsNull() + // bind textures after GLSL program to set mock textures to slots used by program + aCtx->BindTextures (aTextureSet, aCtx->ActiveProgram()); + if (!aTextureSet.IsNull() + && !aTextureSet->IsEmpty() && myDrawMode != GL_POINTS) // transformation is not supported within point sprites { - aCtx->SetTextureMatrix (aCtx->ActiveTextures()->First()->Sampler()->Parameters()); + if (const Handle(OpenGl_Texture)& aFirstTexture = aTextureSet->First()) + { + aCtx->SetTextureMatrix (aFirstTexture->Sampler()->Parameters()); + } } aCtx->SetSampleAlphaToCoverage (aCtx->ShaderManager()->MaterialState().HasAlphaCutoff()); diff --git a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx index 8c0434b0c4..0c1eabe177 100644 --- a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx +++ b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx @@ -24,11 +24,12 @@ enum OpenGl_ProgramOptions { OpenGl_PO_VertColor = 0x0001, //!< per-vertex color - OpenGl_PO_TextureRGB = 0x0002, //!< handle RGB texturing - OpenGl_PO_PointSimple = 0x0004, //!< point marker without sprite - OpenGl_PO_PointSprite = 0x0008, //!< point sprite with RGB image + OpenGl_PO_TextureRGB = 0x0002, //!< handle RGB texturing + OpenGl_PO_TextureEnv = 0x0004, //!< handle environment map (obsolete, to be removed) + OpenGl_PO_TextureNormal = OpenGl_PO_TextureRGB|OpenGl_PO_TextureEnv, //!< extended texture set (with normal map) + OpenGl_PO_PointSimple = 0x0008, //!< point marker without sprite + OpenGl_PO_PointSprite = 0x0010, //!< point sprite with RGB image OpenGl_PO_PointSpriteA = OpenGl_PO_PointSimple|OpenGl_PO_PointSprite, //!< point sprite with Alpha image - OpenGl_PO_TextureEnv = 0x0010, //!< handle environment map OpenGl_PO_StippleLine = 0x0020, //!< stipple line OpenGl_PO_ClipPlanes1 = 0x0040, //!< handle 1 clipping plane OpenGl_PO_ClipPlanes2 = 0x0080, //!< handle 2 clipping planes @@ -40,7 +41,7 @@ enum OpenGl_ProgramOptions // OpenGl_PO_NB = 0x1000, //!< overall number of combinations OpenGl_PO_IsPoint = OpenGl_PO_PointSimple|OpenGl_PO_PointSprite|OpenGl_PO_PointSpriteA, - OpenGl_PO_HasTextures = OpenGl_PO_TextureRGB, + OpenGl_PO_HasTextures = OpenGl_PO_TextureRGB|OpenGl_PO_TextureEnv, OpenGl_PO_NeedsGeomShader = OpenGl_PO_MeshEdges, }; diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index dcb20800ca..ee435d0cc9 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -96,6 +96,7 @@ 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 NormalizedRoughness;" //!< Normalized roughness 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 @@ -1771,7 +1772,8 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr { int aBits = theBits; const bool toUseDerivates = theUsesDerivates - || (theBits & OpenGl_PO_StippleLine) != 0; + || (theBits & OpenGl_PO_StippleLine) != 0 + || (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal; #if !defined(GL_ES_VERSION_2_0) if (myContext->core32 != NULL) { @@ -1971,9 +1973,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha aSrcFragGetColor = EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }"; } - else if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + else if ((theBits & OpenGl_PO_TextureRGB) != 0 && (theBits & OpenGl_PO_VertColor) == 0) { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aSrcVertExtraMain += @@ -2000,9 +2003,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha } else { - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + if ((theBits & OpenGl_PO_TextureRGB) != 0 && (theBits & OpenGl_PO_VertColor) == 0) { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aSrcVertExtraMain += @@ -2019,32 +2023,33 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha } else { - if ((theBits & OpenGl_PO_TextureRGB) != 0 || (theBits & OpenGl_PO_TextureEnv) != 0) + if ((theBits & OpenGl_PO_HasTextures) != 0) { aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - } - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB) - { - aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; + if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureEnv) + { + aSrcVertExtraFunc = THE_FUNC_transformNormal_view; - aSrcFragGetColor = - EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }"; - } - else if ((theBits & OpenGl_PO_TextureEnv) != 0) - { - aSrcVertExtraFunc = THE_FUNC_transformNormal_view; + aSrcVertExtraMain += + EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;" + EOL" vec3 aNormal = transformNormal (occNormal);" + EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);" + EOL" aReflect.z += 1.0;" + EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);"; - aSrcVertExtraMain += - EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;" - EOL" vec3 aNormal = transformNormal (occNormal);" - EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);" - EOL" aReflect.z += 1.0;" - EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);"; + aSrcFragGetColor = + EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }"; + } + else + { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); + aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; - aSrcFragGetColor = - EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }"; + aSrcFragGetColor = + EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }"; + } } } if ((theBits & OpenGl_PO_VertColor) != 0) @@ -2218,7 +2223,8 @@ TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TColl // ======================================================================= TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights, Standard_Boolean theHasVertColor, - Standard_Boolean theIsPBR) + Standard_Boolean theIsPBR, + Standard_Boolean theHasEmissive) { TCollection_AsciiString aLightsFunc, aLightsLoop; theNbLights = 0; @@ -2353,12 +2359,12 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ + EOL" vec4 aMatAmbient = " + aGetMatAmbient + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();" - EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();" - EOL" vec3 aColor = Ambient * aMatAmbient.rgb" - EOL" + Diffuse * aMatDiffuse.rgb" - EOL" + Specular * aMatSpecular.rgb" - EOL" + aMatEmission.rgb;" - EOL" return vec4 (aColor, aMatDiffuse.a);" + EOL" vec3 aColor = Ambient * aMatAmbient.rgb + Diffuse * aMatDiffuse.rgb + Specular * aMatSpecular.rgb;" + EOL" occTextureOcclusion(aColor, TexCoord.st);" + + (theHasEmissive + ? EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();" + EOL" aColor += aMatEmission.rgb;" : "") + + EOL" return vec4 (aColor, aMatDiffuse.a);" EOL"}"; } else @@ -2373,26 +2379,27 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ 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" BaseColor = " + (theHasVertColor ? "getVertColor();" : "occTextureColor(occPBRMaterial_Color (theIsFront), TexCoord.st);") + + EOL" Emission = occTextureEmissive(occPBRMaterial_Emission (theIsFront), TexCoord.st);" + EOL" Metallic = occTextureMetallic(occPBRMaterial_Metallic (theIsFront), TexCoord.st);" + EOL" NormalizedRoughness = occTextureRoughness(occPBRMaterial_NormalizedRoughness (theIsFront), TexCoord.st);" + EOL" Roughness = occRoughness (NormalizedRoughness);" + EOL" IOR = occPBRMaterial_IOR (theIsFront);" 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" vec2 aCoeff = occTexture2D (occEnvLUT, vec2(abs(dot(theView, theNormal)), NormalizedRoughness)).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" anIndirectLightingSpec *= occTextureCubeLod (occSpecIBLMap, -reflect (theView, theNormal), NormalizedRoughness * float (occNbSpecIBLLevels - 1)).rgb;" + EOL" vec3 aRefractionCoeff = 1.0 - occPBRFresnel (BaseColor.rgb, Metallic, NormalizedRoughness, 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" occTextureOcclusion(aColor, TexCoord.st);" EOL" return vec4 (aColor, mix(1.0, BaseColor.a, aRefractionCoeff.x));" EOL"}"; } @@ -2431,17 +2438,19 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits); } - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + if ((theBits & OpenGl_PO_TextureRGB) != 0 && (theBits & OpenGl_PO_VertColor) == 0) { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }"; } } else { - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB) + if ((theBits & OpenGl_PO_TextureRGB) != 0) { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; @@ -2499,7 +2508,7 @@ 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(), false); + const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false, true); aSrcVert = TCollection_AsciiString() + THE_FUNC_transformNormal_view + EOL @@ -2584,13 +2593,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha aProgramSrc->SetPBR (theIsPBR); TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain; - TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain; + TCollection_AsciiString aSrcFrag, aSrcFragExtraFunc, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain; 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) { @@ -2612,9 +2616,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha aSrcFragGetColor = pointSpriteShadingSrc (aPhongCompLight, theBits); } - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB + if ((theBits & OpenGl_PO_TextureRGB) != 0 && (theBits & OpenGl_PO_VertColor) == 0) { + aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor); aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); @@ -2624,30 +2629,44 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha } else { - if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB) + if ((theBits & OpenGl_PO_TextureRGB) != 0) { aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aSrcVertExtraMain += THE_VARY_TexCoord_Trsf; + Standard_Integer aTextureBits = Graphic3d_TextureSetBits_BaseColor | Graphic3d_TextureSetBits_Occlusion | Graphic3d_TextureSetBits_Emissive; if (!theIsPBR) { aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void)" EOL"{" + EOL" vec2 aTexUV = TexCoord.st / TexCoord.w;" EOL" vec4 aColor = " + aPhongCompLight + ";" - EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;" + EOL" aColor *= occTexture2D(occSamplerBaseColor, aTexUV);" + EOL" vec3 anEmission = occTextureEmissive((gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission()).rgb, aTexUV);" + EOL" aColor.rgb += anEmission;" + EOL" return 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"}"; + aTextureBits |= Graphic3d_TextureSetBits_MetallicRoughness; } + if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal + && !isFlatNormal) + { + if (myContext->hasFlatShading != OpenGl_FeatureNotAvailable) + { + aTextureBits |= Graphic3d_TextureSetBits_Normal; + } + else + { + myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM, + "Warning: ignoring Normal Map texture due to hardware capabilities"); + } + } + aProgramSrc->SetTextureSetBits (aTextureBits); } } @@ -2696,9 +2715,37 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha } else { - aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 Normal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - aSrcVertExtraFunc += theIsPBR ? THE_FUNC_transformNormal_world : THE_FUNC_transformNormal_view; - aSrcVertExtraMain += EOL" Normal = transformNormal (occNormal);"; + aStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable("vec3 vNormal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); + aSrcVertExtraFunc += THE_FUNC_transformNormal_world; + aSrcVertExtraMain += EOL" vNormal = transformNormal (occNormal);"; + aSrcFragExtraFunc += EOL" vec3 Normal = vNormal;"; + + if ((theBits & OpenGl_PO_IsPoint) == 0 + && (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal + && myContext->hasFlatShading != OpenGl_FeatureNotAvailable) + { + // apply normal map texture + aSrcFragExtraMain += + EOL"#if defined(THE_HAS_TEXTURE_NORMAL)" + EOL" vec4 aMapNormalValue = occTextureNormal(TexCoord.st / TexCoord.w);" + EOL" if (aMapNormalValue.w > 0.5)" + EOL" {" + EOL" aMapNormalValue.xyz = normalize (aMapNormalValue.xyz * 2.0 - vec3(1.0));" + EOL" mat2 aDeltaUVMatrix = mat2 (dFdx(TexCoord.st / TexCoord.w), dFdy(TexCoord.st / TexCoord.w));" + EOL" aDeltaUVMatrix = mat2 (aDeltaUVMatrix[1][1], -aDeltaUVMatrix[0][1], -aDeltaUVMatrix[1][0], aDeltaUVMatrix[0][0]);" + EOL" mat2x3 aDeltaVectorMatrix = mat2x3 (dFdx (PositionWorld.xyz), dFdy (PositionWorld.xyz));" + EOL" aDeltaVectorMatrix = aDeltaVectorMatrix * aDeltaUVMatrix;" + EOL" aDeltaVectorMatrix[0] = aDeltaVectorMatrix[0] - dot(Normal, aDeltaVectorMatrix[0]) * Normal;" + EOL" aDeltaVectorMatrix[1] = aDeltaVectorMatrix[1] - dot(Normal, aDeltaVectorMatrix[1]) * Normal;" + EOL" Normal = mat3 (-normalize(aDeltaVectorMatrix[0]), -normalize(aDeltaVectorMatrix[1]), Normal) * aMapNormalValue.xyz;" + EOL" }" + EOL"#endif"; + } + if (!theIsPBR) + { + aSrcFragExtraMain += + EOL" Normal = normalize ((occWorldViewMatrixInverseTranspose * vec4 (Normal, 0.0)).xyz);"; + } } aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); @@ -2730,12 +2777,14 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha : EOL"#define getFinalColor getColor"; Standard_Integer aNbLights = 0; - const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR); + const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR, + (theBits & OpenGl_PO_TextureRGB) == 0 + || (theBits & OpenGl_PO_IsPoint) != 0); aSrcFrag = TCollection_AsciiString() + EOL + + aSrcFragExtraFunc + aSrcFragExtraOut + aSrcFragGetVertColor - + (theIsPBR ? aSrcFragPBRGetBaseColor : "") + aLights + aSrcFragGetColor + EOL diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 793ac51705..ea56a4814d 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -618,6 +618,10 @@ protected: && theTextures->HasNonPointSprite()) { aBits |= OpenGl_PO_TextureRGB; + if ((theTextures->TextureSetBits() & Graphic3d_TextureSetBits_Normal) != 0) + { + aBits |= OpenGl_PO_TextureNormal; + } } if (theHasVertColor && theInteriorStyle != Aspect_IS_HIDDENLINE) @@ -637,7 +641,7 @@ protected: Standard_Integer theBits) { if (theShadingModel == Graphic3d_TOSM_UNLIT - || (theBits & OpenGl_PO_TextureEnv) != 0) + || (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureEnv) { // If environment map is enabled lighting calculations are // not needed (in accordance with default OCCT behavior) @@ -714,9 +718,11 @@ protected: //! @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 + //! @param theHasEmissive [in] flag to include emissive Standard_EXPORT TCollection_AsciiString stdComputeLighting (Standard_Integer& theNbLights, Standard_Boolean theHasVertColor, - Standard_Boolean theIsPBR); + Standard_Boolean theIsPBR, + Standard_Boolean theHasEmissive = true); //! Bind specified program to current context and apply state. Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram); diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 68b3af2f3f..651bb34793 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -171,6 +171,7 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram myNbLightsMax (0), myNbClipPlanesMax (0), myNbFragOutputs (1), + myTextureSetBits (Graphic3d_TextureSetBits_NONE), myHasAlphaTest (false), myHasWeightOitOutput (false), myHasTessShader (false) @@ -199,6 +200,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0; myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1; + myTextureSetBits = Graphic3d_TextureSetBits_NONE; myHasAlphaTest = !myProxy.IsNull() && myProxy->HasAlphaTest(); myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1; @@ -413,10 +415,32 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& { aHeaderConstants += "#define THE_HAS_DEFAULT_SAMPLER\n"; } - if (!myProxy.IsNull() - && myProxy->IsPBR()) + if (!myProxy.IsNull()) { - aHeaderConstants += "#define THE_IS_PBR\n"; + if (myProxy->IsPBR()) + { + aHeaderConstants += "#define THE_IS_PBR\n"; + } + if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_BaseColor) != 0) + { + aHeaderConstants += "#define THE_HAS_TEXTURE_COLOR\n"; + } + if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Emissive) != 0) + { + aHeaderConstants += "#define THE_HAS_TEXTURE_EMISSIVE\n"; + } + if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Normal) != 0) + { + aHeaderConstants += "#define THE_HAS_TEXTURE_NORMAL\n"; + } + if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Occlusion) != 0) + { + aHeaderConstants += "#define THE_HAS_TEXTURE_OCCLUSION\n"; + } + if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_MetallicRoughness) != 0) + { + aHeaderConstants += "#define THE_HAS_TEXTURE_METALROUGHNESS\n"; + } } const TCollection_AsciiString aSource = aHeaderVer // #version - header defining GLSL version, should be first @@ -491,12 +515,35 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerBaseColor")) { + myTextureSetBits |= Graphic3d_TextureSetBits_BaseColor; SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_BaseColor)); } if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerPointSprite")) { + // Graphic3d_TextureUnit_PointSprite + //myTextureSetBits |= Graphic3d_TextureSetBits_PointSprite; SetUniform (theCtx, aLocSampler, GLint(theCtx->SpriteTextureUnit())); } + if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerMetallicRoughness")) + { + myTextureSetBits |= Graphic3d_TextureSetBits_MetallicRoughness; + SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_MetallicRoughness)); + } + if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerEmissive")) + { + myTextureSetBits |= Graphic3d_TextureSetBits_Emissive; + SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Emissive)); + } + if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerOcclusion")) + { + myTextureSetBits |= Graphic3d_TextureSetBits_Occlusion; + SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Occlusion)); + } + if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerNormal")) + { + myTextureSetBits |= Graphic3d_TextureSetBits_Normal; + SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Normal)); + } if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDiffIBLMapSHCoeffs")) { SetUniform (theCtx, aLocSampler, GLint(theCtx->PBRDiffIBLMapSHTexUnit())); diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 93252bbdb5..c86f0ec3c5 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -294,6 +295,9 @@ public: //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default. Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; } + //! Return texture units declared within the program, @sa Graphic3d_TextureSetBits. + Standard_Integer TextureSetBits() const { return myTextureSetBits; } + private: //! Returns index of last modification of variables of specified state type. @@ -656,6 +660,7 @@ protected: Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES) Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) + Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits Standard_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader should perform alpha-test Standard_Boolean myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage Standard_Boolean myHasTessShader; //!< flag indicating that program defines tessellation stage diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index 927a4a0eac..fdc8f36f37 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -39,7 +39,7 @@ void OpenGl_Structure::renderBoundingBox (const Handle(OpenGl_Workspace)& theWor } const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); - const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)()); + const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer); const Graphic3d_Vec3d aMoveVec = myTrsfPers.IsNull() && !aLayer.OriginTransformation().IsNull() @@ -95,7 +95,7 @@ void OpenGl_Structure::renderBoundingBox (const Handle(OpenGl_Workspace)& theWor aCtx->core11->glDisableClientState (GL_VERTEX_ARRAY); } #endif - aCtx->BindTextures (aPrevTexture); + aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)()); } // ======================================================================= diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 2f88a720da..f04c0c0421 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -278,12 +278,12 @@ void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx, // ======================================================================= void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const { - const OpenGl_Aspects* aTextAspect = theWorkspace->ApplyAspects(); + const OpenGl_Aspects* aTextAspect = theWorkspace->ApplyAspects (false); // do not bind textures as they will be disabled anyway const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); - const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)()); // Bind custom shader program or generate default version aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx)); + const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); if (myText->HasPlane() && myText->HasOwnAnchorPoint()) { @@ -306,7 +306,7 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const // restore aspects if (!aPrevTexture.IsNull()) { - aCtx->BindTextures (aPrevTexture); + aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)()); } // restore Z buffer settings diff --git a/src/OpenGl/OpenGl_Texture.hxx b/src/OpenGl/OpenGl_Texture.hxx index 084128626d..e7ffd82ea4 100644 --- a/src/OpenGl/OpenGl_Texture.hxx +++ b/src/OpenGl/OpenGl_Texture.hxx @@ -140,7 +140,7 @@ public: //! Initialize the texture with Graphic3d_TextureMap. //! It is an universal way to initialize. - //! Sitable initialization method will be chosen. + //! Suitable initialization method will be chosen. Standard_EXPORT bool Init (const Handle(OpenGl_Context)& theCtx, const Handle(Graphic3d_TextureMap)& theTextureMap); diff --git a/src/OpenGl/OpenGl_TextureSet.cxx b/src/OpenGl/OpenGl_TextureSet.cxx index bc42d126ab..e676cd704b 100644 --- a/src/OpenGl/OpenGl_TextureSet.cxx +++ b/src/OpenGl/OpenGl_TextureSet.cxx @@ -18,6 +18,21 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_TextureSet, Standard_Transient) +// ======================================================================= +// function : OpenGl_TextureSet +// purpose : +// ======================================================================= +OpenGl_TextureSet::OpenGl_TextureSet (const Handle(OpenGl_Texture)& theTexture) +: myTextures (0, 0), + myTextureSetBits (Graphic3d_TextureSetBits_NONE) +{ + if (!theTexture.IsNull()) + { + myTextures.ChangeFirst().Texture = theTexture; + myTextures.ChangeFirst().Unit = theTexture->Sampler()->Parameters()->TextureUnit(); + } +} + // ======================================================================= // function : IsModulate // purpose : @@ -25,8 +40,8 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_TextureSet, Standard_Transient) bool OpenGl_TextureSet::IsModulate() const { return myTextures.IsEmpty() - || myTextures.First().IsNull() - || myTextures.First()->Sampler()->Parameters()->IsModulate(); + || myTextures.First().Texture.IsNull() + || myTextures.First().Texture->Sampler()->Parameters()->IsModulate(); } // ======================================================================= @@ -41,10 +56,10 @@ bool OpenGl_TextureSet::HasNonPointSprite() const } else if (myTextures.Size() == 1) { - return !myTextures.First().IsNull() - && !myTextures.First()->IsPointSprite(); + return !myTextures.First().Texture.IsNull() + && !myTextures.First().Texture->IsPointSprite(); } - return !myTextures.First().IsNull(); + return !myTextures.First().Texture.IsNull(); } // ======================================================================= @@ -54,6 +69,6 @@ bool OpenGl_TextureSet::HasNonPointSprite() const bool OpenGl_TextureSet::HasPointSprite() const { return !myTextures.IsEmpty() - && !myTextures.Last().IsNull() - && myTextures.Last()->IsPointSprite(); + && !myTextures.Last().Texture.IsNull() + && myTextures.Last().Texture->IsPointSprite(); } diff --git a/src/OpenGl/OpenGl_TextureSet.hxx b/src/OpenGl/OpenGl_TextureSet.hxx index 748ba7da96..e2ce50c5af 100644 --- a/src/OpenGl/OpenGl_TextureSet.hxx +++ b/src/OpenGl/OpenGl_TextureSet.hxx @@ -15,6 +15,7 @@ #define _OpenGl_TextureSet_Header #include +#include class OpenGl_Texture; @@ -24,8 +25,20 @@ class OpenGl_TextureSet : public Standard_Transient DEFINE_STANDARD_RTTIEXT(OpenGl_TextureSet, Standard_Transient) public: + //! Texture slot - combination of Texture and binding Unit. + struct TextureSlot + { + Handle(OpenGl_Texture) Texture; + Graphic3d_TextureUnit Unit; + + operator const Handle(OpenGl_Texture)& () const { return Texture; } + operator Handle(OpenGl_Texture)& () { return Texture; } + + TextureSlot() : Unit (Graphic3d_TextureUnit_0) {} + }; + //! Class for iterating texture set. - class Iterator : public NCollection_Array1::Iterator + class Iterator : public NCollection_Array1::Iterator { public: //! Empty constructor. @@ -36,26 +49,37 @@ public: { if (!theSet.IsNull()) { - NCollection_Array1::Iterator::Init (theSet->myTextures); + NCollection_Array1::Iterator::Init (theSet->myTextures); } } + + //! Access texture. + const Handle(OpenGl_Texture)& Value() const { return NCollection_Array1::Iterator::Value().Texture; } + Handle(OpenGl_Texture)& ChangeValue() { return NCollection_Array1::Iterator::ChangeValue().Texture; } + + //! Access texture unit. + Graphic3d_TextureUnit Unit() const { return NCollection_Array1::Iterator::Value().Unit; } + Graphic3d_TextureUnit& ChangeUnit() { return NCollection_Array1::Iterator::ChangeValue().Unit; } }; public: //! Empty constructor. - OpenGl_TextureSet() {} + OpenGl_TextureSet() : myTextureSetBits (Graphic3d_TextureSetBits_NONE) {} //! Constructor. OpenGl_TextureSet (Standard_Integer theNbTextures) - : myTextures (0, theNbTextures - 1) {} + : myTextures (0, theNbTextures - 1), + myTextureSetBits (Graphic3d_TextureSetBits_NONE) {} //! Constructor for a single texture. - OpenGl_TextureSet (const Handle(OpenGl_Texture)& theTexture) - : myTextures (0, 0) - { - myTextures.ChangeFirst() = theTexture; - } + Standard_EXPORT OpenGl_TextureSet (const Handle(OpenGl_Texture)& theTexture); + + //! Return texture units declared within the program, @sa Graphic3d_TextureSetBits. + Standard_Integer TextureSetBits() const { return myTextureSetBits; } + + //! Return texture units declared within the program, @sa Graphic3d_TextureSetBits. + Standard_Integer& ChangeTextureSetBits() { return myTextureSetBits; } //! Return TRUE if texture array is empty. Standard_Boolean IsEmpty() const { return myTextures.IsEmpty(); } @@ -70,22 +94,25 @@ public: Standard_Integer Upper() const { return myTextures.Upper(); } //! Return the first texture. - const Handle(OpenGl_Texture)& First() const { return myTextures.First(); } + const Handle(OpenGl_Texture)& First() const { return myTextures.First().Texture; } //! Return the first texture. - Handle(OpenGl_Texture)& ChangeFirst() { return myTextures.ChangeFirst(); } + Handle(OpenGl_Texture)& ChangeFirst() { return myTextures.ChangeFirst().Texture; } //! Return the last texture. - const Handle(OpenGl_Texture)& Last() const { return myTextures.Last(); } + const Handle(OpenGl_Texture)& Last() const { return myTextures.Last().Texture; } //! Return the last texture. - Handle(OpenGl_Texture)& ChangeLast() { return myTextures.ChangeLast(); } + Handle(OpenGl_Texture)& ChangeLast() { return myTextures.ChangeLast().Texture; } + + //! Return the last texture unit. + Graphic3d_TextureUnit& ChangeLastUnit() { return myTextures.ChangeLast().Unit; } //! Return the texture at specified position within [0, Size()) range. - const Handle(OpenGl_Texture)& Value (Standard_Integer theIndex) const { return myTextures.Value (theIndex); } + const Handle(OpenGl_Texture)& Value (Standard_Integer theIndex) const { return myTextures.Value (theIndex).Texture; } //! Return the texture at specified position within [0, Size()) range. - Handle(OpenGl_Texture)& ChangeValue (Standard_Integer theIndex) { return myTextures.ChangeValue (theIndex); } + Handle(OpenGl_Texture)& ChangeValue (Standard_Integer theIndex) { return myTextures.ChangeValue (theIndex).Texture; } //! Return TRUE if texture color modulation has been enabled for the first texture //! or if texture is not set at all. @@ -100,12 +127,14 @@ public: //! Nullify all handles. void InitZero() { - myTextures.Init (Handle(OpenGl_Texture)()); + myTextures.Init (TextureSlot()); + myTextureSetBits = Graphic3d_TextureSetBits_NONE; } protected: - NCollection_Array1 myTextures; + NCollection_Array1 myTextures; + Standard_Integer myTextureSetBits; }; diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 2ee86d6e1a..cd69af0026 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -277,14 +277,13 @@ void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext) return; } - myTextureEnv = new OpenGl_TextureSet (1); - Handle(OpenGl_Texture)& aTextureEnv = myTextureEnv->ChangeFirst(); - aTextureEnv = new OpenGl_Texture (myTextureEnvData->GetId(), myTextureEnvData->GetParams()); - Handle(Image_PixMap) anImage = myTextureEnvData->GetImage(); - if (!anImage.IsNull()) + Handle(OpenGl_Texture) aTextureEnv = new OpenGl_Texture (myTextureEnvData->GetId(), myTextureEnvData->GetParams()); + if (Handle(Image_PixMap) anImage = myTextureEnvData->GetImage()) { aTextureEnv->Init (theContext, *anImage, myTextureEnvData->Type(), true); } + myTextureEnv = new OpenGl_TextureSet (aTextureEnv); + myTextureEnv->ChangeTextureSetBits() = Graphic3d_TextureSetBits_BaseColor; } // ======================================================================= diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index b667440015..86ba3c1099 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -403,9 +403,9 @@ OpenGl_RaytraceMaterial OpenGl_View::convertMaterial (const OpenGl_Aspects* theA aResMat.BSDF.Kc = aBSDF.Kc; aResMat.BSDF.Ks = aBSDF.Ks; - aResMat.BSDF.Kd = BVH_Vec4f (aBSDF.Kd, -1.f); // no texture - aResMat.BSDF.Kt = BVH_Vec4f (aBSDF.Kt, 0.f); - aResMat.BSDF.Le = BVH_Vec4f (aBSDF.Le, 0.f); + aResMat.BSDF.Kd = BVH_Vec4f (aBSDF.Kd, -1.0f); // no base color texture + aResMat.BSDF.Kt = BVH_Vec4f (aBSDF.Kt, -1.0f); // no metallic-roughness texture + aResMat.BSDF.Le = BVH_Vec4f (aBSDF.Le, -1.0f); // no emissive texture aResMat.BSDF.Absorption = aBSDF.Absorption; @@ -428,11 +428,26 @@ OpenGl_RaytraceMaterial OpenGl_View::convertMaterial (const OpenGl_Aspects* theA if (theGlContext->HasRayTracingTextures()) { - const Handle(OpenGl_Texture)& aTexture = aTextureSet->First(); - buildTextureTransform (aTexture->Sampler()->Parameters(), aResMat.TextureTransform); - - // write texture ID to diffuse w-component - aResMat.Diffuse.w() = aResMat.BSDF.Kd.w() = static_cast (myRaytraceGeometry.AddTexture (aTexture)); + // write texture ID to diffuse w-components + for (OpenGl_TextureSet::Iterator aTexIter (aTextureSet); aTexIter.More(); aTexIter.Next()) + { + const Handle(OpenGl_Texture)& aTexture = aTexIter.Value(); + if (aTexIter.Unit() == Graphic3d_TextureUnit_BaseColor) + { + buildTextureTransform (aTexture->Sampler()->Parameters(), aResMat.TextureTransform); + aResMat.Diffuse.w() = aResMat.BSDF.Kd.w() = static_cast (myRaytraceGeometry.AddTexture (aTexture)); + } + else if (aTexIter.Unit() == Graphic3d_TextureUnit_MetallicRoughness) + { + buildTextureTransform (aTexture->Sampler()->Parameters(), aResMat.TextureTransform); + aResMat.BSDF.Kt.w() = static_cast (myRaytraceGeometry.AddTexture (aTexture)); + } + else if (aTexIter.Unit() == Graphic3d_TextureUnit_Emissive) + { + buildTextureTransform (aTexture->Sampler()->Parameters(), aResMat.TextureTransform); + aResMat.BSDF.Le.w() = static_cast (myRaytraceGeometry.AddTexture (aTexture)); + } + } } else if (!myIsRaytraceWarnTextures) { diff --git a/src/OpenGl/OpenGl_View_Redraw.cxx b/src/OpenGl/OpenGl_View_Redraw.cxx index d46bc855e3..18b12102b3 100644 --- a/src/OpenGl/OpenGl_View_Redraw.cxx +++ b/src/OpenGl/OpenGl_View_Redraw.cxx @@ -1311,7 +1311,7 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection, } renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate); - aContext->BindTextures (Handle(OpenGl_TextureSet)()); + aContext->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); // Apply restored view matrix. aContext->ApplyWorldViewMatrix(); @@ -1530,7 +1530,7 @@ bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, } #endif - aCtx->BindTextures (Handle(OpenGl_TextureSet)()); + aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); const Graphic3d_TypeOfTextureFilter aFilter = (aDrawSizeX == aReadSizeX && aDrawSizeY == aReadSizeY) ? Graphic3d_TOTF_NEAREST : Graphic3d_TOTF_BILINEAR; const GLint aFilterGl = aFilter == Graphic3d_TOTF_NEAREST ? GL_NEAREST : GL_LINEAR; @@ -1674,7 +1674,7 @@ void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo) aCtx->core20fwd->glDepthMask (GL_TRUE); aCtx->core20fwd->glEnable (GL_DEPTH_TEST); - aCtx->BindTextures (Handle(OpenGl_TextureSet)()); + aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput); const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index 8e6e308a96..476d529fee 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -238,7 +238,7 @@ const OpenGl_Aspects* OpenGl_Workspace::SetAspects (const OpenGl_Aspects* theAsp // function : ApplyAspects // purpose : // ======================================================================= -const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects() +const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects (bool theToBindTextures) { if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC) { @@ -305,15 +305,10 @@ const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects() myGlContext->SetShadingMaterial (myAspectsSet, myHighlightStyle); } - const Handle(OpenGl_TextureSet)& aTextureSet = myAspectsSet->TextureSet (myGlContext, ToHighlight()); - if (!aTextureSet.IsNull() - || myAspectsSet->Aspect()->ToMapTexture()) + if (theToBindTextures) { - myGlContext->BindTextures (aTextureSet); - } - else - { - myGlContext->BindTextures (myEnvironmentTexture); + const Handle(OpenGl_TextureSet)& aTextureSet = TextureSet(); + myGlContext->BindTextures (aTextureSet, Handle(OpenGl_ShaderProgram)()); } if ((myView->myShadingModel == Graphic3d_TOSM_PBR @@ -359,7 +354,7 @@ Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer t // create the FBO const Handle(OpenGl_Context)& aCtx = GetGlContext(); - aCtx->BindTextures (Handle(OpenGl_TextureSet)()); + aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer(); if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_SRGB8_ALPHA8, GL_DEPTH24_STENCIL8, 0)) { diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index 3a6974e115..6b8b6b696c 100644 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -148,9 +148,20 @@ public: //! Assign new aspects (will be applied within ApplyAspects()). Standard_EXPORT const OpenGl_Aspects* SetAspects (const OpenGl_Aspects* theAspect); + //! Return TextureSet from set Aspects or Environment texture. + const Handle(OpenGl_TextureSet)& TextureSet() const + { + const Handle(OpenGl_TextureSet)& aTextureSet = myAspectsSet->TextureSet (myGlContext, ToHighlight()); + return !aTextureSet.IsNull() + || myAspectsSet->Aspect()->ToMapTexture() + ? aTextureSet + : myEnvironmentTexture; + } + //! Apply aspects. + //! @param theToBindTextures flag to bind texture set defined by applied aspect //! @return aspect set by SetAspects() - Standard_EXPORT const OpenGl_Aspects* ApplyAspects(); + Standard_EXPORT const OpenGl_Aspects* ApplyAspects (bool theToBindTextures = true); //! Clear the applied aspect state to default values. void ResetAppliedAspect(); diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index 53a45bcaaf..0081b83edd 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -175,49 +175,76 @@ uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sour #endif #endif -// Converts roughness value from range [0, 1] to real value for calculations +#if defined(THE_IS_PBR) +//! Converts roughness value from range [0, 1] to real value for calculations float occRoughness (in float theNormalizedRoughness); -// Front material properties accessors -#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 +// Front/back material properties accessors +vec4 occPBRMaterial_Color(in bool theIsFront); //!< Base color of PBR material +float occPBRMaterial_Metallic(in bool theIsFront); //!< Metallic coefficient +float occPBRMaterial_NormalizedRoughness(in bool theIsFront); //!< Normalized roughness coefficient +vec3 occPBRMaterial_Emission(in bool theIsFront); //!< Light intensity emitted by material +float occPBRMaterial_IOR(in bool theIsFront); //!< Index of refraction #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 +// 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 // Back material properties accessors -#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 -#define occSamplerBaseColor occSampler0 //!< alias to a base color texture -uniform sampler2D occSampler0; //!< current active sampler; +#define occActiveSampler occSampler0 //!< alias for backward compatibility +#define occSamplerBaseColor occSampler0 //!< alias to a base color texture +uniform sampler2D occSampler0; //!< current active sampler; +#endif //! occSampler1, occSampler2,... should be defined in GLSL program body for multitexturing + +#if defined(THE_HAS_TEXTURE_COLOR) +#define occTextureColor(theMatColor, theTexCoord) (theMatColor * occTexture2D(occSamplerBaseColor, theTexCoord)) +#else +#define occTextureColor(theMatColor, theTexCoord) theMatColor #endif - //! occSampler1, occSampler2,... should be defined in GLSL program body for multitexturing + +#if defined(THE_HAS_TEXTURE_OCCLUSION) && defined(FRAGMENT_SHADER) +uniform sampler2D occSamplerOcclusion; //!< R occlusion texture sampler +#define occTextureOcclusion(theColor, theTexCoord) theColor *= occTexture2D(occSamplerOcclusion, theTexCoord).r; +#else +#define occTextureOcclusion(theColor, theTexCoord) +#endif + +#if defined(THE_HAS_TEXTURE_EMISSIVE) && defined(FRAGMENT_SHADER) +uniform sampler2D occSamplerEmissive; //!< RGB emissive texture sampler +#define occTextureEmissive(theMatEmis, theTexCoord) (theMatEmis * occTexture2D(occSamplerEmissive, theTexCoord).rgb) +#else +#define occTextureEmissive(theMatEmis, theTexCoord) theMatEmis +#endif + +#if defined(THE_HAS_TEXTURE_NORMAL) && defined(FRAGMENT_SHADER) +uniform sampler2D occSamplerNormal; //!< XYZ normal texture sampler with W==0 indicating no texture +#define occTextureNormal(theTexCoord) occTexture2D(occSamplerNormal, theTexCoord) +#else +#define occTextureNormal(theTexCoord) vec4(0.0) // no normal map +#endif + +#if defined(THE_HAS_TEXTURE_METALROUGHNESS) && defined(FRAGMENT_SHADER) +uniform sampler2D occSamplerMetallicRoughness; //!< BG metallic-roughness texture sampler +#define occTextureRoughness(theRoug, theTexCoord) (theRoug * occTexture2D(occSamplerMetallicRoughness, theTexCoord).g) +#define occTextureMetallic(theMet, theTexCoord) (theMet * occTexture2D(occSamplerMetallicRoughness, theTexCoord).b) +#else +#define occTextureRoughness(theRoug, theTexCoord) theRoug +#define occTextureMetallic(theMet, theTexCoord) theMet +#endif + uniform vec4 occColor; //!< color value (in case of disabled lighting) uniform THE_PREC_ENUM int occDistinguishingMode; //!< Are front and back faces distinguished? uniform THE_PREC_ENUM int occTextureEnable; //!< Is texture enabled? diff --git a/src/Shaders/DeclarationsImpl.glsl b/src/Shaders/DeclarationsImpl.glsl index 047c159443..a2521a56b4 100644 --- a/src/Shaders/DeclarationsImpl.glsl +++ b/src/Shaders/DeclarationsImpl.glsl @@ -52,22 +52,12 @@ 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; } +vec4 occPBRMaterial_Color(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[0] : occPbrBackMaterial[0]; } +vec3 occPBRMaterial_Emission(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[1].rgb : occPbrBackMaterial[1].rgb; } +float occPBRMaterial_IOR(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[1].w : occPbrBackMaterial[1].w; } +float occPBRMaterial_Metallic(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[2].b : occPbrBackMaterial[2].b; } +float occPBRMaterial_NormalizedRoughness(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[2].g : occPbrBackMaterial[2].g; } #else uniform vec4 occFrontMaterial[5]; uniform vec4 occBackMaterial[5]; diff --git a/src/Shaders/PathtraceBase.fs b/src/Shaders/PathtraceBase.fs index f70d99f408..fbc132759e 100644 --- a/src/Shaders/PathtraceBase.fs +++ b/src/Shaders/PathtraceBase.fs @@ -34,14 +34,14 @@ struct SBSDF //! Weight of coat specular/glossy BRDF. vec4 Kc; - //! Weight of base diffuse BRDF. + //! Weight of base diffuse BRDF + base color texture index in W. vec4 Kd; //! Weight of base specular/glossy BRDF. vec4 Ks; - //! Weight of base specular/glossy BTDF. - vec3 Kt; + //! Weight of base specular/glossy BTDF + metallic-roughness texture index in W. + vec4 Kt; //! Fresnel coefficients of coat layer. vec3 FresnelCoat; @@ -816,11 +816,16 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples) aBSDF.Kc = texelFetch (uRaytraceMaterialTexture, MATERIAL_KC (aTriIndex.w)); aBSDF.Kd = texelFetch (uRaytraceMaterialTexture, MATERIAL_KD (aTriIndex.w)); aBSDF.Ks = texelFetch (uRaytraceMaterialTexture, MATERIAL_KS (aTriIndex.w)); - aBSDF.Kt = texelFetch (uRaytraceMaterialTexture, MATERIAL_KT (aTriIndex.w)).rgb; + aBSDF.Kt = texelFetch (uRaytraceMaterialTexture, MATERIAL_KT (aTriIndex.w)); + + // fetch Fresnel reflectance for both layers + aBSDF.FresnelCoat = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_COAT (aTriIndex.w)).xyz; + aBSDF.FresnelBase = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_BASE (aTriIndex.w)).xyz; + + vec4 anLE = texelFetch (uRaytraceMaterialTexture, MATERIAL_LE (aTriIndex.w)); // compute smooth normal (in parallel with fetch) vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex); - aNormal = normalize (vec3 (dot (aInvTransf0, aNormal), dot (aInvTransf1, aNormal), dot (aInvTransf2, aNormal))); @@ -828,7 +833,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples) SLocalSpace aSpace = buildLocalSpace (aNormal); #ifdef USE_TEXTURES - if (aBSDF.Kd.w >= 0.f) + if (aBSDF.Kd.w >= 0.0 || aBSDF.Kt.w >= 0.0 || anLE.w >= 0.0) { vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f); vec4 aTrsfRow1 = texelFetch (uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w)); @@ -836,20 +841,36 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples) aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord), dot (aTrsfRow2, aTexCoord)); - vec4 aTexColor = textureLod (sampler2D (uTextureSamplers[int (aBSDF.Kd.w)]), aTexCoord.st, 0.f); - aBSDF.Kd.rgb *= aTexColor.rgb * aTexColor.w; - if (aTexColor.w != 1.0f) + if (anLE.w >= 0.0) { - // mix transparency BTDF with texture alpha-channel - aBSDF.Kt = (UNIT - aTexColor.www) + aTexColor.w * aBSDF.Kt; + anLE.rgb *= textureLod (sampler2D (uTextureSamplers[int (anLE.w)]), aTexCoord.st, 0.0).rgb; + } + if (aBSDF.Kt.w >= 0.0) + { + vec2 aTexMetRough = textureLod (sampler2D (uTextureSamplers[int (aBSDF.Kt.w)]), aTexCoord.st, 0.0).bg; + float aPbrMetal = aTexMetRough.x; + float aPbrRough2 = aTexMetRough.y * aTexMetRough.y; + aBSDF.Ks.a *= aPbrRough2; + // when using metal-roughness texture, global metalness of material (encoded in FresnelBase) is expected to be 1.0 so that Kd will be 0.0 + aBSDF.Kd.rgb = aBSDF.FresnelBase * (1.0 - aPbrMetal); + aBSDF.FresnelBase *= aPbrMetal; + } + if (aBSDF.Kd.w >= 0.0) + { + vec4 aTexColor = textureLod (sampler2D (uTextureSamplers[int (aBSDF.Kd.w)]), aTexCoord.st, 0.0); + vec3 aDiff = aTexColor.rgb * aTexColor.a; + aBSDF.Kd.rgb *= aDiff; + aBSDF.FresnelBase *= aDiff; + if (aTexColor.a != 1.0) + { + // mix transparency BTDF with texture alpha-channel + aBSDF.Ks.rgb *= aTexColor.a; + aBSDF.Kt.rgb = (UNIT - aTexColor.aaa) + aTexColor.a * aBSDF.Kt.rgb; + } } } #endif - // fetch Fresnel reflectance for both layers - aBSDF.FresnelCoat = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_COAT (aTriIndex.w)).xyz; - aBSDF.FresnelBase = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_BASE (aTriIndex.w)).xyz; - if (uLightCount > 0 && IsNotZero (aBSDF, aThroughput)) { aExpPDF = 1.f / uLightCount; @@ -893,7 +914,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples) } // account for self-emission - aRadiance += aThroughput * texelFetch (uRaytraceMaterialTexture, MATERIAL_LE (aTriIndex.w)).rgb; + aRadiance += aThroughput * anLE.rgb; if (aInMedium) // handle attenuation { diff --git a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx index 3b31ea9693..b2e47cdb2d 100644 --- a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx +++ b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx @@ -55,22 +55,12 @@ static const char Shaders_DeclarationsImpl_glsl[] = "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" + "vec4 occPBRMaterial_Color(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[0] : occPbrBackMaterial[0]; }\n" + "vec3 occPBRMaterial_Emission(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[1].rgb : occPbrBackMaterial[1].rgb; }\n" + "float occPBRMaterial_IOR(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[1].w : occPbrBackMaterial[1].w; }\n" + "float occPBRMaterial_Metallic(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[2].b : occPbrBackMaterial[2].b; }\n" + "float occPBRMaterial_NormalizedRoughness(in bool theIsFront) { return theIsFront ? occPbrFrontMaterial[2].g : occPbrBackMaterial[2].g; }\n" "#else\n" "uniform vec4 occFrontMaterial[5];\n" "uniform vec4 occBackMaterial[5];\n" diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index 586183ad3a..c0e596deb2 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -178,49 +178,76 @@ static const char Shaders_Declarations_glsl[] = "#endif\n" "#endif\n" "\n" - "// Converts roughness value from range [0, 1] to real value for calculations\n" + "#if defined(THE_IS_PBR)\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" - "#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" + "// Front/back material properties accessors\n" + "vec4 occPBRMaterial_Color(in bool theIsFront); //!< Base color of PBR material\n" + "float occPBRMaterial_Metallic(in bool theIsFront); //!< Metallic coefficient\n" + "float occPBRMaterial_NormalizedRoughness(in bool theIsFront); //!< Normalized roughness coefficient\n" + "vec3 occPBRMaterial_Emission(in bool theIsFront); //!< Light intensity emitted by material\n" + "float occPBRMaterial_IOR(in bool theIsFront); //!< Index of refraction\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" + "// 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" "\n" "// Back material properties accessors\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" - "#define occSamplerBaseColor occSampler0 //!< alias to a base color texture\n" - "uniform sampler2D occSampler0; //!< current active sampler;\n" + "#define occActiveSampler occSampler0 //!< alias for backward compatibility\n" + "#define occSamplerBaseColor occSampler0 //!< alias to a base color texture\n" + "uniform sampler2D occSampler0; //!< current active sampler;\n" + "#endif //! occSampler1, occSampler2,... should be defined in GLSL program body for multitexturing\n" + "\n" + "#if defined(THE_HAS_TEXTURE_COLOR)\n" + "#define occTextureColor(theMatColor, theTexCoord) (theMatColor * occTexture2D(occSamplerBaseColor, theTexCoord))\n" + "#else\n" + "#define occTextureColor(theMatColor, theTexCoord) theMatColor\n" "#endif\n" - " //! occSampler1, occSampler2,... should be defined in GLSL program body for multitexturing\n" + "\n" + "#if defined(THE_HAS_TEXTURE_OCCLUSION) && defined(FRAGMENT_SHADER)\n" + "uniform sampler2D occSamplerOcclusion; //!< R occlusion texture sampler\n" + "#define occTextureOcclusion(theColor, theTexCoord) theColor *= occTexture2D(occSamplerOcclusion, theTexCoord).r;\n" + "#else\n" + "#define occTextureOcclusion(theColor, theTexCoord)\n" + "#endif\n" + "\n" + "#if defined(THE_HAS_TEXTURE_EMISSIVE) && defined(FRAGMENT_SHADER)\n" + "uniform sampler2D occSamplerEmissive; //!< RGB emissive texture sampler\n" + "#define occTextureEmissive(theMatEmis, theTexCoord) (theMatEmis * occTexture2D(occSamplerEmissive, theTexCoord).rgb)\n" + "#else\n" + "#define occTextureEmissive(theMatEmis, theTexCoord) theMatEmis\n" + "#endif\n" + "\n" + "#if defined(THE_HAS_TEXTURE_NORMAL) && defined(FRAGMENT_SHADER)\n" + "uniform sampler2D occSamplerNormal; //!< XYZ normal texture sampler with W==0 indicating no texture\n" + "#define occTextureNormal(theTexCoord) occTexture2D(occSamplerNormal, theTexCoord)\n" + "#else\n" + "#define occTextureNormal(theTexCoord) vec4(0.0) // no normal map\n" + "#endif\n" + "\n" + "#if defined(THE_HAS_TEXTURE_METALROUGHNESS) && defined(FRAGMENT_SHADER)\n" + "uniform sampler2D occSamplerMetallicRoughness; //!< BG metallic-roughness texture sampler\n" + "#define occTextureRoughness(theRoug, theTexCoord) (theRoug * occTexture2D(occSamplerMetallicRoughness, theTexCoord).g)\n" + "#define occTextureMetallic(theMet, theTexCoord) (theMet * occTexture2D(occSamplerMetallicRoughness, theTexCoord).b)\n" + "#else\n" + "#define occTextureRoughness(theRoug, theTexCoord) theRoug\n" + "#define occTextureMetallic(theMet, theTexCoord) theMet\n" + "#endif\n" + "\n" "uniform vec4 occColor; //!< color value (in case of disabled lighting)\n" "uniform THE_PREC_ENUM int occDistinguishingMode; //!< Are front and back faces distinguished?\n" "uniform THE_PREC_ENUM int occTextureEnable; //!< Is texture enabled?\n" diff --git a/src/Shaders/Shaders_PathtraceBase_fs.pxx b/src/Shaders/Shaders_PathtraceBase_fs.pxx index 138abbb7cf..6d33da8e9c 100644 --- a/src/Shaders/Shaders_PathtraceBase_fs.pxx +++ b/src/Shaders/Shaders_PathtraceBase_fs.pxx @@ -37,14 +37,14 @@ static const char Shaders_PathtraceBase_fs[] = " //! Weight of coat specular/glossy BRDF.\n" " vec4 Kc;\n" "\n" - " //! Weight of base diffuse BRDF.\n" + " //! Weight of base diffuse BRDF + base color texture index in W.\n" " vec4 Kd;\n" "\n" " //! Weight of base specular/glossy BRDF.\n" " vec4 Ks;\n" "\n" - " //! Weight of base specular/glossy BTDF.\n" - " vec3 Kt;\n" + " //! Weight of base specular/glossy BTDF + metallic-roughness texture index in W.\n" + " vec4 Kt;\n" "\n" " //! Fresnel coefficients of coat layer.\n" " vec3 FresnelCoat;\n" @@ -819,11 +819,16 @@ static const char Shaders_PathtraceBase_fs[] = " aBSDF.Kc = texelFetch (uRaytraceMaterialTexture, MATERIAL_KC (aTriIndex.w));\n" " aBSDF.Kd = texelFetch (uRaytraceMaterialTexture, MATERIAL_KD (aTriIndex.w));\n" " aBSDF.Ks = texelFetch (uRaytraceMaterialTexture, MATERIAL_KS (aTriIndex.w));\n" - " aBSDF.Kt = texelFetch (uRaytraceMaterialTexture, MATERIAL_KT (aTriIndex.w)).rgb;\n" + " aBSDF.Kt = texelFetch (uRaytraceMaterialTexture, MATERIAL_KT (aTriIndex.w));\n" + "\n" + " // fetch Fresnel reflectance for both layers\n" + " aBSDF.FresnelCoat = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_COAT (aTriIndex.w)).xyz;\n" + " aBSDF.FresnelBase = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_BASE (aTriIndex.w)).xyz;\n" + "\n" + " vec4 anLE = texelFetch (uRaytraceMaterialTexture, MATERIAL_LE (aTriIndex.w));\n" "\n" " // compute smooth normal (in parallel with fetch)\n" " vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);\n" - "\n" " aNormal = normalize (vec3 (dot (aInvTransf0, aNormal),\n" " dot (aInvTransf1, aNormal),\n" " dot (aInvTransf2, aNormal)));\n" @@ -831,7 +836,7 @@ static const char Shaders_PathtraceBase_fs[] = " SLocalSpace aSpace = buildLocalSpace (aNormal);\n" "\n" "#ifdef USE_TEXTURES\n" - " if (aBSDF.Kd.w >= 0.f)\n" + " if (aBSDF.Kd.w >= 0.0 || aBSDF.Kt.w >= 0.0 || anLE.w >= 0.0)\n" " {\n" " vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f);\n" " vec4 aTrsfRow1 = texelFetch (uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w));\n" @@ -839,20 +844,36 @@ static const char Shaders_PathtraceBase_fs[] = " aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord),\n" " dot (aTrsfRow2, aTexCoord));\n" "\n" - " vec4 aTexColor = textureLod (sampler2D (uTextureSamplers[int (aBSDF.Kd.w)]), aTexCoord.st, 0.f);\n" - " aBSDF.Kd.rgb *= aTexColor.rgb * aTexColor.w;\n" - " if (aTexColor.w != 1.0f)\n" + " if (anLE.w >= 0.0)\n" " {\n" - " // mix transparency BTDF with texture alpha-channel\n" - " aBSDF.Kt = (UNIT - aTexColor.www) + aTexColor.w * aBSDF.Kt;\n" + " anLE.rgb *= textureLod (sampler2D (uTextureSamplers[int (anLE.w)]), aTexCoord.st, 0.0).rgb;\n" + " }\n" + " if (aBSDF.Kt.w >= 0.0)\n" + " {\n" + " vec2 aTexMetRough = textureLod (sampler2D (uTextureSamplers[int (aBSDF.Kt.w)]), aTexCoord.st, 0.0).bg;\n" + " float aPbrMetal = aTexMetRough.x;\n" + " float aPbrRough2 = aTexMetRough.y * aTexMetRough.y;\n" + " aBSDF.Ks.a *= aPbrRough2;\n" + " // when using metal-roughness texture, global metalness of material (encoded in FresnelBase) is expected to be 1.0 so that Kd will be 0.0\n" + " aBSDF.Kd.rgb = aBSDF.FresnelBase * (1.0 - aPbrMetal);\n" + " aBSDF.FresnelBase *= aPbrMetal;\n" + " }\n" + " if (aBSDF.Kd.w >= 0.0)\n" + " {\n" + " vec4 aTexColor = textureLod (sampler2D (uTextureSamplers[int (aBSDF.Kd.w)]), aTexCoord.st, 0.0);\n" + " vec3 aDiff = aTexColor.rgb * aTexColor.a;\n" + " aBSDF.Kd.rgb *= aDiff;\n" + " aBSDF.FresnelBase *= aDiff;\n" + " if (aTexColor.a != 1.0)\n" + " {\n" + " // mix transparency BTDF with texture alpha-channel\n" + " aBSDF.Ks.rgb *= aTexColor.a;\n" + " aBSDF.Kt.rgb = (UNIT - aTexColor.aaa) + aTexColor.a * aBSDF.Kt.rgb;\n" + " }\n" " }\n" " }\n" "#endif\n" "\n" - " // fetch Fresnel reflectance for both layers\n" - " aBSDF.FresnelCoat = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_COAT (aTriIndex.w)).xyz;\n" - " aBSDF.FresnelBase = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_BASE (aTriIndex.w)).xyz;\n" - "\n" " if (uLightCount > 0 && IsNotZero (aBSDF, aThroughput))\n" " {\n" " aExpPDF = 1.f / uLightCount;\n" @@ -896,7 +917,7 @@ static const char Shaders_PathtraceBase_fs[] = " }\n" "\n" " // account for self-emission\n" - " aRadiance += aThroughput * texelFetch (uRaytraceMaterialTexture, MATERIAL_LE (aTriIndex.w)).rgb;\n" + " aRadiance += aThroughput * anLE.rgb;\n" "\n" " if (aInMedium) // handle attenuation\n" " {\n" diff --git a/src/XCAFDoc/XCAFDoc_VisMaterial.cxx b/src/XCAFDoc/XCAFDoc_VisMaterial.cxx index 3fba8d7ff8..c865308634 100644 --- a/src/XCAFDoc/XCAFDoc_VisMaterial.cxx +++ b/src/XCAFDoc/XCAFDoc_VisMaterial.cxx @@ -236,10 +236,7 @@ void XCAFDoc_VisMaterial::FillMaterialAspect (Graphic3d_MaterialAspect& theAspec aPbr.SetColor (myPbrMat.BaseColor); aPbr.SetMetallic (myPbrMat.Metallic); aPbr.SetRoughness(myPbrMat.Roughness); - if (myPbrMat.EmissiveTexture.IsNull()) // TODO Temporal measure until emissive map will be implemented - { - aPbr.SetEmission(myPbrMat.EmissiveFactor); - } + aPbr.SetEmission (myPbrMat.EmissiveFactor); theAspect.SetPBRMaterial (aPbr); theAspect.SetBSDF (Graphic3d_BSDF::CreateMetallicRoughness (aPbr)); } @@ -262,43 +259,41 @@ void XCAFDoc_VisMaterial::FillAspect (const Handle(Graphic3d_Aspects)& theAspect theAspect->SetAlphaMode (myAlphaMode , myAlphaCutOff); theAspect->SetSuppressBackFaces (!myIsDoubleSided); - Handle(Image_Texture) aColorTexture, aNormTexture; - if (!myCommonMat.DiffuseTexture.IsNull()) + const Handle(Image_Texture)& aColorTexture = !myPbrMat.BaseColorTexture.IsNull() ? myPbrMat.BaseColorTexture : myCommonMat.DiffuseTexture; + Standard_Integer aNbTexUnits = 0; + if (!aColorTexture.IsNull()) { ++aNbTexUnits; } + if (!myPbrMat.EmissiveTexture.IsNull()) { ++aNbTexUnits; } + if (!myPbrMat.NormalTexture.IsNull()) { ++aNbTexUnits; } + if (!myPbrMat.OcclusionTexture.IsNull()) { ++aNbTexUnits; } + if (!myPbrMat.MetallicRoughnessTexture.IsNull()) { ++aNbTexUnits; } + if (aNbTexUnits == 0) { - aColorTexture = myCommonMat.DiffuseTexture; - } - else if (!myPbrMat.BaseColorTexture.IsNull()) - { - aColorTexture = myPbrMat.BaseColorTexture; + return; } - if (!myPbrMat.NormalTexture.IsNull()) - { - aNormTexture = myPbrMat.NormalTexture; - } - - Standard_Integer aNbTextures = 0; + Standard_Integer aTexIter = 0; + Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (aNbTexUnits); if (!aColorTexture.IsNull()) { - ++aNbTextures; + aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*aColorTexture, Graphic3d_TextureUnit_BaseColor)); } - if (!aNormTexture.IsNull()) + if (!myPbrMat.EmissiveTexture.IsNull()) { - //++aNbTextures; + aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.EmissiveTexture, Graphic3d_TextureUnit_Emissive)); } - if (aNbTextures != 0) + if (!myPbrMat.OcclusionTexture.IsNull()) { - Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (aNbTextures); - Standard_Integer aTextureIndex = 0; - if (!aColorTexture.IsNull()) - { - aTextureSet->SetValue (aTextureIndex++, new XCAFPrs_Texture (*aColorTexture, Graphic3d_TextureUnit_BaseColor)); - } - if (!aNormTexture.IsNull()) - { - //aTextureSet->SetValue (aTextureIndex++, new XCAFPrs_Texture (*aColorTexture, Graphic3d_TextureUnit_Normal)); - } - theAspect->SetTextureSet (aTextureSet); - theAspect->SetTextureMapOn (true); + aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.OcclusionTexture, Graphic3d_TextureUnit_Occlusion)); } + if (!myPbrMat.NormalTexture.IsNull()) + { + aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.NormalTexture, Graphic3d_TextureUnit_Normal)); + } + if (!myPbrMat.MetallicRoughnessTexture.IsNull()) + { + aTextureSet->SetValue (aTexIter++, new XCAFPrs_Texture (*myPbrMat.MetallicRoughnessTexture, Graphic3d_TextureUnit_MetallicRoughness)); + } + + theAspect->SetTextureSet (aTextureSet); + theAspect->SetTextureMapOn (true); } diff --git a/src/XCAFPrs/XCAFPrs_Texture.cxx b/src/XCAFPrs/XCAFPrs_Texture.cxx index 1c8b3a0774..798cbab366 100644 --- a/src/XCAFPrs/XCAFPrs_Texture.cxx +++ b/src/XCAFPrs/XCAFPrs_Texture.cxx @@ -31,6 +31,8 @@ XCAFPrs_Texture::XCAFPrs_Texture (const Image_Texture& theImageSource, myTexId = myImageSource.TextureId(); } myParams->SetTextureUnit (theUnit); + myIsColorMap = theUnit == Graphic3d_TextureUnit_BaseColor + || theUnit == Graphic3d_TextureUnit_Emissive; } //======================================================================= diff --git a/tests/v3d/raytrace/helmet b/tests/v3d/raytrace/helmet new file mode 100644 index 0000000000..d547ae25d3 --- /dev/null +++ b/tests/v3d/raytrace/helmet @@ -0,0 +1,25 @@ +puts "========" +puts "0031096: Visualization, TKOpenGl - support metallic-roughness texture mapping" +puts "========" + +pload XDE OCAF MODELING VISUALIZATION +catch { Close D } +ReadGltf D [locate_data_file bug30691_DamagedHelmet.gltf] + +vclear +vinit View1 +XDisplay -dispMode 1 D +vaxo +vcamera -persp +vviewparams -scale 0.412548 -proj 0.54479 -0.790649 0.279424 -up -0.248339 0.166151 0.954317 -at -27.3419 382.603 -233.934 + +vtextureenv on 2 +vlight -change 0 -intensity 2.5 +vlight -change 1 -intensity 0.3 + +vrenderparams -shadingModel PBR +vdump ${imagedir}/${casename}_pbr.png + +vrenderparams -ray -gi -rayDepth 10 +vfps 200 +vdump ${imagedir}/${casename}_pt.png