3a9b5dc8 |
1 | // Created on: 2016-06-16 |
2 | // Created by: Denis BOGOLEPOV & Danila ULYANOV |
3 | // Copyright (c) 2016 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
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. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #include <OpenGl_Context.hxx> |
17 | #include <OpenGl_TileSampler.hxx> |
18 | #include <TCollection_ExtendedString.hxx> |
19 | |
20 | namespace |
21 | { |
22 | //! Scale factor for estimating visual error. |
23 | static const float THE_SCALE_FACTOR = 1.0f / 1e6f; |
24 | } |
25 | |
26 | //======================================================================= |
27 | //function : OpenGl_TileSampler |
28 | //purpose : |
29 | //======================================================================= |
30 | OpenGl_TileSampler::OpenGl_TileSampler() |
31 | : mySample (0), |
32 | mySizeX (0), |
33 | mySizeY (0), |
34 | myTilesX (0), |
35 | myTilesY (0) |
36 | { |
37 | mySampler.initFaure(); |
38 | } |
39 | |
40 | //======================================================================= |
41 | //function : GrabVarianceMap |
42 | //purpose : |
43 | //======================================================================= |
44 | void OpenGl_TileSampler::GrabVarianceMap (const Handle(OpenGl_Context)& theContext) |
45 | { |
46 | #if !defined(GL_ES_VERSION_2_0) |
47 | std::vector<GLint> aRawData (NbTiles(), 0); |
48 | |
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) |
52 | { |
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"); |
55 | } |
56 | else |
57 | { |
58 | for (int aTileIdx = 0, aNbTiles = NbTiles(); aTileIdx < aNbTiles; ++aTileIdx) |
59 | { |
60 | myVarianceMap[aTileIdx] = aRawData[aTileIdx] * THE_SCALE_FACTOR; |
61 | } |
62 | |
63 | for (int aX = 0; aX < myTilesX; ++aX) |
64 | { |
65 | for (int aY = 0; aY < myTilesY; ++aY) |
66 | { |
67 | ChangeTile (aX, aY) *= 1.0f / TileArea (aX, aY); // average error over the tile |
68 | |
69 | if (aY > 0) |
70 | { |
71 | ChangeTile (aX, aY) += Tile (aX, aY - 1); |
72 | } |
73 | } |
74 | } |
75 | |
76 | myMarginalMap.resize (myTilesX); // build marginal distribution |
77 | for (int aX = 0; aX < myTilesX; ++aX) |
78 | { |
79 | myMarginalMap[aX] = Tile (aX, myTilesY - 1); |
80 | |
81 | if (aX > 0) |
82 | myMarginalMap[aX] += myMarginalMap[aX - 1]; |
83 | } |
84 | } |
85 | #else |
86 | // glGetTexImage() is unavailable on OpenGL ES, FBO + glReadPixels() can be used instead |
87 | (void )theContext; |
88 | #endif |
89 | } |
90 | |
91 | //======================================================================= |
92 | //function : Sample |
93 | //purpose : |
94 | //======================================================================= |
95 | void OpenGl_TileSampler::Sample (int& theOffsetX, |
96 | int& theOffsetY) |
97 | { |
98 | int aX = 0; |
99 | int aY = 0; |
100 | |
101 | const float aKsiX = mySampler.sample (0, mySample) * myMarginalMap.back(); |
102 | for (; aX < myTilesX - 1; ++aX) |
103 | { |
104 | if (aKsiX <= myMarginalMap[aX]) |
105 | { |
106 | break; |
107 | } |
108 | } |
109 | |
110 | const float aKsiY = mySampler.sample (1, mySample) * Tile (aX, myTilesY - 1); |
111 | for (; aY < myTilesY - 1; ++aY) |
112 | { |
113 | if (aKsiY <= Tile (aX, aY)) |
114 | { |
115 | break; |
116 | } |
117 | } |
118 | |
119 | theOffsetX = aX * TileSize(); |
120 | theOffsetY = aY * TileSize(); |
121 | |
122 | ++mySample; |
123 | } |
124 | |
125 | //======================================================================= |
126 | //function : SetSize |
127 | //purpose : |
128 | //======================================================================= |
129 | void OpenGl_TileSampler::SetSize (const int theSizeX, |
130 | const int theSizeY) |
131 | { |
132 | if (mySizeX == theSizeX |
133 | && mySizeY == theSizeY) |
134 | { |
135 | return; |
136 | } |
137 | |
138 | mySizeX = theSizeX; |
139 | mySizeY = theSizeY; |
140 | |
141 | myTilesX = static_cast<int> (ceilf (static_cast<float> (mySizeX) / TileSize())); |
142 | myTilesY = static_cast<int> (ceilf (static_cast<float> (mySizeY) / TileSize())); |
143 | |
144 | myVarianceMap.resize (myTilesX * myTilesY); |
145 | } |
146 | |
147 | //======================================================================= |
148 | //function : Upload |
149 | //purpose : |
150 | //======================================================================= |
151 | void OpenGl_TileSampler::Upload (const Handle(OpenGl_Context)& theContext, |
152 | const Handle(OpenGl_Texture)& theTexture, |
153 | bool theAdaptive) |
154 | { |
155 | if (theTexture.IsNull()) |
156 | { |
157 | return; |
158 | } |
159 | |
160 | std::vector<GLint> aData (myTilesX * myTilesY * 2); |
161 | for (int aX = 0; aX < myTilesX; ++aX) |
162 | { |
163 | for (int aY = 0; aY < myTilesY; ++aY) |
164 | { |
165 | if (!theAdaptive) |
166 | { |
167 | aData[(aY * myTilesX + aX) * 2 + 0] = aX * TileSize(); |
168 | aData[(aY * myTilesX + aX) * 2 + 1] = aY * TileSize(); |
169 | } |
170 | else |
171 | { |
172 | Sample (aData[(aY * myTilesX + aX) * 2 + 0], |
173 | aData[(aY * myTilesX + aX) * 2 + 1]); |
174 | } |
175 | } |
176 | } |
177 | |
178 | theTexture->Bind (theContext); |
179 | |
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) |
183 | { |
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"); |
186 | } |
187 | } |