vtkScalarBarActor in WebAssembly

I am having an issue using vtkScalarBarActor in WebAssembly. The code works correctly in C++ desktop VTK, but I get the following error when running it in WebAssembly in a browser:

WebGL: INVALID_ENUM: texParameter: invalid texture target

Here is the code:

vtkSmartPointer<vtkLookupTable>  lookuptable = vtkSmartPointer<vtkLookupTable>::New();


lookuptable->SetNumberOfTableValues(256);
lookuptable->SetTableRange(minlev, maxlev);
lookuptable->SetRampToLinear();
lookuptable->SetScaleToLinear();
lookuptable->GlobalWarningDisplayOff();
lookuptable->Build();

int annotind = 0;

for (int tblid = 0; tblid < cols.size(); tblid++)
{
	// Set the ref bin colors

	double r, g, b, a;

	r = cols[tblid].r / 255.0;
	g = cols[tblid].g / 255.0;
	b = cols[tblid].b / 255.0;
	a = cols[tblid].a / 255.0;
	
	lookuptable->SetTableValue(tblid, r, g, b, a);
	
}

vtkSmartPointer<vtkScalarBarActor> scalarBar = vtkSmartPointer<vtkScalarBarActor>::New();
scalarBar->SetMaximumNumberOfColors(256);
scalarBar->SetLookupTable(lookuptable);
scalarBar->SetHeight(0.05);
scalarBar->SetWidth(1.0);
scalarBar->GetPositionCoordinate()->SetValue(0, 0);
scalarBar->GetPosition2Coordinate()->SetValue(1.0, .10);
scalarBar->SetOrientationToHorizontal();
scalarBar->SetNumberOfLabels(20);
scalarBar->SetLabelFormat("%.0f");
scalarBar->SetMaximumWidthInPixels(1000);
scalarBar->SetMaximumHeightInPixels(60);
scalarBar->SetTitle("Units: dBZ");
scalarBar->VisibilityOn();

m_renderer->AddActor(scalarBar);

@ken-martin

I am trying to debug the issue and it appears vtkScalarBarActor is calling bindTexture with a target value of 0. All of the other calls to this function from my program are passing a value of 3553 (gl.TEXTURE_2D) for a target.

I have done. Sorry

If it’s okay. I want to share my project with you.
It’s for implementing vtk features to React js project.
Are you interested?

@ken-martin Here is a screenshot of the breakpoint and the values of the parameters to bindTexture:

image

Here is the stack trace at that breakpoint:

_glBindTexture (SwisRadar.js:10994)
__ZN16vtkTextureObject8ActivateEv (SwisRadar.wasm:0xa5654)
__ZN25vtkOpenGLPolyDataMapper2D13RenderOverlayEP11vtkViewportP10vtkActor2D (SwisRadar.wasm:0x69c73)
__ZN10vtkActor2D13RenderOverlayEP11vtkViewport (SwisRadar.wasm:0x127ecc)
__ZN17vtkScalarBarActor13RenderOverlayEP11vtkViewport (SwisRadar.wasm:0xc2ea1)
__ZN17vtkOpenGLRenderer14UpdateGeometryEP24vtkFrameBufferObjectBase (SwisRadar.wasm:0x7a93c)
__ZN17vtkOpenGLRenderer12DeviceRenderEv (SwisRadar.wasm:0x7818f)
__ZN11vtkRenderer6RenderEv (SwisRadar.wasm:0x153fdc)
__ZN21vtkRendererCollection6RenderEv (SwisRadar.wasm:0x156e82)
__ZN15vtkRenderWindow14DoStereoRenderEv (SwisRadar.wasm:0x14f1cf)
__ZN15vtkRenderWindow6RenderEv (SwisRadar.wasm:0x14e7dd)
__ZN21vtkOpenGLRenderWindow6RenderEv (SwisRadar.wasm:0x7303c)
__ZN25vtkRenderWindowInteractor6RenderEv (SwisRadar.wasm:0x1504b2)
__ZN18SwisVtkRadarWindow6renderEv (SwisRadar.wasm:0x17477)
__ZN18SwisVtkRadarWindow11GotoNextCueEv (SwisRadar.wasm:0x180db)
__ZN18SwisVtkRadarWindow15DownloadSuccessENSt3__26vectorIcNS0_9allocatorIcEEEEi (SwisRadar.wasm:0x17f27)
__Z17downloadSucceededP18emscripten_fetch_t (SwisRadar.wasm:0x165ba)
dynCall_vi (SwisRadar.wasm:0x540be3)
Module.dynCall_vi (SwisRadar.js:13437)
reportSuccess (SwisRadar.js:10865)
xhr.onload (SwisRadar.js:10670)
load (async)
__emscripten_fetch_xhr (SwisRadar.js:10642)
performUncachedXhr (SwisRadar.js:10885)
getRequest.onsuccess (SwisRadar.js:10793)
IndexedDB (async)
__emscripten_fetch_load_cached_data (SwisRadar.js:10771)
_emscripten_start_fetch (SwisRadar.js:10911)
_emscripten_fetch (SwisRadar.wasm:0x51f22d)
__ZN18SwisVtkRadarWindow10AddProductENSt3__212basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEi (SwisRadar.wasm:0x1814d)
_addRadarCue (SwisRadar.wasm:0x15612)
Module._addRadarCue (SwisRadar.js:12819)
ccall (SwisRadar.js:795)
(anonymous) (SwisRadar.js:814)
DequeRadar1 (SwisRadarPage.js:247)
setTimeout (async)
success (SwisRadarPage.js:174)
c (jquery.min.js:2)
fireWith (jquery.min.js:2)
l (jquery.min.js:2)
(anonymous) (jquery.min.js:2)
load (async)
send (jquery.min.js:2)
ajax (jquery.min.js:2)
createRadar1 (SwisRadarPage.js:151)
createRadar (SwisRadarPage.js:130)
createScene (SwisRadarPage.js:111)
onclick (SwisRadar.aspx:89)

