From 6ac7b3efbb094cd538cf31ed73ce2adc8ac07c9f Mon Sep 17 00:00:00 2001 From: StasJ Date: Wed, 28 Feb 2024 16:16:37 -0700 Subject: [PATCH] Fix #3534 --- apps/vaporgui/ParticleEventRouter.cpp | 13 ++++ include/vapor/ParamsBase.h | 2 + include/vapor/ParticleParams.h | 2 + include/vapor/ParticleRenderer.h | 1 + lib/params/ParticleParams.cpp | 3 + lib/render/ParticleRenderer.cpp | 87 +++++++++++++++++++-------- share/shaders/ParticleDirection.geom | 21 +++++-- share/shaders/ParticleDirection.vert | 9 +++ share/shaders/ParticlePoint.geom | 19 ++++-- share/shaders/ParticlePoint.vert | 9 +++ 10 files changed, 132 insertions(+), 34 deletions(-) diff --git a/apps/vaporgui/ParticleEventRouter.cpp b/apps/vaporgui/ParticleEventRouter.cpp index 88a02fa564..d616b07413 100644 --- a/apps/vaporgui/ParticleEventRouter.cpp +++ b/apps/vaporgui/ParticleEventRouter.cpp @@ -8,6 +8,14 @@ using namespace VAPoR; static RenderEventRouterRegistrar registrar(ParticleEventRouter::GetClassType()); +struct PParticleRadiusVariableSelector : public PVariableSelector { + PParticleRadiusVariableSelector() + : PVariableSelector(ParticleParams::RenderRadiusVariableTag, "Particle Radius Scalar") { + AddNullOption(); + ShowParticleVars(); + } +}; + ParticleEventRouter::ParticleEventRouter(QWidget *parent, ControlExec *ce) : RenderEventRouterGUI(ce, BarbParams::GetClassType()) { // clang-format off @@ -18,6 +26,7 @@ ParticleEventRouter::ParticleEventRouter(QWidget *parent, ControlExec *ce) : Ren (new PXFieldVariableSelector)->ShowParticleVars(), (new PYFieldVariableSelector)->ShowParticleVars(), (new PZFieldVariableSelector)->ShowParticleVars(), + (new PParticleRadiusVariableSelector()), }), new PSection("Data Fidelity", { (new PIntegerInput(ParticleParams::StrideTag, "Stride"))->SetRange(1, 1000) @@ -28,6 +37,10 @@ ParticleEventRouter::ParticleEventRouter(QWidget *parent, ControlExec *ce) : Ren new PTFEditor, new PSection("Particles", { (new PDoubleSliderEdit(ParticleParams::RenderRadiusScalarTag, "Radius"))->SetRange(0.5, 25)->AllowUserRange(true)->EnableDynamicUpdate()->EnableBasedOnParam(ParticleParams::RenderLegacyTag, false), + (new PParticleRadiusVariableSelector()), +// (new PShowIf(ParticleParams::RenderRadiusVariableTag))->Not()->Equals("")->Then({ +// (new PDoubleSliderEdit(ParticleParams::RenderRadiusVariableStrengthTag, "Radius Variable Strength"))->SetRange(0.001, 1)->AllowUserRange(true)->EnableDynamicUpdate() +// }), new PCheckbox(ParticleParams::ShowDirectionTag, "Show direction"), (new PDoubleSliderEdit(ParticleParams::DirectionScaleTag, "Length scale"))->SetRange(0.0001, 10)->AllowUserRange(true)->EnableDynamicUpdate()->EnableBasedOnParam(ParticleParams::ShowDirectionTag), (new PXFieldVariableSelector)->ShowParticleVars()->EnableBasedOnParam(ParticleParams::ShowDirectionTag), diff --git a/include/vapor/ParamsBase.h b/include/vapor/ParamsBase.h index 2ef6ccad70..15f85afb9d 100644 --- a/include/vapor/ParamsBase.h +++ b/include/vapor/ParamsBase.h @@ -28,6 +28,8 @@ #include #include +#define PARAMS_IMPL_TAG(class, tag) const std::string class::tag = #tag; + namespace VAPoR { // diff --git a/include/vapor/ParticleParams.h b/include/vapor/ParticleParams.h index f90350c2ef..1ed66e3cfb 100644 --- a/include/vapor/ParticleParams.h +++ b/include/vapor/ParticleParams.h @@ -36,6 +36,8 @@ class PARAMS_API ParticleParams : public RenderParams { //! Scale the rendered particle size static const std::string RenderRadiusScalarTag; + static const std::string RenderRadiusVariableTag; + static const std::string RenderRadiusVariableStrengthTag; static const std::string RenderRadiusBaseTag; static const std::string RenderLegacyTag; diff --git a/include/vapor/ParticleRenderer.h b/include/vapor/ParticleRenderer.h index 464fef5719..832852bae6 100644 --- a/include/vapor/ParticleRenderer.h +++ b/include/vapor/ParticleRenderer.h @@ -64,6 +64,7 @@ class RENDER_API ParticleRenderer : public Renderer { float directionScale; size_t stride; string varName; + string radiusVarName; std::vector fieldVars; } _cacheParams; diff --git a/lib/params/ParticleParams.cpp b/lib/params/ParticleParams.cpp index a5b3f7d3dd..13d46ba7b8 100644 --- a/lib/params/ParticleParams.cpp +++ b/lib/params/ParticleParams.cpp @@ -13,6 +13,8 @@ const std::string ParticleParams::ShowDirectionTag = "ShowDirectionTag"; const std::string ParticleParams::DirectionScaleTag = "DirectionScaleTag"; const std::string ParticleParams::StrideTag = "StrideTag"; const std::string ParticleParams::RenderRadiusScalarTag = "RenderRadiusScalarTag"; +PARAMS_IMPL_TAG(ParticleParams, RenderRadiusVariableTag); +PARAMS_IMPL_TAG(ParticleParams, RenderRadiusVariableStrengthTag); const std::string ParticleParams::LightingEnabledTag = "LightingEnabledTag"; const std::string ParticleParams::RenderRadiusBaseTag = "RenderRadiusBaseTag"; const std::string ParticleParams::RenderLegacyTag = "RenderLegacyTag"; @@ -47,6 +49,7 @@ void ParticleParams::_init() SetValueDouble(DirectionScaleTag, "", 1); SetValueLong(StrideTag, "", 1); SetValueDouble(RenderRadiusScalarTag, "", 8.); + SetValueDouble(RenderRadiusVariableStrengthTag, "", 1.); SetValueDouble(RenderRadiusBaseTag, "", -1); SetValueLong(RenderLegacyTag, "", false); SetValueLong(LightingEnabledTag, "", true); diff --git a/lib/render/ParticleRenderer.cpp b/lib/render/ParticleRenderer.cpp index f50ef6d676..b989177f76 100644 --- a/lib/render/ParticleRenderer.cpp +++ b/lib/render/ParticleRenderer.cpp @@ -159,26 +159,38 @@ int ParticleRenderer::_initializeGL() { return 0; } -static void SetupParticlePointGL(const int VAO, const int VBO) { +static void SetupParticlePointGL(const int VAO, const int VBO, const bool dynamicSize) { glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), NULL); - glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (void *)sizeof(glm::vec3)); + int elSize = sizeof(glm::vec4); + if (dynamicSize) elSize += sizeof(float); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, elSize, NULL); + glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, elSize, (void *)sizeof(glm::vec3)); + if (dynamicSize) + glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, elSize, (void *)sizeof(glm::vec4)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); + if (dynamicSize) + glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } -static void SetupParticleDirectionGL(const int VAO, const int VBO) { +static void SetupParticleDirectionGL(const int VAO, const int VBO, const bool dynamicSize) { glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float)*7, NULL); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float)*7, (void *)sizeof(glm::vec3)); - glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(float)*7, (void *)(2*sizeof(glm::vec3))); + int elSize = sizeof(float)*7; + if (dynamicSize) elSize += sizeof(float); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, elSize, NULL); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, elSize, (void *)sizeof(glm::vec3)); + glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, elSize, (void *)(2*sizeof(glm::vec3))); + if (dynamicSize) + glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, elSize, (void *)(sizeof(float)*7)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); + if (dynamicSize) + glEnableVertexAttribArray(3); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } @@ -198,6 +210,7 @@ bool ParticleRenderer::_particleCacheIsDirty() const { if (_cacheParams.stride != p->GetValueLong( ParticleParams::StrideTag, 1)) return true; if (_cacheParams.varName != p->GetVariableName() ) return true; if (_cacheParams.fieldVars != p->GetFieldVariableNames() ) return true; + if (_cacheParams.radiusVarName != p->GetValueString( ParticleParams::RenderRadiusVariableTag, "")) return true; if (_cacheParams.direction != (bool)p->GetValueLong( ParticleParams::ShowDirectionTag, false)) return true; if (_cacheParams.directionScale != p->GetValueDouble( ParticleParams::DirectionScaleTag, false)) return true; @@ -220,6 +233,7 @@ void ParticleRenderer::_resetParticleCache() { _cacheParams.stride = p->GetValueLong(ParticleParams::StrideTag, 1); _cacheParams.varName = p->GetVariableName(); _cacheParams.fieldVars = p->GetFieldVariableNames(); + _cacheParams.radiusVarName = p->GetValueString( ParticleParams::RenderRadiusVariableTag, ""); } bool ParticleRenderer::_colormapCacheIsDirty() const { @@ -264,12 +278,16 @@ int ParticleRenderer::_renderParticlesHelper() } float radius = radiusBase * rp->GetValueDouble(ParticleParams::RenderRadiusScalarTag, 1.); - ShaderProgram *shader = nullptr; - + string shaderKey; if (_cacheParams.direction) - shader = _glManager->shaderManager->GetShader("ParticleDirection"); + shaderKey = "ParticleDirection"; else - shader = _glManager->shaderManager->GetShader("ParticlePoint"); + shaderKey = "ParticlePoint"; + + if (!_cacheParams.radiusVarName.empty()) + shaderKey += ":DYNAMIC_RADIUS"; + + ShaderProgram *shader = _glManager->shaderManager->GetShader(shaderKey); if (!shader) return -1; double m[16]; @@ -284,6 +302,7 @@ int ParticleRenderer::_renderParticlesHelper() shader->SetUniform("MV", _glManager->matrixManager->GetModelViewMatrix()); shader->SetUniform("aspect", _glManager->matrixManager->GetProjectionAspectRatio()); shader->SetUniform("radius", radius); +// shader->SetUniform("radiusVarStrength", (float)rp->GetValueDouble(ParticleParams::RenderRadiusVariableStrengthTag, 1.)); shader->SetUniform("dirScale", (float)rp->GetValueDouble(ParticleParams::DirectionScaleTag, 1.)); shader->SetUniform("lightingEnabled", (bool)rp->GetValueLong(ParticleParams::LightingEnabledTag, true)); shader->SetUniform("scales", _getScales()); @@ -367,11 +386,20 @@ int ParticleRenderer::_getGrids(Grid*& grid, std::vector& vecGrids) const } } + if (!_cacheParams.radiusVarName.empty()) { + vecGrids.push_back(_dataMgr->GetVariable(_cacheParams.ts, _cacheParams.radiusVarName, _cacheParams.rLevel, _cacheParams.cLevel, _cacheParams.boxMin, _cacheParams.boxMax, true)); + } + return 0; } +template static void UploadDataBuffer(T buffer) { + glBufferData(GL_ARRAY_BUFFER, sizeof(T) * buffer.size(), buffer.data(), GL_STATIC_DRAW); +} + void ParticleRenderer::_generateTextureData(const Grid* grid, const std::vector& vecGrids) { bool showDir = _cacheParams.direction; + bool dynamicSize = !_cacheParams.radiusVarName.empty(); size_t stride = max(1L, (long)_cacheParams.stride); float dirScale = _cacheParams.directionScale; auto node = grid->ConstNodeBegin(_cacheParams.boxMin, _cacheParams.boxMax); @@ -379,21 +407,21 @@ void ParticleRenderer::_generateTextureData(const Grid* grid, const std::vector< CoordType coordsBuf; vector dirs; - if (showDir) for (auto g : vecGrids) dirs.push_back(g->cbegin(_cacheParams.boxMin, _cacheParams.boxMax)); - - struct PointDataT {vec3 pos; float val;}; - vector pointData; + if (showDir) for (int i = 0; i < 3; i++) dirs.push_back(vecGrids[i]->cbegin(_cacheParams.boxMin, _cacheParams.boxMax)); + if (dynamicSize) dirs.push_back(vecGrids[vecGrids.size()-1]); - struct DirectionDataT {vec3 pos; vec3 norm; float val;}; - vector directionData; + struct PointDataT {vec3 pos; float val;}; vector pointData; + struct DirectionDataT {vec3 pos; vec3 norm; float val;}; vector directionData; + struct PointDynSizeDataT {vec3 pos; float val; float radius;}; vector pointDynSizeData; + struct DirectionDynSizeDataT {vec3 pos; vec3 norm; float val; float radius;}; vector directionDynSizeData; _particlesCount = grid->GetCoordDimensions(1)[0] / stride; if (showDir) { - SetupParticleDirectionGL(_VAO, _VBO); + SetupParticleDirectionGL(_VAO, _VBO, dynamicSize); directionData.reserve(_particlesCount); } else { - SetupParticlePointGL(_VAO, _VBO); + SetupParticlePointGL(_VAO, _VBO, dynamicSize); pointData.reserve(_particlesCount); } assert(glIsVertexArray(_VAO) == GL_TRUE); @@ -408,9 +436,15 @@ void ParticleRenderer::_generateTextureData(const Grid* grid, const std::vector< if (showDir){ const glm::vec3 norm(*(dirs[0]), *(dirs[1]), *(dirs[2])); - directionData.push_back({p, norm, value}); + if (dynamicSize) + directionDynSizeData.push_back({p, norm, value, *(dirs[dirs.size()-1])}); + else + directionData.push_back({p, norm, value}); } else { - pointData.push_back({p, value}); + if (dynamicSize) + pointDynSizeData.push_back({p, value, *(dirs[dirs.size()-1])}); + else + pointData.push_back({p, value}); } } step: @@ -420,10 +454,13 @@ void ParticleRenderer::_generateTextureData(const Grid* grid, const std::vector< glBindVertexArray(_VAO); glBindBuffer(GL_ARRAY_BUFFER, _VBO); - if (showDir) - glBufferData(GL_ARRAY_BUFFER, sizeof(DirectionDataT) * directionData.size(), directionData.data(), GL_STATIC_DRAW); - else - glBufferData(GL_ARRAY_BUFFER, sizeof(PointDataT) * pointData.size(), pointData.data(), GL_STATIC_DRAW); + if (dynamicSize) { + if (showDir) UploadDataBuffer(directionDynSizeData); + else UploadDataBuffer(pointDynSizeData); + } else { + if (showDir) UploadDataBuffer(directionData); + else UploadDataBuffer(pointData); + } glBindBuffer(GL_ARRAY_BUFFER, 0); } diff --git a/share/shaders/ParticleDirection.geom b/share/shaders/ParticleDirection.geom index c451d3c77b..27bbad9a36 100644 --- a/share/shaders/ParticleDirection.geom +++ b/share/shaders/ParticleDirection.geom @@ -24,6 +24,11 @@ out float fValue; out vec3 fNormal; +#ifdef DYNAMIC_RADIUS +in float gRadius[]; +#endif + + uniform mat4 P; uniform mat4 MV; uniform vec3 scales; @@ -31,11 +36,11 @@ uniform float radius = 0.05; uniform float dirScale = 0.05; void EmitWorld(const vec3 v); -void CylinderVert(const vec3 v, const vec3 d, const float value); +void CylinderVert(const vec3 v, const vec3 d, const float value, const float radius); void main() -{ +{gs //fValue = gValue[0]; //EmitWorld(gl_in[0].gl_Position.xyz); //EmitWorld(gl_in[0].gl_Position.xyz + gNorm[0] * dirScale); @@ -61,6 +66,12 @@ void main() XH = normalize(cross(N, up)); YH = normalize(cross(XH, N)); + #ifdef DYNAMIC_RADIUS + float finalRadius = radius * gRadius[0]; + #else + float finalRadius = radius; + #endif + vec2 fade = CalculateFade(); //fNormal = vec3(1,0,0); fValue = 1; EmitWorld(gl_in[0].gl_Position.xyz); EmitWorld(gl_in[1].gl_Position.xyz); EndPrimitive(); return; @@ -70,8 +81,8 @@ void main() vec3 D; D = XH*cos(t) + YH*sin(t); - CylinderVert(V[0], D, gValue[0]); - CylinderVert(V[1], D, gValue[0]); + CylinderVert(V[0], D, gValue[0], finalRadius); + CylinderVert(V[1], D, gValue[0], finalRadius); } EndPrimitive(); } @@ -84,7 +95,7 @@ void EmitWorld(const vec3 v) } -void CylinderVert(const vec3 v, const vec3 d, const float value) +void CylinderVert(const vec3 v, const vec3 d, const float value, const float radius) { fNormal = d; fValue = value; diff --git a/share/shaders/ParticleDirection.vert b/share/shaders/ParticleDirection.vert index 9b30a2bcd6..ba3bcf643c 100644 --- a/share/shaders/ParticleDirection.vert +++ b/share/shaders/ParticleDirection.vert @@ -7,8 +7,17 @@ layout (location = 2) in float vValue; out vec3 gNorm; out float gValue; +#ifdef DYNAMIC_RADIUS +layout (location = 3) in float vRadius; +out float gRadius; +#endif + void main() { gValue = vValue; gNorm = vNorm; gl_Position = vec4(vPos, 1.0f); + + #ifdef DYNAMIC_RADIUS + gRadius = vRadius; + #endif } diff --git a/share/shaders/ParticlePoint.geom b/share/shaders/ParticlePoint.geom index f26ab01343..4d4c57b801 100644 --- a/share/shaders/ParticlePoint.geom +++ b/share/shaders/ParticlePoint.geom @@ -13,6 +13,11 @@ out float fValue; out vec2 fC; +#ifdef DYNAMIC_RADIUS +in float gRadius[]; +#endif + + uniform mat4 P; uniform mat4 MV; uniform vec3 cameraPos; @@ -36,11 +41,17 @@ void main() xh /= scales; yh /= scales; + #ifdef DYNAMIC_RADIUS + float finalRadius = radius * gRadius[0]; + #else + float finalRadius = radius; + #endif + // Billboard - fC = vec2(-1.0, -1.0); EmitWorld(o + radius * (-xh + -yh)); - fC = vec2( 1.0, -1.0); EmitWorld(o + radius * ( xh + -yh)); - fC = vec2(-1.0, 1.0); EmitWorld(o + radius * (-xh + yh)); - fC = vec2( 1.0, 1.0); EmitWorld(o + radius * ( xh + yh)); + fC = vec2(-1.0, -1.0); EmitWorld(o + finalRadius * (-xh + -yh)); + fC = vec2( 1.0, -1.0); EmitWorld(o + finalRadius * ( xh + -yh)); + fC = vec2(-1.0, 1.0); EmitWorld(o + finalRadius * (-xh + yh)); + fC = vec2( 1.0, 1.0); EmitWorld(o + finalRadius * ( xh + yh)); EndPrimitive(); } diff --git a/share/shaders/ParticlePoint.vert b/share/shaders/ParticlePoint.vert index 6ea59b3751..b9db81852c 100644 --- a/share/shaders/ParticlePoint.vert +++ b/share/shaders/ParticlePoint.vert @@ -5,7 +5,16 @@ layout (location = 1) in float vValue; out float gValue; +#ifdef DYNAMIC_RADIUS +layout (location = 2) in float vRadius; +out float gRadius; +#endif + void main() { gValue = vValue; gl_Position = vec4(vPos, 1.0f); + + #ifdef DYNAMIC_RADIUS + gRadius = vRadius; + #endif }