Batch voxel drawing, too.

This commit is contained in:
Andrzej Kapolka 2014-11-20 16:37:37 -08:00
parent da85714dc8
commit 1e294e043b
2 changed files with 309 additions and 280 deletions

View file

@ -56,12 +56,50 @@ MetavoxelSystem::~MetavoxelSystem() {
void MetavoxelSystem::init() {
MetavoxelClientManager::init();
DefaultMetavoxelRendererImplementation::init();
_voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(
new BufferDataAttribute("voxelBuffer"));
_voxelBufferAttribute->setLODThresholdMultiplier(
AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier());
_baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield_base.vert");
_baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_heightfield_base.frag");
_baseHeightfieldProgram.link();
_baseHeightfieldProgram.bind();
_baseHeightfieldProgram.setUniformValue("heightMap", 0);
_baseHeightfieldProgram.setUniformValue("diffuseMap", 1);
_baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale");
_baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale");
_baseHeightfieldProgram.release();
loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations);
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield_cursor.vert");
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_cursor.frag");
_heightfieldCursorProgram.link();
_heightfieldCursorProgram.bind();
_heightfieldCursorProgram.setUniformValue("heightMap", 0);
_heightfieldCursorProgram.release();
_baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_voxel_base.vert");
_baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_voxel_base.frag");
_baseVoxelProgram.link();
loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations);
_voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_voxel_cursor.vert");
_voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_cursor.frag");
_voxelCursorProgram.link();
}
MetavoxelLOD MetavoxelSystem::getLOD() {
@ -175,7 +213,7 @@ void MetavoxelSystem::render() {
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
_baseHeightfieldProgram.bind();
foreach (const HeightfieldBaseBatch& batch, _heightfieldBaseBatches) {
glPushMatrix();
@ -193,10 +231,8 @@ void MetavoxelSystem::render() {
glBindTexture(GL_TEXTURE_2D, batch.heightTextureID);
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniform(
DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), batch.heightScale);
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniform(
DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), batch.colorScale);
_baseHeightfieldProgram.setUniform(_baseHeightScaleLocation, batch.heightScale);
_baseHeightfieldProgram.setUniform(_baseColorScaleLocation, batch.colorScale);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, batch.colorTextureID);
@ -208,12 +244,15 @@ void MetavoxelSystem::render() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
batch.vertexBuffer->release();
batch.indexBuffer->release();
glPopMatrix();
}
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release();
_baseHeightfieldProgram.release();
glDisable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
@ -224,10 +263,8 @@ void MetavoxelSystem::render() {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind();
const DefaultMetavoxelRendererImplementation::SplatLocations& locations =
DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations();
_splatHeightfieldProgram.bind();
foreach (const HeightfieldSplatBatch& batch, _heightfieldSplatBatches) {
glPushMatrix();
glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z);
@ -244,26 +281,22 @@ void MetavoxelSystem::render() {
glBindTexture(GL_TEXTURE_2D, batch.heightTextureID);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
locations.heightScale, batch.heightScale.x, batch.heightScale.y);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(
locations.textureScale, batch.textureScale);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(locations.splatTextureOffset,
batch.splatTextureOffset);
_splatHeightfieldProgram.setUniformValue(_splatHeightfieldLocations.heightScale,
batch.heightScale.x, batch.heightScale.y);
_splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.textureScale, batch.textureScale);
_splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureOffset, batch.splatTextureOffset);
const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(
locations.splatTextureScalesS, batch.splatTextureScalesS);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(
locations.splatTextureScalesT, batch.splatTextureScalesT);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
locations.textureValueMinima,
_splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesS, batch.splatTextureScalesS);
_splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesT, batch.splatTextureScalesT);
_splatHeightfieldProgram.setUniformValue(
_splatHeightfieldLocations.textureValueMinima,
(batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
(batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
(batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
(batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
locations.textureValueMaxima,
_splatHeightfieldProgram.setUniformValue(
_splatHeightfieldLocations.textureValueMaxima,
(batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
(batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
(batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
@ -290,10 +323,13 @@ void MetavoxelSystem::render() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
batch.vertexBuffer->release();
batch.indexBuffer->release();
glPopMatrix();
}
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().release();
_splatHeightfieldProgram.release();
glDisable(GL_POLYGON_OFFSET_FILL);
glDepthMask(true);
@ -310,6 +346,121 @@ void MetavoxelSystem::render() {
_heightfieldBaseBatches.clear();
}
if (!_voxelBaseBatches.isEmpty()) {
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
glEnableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_EQUAL, 0.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
_baseVoxelProgram.bind();
foreach (const VoxelBaseBatch& batch, _voxelBaseBatches) {
batch.vertexBuffer->bind();
batch.indexBuffer->bind();
VoxelPoint* point = 0;
glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex);
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color);
glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal);
glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);
batch.vertexBuffer->release();
batch.indexBuffer->release();
}
_baseVoxelProgram.release();
glDisable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
if (!_voxelSplatBatches.isEmpty()) {
glDepthFunc(GL_LEQUAL);
glDepthMask(false);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
_splatVoxelProgram.bind();
_splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materials);
_splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materialWeights);
foreach (const VoxelSplatBatch& batch, _voxelSplatBatches) {
batch.vertexBuffer->bind();
batch.indexBuffer->bind();
VoxelPoint* point = 0;
glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex);
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color);
glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal);
_splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materials,
GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint));
_splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materialWeights,
GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint));
const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
_splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesS, batch.splatTextureScalesS);
_splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesT, batch.splatTextureScalesT);
_splatVoxelProgram.setUniformValue(
_splatVoxelLocations.textureValueMinima,
(batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
(batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
(batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
(batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);
_splatVoxelProgram.setUniformValue(
_splatVoxelLocations.textureValueMaxima,
(batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
(batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
(batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
(batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);
for (int i = 0; i < SPLAT_COUNT; i++) {
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]);
}
glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);
for (int i = 0; i < SPLAT_COUNT; i++) {
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
glBindTexture(GL_TEXTURE_2D, 0);
}
glActiveTexture(GL_TEXTURE0);
batch.vertexBuffer->release();
batch.indexBuffer->release();
}
glDisable(GL_POLYGON_OFFSET_FILL);
glDepthMask(true);
glDepthFunc(GL_LESS);
_splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materials);
_splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materialWeights);
_voxelSplatBatches.clear();
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisable(GL_CULL_FACE);
_voxelBaseBatches.clear();
}
// give external parties a chance to join in
emit rendering();
}
@ -440,7 +591,7 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().bind();
_heightfieldCursorProgram.bind();
glActiveTexture(GL_TEXTURE4);
float scale = 1.0f / radius;
@ -456,7 +607,7 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r
SpannerCursorRenderVisitor visitor(Box(position - extents, position + extents));
guide(visitor);
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release();
_heightfieldCursorProgram.release();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
@ -504,7 +655,7 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius)
glEnableClientState(GL_VERTEX_ARRAY);
DefaultMetavoxelRendererImplementation::getVoxelCursorProgram().bind();
_voxelCursorProgram.bind();
glActiveTexture(GL_TEXTURE4);
float scale = 1.0f / radius;
@ -521,16 +672,16 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius)
BufferCursorRenderVisitor voxelVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), bounds);
guideToAugmented(voxelVisitor);
DefaultMetavoxelRendererImplementation::getVoxelCursorProgram().release();
_voxelCursorProgram.release();
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().bind();
_heightfieldCursorProgram.bind();
SpannerCursorRenderVisitor spannerVisitor(bounds);
guide(spannerVisitor);
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release();
_heightfieldCursorProgram.release();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@ -612,6 +763,29 @@ void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) {
}
}
void MetavoxelSystem::loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations) {
program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_" + type + "_splat.vert");
program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_" + type + "_splat.frag");
program.link();
program.bind();
program.setUniformValue("heightMap", 0);
program.setUniformValue("textureMap", 1);
program.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT);
locations.heightScale = program.uniformLocation("heightScale");
locations.textureScale = program.uniformLocation("textureScale");
locations.splatTextureOffset = program.uniformLocation("splatTextureOffset");
locations.splatTextureScalesS = program.uniformLocation("splatTextureScalesS");
locations.splatTextureScalesT = program.uniformLocation("splatTextureScalesT");
locations.textureValueMinima = program.uniformLocation("textureValueMinima");
locations.textureValueMaxima = program.uniformLocation("textureValueMaxima");
locations.materials = program.attributeLocation("materials");
locations.materialWeights = program.attributeLocation("materialWeights");
program.release();
}
Throttle::Throttle() :
_limit(INT_MAX),
_total(0) {
@ -946,10 +1120,12 @@ void VoxelBuffer::render(bool cursor) {
_vertexBuffer.create();
_vertexBuffer.bind();
_vertexBuffer.allocate(_vertices.constData(), _vertices.size() * sizeof(VoxelPoint));
_vertexBuffer.release();
_indexBuffer.create();
_indexBuffer.bind();
_indexBuffer.allocate(_indices.constData(), _indices.size() * sizeof(int));
_indexBuffer.release();
if (!_materials.isEmpty()) {
_networkTextures.resize(_materials.size());
@ -961,101 +1137,62 @@ void VoxelBuffer::render(bool cursor) {
}
}
}
} else {
_vertexBuffer.bind();
_indexBuffer.bind();
}
VoxelPoint* point = 0;
glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex);
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color);
glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal);
if (cursor) {
_vertexBuffer.bind();
_indexBuffer.bind();
VoxelPoint* point = 0;
glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex);
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color);
glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal);
glDrawRangeElements(GL_QUADS, 0, _vertexCount - 1, _indexCount, GL_UNSIGNED_INT, 0);
_vertexBuffer.release();
_indexBuffer.release();
return;
}
glDrawRangeElements(GL_QUADS, 0, _vertexCount - 1, _indexCount, GL_UNSIGNED_INT, 0);
VoxelBaseBatch baseBatch;
baseBatch.vertexBuffer = &_vertexBuffer;
baseBatch.indexBuffer = &_indexBuffer;
baseBatch.vertexCount = _vertexCount;
baseBatch.indexCount = _indexCount;
Application::getInstance()->getMetavoxels()->addVoxelBaseBatch(baseBatch);
if (!_materials.isEmpty()) {
VoxelSplatBatch splatBatch;
splatBatch.vertexBuffer = &_vertexBuffer;
splatBatch.indexBuffer = &_indexBuffer;
splatBatch.vertexCount = _vertexCount;
splatBatch.indexCount = _indexCount;
if (!(_materials.isEmpty() || cursor)) {
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
glDepthFunc(GL_LEQUAL);
glDepthMask(false);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().bind();
const DefaultMetavoxelRendererImplementation::SplatLocations& locations =
DefaultMetavoxelRendererImplementation::getSplatVoxelLocations();
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setAttributeBuffer(locations.materials,
GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint));
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().enableAttributeArray(locations.materials);
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setAttributeBuffer(locations.materialWeights,
GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint));
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().enableAttributeArray(locations.materialWeights);
for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) {
QVector4D scalesS, scalesT;
for (int j = 0; j < SPLAT_COUNT; j++) {
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]);
int index = i + j;
if (index < _networkTextures.size()) {
const NetworkTexturePointer& texture = _networkTextures.at(index);
if (texture) {
MaterialObject* material = static_cast<MaterialObject*>(_materials.at(index).data());
scalesS[j] = 1.0f / material->getScaleS();
scalesT[j] = 1.0f / material->getScaleT();
glBindTexture(GL_TEXTURE_2D, texture->getID());
splatBatch.splatTextureScalesS[j] = 1.0f / material->getScaleS();
splatBatch.splatTextureScalesT[j] = 1.0f / material->getScaleT();
splatBatch.splatTextureIDs[j] = texture->getID();
} else {
glBindTexture(GL_TEXTURE_2D, 0);
splatBatch.splatTextureIDs[j] = 0;
}
} else {
glBindTexture(GL_TEXTURE_2D, 0);
splatBatch.splatTextureIDs[j] = 0;
}
}
const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue(
locations.splatTextureScalesS, scalesS);
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue(
locations.splatTextureScalesT, scalesT);
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue(
locations.textureValueMinima,
(i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
(i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().setUniformValue(
locations.textureValueMaxima,
(i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
(i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);
glDrawRangeElements(GL_QUADS, 0, _vertexCount - 1, _indexCount, GL_UNSIGNED_INT, 0);
splatBatch.materialIndex = i;
Application::getInstance()->getMetavoxels()->addVoxelSplatBatch(splatBatch);
}
for (int i = 0; i < SPLAT_COUNT; i++) {
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
glBindTexture(GL_TEXTURE_2D, 0);
}
glActiveTexture(GL_TEXTURE0);
glDisable(GL_POLYGON_OFFSET_FILL);
glEnable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDepthMask(true);
glDepthFunc(GL_LESS);
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materials);
DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materialWeights);
DefaultMetavoxelRendererImplementation::getBaseVoxelProgram().bind();
}
_vertexBuffer.release();
_indexBuffer.release();
if (_hermiteCount > 0 && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData) && !cursor) {
if (_hermiteCount > 0 && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) {
if (!_hermiteBuffer.isCreated()) {
_hermiteBuffer.create();
_hermiteBuffer.bind();
@ -1066,9 +1203,6 @@ void VoxelBuffer::render(bool cursor) {
_hermiteBuffer.bind();
}
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
Application::getInstance()->getDeferredLightingEffect()->getSimpleProgram().bind();
@ -1080,10 +1214,7 @@ void VoxelBuffer::render(bool cursor) {
glDrawArrays(GL_LINES, 0, _hermiteCount);
DefaultMetavoxelRendererImplementation::getBaseVoxelProgram().bind();
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
Application::getInstance()->getDeferredLightingEffect()->getSimpleProgram().release();
_hermiteBuffer.release();
}
@ -1107,49 +1238,6 @@ AttributeValue BufferDataAttribute::inherit(const AttributeValue& parentValue) c
return AttributeValue(parentValue.getAttribute());
}
void DefaultMetavoxelRendererImplementation::init() {
if (!_baseHeightfieldProgram.isLinked()) {
_baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield_base.vert");
_baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_heightfield_base.frag");
_baseHeightfieldProgram.link();
_baseHeightfieldProgram.bind();
_baseHeightfieldProgram.setUniformValue("heightMap", 0);
_baseHeightfieldProgram.setUniformValue("diffuseMap", 1);
_baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale");
_baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale");
_baseHeightfieldProgram.release();
loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations);
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_heightfield_cursor.vert");
_heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_cursor.frag");
_heightfieldCursorProgram.link();
_heightfieldCursorProgram.bind();
_heightfieldCursorProgram.setUniformValue("heightMap", 0);
_heightfieldCursorProgram.release();
_baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_voxel_base.vert");
_baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_voxel_base.frag");
_baseVoxelProgram.link();
loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations);
_voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_voxel_cursor.vert");
_voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_cursor.frag");
_voxelCursorProgram.link();
}
}
DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {
}
@ -1872,76 +1960,12 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
SpannerRenderVisitor spannerRenderVisitor(lod);
data.guide(spannerRenderVisitor);
}
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
glEnableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_EQUAL, 0.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) {
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
_baseVoxelProgram.bind();
BufferRenderVisitor voxelRenderVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute());
data.guide(voxelRenderVisitor);
_baseVoxelProgram.release();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glDisableClientState(GL_VERTEX_ARRAY);
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
}
void DefaultMetavoxelRendererImplementation::loadSplatProgram(const char* type,
ProgramObject& program, SplatLocations& locations) {
program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +
"shaders/metavoxel_" + type + "_splat.vert");
program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
"shaders/metavoxel_" + type + "_splat.frag");
program.link();
program.bind();
program.setUniformValue("heightMap", 0);
program.setUniformValue("textureMap", 1);
program.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT);
locations.heightScale = program.uniformLocation("heightScale");
locations.textureScale = program.uniformLocation("textureScale");
locations.splatTextureOffset = program.uniformLocation("splatTextureOffset");
locations.splatTextureScalesS = program.uniformLocation("splatTextureScalesS");
locations.splatTextureScalesT = program.uniformLocation("splatTextureScalesT");
locations.textureValueMinima = program.uniformLocation("textureValueMinima");
locations.textureValueMaxima = program.uniformLocation("textureValueMaxima");
locations.materials = program.attributeLocation("materials");
locations.materialWeights = program.attributeLocation("materialWeights");
program.release();
}
ProgramObject DefaultMetavoxelRendererImplementation::_baseHeightfieldProgram;
int DefaultMetavoxelRendererImplementation::_baseHeightScaleLocation;
int DefaultMetavoxelRendererImplementation::_baseColorScaleLocation;
ProgramObject DefaultMetavoxelRendererImplementation::_splatHeightfieldProgram;
DefaultMetavoxelRendererImplementation::SplatLocations DefaultMetavoxelRendererImplementation::_splatHeightfieldLocations;
ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram;
ProgramObject DefaultMetavoxelRendererImplementation::_baseVoxelProgram;
ProgramObject DefaultMetavoxelRendererImplementation::_splatVoxelProgram;
DefaultMetavoxelRendererImplementation::SplatLocations DefaultMetavoxelRendererImplementation::_splatVoxelLocations;
ProgramObject DefaultMetavoxelRendererImplementation::_voxelCursorProgram;
SphereRenderer::SphereRenderer() {
}

View file

@ -26,6 +26,8 @@
class HeightfieldBaseBatch;
class HeightfieldSplatBatch;
class Model;
class VoxelBaseBatch;
class VoxelSplatBatch;
/// Renders a metavoxel tree.
class MetavoxelSystem : public MetavoxelClientManager {
@ -83,6 +85,9 @@ public:
void addHeightfieldBaseBatch(const HeightfieldBaseBatch& batch) { _heightfieldBaseBatches.append(batch); }
void addHeightfieldSplatBatch(const HeightfieldSplatBatch& batch) { _heightfieldSplatBatches.append(batch); }
void addVoxelBaseBatch(const VoxelBaseBatch& batch) { _voxelBaseBatches.append(batch); }
void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); }
signals:
void rendering();
@ -113,6 +118,46 @@ private:
QVector<HeightfieldBaseBatch> _heightfieldBaseBatches;
QVector<HeightfieldSplatBatch> _heightfieldSplatBatches;
QVector<VoxelBaseBatch> _voxelBaseBatches;
QVector<VoxelSplatBatch> _voxelSplatBatches;
ProgramObject _baseHeightfieldProgram;
int _baseHeightScaleLocation;
int _baseColorScaleLocation;
class SplatLocations {
public:
int heightScale;
int textureScale;
int splatTextureOffset;
int splatTextureScalesS;
int splatTextureScalesT;
int textureValueMinima;
int textureValueMaxima;
int materials;
int materialWeights;
};
ProgramObject _splatHeightfieldProgram;
SplatLocations _splatHeightfieldLocations;
int _splatHeightScaleLocation;
int _splatTextureScaleLocation;
int _splatTextureOffsetLocation;
int _splatTextureScalesSLocation;
int _splatTextureScalesTLocation;
int _splatTextureValueMinimaLocation;
int _splatTextureValueMaximaLocation;
ProgramObject _heightfieldCursorProgram;
ProgramObject _baseVoxelProgram;
ProgramObject _splatVoxelProgram;
SplatLocations _splatVoxelLocations;
ProgramObject _voxelCursorProgram;
static void loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations);
};
/// Base class for heightfield batches.
@ -157,6 +202,24 @@ public:
int materialIndex;
};
/// Base class for voxel batches.
class VoxelBaseBatch {
public:
QOpenGLBuffer* vertexBuffer;
QOpenGLBuffer* indexBuffer;
int vertexCount;
int indexCount;
};
/// A batch containing a voxel splat.
class VoxelSplatBatch : public VoxelBaseBatch {
public:
int splatTextureIDs[4];
glm::vec4 splatTextureScalesS;
glm::vec4 splatTextureScalesT;
int materialIndex;
};
/// Generic abstract base class for objects that handle a signal.
class SignalHandler : public QObject {
Q_OBJECT
@ -296,69 +359,11 @@ class DefaultMetavoxelRendererImplementation : public MetavoxelRendererImplement
public:
static void init();
static ProgramObject& getBaseHeightfieldProgram() { return _baseHeightfieldProgram; }
static int getBaseHeightScaleLocation() { return _baseHeightScaleLocation; }
static int getBaseColorScaleLocation() { return _baseColorScaleLocation; }
class SplatLocations {
public:
int heightScale;
int textureScale;
int splatTextureOffset;
int splatTextureScalesS;
int splatTextureScalesT;
int textureValueMinima;
int textureValueMaxima;
int materials;
int materialWeights;
};
static ProgramObject& getSplatHeightfieldProgram() { return _splatHeightfieldProgram; }
static const SplatLocations& getSplatHeightfieldLocations() { return _splatHeightfieldLocations; }
static ProgramObject& getHeightfieldCursorProgram() { return _heightfieldCursorProgram; }
static ProgramObject& getBaseVoxelProgram() { return _baseVoxelProgram; }
static ProgramObject& getSplatVoxelProgram() { return _splatVoxelProgram; }
static const SplatLocations& getSplatVoxelLocations() { return _splatVoxelLocations; }
static ProgramObject& getVoxelCursorProgram() { return _voxelCursorProgram; }
Q_INVOKABLE DefaultMetavoxelRendererImplementation();
virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod);
virtual void simulate(MetavoxelData& data, float deltaTime, MetavoxelInfo& info, const MetavoxelLOD& lod);
virtual void render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod);
private:
static void loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations);
static ProgramObject _baseHeightfieldProgram;
static int _baseHeightScaleLocation;
static int _baseColorScaleLocation;
static ProgramObject _splatHeightfieldProgram;
static SplatLocations _splatHeightfieldLocations;
static int _splatHeightScaleLocation;
static int _splatTextureScaleLocation;
static int _splatTextureOffsetLocation;
static int _splatTextureScalesSLocation;
static int _splatTextureScalesTLocation;
static int _splatTextureValueMinimaLocation;
static int _splatTextureValueMaximaLocation;
static ProgramObject _heightfieldCursorProgram;
static ProgramObject _baseVoxelProgram;
static ProgramObject _splatVoxelProgram;
static SplatLocations _splatVoxelLocations;
static ProgramObject _voxelCursorProgram;
};
/// Renders spheres.