@Donny_Zimmerman
No problem. Thanks anyway.

Here is the PrintSelf of the vtkTextureObject that is failing:

WrapS: Repeat
WrapT: Repeat
WrapR: Repeat
MinificationFilter: Nearest
MagnificationFilter: Nearest
MinLOD: -1000
MaxLOD: 1000
BaseLevel: 0
MaxLevel: 0
DepthTextureCompare: 0
DepthTextureCompareFunction: Lequal
GenerateMipmap: 0
Debug: Off
Modified Time: 239314
Reference Count: 1
Registered Events: (none)
Width: 0
Height: 0
Depth: 0
Components: 0
Handle: 0
Target: unknown value: 0x0
NumberOfDimensions: 0
Format: 0
InternalFormat: 0
Type: 0

Here is the vtkOpenGLPolyDataMapper2D PrintSelf:

Debug: Off
Modified Time: 78110
Reference Count: 3
Registered Events: (none)
Executive: 0x1d30ce8
ErrorCode: No error information
Information: 0x1d30050
AbortExecute: Off
Progress: 0
Progress Text: (None)
TimeToDraw: 0
ClippingPlanes: (none)
Lookup Table:
Debug: Off
Modified Time: 78110
Reference Count: 1
Registered Events: (none)
Alpha: 1
VectorMode: Component
VectorComponent: 0
VectorSize: -1
IndexedLookup: OFF
AnnotatedValues: 0 entries.
TableRange: (0, 1)
Scale: Linear
HueRange: (0, 0.66667)
SaturationRange: (1, 1)
ValueRange: (1, 1)
AlphaRange: (1, 1)
NanColor: (0.5, 0, 0, 1)
BelowRangeColor: (0, 0, 0, 1)
UseBelowRangeColor: OFF
AboveRangeColor: (1, 1, 1, 1)
UseAboveRangeColor: OFF
NumberOfTableValues: 256
NumberOfColors: 256
Ramp: SCurve
InsertTime: 0
BuildTime: 78115
Table:
Debug: Off
Modified Time: 78113
Reference Count: 1
Registered Events: (none)
Name: (none)
Data type: unsigned char
Size: 1040
MaxId: 1023
NumberOfComponents: 4
Information: 0
Name: (none)
Number Of Components: 4
Number Of Tuples: 256
Size: 1040
MaxId: 1023
LookupTable: (none)
Scalar Visibility: On
Scalar Mode: Default
Scalar Range: (0, 1)
UseLookupTableScalarRange: 0
Color Mode: Default
No Transform Coordinate
Transform Coordinate use double: False

@ken-martin

I think the issue is because TextureBuffers are not supported in OpenGL ES.

Here is the VTK code for vtkTextureObject starting at line 1126. There is an #ifdef checking for ES on line 898:

