1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0027925: Visualization - implement order-independent transparency algorithm within rasterization rendering

Weighted, Blended Order-Independent Transparency algorithm has been added rasterization pipeline.
In contrast to classical blending transparency it makes transparent objects look independent
from point of view. It also gives better depth occlusion when being used together with a weight factor
based on value of a GL depth buffer. The feature supports desktop OpenGL, OpenGL ES 3.0, ANGLE
and can be used together with MSAA on desktop GL.

To be used it require availability of:
1) Shaders pipeline.
2) Floating point color format for framebuffer (GL_ARB_color_buffer_float).
3) Multiple render targets (GL_ARB_draw_buffers).

Patch does not modify API and does not require application porting.
It adds new rendering options to Graphic3d_RenderingParams structure:
a) Transparency method from enumeration.
b) Scalar factor [0-1] controlling influence of a fragment's depth to its visibility.

Patch also simplifies processing of transparent objects for standard method:
rendering priority of transparent graphical structures is managed automatically,
therefore there is no need to care about it at application's side.
This commit is contained in:
apl
2017-04-25 15:10:15 +03:00
committed by bugmaster
parent 9151562167
commit a1073ae267
41 changed files with 1947 additions and 299 deletions

View File

@@ -249,6 +249,12 @@ const char THE_FRAG_CLIP_PLANES_2[] =
EOL" discard;"
EOL" }";
//! Output color and coverage for accumulation by OIT algorithm.
const char THE_FRAG_write_oit_buffers[] =
EOL" float aWeight = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);"
EOL" occFragCoverage.r = occFragColor.a * aWeight;"
EOL" occFragColor = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);";
#if !defined(GL_ES_VERSION_2_0)
static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
@@ -1069,6 +1075,35 @@ void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)
}
}
// =======================================================================
// function : PushOitState
// purpose : Pushes state of OIT uniforms to the specified program
// =======================================================================
void OpenGl_ShaderManager::PushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
{
if (!theProgram->IsValid())
{
return;
}
if (myOitState.Index() == theProgram->ActiveState (OpenGL_OIT_STATE))
{
return;
}
const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
{
theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
}
const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
{
theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
}
}
// =======================================================================
// function : PushState
// purpose : Pushes state of OCCT graphics parameters to the program
@@ -1082,6 +1117,7 @@ void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& thePro
PushProjectionState (aProgram);
PushLightSourceState (aProgram);
PushMaterialState (aProgram);
PushOitState (aProgram);
}
// =======================================================================
@@ -1124,6 +1160,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
{
aProgramSrc->SetHeader ("#version 150");
}
#else
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
@@ -1208,6 +1249,94 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
return Standard_True;
}
// =======================================================================
// function : prepareStdProgramOitCompositing
// purpose :
// =======================================================================
Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
{
Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
TCollection_AsciiString aSrcVert, aSrcFrag;
aSrcVert =
EOL"THE_SHADER_OUT vec2 TexCoord;"
EOL"void main()"
EOL"{"
EOL" TexCoord = occVertex.zw;"
EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
EOL"}";
if (!theMsaa)
{
aSrcFrag =
EOL"uniform sampler2D uAccumTexture;"
EOL"uniform sampler2D uWeightTexture;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
EOL" occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
EOL"}";
#if !defined(GL_ES_VERSION_2_0)
if (myContext->IsGlGreaterEqual (3, 2))
{
aProgramSrc->SetHeader ("#version 150");
}
#else
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
}
else
{
aSrcFrag =
EOL"uniform sampler2DMS uAccumTexture;"
EOL"uniform sampler2DMS uWeightTexture;"
EOL
EOL"THE_SHADER_IN vec2 TexCoord;"
EOL
EOL"void main()"
EOL"{"
EOL" ivec2 aTexel = ivec2 (textureSize (uAccumTexture) * TexCoord);"
EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
EOL" occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
EOL"}";
#if !defined(GL_ES_VERSION_2_0)
if (myContext->IsGlGreaterEqual (4, 0))
{
aProgramSrc->SetHeader ("#version 400");
}
#else
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
}
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
TCollection_AsciiString aKey;
if (!Create (aProgramSrc, aKey, aProgram))
{
aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
return Standard_False;
}
myContext->BindProgram (aProgram);
aProgram->SetSampler (myContext, "uAccumTexture", 0);
aProgram->SetSampler (myContext, "uWeightTexture", 1);
myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
return Standard_True;
}
// =======================================================================
// function : pointSpriteAlphaSrc
// purpose :
@@ -1249,7 +1378,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
const Standard_Integer theBits)
{
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha;
TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
if ((theBits & OpenGl_PO_Point) != 0)
@@ -1351,6 +1481,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
}
}
if ((theBits & OpenGl_PO_WriteOit) != 0)
{
aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
}
TCollection_AsciiString aSrcVertEndMain;
if ((theBits & OpenGl_PO_StippleLine) != 0)
@@ -1359,7 +1493,6 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
#if defined(GL_ES_VERSION_2_0)
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
hasGlslBitOps = true;
}
#else
@@ -1421,6 +1554,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
EOL"{"
+ aSrcFragExtraMain
+ aSrcFragMainGetColor
+ aSrcFragWriteOit
+ EOL"}";
#if !defined(GL_ES_VERSION_2_0)
@@ -1428,6 +1562,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
{
aProgramSrc->SetHeader ("#version 150");
}
#else
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
@@ -1572,7 +1711,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
const Standard_Integer theBits)
{
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain;
TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
if ((theBits & OpenGl_PO_Point) != 0)
{
@@ -1640,6 +1780,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
}
}
if ((theBits & OpenGl_PO_WriteOit) != 0)
{
aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
}
const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
aSrcVert = TCollection_AsciiString()
@@ -1673,13 +1817,19 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
EOL"{"
+ aSrcFragExtraMain
+ EOL" occFragColor = getColor();"
EOL"}";
+ aSrcFragWriteOit
+ EOL"}";
#if !defined(GL_ES_VERSION_2_0)
if (myContext->core32 != NULL)
{
aProgramSrc->SetHeader ("#version 150");
}
#else
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
@@ -1702,7 +1852,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
#define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain;
TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain, aSrcFragWriteOit;
TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
if ((theBits & OpenGl_PO_Point) != 0)
{
@@ -1763,6 +1914,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
}
}
if ((theBits & OpenGl_PO_WriteOit) != 0)
{
aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
}
aSrcVert = TCollection_AsciiString()
+ THE_FUNC_transformNormal
@@ -1799,13 +1954,19 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
EOL"{"
+ aSrcFragExtraMain
+ EOL" occFragColor = getColor();"
EOL"}";
+ aSrcFragWriteOit
+ EOL"}";
#if !defined(GL_ES_VERSION_2_0)
if (myContext->core32 != NULL)
{
aProgramSrc->SetHeader ("#version 150");
}
#else
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
@@ -2022,6 +2183,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
{
aProgramSrc->SetHeader ("#version 150");
}
#else
if (myContext->IsGlGreaterEqual (3, 0))
{
aProgramSrc->SetHeader ("#version 300 es");
}
#endif
aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));