Interpolating points (#3002)

* Add a class for rendering an interpolated point cloud (WIP)

* Make sure that we render the correct number of points

* Group interpolation properties into a property owner

* Update interpolation stuff (which was broken :) )

* Prevent interpolation from breaking with only one step or invalid interpolation values

* Add trigger properties for controlling interpolation

* Allow setting start interpolation value from asset

* Implement spline-based interpolation

* Cleanup, and interpolate to start and end

* And asset type documentation

* Add example asset

* Handle missing data values in interpolation

* Always show values at the knots, if there is one

* Experiment with more dynamic rendering (batching)

* Speed up interpolation by doing it on GPU instead of CPU

* Bring back spline interpolation (this time on GPU)

* Refactor initial data buffering

* Add a helper function to compute transformed positions

* Use vec3 positions instead of vec4 (less data to transfer)

* Update interpolation value documentation

* Apply suggestions from code review

Co-authored-by: Alexander Bock <alexander.bock@liu.se>

* Increase interpolation speed max value

* Fix faulty indentation

* I banish thee, redundant empty line

---------

Co-authored-by: Alexander Bock <alexander.bock@liu.se>
This commit is contained in:
Emma Broman
2024-01-30 09:43:11 +01:00
committed by GitHub
parent bcc728cbfd
commit 2406a886ec
13 changed files with 1063 additions and 76 deletions
@@ -628,17 +628,7 @@ void RenderablePointCloud::initialize() {
void RenderablePointCloud::initializeGL() {
ZoneScoped;
_program = BaseModule::ProgramObjectManager.request(
"RenderablePointCloud",
[]() {
return global::renderEngine->buildRenderProgram(
"RenderablePointCloud",
absPath("${MODULE_BASE}/shaders/billboardpoint_vs.glsl"),
absPath("${MODULE_BASE}/shaders/billboardpoint_fs.glsl"),
absPath("${MODULE_BASE}/shaders/billboardpoint_gs.glsl")
);
}
);
initializeShadersAndGlExtras();
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
@@ -653,6 +643,27 @@ void RenderablePointCloud::deinitializeGL() {
glDeleteVertexArrays(1, &_vao);
_vao = 0;
deinitializeShaders();
BaseModule::TextureManager.release(_spriteTexture);
_spriteTexture = nullptr;
}
void RenderablePointCloud::initializeShadersAndGlExtras() {
_program = BaseModule::ProgramObjectManager.request(
"RenderablePointCloud",
[]() {
return global::renderEngine->buildRenderProgram(
"RenderablePointCloud",
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_vs.glsl"),
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_fs.glsl"),
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_gs.glsl")
);
}
);
}
void RenderablePointCloud::deinitializeShaders() {
BaseModule::ProgramObjectManager.release(
"RenderablePointCloud",
[](ghoul::opengl::ProgramObject* p) {
@@ -660,9 +671,6 @@ void RenderablePointCloud::deinitializeGL() {
}
);
_program = nullptr;
BaseModule::TextureManager.release(_spriteTexture);
_spriteTexture = nullptr;
}
void RenderablePointCloud::bindTextureForRendering() const {
@@ -699,51 +707,8 @@ float RenderablePointCloud::computeDistanceFadeValue(const RenderData& data) con
return fadeValue * funcValue;
}
void RenderablePointCloud::renderBillboards(const RenderData& data,
const glm::dmat4& modelMatrix,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp,
float fadeInVariable)
{
if (!_hasDataFile || _dataset.entries.empty()) {
return;
}
glEnablei(GL_BLEND, 0);
if (_useAdditiveBlending) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
else {
// Normal blending, with transparency
glDepthMask(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
_program->activate();
_program->setUniform(_uniformCache.cameraPos, data.camera.positionVec3());
_program->setUniform(
_uniformCache.cameraLookup,
glm::vec3(data.camera.lookUpVectorWorldSpace())
);
void RenderablePointCloud::bindDataForPointRendering() {
_program->setUniform(_uniformCache.renderOption, _renderOption.value());
_program->setUniform(_uniformCache.modelMatrix, modelMatrix);
_program->setUniform(
_uniformCache.cameraViewMatrix,
data.camera.combinedViewMatrix()
);
_program->setUniform(
_uniformCache.projectionMatrix,
glm::dmat4(data.camera.projectionMatrix())
);
_program->setUniform(_uniformCache.up, glm::vec3(orthoUp));
_program->setUniform(_uniformCache.right, glm::vec3(orthoRight));
_program->setUniform(_uniformCache.fadeInValue, fadeInVariable);
_program->setUniform(_uniformCache.opacity, opacity());
_program->setUniform(_uniformCache.scaleExponent, _sizeSettings.scaleExponent);
@@ -811,9 +776,58 @@ void RenderablePointCloud::renderBillboards(const RenderData& data,
_colorSettings.colorMapping->useBelowRangeColor
);
}
}
void RenderablePointCloud::renderBillboards(const RenderData& data,
const glm::dmat4& modelMatrix,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp,
float fadeInVariable)
{
if (!_hasDataFile || _dataset.entries.empty()) {
return;
}
glEnablei(GL_BLEND, 0);
if (_useAdditiveBlending) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
else {
// Normal blending, with transparency
glDepthMask(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
_program->activate();
_program->setUniform(_uniformCache.cameraPos, data.camera.positionVec3());
_program->setUniform(
_uniformCache.cameraLookup,
glm::vec3(data.camera.lookUpVectorWorldSpace())
);
_program->setUniform(_uniformCache.renderOption, _renderOption.value());
_program->setUniform(_uniformCache.modelMatrix, modelMatrix);
_program->setUniform(
_uniformCache.cameraViewMatrix,
data.camera.combinedViewMatrix()
);
_program->setUniform(
_uniformCache.projectionMatrix,
glm::dmat4(data.camera.projectionMatrix())
);
_program->setUniform(_uniformCache.up, glm::vec3(orthoUp));
_program->setUniform(_uniformCache.right, glm::vec3(orthoRight));
_program->setUniform(_uniformCache.fadeInValue, fadeInVariable);
bindDataForPointRendering();
glBindVertexArray(_vao);
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(_dataset.entries.size()));
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(_nDataPoints));
glBindVertexArray(0);
_program->deactivate();
@@ -857,9 +871,13 @@ void RenderablePointCloud::render(const RenderData& data, RendererTasks&) {
}
}
void RenderablePointCloud::preUpdate() {}
void RenderablePointCloud::update(const UpdateData&) {
ZoneScoped;
preUpdate();
if (_dataIsDirty) {
updateBufferData();
}
@@ -869,8 +887,16 @@ void RenderablePointCloud::update(const UpdateData&) {
}
}
glm::dvec3 RenderablePointCloud::transformedPosition(
const dataloader::Dataset::Entry& e) const
{
const double unitMeter = toMeter(_unit);
glm::dvec4 position = glm::dvec4(glm::dvec3(e.position) * unitMeter, 1.0);
return glm::dvec3(_transformationMatrix * position);
}
int RenderablePointCloud::nAttributesPerPoint() const {
int n = 4; // position
int n = 3; // position
n += _hasColorMapFile ? 1 : 0;
n += _hasDatavarSize ? 1 : 0;
return n;
@@ -909,13 +935,13 @@ void RenderablePointCloud::updateBufferData() {
glEnableVertexAttribArray(positionAttrib);
glVertexAttribPointer(
positionAttrib,
4,
3,
GL_FLOAT,
GL_FALSE,
attibutesPerPoint * sizeof(float),
nullptr
);
attributeOffset += 4;
attributeOffset += 3;
if (_hasColorMapFile) {
GLint colorParamAttrib = _program->attributeLocation("in_colorParameter");
@@ -1022,24 +1048,20 @@ std::vector<float> RenderablePointCloud::createDataSlice() {
int sizeParamIndex = currentSizeParameterIndex();
double maxRadius = 0.0;
double biggestCoord = -1.0;
for (const dataloader::Dataset::Entry& e : _dataset.entries) {
const double unitMeter = toMeter(_unit);
glm::dvec4 position = glm::dvec4(glm::dvec3(e.position) * unitMeter, 1.0);
position = _transformationMatrix * position;
glm::dvec3 position = transformedPosition(e);
const double r = glm::length(position);
maxRadius = std::max(maxRadius, r);
// Positions
for (int j = 0; j < 4; ++j) {
for (int j = 0; j < 3; ++j) {
result.push_back(static_cast<float>(position[j]));
}
// Colors
if (_hasColorMapFile) {
biggestCoord = std::max(biggestCoord, glm::compMax(position));
result.push_back(e.data[colorParamIndex]);
}