// Description:
// Create a texture buffer basically a 1D texture that can be
// very large for passing data into the fragment shader
bool vtkTextureObject::CreateTextureBuffer(
unsigned int numValues, int numComps, int dataType, vtkOpenGLBufferObject* bo)
{
assert(this->Context);
vtkErrorMacro(“TextureBuffers not supported in OpenGL ES”);
// TODO: implement 1D and Texture buffers using 2D textures
return false;
}

#endif // not ES 2.0 or 3.0

I have no idea how to implement the TODO as mentioned in the above code. Any idea when this will be implemented or a workaround?

Thanks!

I know of no plans to implement it in the future, we will eventually move away from OpenGL so at some point it will be legacy. But if someone implements it I’d be happy to review the topic etc. of course.

Thanks @ken-martin . Is it a requirement for the vtkScalarActor to use textures. I was thinking it could just use geometry and shading to accomplish rendering. I will dig a little deeper to see if I can disable using textures for this actor. I am using the vtkLegendBoxActor in the same project and it is rendering correctly so I would think a scalar bar could be implemented.

If you are moving away from OpenGL, what will the new backend be using? Does this mean using VTK in WebAssembly will not be possible?

Thanks!

We are thinking vulkan or Dawn. If we go with Dawn then web assembly should work as I believe dawn converts properly.

I solved my immediate issue by modifying the vtkScalarBarActor code by setting point scalars instead of cell scalars on the scalar bar polydata object. This works in this instance, but anytime you use a vtkPolyDataActor2D with cell scalars it will fail when using WebAssembly. Hope this helps someone else in the future. I am just not good enough to re-implement texture buffers in OpenGL ES.

1 Like

If everyone agrees, can someone push the following changes to the vtkScalarBarActor source code. I just did #ifndef GL_ES_VERSION_3_0 checks so it will work with WebAssembly. I just don’t have the setup to push changes right now. The only change is in the function ConfigureScalarBar. Below is the complete code for that function.

void vtkScalarBarActor::ConfigureScalarBar()
{
vtkScalarsToColors* lut = this->LookupTable;
const double* range = lut->GetRange();
this->P->NumColors =
lut->GetIndexedLookup() ? lut->GetNumberOfAnnotatedValues() : this->MaximumNumberOfColors;
this->P->NumSwatches = this->P->NumColors + (this->DrawNanAnnotation ? 1 : 0);
int numPts = 2 * (this->P->NumColors + 1) + (this->DrawNanAnnotation ? 4 : 0);

this->P->NumSwatches = this->P->NumColors + (this->DrawBelowRangeSwatch ? 1 : 0);
numPts += (this->DrawBelowRangeSwatch ? 4 : 0);

this->P->SwatchPts = vtkPoints::New();
this->P->SwatchPts->SetNumberOfPoints(numPts);
this->P->Polys = vtkCellArray::New();
this->P->Polys->AllocateEstimate(this->P->NumSwatches, 4);
this->P->SwatchColors = vtkUnsignedCharArray::New();

unsigned int nComponents = ((this->UseOpacity) ? 4 : 3);
this->P->SwatchColors->SetNumberOfComponents(nComponents);

// 1D textures are not supported in ES 2.0 or 3.0
#ifndef GL_ES_VERSION_3_0
this->P->SwatchColors->SetNumberOfTuples(this->P->NumSwatches);
#else
this->P->SwatchColors->SetNumberOfTuples(numPts);
#endif

this->ScalarBarActor->SetProperty(this->GetProperty());
this->ScalarBar->Initialize();
this->ScalarBar->SetPoints(this->P->SwatchPts);
this->ScalarBar->SetPolys(this->P->Polys);

// 1D textures are not supported in ES 2.0 or 3.0
#ifndef GL_ES_VERSION_3_0
this->ScalarBar->GetCellData()->SetScalars(this->P->SwatchColors);
#else
this->ScalarBar->GetPointData()->SetScalars(this->P->SwatchColors);
#endif

this->P->SwatchPts->Delete();
this->P->Polys->Delete();
this->P->SwatchColors->Delete();

double delta = static_cast(this->P->ScalarBarBox.Size[1]) / this->P->NumColors;
double x[3];
x[2] = 0.;
for (int i = 0; i < numPts / 2 - (this->DrawNanAnnotation ? 2 : 0) - (this->DrawBelowRangeSwatch ? 2 : 0); ++i)
{
x[this->P->TL[0]] = this->P->ScalarBarBox.Posn[this->P->TL[0]];
x[this->P->TL[1]] = this->P->ScalarBarBox.Posn[this->P->TL[1]] + i * delta;
this->P->SwatchPts->SetPoint(2 * i, x);

  x[this->P->TL[0]] = this->P->ScalarBarBox.Posn[this->P->TL[0]] + this->P->ScalarBarBox.Size[0];
  this->P->SwatchPts->SetPoint(2 * i + 1, x);

}

// polygons & cell colors
unsigned char* rgb;
double rgba[4];
vtkIdType ptIds[4];
for (int i = 0; i < this->P->NumColors; ++i)
{
ptIds[0] = 2 * i;
ptIds[1] = ptIds[0] + 1;
ptIds[2] = ptIds[1] + 2;
ptIds[3] = ptIds[0] + 2;
this->P->Polys->InsertNextCell(4, ptIds);

  double rgbval;
  if (this->LookupTable->UsingLogScale())
  {
  	rgbval = log10(range[0]) + i * (log10(range[1]) - log10(range[0])) / this->P->NumColors;
  	rgbval = pow(10.0, rgbval);
  }
  else
  {
  	rgbval = range[0] + (range[1] - range[0]) * (i / static_cast<double>(this->P->NumColors));
  }
  lut->GetColor(rgbval, rgba);
  rgba[3] = lut->GetOpacity(rgbval);

  // write into array directly

// 1D textures are not supported in ES 2.0 or 3.0
#ifndef GL_ES_VERSION_3_0
rgb = this->P->SwatchColors->GetPointer(nComponents * i);
rgb[0] = static_cast(rgba[0] * 255.);
rgb[1] = static_cast(rgba[1] * 255.);
rgb[2] = static_cast(rgba[2] * 255.);
if (this->P->SwatchColors->GetNumberOfComponents() > 3)
{
rgb[3] = static_cast(this->UseOpacity ? rgba[3] * 255. : 255.);
}

#else

  	rgb = this->P->SwatchColors->GetPointer(nComponents * (i * 2));
  	rgb[0] = static_cast<unsigned char>(rgba[0] * 255.);
  	rgb[1] = static_cast<unsigned char>(rgba[1] * 255.);
  	rgb[2] = static_cast<unsigned char>(rgba[2] * 255.);
  	if (this->P->SwatchColors->GetNumberOfComponents() > 3)
  	{
  		rgb[3] = static_cast<unsigned char>(this->UseOpacity ? rgba[3] * 255. : 255.);
  	}

  	rgb = this->P->SwatchColors->GetPointer(nComponents * (i * 2 + 1));
  	rgb[0] = static_cast<unsigned char>(rgba[0] * 255.);
  	rgb[1] = static_cast<unsigned char>(rgba[1] * 255.);
  	rgb[2] = static_cast<unsigned char>(rgba[2] * 255.);
  	if (this->P->SwatchColors->GetNumberOfComponents() > 3)
  	{
  		rgb[3] = static_cast<unsigned char>(this->UseOpacity ? rgba[3] * 255. : 255.);
  	}

#endif

}

// Set up a texture actor as an alternative to the 1-quad-per-color
// scalar bar polydata.
vtkPoints* texturePoints = vtkPoints::New();
texturePoints->SetNumberOfPoints(4);
this->TexturePolyData->SetPoints(texturePoints);
texturePoints->SetPoint(0, 0.0, 0.0, 0.0);

double p1[2], p2[2];
p1[0] = this->P->ScalarBarBox.Posn[0];
p1[1] = this->P->ScalarBarBox.Posn[1];
p2[0] = p1[0] + this->P->ScalarBarBox.Size[this->P->TL[0]];
p2[1] = p1[1] + this->P->ScalarBarBox.Size[this->P->TL[1]];

texturePoints->SetPoint(0, p1[0], p1[1], 0.0);
texturePoints->SetPoint(1, p2[0], p1[1], 0.0);
texturePoints->SetPoint(2, p2[0], p2[1], 0.0);
texturePoints->SetPoint(3, p1[0], p2[1], 0.0);
texturePoints->Delete();

double barWidth = this->P->ScalarBarBox.Size[this->P->TL[0]];
double barHeight = this->P->ScalarBarBox.Size[this->P->TL[1]];
vtkDataArray* tc = this->TexturePolyData->GetPointData()->GetTCoords();
tc->SetTuple2(1, barWidth / this->TextureGridWidth, 0.0);
tc->SetTuple2(2, barWidth / this->TextureGridWidth, barHeight / this->TextureGridWidth);
tc->SetTuple2(3, 0.0, barHeight / this->TextureGridWidth);
}

