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();
|
||||
|
||||
/*if (preset == VEGETATION_PRESET_TEMPERATE) {
|
||||
if (preset == VEGETATION_PRESET_TEMPERATE) {
|
||||
layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random);
|
||||
layer.setName("Basic tree");
|
||||
addLayer(layer);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,12 +59,41 @@ void OpenGLVegetationImpostor::render(OpenGLShaderProgram *program, const OpenGL
|
|||
state->set("impostorTexture", texture);
|
||||
}
|
||||
|
||||
// FIXME Deprecated, use renderBatch always
|
||||
vertices->clearIndexes();
|
||||
|
||||
int index = getIndex(camera_location, instance->getBase());
|
||||
state->set("offset", instance->getBase());
|
||||
state->set("size", 2.0 * instance->getSize());
|
||||
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,
|
||||
bool *interrupt) {
|
||||
Scenery scenery;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "opengl_global.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace paysages {
|
||||
namespace opengl {
|
||||
|
||||
|
@ -23,6 +25,12 @@ class OPENGLSHARED_EXPORT OpenGLVegetationImpostor {
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -115,9 +115,10 @@ void OpenGLVegetationLayer::render() {
|
|||
lock_instances->acquire();
|
||||
|
||||
// TODO Instanced rendering
|
||||
for (auto instance : instances) {
|
||||
/*for (auto instance : instances) {
|
||||
impostor->render(parent->getProgram(), instance, *camera_location);
|
||||
}
|
||||
}*/
|
||||
impostor->renderBatch(parent->getProgram(), instances, *camera_location);
|
||||
|
||||
lock_instances->release();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "OpenGLVertexArray.h"
|
||||
|
||||
#include <cassert>
|
||||
#include "OpenGLFunctions.h"
|
||||
#include "Logs.h"
|
||||
#include "Vector3.h"
|
||||
|
@ -51,15 +52,32 @@ void OpenGLVertexArray::render(OpenGLFunctions *functions, int start, int count)
|
|||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (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_uv, array_uv, sizeof(float) * vertexcount * 2);
|
||||
}
|
||||
destination->setIndexes(indexes);
|
||||
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) {
|
||||
if (not vao) {
|
||||
functions->glGenVertexArrays(1, &vao);
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
|
||||
#include "opengl_global.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace paysages {
|
||||
namespace opengl {
|
||||
|
||||
const unsigned short OPENGL_RESTART_PRIMITIVE_INDEX = 65535;
|
||||
|
||||
/**
|
||||
* Vertex arrays storage and binding, to render triangles.
|
||||
*
|
||||
|
@ -62,6 +66,21 @@ class OpenGLVertexArray {
|
|||
*/
|
||||
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:
|
||||
/**
|
||||
* Update the opengl state.
|
||||
|
@ -87,6 +106,7 @@ class OpenGLVertexArray {
|
|||
int vertexcount;
|
||||
float *array_vertex;
|
||||
float *array_uv;
|
||||
vector<unsigned short> indexes;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,4 +13,6 @@ void main(void)
|
|||
|
||||
final_color = applyMouseTracking(unprojected, final_color);
|
||||
final_color.a = alpha;
|
||||
|
||||
//final_color = vec4(0, 1, 0, 1);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue