WIP on impostor instancing
This commit is contained in:
parent
1a59c44d0c
commit
a7b3068e9f
7 changed files with 98 additions and 6 deletions
|
@ -29,9 +29,9 @@ void VegetationDefinition::applyPreset(VegetationPreset preset, RandomGenerator
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
/*if (preset == VEGETATION_PRESET_TEMPERATE) {
|
if (preset == VEGETATION_PRESET_TEMPERATE) {
|
||||||
layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random);
|
layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random);
|
||||||
layer.setName("Basic tree");
|
layer.setName("Basic tree");
|
||||||
addLayer(layer);
|
addLayer(layer);
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,12 +59,41 @@ void OpenGLVegetationImpostor::render(OpenGLShaderProgram *program, const OpenGL
|
||||||
state->set("impostorTexture", texture);
|
state->set("impostorTexture", texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME Deprecated, use renderBatch always
|
||||||
|
vertices->clearIndexes();
|
||||||
|
|
||||||
int index = getIndex(camera_location, instance->getBase());
|
int index = getIndex(camera_location, instance->getBase());
|
||||||
state->set("offset", instance->getBase());
|
state->set("offset", instance->getBase());
|
||||||
state->set("size", 2.0 * instance->getSize());
|
state->set("size", 2.0 * instance->getSize());
|
||||||
program->draw(vertices, state, index * 4, 4);
|
program->draw(vertices, state, index * 4, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLVegetationImpostor::renderBatch(OpenGLShaderProgram *program,
|
||||||
|
const vector<OpenGLVegetationInstance *> &instances,
|
||||||
|
const Vector3 &camera_location) {
|
||||||
|
if (texture_changed) {
|
||||||
|
texture_changed = false;
|
||||||
|
state->set("impostorTexture", texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Cache buffers
|
||||||
|
vector<unsigned short> indexes(instances.size() * 5);
|
||||||
|
int i = 0;
|
||||||
|
for (auto &instance: instances) {
|
||||||
|
int index = getIndex(camera_location, instance->getBase());
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
indexes[i * 5 + j] = index * 4 + j;
|
||||||
|
}
|
||||||
|
indexes[i * 5 + 4] = OPENGL_RESTART_PRIMITIVE_INDEX;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
vertices->setIndexes(indexes);
|
||||||
|
|
||||||
|
state->set("offset", VECTOR_UP.scale(10.0));
|
||||||
|
state->set("size", 1.0);
|
||||||
|
program->draw(vertices, state);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &model, const Scenery &environment,
|
void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &model, const Scenery &environment,
|
||||||
bool *interrupt) {
|
bool *interrupt) {
|
||||||
Scenery scenery;
|
Scenery scenery;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "opengl_global.h"
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
|
|
||||||
|
@ -23,6 +25,12 @@ class OPENGLSHARED_EXPORT OpenGLVegetationImpostor {
|
||||||
*/
|
*/
|
||||||
void render(OpenGLShaderProgram *program, const OpenGLVegetationInstance *instance, const Vector3 &camera_location);
|
void render(OpenGLShaderProgram *program, const OpenGLVegetationInstance *instance, const Vector3 &camera_location);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a whole lot of instances using this impostor.
|
||||||
|
*/
|
||||||
|
void renderBatch(OpenGLShaderProgram *program, const vector<OpenGLVegetationInstance *> &instances,
|
||||||
|
const Vector3 &camera_location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the texture grid for a given model.
|
* Prepare the texture grid for a given model.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -115,9 +115,10 @@ void OpenGLVegetationLayer::render() {
|
||||||
lock_instances->acquire();
|
lock_instances->acquire();
|
||||||
|
|
||||||
// TODO Instanced rendering
|
// TODO Instanced rendering
|
||||||
for (auto instance : instances) {
|
/*for (auto instance : instances) {
|
||||||
impostor->render(parent->getProgram(), instance, *camera_location);
|
impostor->render(parent->getProgram(), instance, *camera_location);
|
||||||
}
|
}*/
|
||||||
|
impostor->renderBatch(parent->getProgram(), instances, *camera_location);
|
||||||
|
|
||||||
lock_instances->release();
|
lock_instances->release();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "OpenGLVertexArray.h"
|
#include "OpenGLVertexArray.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include "OpenGLFunctions.h"
|
#include "OpenGLFunctions.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "Vector3.h"
|
#include "Vector3.h"
|
||||||
|
@ -51,15 +52,32 @@ void OpenGLVertexArray::render(OpenGLFunctions *functions, int start, int count)
|
||||||
update(functions);
|
update(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(start >= 0);
|
||||||
|
int max_count = indexes.empty() ? vertexcount : indexes.size();
|
||||||
|
if (count < 0) {
|
||||||
|
count = max_count - start;
|
||||||
|
}
|
||||||
|
assert(start + count <= max_count);
|
||||||
|
|
||||||
if (vertexcount and vao) {
|
if (vertexcount and vao) {
|
||||||
functions->glBindVertexArray(vao);
|
functions->glBindVertexArray(vao);
|
||||||
functions->glDrawArrays(draw_mode, start, count < 0 ? vertexcount : count);
|
|
||||||
|
if (indexes.empty()) {
|
||||||
|
functions->glDrawArrays(draw_mode, start, count);
|
||||||
|
} else {
|
||||||
|
// TODO Break in sub-ranges if count is too big
|
||||||
|
functions->glPrimitiveRestartIndex(OPENGL_RESTART_PRIMITIVE_INDEX);
|
||||||
|
functions->glDrawRangeElements(draw_mode, 0, vertexcount, count, GL_UNSIGNED_SHORT, indexes.data() + start);
|
||||||
|
}
|
||||||
|
|
||||||
functions->glBindVertexArray(0);
|
functions->glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVertexArray::setVertexCount(int count) {
|
void OpenGLVertexArray::setVertexCount(int count) {
|
||||||
if (count != vertexcount) {
|
if (count >= OPENGL_RESTART_PRIMITIVE_INDEX) {
|
||||||
|
Logs::error("OpenGL") << "Can't set vertex count higher than " << OPENGL_RESTART_PRIMITIVE_INDEX << endl;
|
||||||
|
} else if (count != vertexcount) {
|
||||||
vertexcount = count;
|
vertexcount = count;
|
||||||
if (count < 1) {
|
if (count < 1) {
|
||||||
count = 1;
|
count = 1;
|
||||||
|
@ -101,9 +119,23 @@ void OpenGLVertexArray::copyTo(OpenGLVertexArray *destination) const {
|
||||||
memcpy(destination->array_vertex, array_vertex, sizeof(float) * vertexcount * 3);
|
memcpy(destination->array_vertex, array_vertex, sizeof(float) * vertexcount * 3);
|
||||||
memcpy(destination->array_uv, array_uv, sizeof(float) * vertexcount * 2);
|
memcpy(destination->array_uv, array_uv, sizeof(float) * vertexcount * 2);
|
||||||
}
|
}
|
||||||
|
destination->setIndexes(indexes);
|
||||||
destination->changed = true;
|
destination->changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLVertexArray::setIndexes(const vector<unsigned short> &indexes) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (auto index : indexes) {
|
||||||
|
assert(index < vertexcount or index == OPENGL_RESTART_PRIMITIVE_INDEX);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
this->indexes = indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVertexArray::clearIndexes() {
|
||||||
|
indexes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLVertexArray::update(OpenGLFunctions *functions) {
|
void OpenGLVertexArray::update(OpenGLFunctions *functions) {
|
||||||
if (not vao) {
|
if (not vao) {
|
||||||
functions->glGenVertexArrays(1, &vao);
|
functions->glGenVertexArrays(1, &vao);
|
||||||
|
|
|
@ -3,9 +3,13 @@
|
||||||
|
|
||||||
#include "opengl_global.h"
|
#include "opengl_global.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace paysages {
|
namespace paysages {
|
||||||
namespace opengl {
|
namespace opengl {
|
||||||
|
|
||||||
|
const unsigned short OPENGL_RESTART_PRIMITIVE_INDEX = 65535;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vertex arrays storage and binding, to render triangles.
|
* Vertex arrays storage and binding, to render triangles.
|
||||||
*
|
*
|
||||||
|
@ -62,6 +66,21 @@ class OpenGLVertexArray {
|
||||||
*/
|
*/
|
||||||
void copyTo(OpenGLVertexArray *destination) const;
|
void copyTo(OpenGLVertexArray *destination) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the indexes to define the draw order.
|
||||||
|
*
|
||||||
|
* Vertex count must have been properly set before calling this.
|
||||||
|
*
|
||||||
|
* When this is called, vertices are drawn by specified indexes order,
|
||||||
|
* instead of their sequential order, thus allowing vertex reuse.
|
||||||
|
*/
|
||||||
|
void setIndexes(const vector<unsigned short> &indexes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go back to sequential drawing, after calling setIndexes.
|
||||||
|
*/
|
||||||
|
void clearIndexes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Update the opengl state.
|
* Update the opengl state.
|
||||||
|
@ -87,6 +106,7 @@ class OpenGLVertexArray {
|
||||||
int vertexcount;
|
int vertexcount;
|
||||||
float *array_vertex;
|
float *array_vertex;
|
||||||
float *array_uv;
|
float *array_uv;
|
||||||
|
vector<unsigned short> indexes;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,6 @@ void main(void)
|
||||||
|
|
||||||
final_color = applyMouseTracking(unprojected, final_color);
|
final_color = applyMouseTracking(unprojected, final_color);
|
||||||
final_color.a = alpha;
|
final_color.a = alpha;
|
||||||
|
|
||||||
|
//final_color = vec4(0, 1, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue