History

Batch heightfield sections for better performance.

Andrzej Kapolka committed 11 years ago

Commit da857141 parent 53809804 files · +298 −138Browse files

Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 4 files). Show all

Unified · Split

interface/src/MetavoxelSystem.cpp+227−137
@@ -140,6 +140,18 @@ int RenderVisitor::visit(MetavoxelInfo& info) { · 139 unmodified lines
140140 return STOP_RECURSION;
141141 }
142142
143+class HeightfieldPoint {
144+public:
145+ glm::vec3 vertex;
146+ glm::vec2 textureCoord;
147+};
148+
149+const int SPLAT_COUNT = 4;
150+const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 };
151+
152+static const int EIGHT_BIT_MAXIMUM = 255;
153+static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM;
154+
143155 void MetavoxelSystem::render() {
144156 // update the frustum
145157 ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum();
@@ -150,6 +162,154 @@ void MetavoxelSystem::render() { · 4 unmodified lines
150162 RenderVisitor renderVisitor(getLOD());
151163 guideToAugmented(renderVisitor, true);
152164
165+ if (!_heightfieldBaseBatches.isEmpty()) {
166+ glEnableClientState(GL_VERTEX_ARRAY);
167+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
168+
169+ Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
170+
171+ glDisable(GL_BLEND);
172+ glEnable(GL_CULL_FACE);
173+ glEnable(GL_ALPHA_TEST);
174+ glAlphaFunc(GL_EQUAL, 0.0f);
175+
176+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
177+
178+ DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
179+
180+ foreach (const HeightfieldBaseBatch& batch, _heightfieldBaseBatches) {
181+ glPushMatrix();
182+ glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z);
183+ glm::vec3 axis = glm::axis(batch.rotation);
184+ glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z);
185+ glScalef(batch.scale.x, batch.scale.y, batch.scale.z);
186+
187+ batch.vertexBuffer->bind();
188+ batch.indexBuffer->bind();
189+
190+ HeightfieldPoint* point = 0;
191+ glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);
192+ glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);
193+
194+ glBindTexture(GL_TEXTURE_2D, batch.heightTextureID);
195+
196+ DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniform(
197+ DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), batch.heightScale);
198+ DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniform(
199+ DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), batch.colorScale);
200+
201+ glActiveTexture(GL_TEXTURE1);
202+ glBindTexture(GL_TEXTURE_2D, batch.colorTextureID);
203+
204+ glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);
205+
206+ glBindTexture(GL_TEXTURE_2D, 0);
207+
208+ glActiveTexture(GL_TEXTURE0);
209+ glBindTexture(GL_TEXTURE_2D, 0);
210+
211+ glPopMatrix();
212+ }
213+
214+ Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
215+
216+ DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release();
217+
218+ glDisable(GL_ALPHA_TEST);
219+ glEnable(GL_BLEND);
220+
221+ if (!_heightfieldSplatBatches.isEmpty()) {
222+ glDepthFunc(GL_LEQUAL);
223+ glDepthMask(false);
224+ glEnable(GL_POLYGON_OFFSET_FILL);
225+ glPolygonOffset(-1.0f, -1.0f);
226+
227+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind();
228+ const DefaultMetavoxelRendererImplementation::SplatLocations& locations =
229+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations();
230+
231+ foreach (const HeightfieldSplatBatch& batch, _heightfieldSplatBatches) {
232+ glPushMatrix();
233+ glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z);
234+ glm::vec3 axis = glm::axis(batch.rotation);
235+ glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z);
236+ glScalef(batch.scale.x, batch.scale.y, batch.scale.z);
237+
238+ batch.vertexBuffer->bind();
239+ batch.indexBuffer->bind();
240+
241+ HeightfieldPoint* point = 0;
242+ glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);
243+ glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);
244+
245+ glBindTexture(GL_TEXTURE_2D, batch.heightTextureID);
246+
247+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
248+ locations.heightScale, batch.heightScale.x, batch.heightScale.y);
249+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(
250+ locations.textureScale, batch.textureScale);
251+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(locations.splatTextureOffset,
252+ batch.splatTextureOffset);
253+
254+ const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
255+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(
256+ locations.splatTextureScalesS, batch.splatTextureScalesS);
257+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(
258+ locations.splatTextureScalesT, batch.splatTextureScalesT);
259+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
260+ locations.textureValueMinima,
261+ (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
262+ (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
263+ (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
264+ (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);
265+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
266+ locations.textureValueMaxima,
267+ (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
268+ (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
269+ (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
270+ (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);
271+
272+ glActiveTexture(GL_TEXTURE1);
273+ glBindTexture(GL_TEXTURE_2D, batch.materialTextureID);
274+
275+ for (int i = 0; i < SPLAT_COUNT; i++) {
276+ glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
277+ glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]);
278+ }
279+
280+ glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);
281+
282+ for (int i = 0; i < SPLAT_COUNT; i++) {
283+ glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
284+ glBindTexture(GL_TEXTURE_2D, 0);
285+ }
286+
287+ glActiveTexture(GL_TEXTURE1);
288+ glBindTexture(GL_TEXTURE_2D, 0);
289+
290+ glActiveTexture(GL_TEXTURE0);
291+ glBindTexture(GL_TEXTURE_2D, 0);
292+
293+ glPopMatrix();
294+ }
295+
296+ DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().release();
297+
298+ glDisable(GL_POLYGON_OFFSET_FILL);
299+ glDepthMask(true);
300+ glDepthFunc(GL_LESS);
301+
302+ _heightfieldSplatBatches.clear();
303+ }
304+
305+ glDisable(GL_CULL_FACE);
306+
307+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
308+ glDisableClientState(GL_VERTEX_ARRAY);
309+
310+ _heightfieldBaseBatches.clear();
311+ }
312+
153313 // give external parties a chance to join in
154314 emit rendering();
155315 }
@@ -670,12 +830,6 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { · 514 unmodified lines
670830 BufferData::~BufferData() {
671831 }
672832
673−const int SPLAT_COUNT = 4;
674−const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 };
675−
676−static const int EIGHT_BIT_MAXIMUM = 255;
677−static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM;
678−
679833 void VoxelPoint::setNormal(const glm::vec3& normal) {
680834 this->normal[0] = (char)(normal.x * 127.0f);
681835 this->normal[1] = (char)(normal.y * 127.0f);
@@ -1937,12 +2091,6 @@ void HeightfieldRenderer::init(Spanner* spanner) { · 1255 unmodified lines
19372091 connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial);
19382092 }
19392093
1940−class HeightfieldPoint {
1941−public:
1942− glm::vec3 vertex;
1943− glm::vec2 textureCoord;
1944−};
1945−
19462094 void HeightfieldRenderer::render(bool cursor) {
19472095 // create the buffer objects lazily
19482096 Heightfield* heightfield = static_cast<Heightfield*>(_spanner);
@@ -1984,6 +2132,7 @@ void HeightfieldRenderer::render(bool cursor) { · 35 unmodified lines
19842132 bufferPair.first.create();
19852133 bufferPair.first.bind();
19862134 bufferPair.first.allocate(vertices.constData(), vertexCount * sizeof(HeightfieldPoint));
2135+ bufferPair.first.release();
19872136
19882137 QVector<int> indices(indexCount);
19892138 int* index = indices.data();
@@ -2005,150 +2154,91 @@ void HeightfieldRenderer::render(bool cursor) { · 15 unmodified lines
20052154 bufferPair.second.create();
20062155 bufferPair.second.bind();
20072156 bufferPair.second.allocate(indices.constData(), indexCount * sizeof(int));
2008−
2009− } else {
2010− bufferPair.first.bind();
2011− bufferPair.second.bind();
2157+ bufferPair.second.release();
20122158 }
2013− glPushMatrix();
2014− glTranslatef(heightfield->getTranslation().x, heightfield->getTranslation().y, heightfield->getTranslation().z);
2015− glm::vec3 axis = glm::axis(heightfield->getRotation());
2016− glRotatef(glm::degrees(glm::angle(heightfield->getRotation())), axis.x, axis.y, axis.z);
2017− float xScale = heightfield->getScale(), zScale = xScale * heightfield->getAspectZ();
2018− glScalef(xScale, xScale * heightfield->getAspectY(), zScale);
2019−
2020− HeightfieldPoint* point = 0;
2021− glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);
2022− glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);
2023−
2024− glBindTexture(GL_TEXTURE_2D, _heightTextureID);
20252159
2160+ float xScale = heightfield->getScale(), zScale = xScale * heightfield->getAspectZ();
20262161 if (cursor) {
2027− glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
2028−
2029− } else {
2030− glEnableClientState(GL_VERTEX_ARRAY);
2031− glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2032−
2033− Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
2162+ bufferPair.first.bind();
2163+ bufferPair.second.bind();
20342164
2035− glDisable(GL_BLEND);
2036− glEnable(GL_CULL_FACE);
2037− glEnable(GL_ALPHA_TEST);
2038− glAlphaFunc(GL_EQUAL, 0.0f);
2165+ glPushMatrix();
2166+ glTranslatef(heightfield->getTranslation().x, heightfield->getTranslation().y, heightfield->getTranslation().z);
2167+ glm::vec3 axis = glm::axis(heightfield->getRotation());
2168+ glRotatef(glm::degrees(glm::angle(heightfield->getRotation())), axis.x, axis.y, axis.z);
2169+ glScalef(xScale, xScale * heightfield->getAspectY(), zScale);
20392170
2040− glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
2171+ HeightfieldPoint* point = 0;
2172+ glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);
2173+ glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);
20412174
2042− DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
2043− DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
2044− DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / width, 1.0f / height,
2045− (innerWidth - 1) / -2.0f, (innerHeight - 1) / -2.0f);
2046− DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
2047− DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)width / innerWidth,
2048− (float)height / innerHeight);
2049−
2050− glActiveTexture(GL_TEXTURE1);
2051− glBindTexture(GL_TEXTURE_2D, _colorTextureID);
2175+ glBindTexture(GL_TEXTURE_2D, _heightTextureID);
20522176
20532177 glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
20542178
20552179 glBindTexture(GL_TEXTURE_2D, 0);
2056−
2057− Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
2058−
2059− DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release();
20602180
2061− glDisable(GL_ALPHA_TEST);
2062− glEnable(GL_BLEND);
2181+ glPopMatrix();
20632182
2064− if (heightfield->getMaterial() && !_networkTextures.isEmpty()) {
2065− glDepthFunc(GL_LEQUAL);
2066− glDepthMask(false);
2067− glEnable(GL_POLYGON_OFFSET_FILL);
2068− glPolygonOffset(-1.0f, -1.0f);
2069−
2070− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind();
2071− const DefaultMetavoxelRendererImplementation::SplatLocations& locations =
2072− DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations();
2073− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
2074− locations.heightScale, 1.0f / width, 1.0f / height);
2075− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
2076− locations.textureScale, (float)width / innerWidth, (float)height / innerHeight);
2077− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(locations.splatTextureOffset,
2078− glm::dot(heightfield->getTranslation(), heightfield->getRotation() * glm::vec3(1.0f, 0.0f, 0.0f)) / xScale,
2079− glm::dot(heightfield->getTranslation(), heightfield->getRotation() * glm::vec3(0.0f, 0.0f, 1.0f)) / zScale);
2080−
2081− glBindTexture(GL_TEXTURE_2D, _materialTextureID);
2183+ bufferPair.first.release();
2184+ bufferPair.second.release();
2185+ return;
2186+ }
2187+
2188+ HeightfieldBaseBatch baseBatch;
2189+ baseBatch.vertexBuffer = &bufferPair.first;
2190+ baseBatch.indexBuffer = &bufferPair.second;
2191+ baseBatch.translation = heightfield->getTranslation();
2192+ baseBatch.rotation = heightfield->getRotation();
2193+ baseBatch.scale = glm::vec3(xScale, xScale * heightfield->getAspectY(), zScale);
2194+ baseBatch.vertexCount = vertexCount;
2195+ baseBatch.indexCount = indexCount;
2196+ baseBatch.heightTextureID = _heightTextureID;
2197+ baseBatch.heightScale = glm::vec4(1.0f / width, 1.0f / height, (innerWidth - 1) / -2.0f, (innerHeight - 1) / -2.0f);
2198+ baseBatch.colorTextureID = _colorTextureID;
2199+ baseBatch.colorScale = glm::vec2((float)width / innerWidth, (float)height / innerHeight);
2200+ Application::getInstance()->getMetavoxels()->addHeightfieldBaseBatch(baseBatch);
2201+
2202+ if (heightfield->getMaterial() && !_networkTextures.isEmpty()) {
2203+ HeightfieldSplatBatch splatBatch;
2204+ splatBatch.vertexBuffer = &bufferPair.first;
2205+ splatBatch.indexBuffer = &bufferPair.second;
2206+ splatBatch.translation = heightfield->getTranslation();
2207+ splatBatch.rotation = heightfield->getRotation();
2208+ splatBatch.scale = glm::vec3(xScale, xScale * heightfield->getAspectY(), zScale);
2209+ splatBatch.vertexCount = vertexCount;
2210+ splatBatch.indexCount = indexCount;
2211+ splatBatch.heightTextureID = _heightTextureID;
2212+ splatBatch.heightScale = glm::vec4(1.0f / width, 1.0f / height, 0.0f, 0.0f);
2213+ splatBatch.materialTextureID = _materialTextureID;
2214+ splatBatch.textureScale = glm::vec2((float)width / innerWidth, (float)height / innerHeight);
2215+ splatBatch.splatTextureOffset = glm::vec2(
2216+ glm::dot(heightfield->getTranslation(), heightfield->getRotation() * glm::vec3(1.0f, 0.0f, 0.0f)) / xScale,
2217+ glm::dot(heightfield->getTranslation(), heightfield->getRotation() * glm::vec3(0.0f, 0.0f, 1.0f)) / zScale);
20822218
2083− const QVector<SharedObjectPointer>& materials = heightfield->getMaterial()->getMaterials();
2084− for (int i = 0; i < materials.size(); i += SPLAT_COUNT) {
2085− QVector4D scalesS, scalesT;
2086−
2087− for (int j = 0; j < SPLAT_COUNT; j++) {
2088− glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]);
2089− int index = i + j;
2090− if (index < _networkTextures.size()) {
2091− const NetworkTexturePointer& texture = _networkTextures.at(index);
2092− if (texture) {
2093− MaterialObject* material = static_cast<MaterialObject*>(materials.at(index).data());
2094− scalesS[j] = xScale / material->getScaleS();
2095− scalesT[j] = zScale / material->getScaleT();
2096− glBindTexture(GL_TEXTURE_2D, texture->getID());
2097− } else {
2098− glBindTexture(GL_TEXTURE_2D, 0);
2099− }
2219+ const QVector<SharedObjectPointer>& materials = heightfield->getMaterial()->getMaterials();
2220+ for (int i = 0; i < materials.size(); i += SPLAT_COUNT) {
2221+ for (int j = 0; j < SPLAT_COUNT; j++) {
2222+ int index = i + j;
2223+ if (index < _networkTextures.size()) {
2224+ const NetworkTexturePointer& texture = _networkTextures.at(index);
2225+ if (texture) {
2226+ MaterialObject* material = static_cast<MaterialObject*>(materials.at(index).data());
2227+ splatBatch.splatTextureScalesS[j] = xScale / material->getScaleS();
2228+ splatBatch.splatTextureScalesT[j] = zScale / material->getScaleT();
2229+ splatBatch.splatTextureIDs[j] = texture->getID();
2230+
21002231 } else {
2101− glBindTexture(GL_TEXTURE_2D, 0);
2232+ splatBatch.splatTextureIDs[j] = 0;
21022233 }
2234+ } else {
2235+ splatBatch.splatTextureIDs[j] = 0;
21032236 }
2104− const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
2105− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
2106− locations.splatTextureScalesS, scalesS);
2107− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
2108− locations.splatTextureScalesT, scalesT);
2109− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
2110− locations.textureValueMinima,
2111− (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
2112− (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
2113− (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
2114− (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);
2115− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
2116− locations.textureValueMaxima,
2117− (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
2118− (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
2119− (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
2120− (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);
2121− glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
21222237 }
2123−
2124− for (int i = 0; i < SPLAT_COUNT; i++) {
2125− glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
2126− glBindTexture(GL_TEXTURE_2D, 0);
2127− }
2128−
2129− glActiveTexture(GL_TEXTURE1);
2130− glBindTexture(GL_TEXTURE_2D, 0);
2131−
2132− DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().release();
2133−
2134− glDisable(GL_POLYGON_OFFSET_FILL);
2135− glDepthMask(true);
2136− glDepthFunc(GL_LESS);
2238+ splatBatch.materialIndex = i;
2239+ Application::getInstance()->getMetavoxels()->addHeightfieldSplatBatch(splatBatch);
21372240 }
2138− glActiveTexture(GL_TEXTURE0);
2139−
2140− glDisable(GL_CULL_FACE);
2141−
2142− glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2143− glDisableClientState(GL_VERTEX_ARRAY);
21442241 }
2145−
2146− glBindTexture(GL_TEXTURE_2D, 0);
2147−
2148− glPopMatrix();
2149−
2150− bufferPair.first.release();
2151− bufferPair.second.release();
21522242 }
21532243
21542244 void HeightfieldRenderer::applyHeight(const HeightfieldHeightPointer& height) {