Thanks!

Hmm, the trick is that class is not part of any of the OpenGL libraries in VTK. It is a API generic class. So I’m not sure how it will get the value of the definition. It must be working for you somehow but I’m not seeing where it could get that definition. Normally it is provided by gl.h but that is not included here.

So what I am thinking is that the way to do this is to add an ivar like UsePointData, that defaults to false but can be turned on. For your code you would set it to true and then it would use your new code paths. Does that work for you?

@ken-martin That is funny because that is exactly how I got my code to work. I just thought maybe I should stick with the same #defines used in the vtkTextureObject. Below is the function as I used it:

void vtkScalarBarActor::ConfigureScalarBar()
{
vtkScalarsToColors* lut = this->LookupTable;
const double* range = lut->GetRange();
this->P->NumColors =
lut->GetIndexedLookup() ? lut->GetNumberOfAnnotatedValues() : this->MaximumNumberOfColors;
this->P->NumSwatches = this->P->NumColors + (this->DrawNanAnnotation ? 1 : 0);
int numPts = 2 * (this->P->NumColors + 1) + (this->DrawNanAnnotation ? 4 : 0);

this->P->NumSwatches = this->P->NumColors + (this->DrawBelowRangeSwatch ? 1 : 0);
numPts += (this->DrawBelowRangeSwatch ? 4 : 0);

this->P->SwatchPts = vtkPoints::New();
this->P->SwatchPts->SetNumberOfPoints(numPts);
this->P->Polys = vtkCellArray::New();
this->P->Polys->AllocateEstimate(this->P->NumSwatches, 4);
this->P->SwatchColors = vtkUnsignedCharArray::New();

unsigned int nComponents = ((this->UseOpacity) ? 4 : 3);
this->P->SwatchColors->SetNumberOfComponents(nComponents);
if (!this->UseColorBarPointScalars)
{
this->P->SwatchColors->SetNumberOfTuples(this->P->NumSwatches);
}
else
{
this->P->SwatchColors->SetNumberOfTuples(numPts);
}

this->ScalarBarActor->SetProperty(this->GetProperty());
this->ScalarBar->Initialize();
this->ScalarBar->SetPoints(this->P->SwatchPts);
this->ScalarBar->SetPolys(this->P->Polys);
if (!this->UseColorBarPointScalars)
{
this->ScalarBar->GetCellData()->SetScalars(this->P->SwatchColors);
}
else
{
this->ScalarBar->GetPointData()->SetScalars(this->P->SwatchColors);
}
this->P->SwatchPts->Delete();
this->P->Polys->Delete();
this->P->SwatchColors->Delete();

double delta = static_cast(this->P->ScalarBarBox.Size[1]) / this->P->NumColors;
double x[3];
x[2] = 0.;
for (int i = 0; i < numPts / 2 - (this->DrawNanAnnotation ? 2 : 0) - (this->DrawBelowRangeSwatch ? 2 : 0); ++i)
{
x[this->P->TL[0]] = this->P->ScalarBarBox.Posn[this->P->TL[0]];
x[this->P->TL[1]] = this->P->ScalarBarBox.Posn[this->P->TL[1]] + i * delta;
this->P->SwatchPts->SetPoint(2 * i, x);

x[this->P->TL[0]] = this->P->ScalarBarBox.Posn[this->P->TL[0]] + this->P->ScalarBarBox.Size[0];
this->P->SwatchPts->SetPoint(2 * i + 1, x);

}

// polygons & cell colors
unsigned char* rgb;
double rgba[4];
vtkIdType ptIds[4];
for (int i = 0; i < this->P->NumColors; ++i)
{
ptIds[0] = 2 * i;
ptIds[1] = ptIds[0] + 1;
ptIds[2] = ptIds[1] + 2;
ptIds[3] = ptIds[0] + 2;
this->P->Polys->InsertNextCell(4, ptIds);

double rgbval;
if (this->LookupTable->UsingLogScale())
{
  rgbval = log10(range[0]) + i * (log10(range[1]) - log10(range[0])) / this->P->NumColors;
  rgbval = pow(10.0, rgbval);
}
else
{
  rgbval = range[0] + (range[1] - range[0]) * (i / static_cast<double>(this->P->NumColors));
}
lut->GetColor(rgbval, rgba);
rgba[3] = lut->GetOpacity(rgbval);

// write into array directly

if (!this->UseColorBarPointScalars)
{
rgb = this->P->SwatchColors->GetPointer(nComponents * i);
rgb[0] = static_cast(rgba[0] * 255.);
rgb[1] = static_cast(rgba[1] * 255.);
rgb[2] = static_cast(rgba[2] * 255.);
if (this->P->SwatchColors->GetNumberOfComponents() > 3)
{
rgb[3] = static_cast(this->UseOpacity ? rgba[3] * 255. : 255.);
}
}
else
{

  rgb = this->P->SwatchColors->GetPointer(nComponents * (i * 2));
  rgb[0] = static_cast<unsigned char>(rgba[0] * 255.);
  rgb[1] = static_cast<unsigned char>(rgba[1] * 255.);
  rgb[2] = static_cast<unsigned char>(rgba[2] * 255.);
  if (this->P->SwatchColors->GetNumberOfComponents() > 3)
  {
  	rgb[3] = static_cast<unsigned char>(this->UseOpacity ? rgba[3] * 255. : 255.);
  }

  rgb = this->P->SwatchColors->GetPointer(nComponents * (i * 2 + 1));
  rgb[0] = static_cast<unsigned char>(rgba[0] * 255.);
  rgb[1] = static_cast<unsigned char>(rgba[1] * 255.);
  rgb[2] = static_cast<unsigned char>(rgba[2] * 255.);
  if (this->P->SwatchColors->GetNumberOfComponents() > 3)
  {
  	rgb[3] = static_cast<unsigned char>(this->UseOpacity ? rgba[3] * 255. : 255.);
  }

}

}

// Set up a texture actor as an alternative to the 1-quad-per-color
// scalar bar polydata.
vtkPoints* texturePoints = vtkPoints::New();
texturePoints->SetNumberOfPoints(4);
this->TexturePolyData->SetPoints(texturePoints);
texturePoints->SetPoint(0, 0.0, 0.0, 0.0);

double p1[2], p2[2];
p1[0] = this->P->ScalarBarBox.Posn[0];
p1[1] = this->P->ScalarBarBox.Posn[1];
p2[0] = p1[0] + this->P->ScalarBarBox.Size[this->P->TL[0]];
p2[1] = p1[1] + this->P->ScalarBarBox.Size[this->P->TL[1]];

texturePoints->SetPoint(0, p1[0], p1[1], 0.0);
texturePoints->SetPoint(1, p2[0], p1[1], 0.0);
texturePoints->SetPoint(2, p2[0], p2[1], 0.0);
texturePoints->SetPoint(3, p1[0], p2[1], 0.0);
texturePoints->Delete();

double barWidth = this->P->ScalarBarBox.Size[this->P->TL[0]];
double barHeight = this->P->ScalarBarBox.Size[this->P->TL[1]];
vtkDataArray* tc = this->TexturePolyData->GetPointData()->GetTCoords();
tc->SetTuple2(1, barWidth / this->TextureGridWidth, 0.0);
tc->SetTuple2(2, barWidth / this->TextureGridWidth, barHeight / this->TextureGridWidth);
tc->SetTuple2(3, 0.0, barHeight / this->TextureGridWidth);
}

Here is what I added to the header file:

//@{
/**

  • Set to true to use point scalars on the scalar bar polydata.
  • If set to false the scalar bar polydata will use cell scalars.
  • For use in WebGL and OPENGL ES this must be set to true.
  • [Default: off]
    */
    vtkSetMacro(UseColorBarPointScalars, vtkTypeBool);
    vtkGetMacro(UseColorBarPointScalars, vtkTypeBool);
    vtkBooleanMacro(UseColorBarPointScalars, vtkTypeBool);
    //@}

Thanks!

1 Like

Thanks a lot. It worked. However in your code at some places static cast syntax is incorrect.

While the proposed solution is a good workaround, this issue has been resolved in VTK. vtkScalarBarActor relied on OpenGL implementation of vtkPolyDataMapper2D which targets desktop GL contexts but left out WebGL2 based contexts.

vtkOpenGLES30PolyDataMapper2D provides a GLES 3.0 (hence WebGL2) compatible implementation. vtkScalarBarActor, and by extension, all 2D actors with 2D polydata mappers will work out of the box in webassembly without external workarounds.