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

0027607: Visualization - Implement adaptive screen space sampling in path tracing

This commit provides useful functionality for path tracing rendering core.

1) Graphic3d_RenderingParams class was extended with additional AdaptiveScreenSampling option (disabled by default).
   If this option is enabled, path tracing tries to adjust the number of samples for different screen areas.

   In this way, the more complex areas (from the point of light conditions) are sampled more intensively,
   while the simple areas are sampled very rarely.
   For example, caustics and glossy reflections are typical candidates for more precise sampling.

   In general, this allows to equalize image convergence and not to waste resources for already converged areas.
   It is also possible to visualize sampling densities by enabling ShowSamplingTiles option
   (activating and deactivating this option does not affect on the accumulated image).

2) Mixing OpenGL and ray-tracing output has been changed.
   Now blending is performed using OpenGL functionality, while ray-tracing shaders only output correct Z-value.

Test case bugs vis bug27083 has been updated,
since the alpha value is now correctly set by Ray-Tracing to 1, opaque.
This commit is contained in:
dbp
2016-07-13 12:19:27 +03:00
committed by kgv
parent 6a24c6ded9
commit 3a9b5dc86a
22 changed files with 1303 additions and 378 deletions

View File

@@ -0,0 +1,187 @@
// Created on: 2016-06-16
// Created by: Denis BOGOLEPOV & Danila ULYANOV
// Copyright (c) 2016 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <OpenGl_Context.hxx>
#include <OpenGl_TileSampler.hxx>
#include <TCollection_ExtendedString.hxx>
namespace
{
//! Scale factor for estimating visual error.
static const float THE_SCALE_FACTOR = 1.0f / 1e6f;
}
//=======================================================================
//function : OpenGl_TileSampler
//purpose :
//=======================================================================
OpenGl_TileSampler::OpenGl_TileSampler()
: mySample (0),
mySizeX (0),
mySizeY (0),
myTilesX (0),
myTilesY (0)
{
mySampler.initFaure();
}
//=======================================================================
//function : GrabVarianceMap
//purpose :
//=======================================================================
void OpenGl_TileSampler::GrabVarianceMap (const Handle(OpenGl_Context)& theContext)
{
#if !defined(GL_ES_VERSION_2_0)
std::vector<GLint> aRawData (NbTiles(), 0);
theContext->core11fwd->glGetTexImage (GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &aRawData.front());
const GLenum anErr = theContext->core11fwd->glGetError();
if (anErr != GL_NO_ERROR)
{
theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_MEDIUM,
"Error! Failed to fetch visual error map from the GPU");
}
else
{
for (int aTileIdx = 0, aNbTiles = NbTiles(); aTileIdx < aNbTiles; ++aTileIdx)
{
myVarianceMap[aTileIdx] = aRawData[aTileIdx] * THE_SCALE_FACTOR;
}
for (int aX = 0; aX < myTilesX; ++aX)
{
for (int aY = 0; aY < myTilesY; ++aY)
{
ChangeTile (aX, aY) *= 1.0f / TileArea (aX, aY); // average error over the tile
if (aY > 0)
{
ChangeTile (aX, aY) += Tile (aX, aY - 1);
}
}
}
myMarginalMap.resize (myTilesX); // build marginal distribution
for (int aX = 0; aX < myTilesX; ++aX)
{
myMarginalMap[aX] = Tile (aX, myTilesY - 1);
if (aX > 0)
myMarginalMap[aX] += myMarginalMap[aX - 1];
}
}
#else
// glGetTexImage() is unavailable on OpenGL ES, FBO + glReadPixels() can be used instead
(void )theContext;
#endif
}
//=======================================================================
//function : Sample
//purpose :
//=======================================================================
void OpenGl_TileSampler::Sample (int& theOffsetX,
int& theOffsetY)
{
int aX = 0;
int aY = 0;
const float aKsiX = mySampler.sample (0, mySample) * myMarginalMap.back();
for (; aX < myTilesX - 1; ++aX)
{
if (aKsiX <= myMarginalMap[aX])
{
break;
}
}
const float aKsiY = mySampler.sample (1, mySample) * Tile (aX, myTilesY - 1);
for (; aY < myTilesY - 1; ++aY)
{
if (aKsiY <= Tile (aX, aY))
{
break;
}
}
theOffsetX = aX * TileSize();
theOffsetY = aY * TileSize();
++mySample;
}
//=======================================================================
//function : SetSize
//purpose :
//=======================================================================
void OpenGl_TileSampler::SetSize (const int theSizeX,
const int theSizeY)
{
if (mySizeX == theSizeX
&& mySizeY == theSizeY)
{
return;
}
mySizeX = theSizeX;
mySizeY = theSizeY;
myTilesX = static_cast<int> (ceilf (static_cast<float> (mySizeX) / TileSize()));
myTilesY = static_cast<int> (ceilf (static_cast<float> (mySizeY) / TileSize()));
myVarianceMap.resize (myTilesX * myTilesY);
}
//=======================================================================
//function : Upload
//purpose :
//=======================================================================
void OpenGl_TileSampler::Upload (const Handle(OpenGl_Context)& theContext,
const Handle(OpenGl_Texture)& theTexture,
bool theAdaptive)
{
if (theTexture.IsNull())
{
return;
}
std::vector<GLint> aData (myTilesX * myTilesY * 2);
for (int aX = 0; aX < myTilesX; ++aX)
{
for (int aY = 0; aY < myTilesY; ++aY)
{
if (!theAdaptive)
{
aData[(aY * myTilesX + aX) * 2 + 0] = aX * TileSize();
aData[(aY * myTilesX + aX) * 2 + 1] = aY * TileSize();
}
else
{
Sample (aData[(aY * myTilesX + aX) * 2 + 0],
aData[(aY * myTilesX + aX) * 2 + 1]);
}
}
}
theTexture->Bind (theContext);
theContext->core11fwd->glTexImage2D (GL_TEXTURE_2D, 0, GL_RG32I, myTilesX, myTilesY, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, &aData.front());
const GLenum anErr = theContext->core11fwd->glGetError();
if (anErr != GL_NO_ERROR)
{
theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_MEDIUM,
"Error! Failed to upload tile offset map on the GPU");
}
}