1 // Created on: 2016-06-16
2 // Created by: Denis BOGOLEPOV & Danila ULYANOV
3 // Copyright (c) 2016 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OpenGl_Context.hxx>
17 #include <OpenGl_TileSampler.hxx>
18 #include <TCollection_ExtendedString.hxx>
22 //! Scale factor for estimating visual error.
23 static const float THE_SCALE_FACTOR = 1.0f / 1e6f;
26 //=======================================================================
27 //function : OpenGl_TileSampler
29 //=======================================================================
30 OpenGl_TileSampler::OpenGl_TileSampler()
37 mySampler.initFaure();
40 //=======================================================================
41 //function : GrabVarianceMap
43 //=======================================================================
44 void OpenGl_TileSampler::GrabVarianceMap (const Handle(OpenGl_Context)& theContext)
46 #if !defined(GL_ES_VERSION_2_0)
47 std::vector<GLint> aRawData (NbTiles(), 0);
49 theContext->core11fwd->glGetTexImage (GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &aRawData.front());
50 const GLenum anErr = theContext->core11fwd->glGetError();
51 if (anErr != GL_NO_ERROR)
53 theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_MEDIUM,
54 "Error! Failed to fetch visual error map from the GPU");
58 for (int aTileIdx = 0, aNbTiles = NbTiles(); aTileIdx < aNbTiles; ++aTileIdx)
60 myVarianceMap[aTileIdx] = aRawData[aTileIdx] * THE_SCALE_FACTOR;
63 for (int aX = 0; aX < myTilesX; ++aX)
65 for (int aY = 0; aY < myTilesY; ++aY)
67 ChangeTile (aX, aY) *= 1.0f / TileArea (aX, aY); // average error over the tile
71 ChangeTile (aX, aY) += Tile (aX, aY - 1);
76 myMarginalMap.resize (myTilesX); // build marginal distribution
77 for (int aX = 0; aX < myTilesX; ++aX)
79 myMarginalMap[aX] = Tile (aX, myTilesY - 1);
82 myMarginalMap[aX] += myMarginalMap[aX - 1];
86 // glGetTexImage() is unavailable on OpenGL ES, FBO + glReadPixels() can be used instead
91 //=======================================================================
94 //=======================================================================
95 void OpenGl_TileSampler::Sample (int& theOffsetX,
101 const float aKsiX = mySampler.sample (0, mySample) * myMarginalMap.back();
102 for (; aX < myTilesX - 1; ++aX)
104 if (aKsiX <= myMarginalMap[aX])
110 const float aKsiY = mySampler.sample (1, mySample) * Tile (aX, myTilesY - 1);
111 for (; aY < myTilesY - 1; ++aY)
113 if (aKsiY <= Tile (aX, aY))
119 theOffsetX = aX * TileSize();
120 theOffsetY = aY * TileSize();
125 //=======================================================================
128 //=======================================================================
129 void OpenGl_TileSampler::SetSize (const int theSizeX,
132 if (mySizeX == theSizeX
133 && mySizeY == theSizeY)
141 myTilesX = static_cast<int> (ceilf (static_cast<float> (mySizeX) / TileSize()));
142 myTilesY = static_cast<int> (ceilf (static_cast<float> (mySizeY) / TileSize()));
144 myVarianceMap.resize (myTilesX * myTilesY);
147 //=======================================================================
150 //=======================================================================
151 void OpenGl_TileSampler::Upload (const Handle(OpenGl_Context)& theContext,
152 const Handle(OpenGl_Texture)& theTexture,
155 if (theTexture.IsNull())
160 std::vector<GLint> aData (myTilesX * myTilesY * 2);
161 for (int aX = 0; aX < myTilesX; ++aX)
163 for (int aY = 0; aY < myTilesY; ++aY)
167 aData[(aY * myTilesX + aX) * 2 + 0] = aX * TileSize();
168 aData[(aY * myTilesX + aX) * 2 + 1] = aY * TileSize();
172 Sample (aData[(aY * myTilesX + aX) * 2 + 0],
173 aData[(aY * myTilesX + aX) * 2 + 1]);
178 theTexture->Bind (theContext);
180 theContext->core11fwd->glTexImage2D (GL_TEXTURE_2D, 0, GL_RG32I, myTilesX, myTilesY, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, &aData.front());
181 const GLenum anErr = theContext->core11fwd->glGetError();
182 if (anErr != GL_NO_ERROR)
184 theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_MEDIUM,
185 "Error! Failed to upload tile offset map on the GPU");