Skip to content

Commit bdc7e01

Browse files
sankheshfloryst
authored andcommitted
feat(polydatamapper2d): cell scalar based coloring for PolyDataMapper2D
1 parent d259125 commit bdc7e01

File tree

1 file changed

+144
-51
lines changed
  • Sources/Rendering/OpenGL/PolyDataMapper2D

1 file changed

+144
-51
lines changed

Sources/Rendering/OpenGL/PolyDataMapper2D/index.js

Lines changed: 144 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ import vtkPolyData2DVS from 'vtk.js/Sources/Rendering/OpenGL/glsl/vtkPolyData2DV
1010
import vtkReplacementShaderMapper from 'vtk.js/Sources/Rendering/OpenGL/ReplacementShaderMapper';
1111
import vtkShaderProgram from 'vtk.js/Sources/Rendering/OpenGL/ShaderProgram';
1212
import vtkViewNode from 'vtk.js/Sources/Rendering/SceneGraph/ViewNode';
13+
import vtkOpenGLTexture from 'vtk.js/Sources/Rendering/OpenGL/Texture';
1314

1415
import { round } from 'vtk.js/Sources/Common/Core/Math';
1516

1617
import { DisplayLocation } from 'vtk.js/Sources/Rendering/Core/Property2D/Constants';
1718

1819
import { registerOverride } from 'vtk.js/Sources/Rendering/OpenGL/ViewNodeFactory';
1920

21+
import { ScalarMode } from 'vtk.js/Sources/Rendering/Core/Mapper/Constants';
22+
2023
const { primTypes } = vtkHelper;
21-
const { ScalarMode } = vtkMapper2D;
24+
const { Filter, Wrap } = vtkOpenGLTexture;
2225
const { vtkErrorMacro } = macro;
2326
const StartEvent = { type: 'StartEvent' };
2427
const EndEvent = { type: 'EndEvent' };
@@ -91,6 +94,12 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
9194
) {
9295
return;
9396
}
97+
98+
// cull back face to avoid double drawing
99+
const gl = model.context;
100+
model._openGLRenderWindow.enableCullFace();
101+
gl.cullFace(gl.BACK);
102+
94103
publicAPI.renderPieceStart(ren, actor);
95104
publicAPI.renderPieceDraw(ren, actor);
96105
publicAPI.renderPieceFinish(ren, actor);
@@ -105,6 +114,13 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
105114
model._openGLRenderer.getSelector().renderProp(actor);
106115
}
107116
}
117+
118+
// If we are coloring by texture, then load the texture map.
119+
// Use Map as indicator, because texture hangs around.
120+
if (model.renderable.getColorTextureMap()) {
121+
model.internalColorTexture.activate();
122+
}
123+
108124
// make sure the BOs are up to date
109125
publicAPI.updateBufferObjects(ren, actor);
110126

@@ -161,30 +177,47 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
161177

162178
model.renderable.mapScalars(poly, actor.getProperty().getOpacity());
163179
const c = model.renderable.getColorMapColors();
164-
165-
model.haveCellScalars = false;
166-
const scalarMode = model.renderable.getScalarMode();
167-
if (model.renderable.getScalarVisibility()) {
168-
// We must figure out how the scalars should be mapped to the polydata.
169-
if (
170-
(scalarMode === ScalarMode.USE_CELL_DATA ||
171-
scalarMode === ScalarMode.USE_CELL_FIELD_DATA ||
172-
scalarMode === ScalarMode.USE_FIELD_DATA ||
173-
!poly.getPointData().getScalars()) &&
174-
scalarMode !== ScalarMode.USE_POINT_FIELD_DATA &&
175-
c
176-
) {
177-
model.haveCellScalars = true;
178-
}
179-
}
180-
181180
const representation = actor.getProperty().getRepresentation();
182181

183182
let tcoords = poly.getPointData().getTCoords();
184183
if (!model.openGLActor2D.getActiveTextures()) {
185184
tcoords = null;
186185
}
187186

187+
// Flag to check if tcoords are per cell instead of per point
188+
let useTCoordsPerCell = false;
189+
// handle color mapping via texture
190+
if (model.renderable.getColorCoordinates()) {
191+
tcoords = model.renderable.getColorCoordinates();
192+
useTCoordsPerCell = model.renderable.getAreScalarsMappedFromCells();
193+
if (!model.internalColorTexture) {
194+
model.internalColorTexture = vtkOpenGLTexture.newInstance({
195+
resizable: true,
196+
});
197+
}
198+
const tex = model.internalColorTexture;
199+
// the following 4 lines allow for NPOT textures
200+
tex.setMinificationFilter(Filter.NEAREST);
201+
tex.setMagnificationFilter(Filter.NEAREST);
202+
tex.setWrapS(Wrap.CLAMP_TO_EDGE);
203+
tex.setWrapT(Wrap.CLAMP_TO_EDGE);
204+
tex.setOpenGLRenderWindow(model._openGLRenderWindow);
205+
206+
const input = model.renderable.getColorTextureMap();
207+
const ext = input.getExtent();
208+
const inScalars = input.getPointData().getScalars();
209+
tex.create2DFromRaw({
210+
width: ext[1] - ext[0] + 1,
211+
height: ext[3] - ext[2] + 1,
212+
numComps: inScalars.getNumberOfComponents(),
213+
dataType: inScalars.getDataType(),
214+
data: inScalars.getData(),
215+
});
216+
tex.activate();
217+
tex.sendParameters();
218+
tex.deactivate();
219+
}
220+
188221
const transformCoordinate = model.renderable.getTransformCoordinate();
189222

190223
const view = ren.getRenderWindow().getViews()[0];
@@ -216,7 +249,8 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
216249
tcoords,
217250
colors: c,
218251
cellOffset: 0,
219-
haveCellScalars: model.haveCellSCalars,
252+
useTCoordsPerCell,
253+
haveCellScalars: model.renderable.getAreScalarsMappedFromCells(),
220254
customAttributes: model.renderable
221255
.getCustomShaderAttributes()
222256
.map((arrayName) => poly.getPointData().getArrayByName(arrayName)),
@@ -264,6 +298,9 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
264298
if (model.lastBoundBO) {
265299
model.lastBoundBO.getVAO().release();
266300
}
301+
if (model.renderable.getColorTextureMap()) {
302+
model.internalColorTexture.deactivate();
303+
}
267304
};
268305

269306
publicAPI.replaceShaderValues = (shaders, ren, actor) => {
@@ -277,44 +314,71 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
277314
let VSSource = shaders.Vertex;
278315
let GSSource = shaders.Geometry;
279316
let FSSource = shaders.Fragment;
280-
if (model.haveCellScalars) {
281-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Dec', [
282-
'uniform samplerBuffer texture1;',
283-
]).result;
284-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Impl', [
285-
'gl_FragData[0] = texelFetchBuffer(texture1, gl_PrimitiveID + PrimitiveIDOffset);',
286-
]).result;
287-
}
317+
318+
// create the color property declarations
319+
// these are always defined
320+
let colorDec = [
321+
'uniform vec3 diffuseColorUniform;',
322+
'uniform float opacityUniform;',
323+
];
324+
325+
// now handle the more complex fragment shader implementation
326+
let colorImpl = [
327+
'vec3 diffuseColor = diffuseColorUniform;',
328+
'float opacity = opacityUniform;',
329+
];
330+
331+
// add scalar vertex colors
288332
if (model.lastBoundBO.getCABO().getColorComponents() !== 0) {
333+
colorDec = colorDec.concat(['varying vec4 vertexColorVSOutput;']);
289334
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Color::Dec', [
290-
'in vec4 diffuseColor;',
291-
'out vec4 fcolorVSOutput;',
335+
'attribute vec4 scalarColor;',
336+
'varying vec4 vertexColorVSOutput;',
292337
]).result;
293338
VSSource = vtkShaderProgram.substitute(VSSource, '//VTK::Color::Impl', [
294-
'fcolorVSOutput = diffuseColor;',
339+
'vertexColorVSOutput = scalarColor;',
295340
]).result;
296341
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::Color::Dec', [
297-
'in vec4 fcolorVSOutput[];\n',
298-
'out vec4 fcolorGSOutput;',
342+
'in vec4 vertexColorVSOutput[];',
343+
'out vec4 vertexColorGSOutput;',
299344
]).result;
300345
GSSource = vtkShaderProgram.substitute(GSSource, '//VTK::Color::Impl', [
301-
'fcolorGSOutput = fcolorVSOutput[i];',
302-
]).result;
303-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Dec', [
304-
'in vec4 fcolorVSOutput;',
305-
]).result;
306-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Impl', [
307-
'gl_FragData[0] = fcolorVSOutput;',
346+
'vertexColorGSOutput = vertexColorVSOutput[i];',
308347
]).result;
348+
FSSource = vtkShaderProgram.substitute(
349+
FSSource,
350+
'//VTK::Color::Impl',
351+
colorImpl.concat([
352+
' diffuseColor = vertexColorVSOutput.rgb;',
353+
' ambientColor = vertexColorVSOutput.rgb;',
354+
' opacity = opacity*vertexColorVSOutput.a;',
355+
])
356+
).result;
309357
} else {
310-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Dec', [
311-
'uniform vec4 diffuseColor;',
312-
]).result;
313-
FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::Color::Impl', [
314-
'gl_FragData[0] = diffuseColor;',
315-
]).result;
358+
if (model.renderable.getAreScalarsMappedFromCells()) {
359+
colorImpl = colorImpl.concat([
360+
' vec4 texColor = texture2D(texture1, tcoordVCVSOutput.st);',
361+
' diffuseColor = texColor.rgb;',
362+
' opacity = opacity*texColor.a;',
363+
]);
364+
}
316365
}
317366

367+
colorImpl = colorImpl.concat([
368+
'gl_FragData[0] = vec4(diffuseColor, opacity);',
369+
]);
370+
371+
FSSource = vtkShaderProgram.substitute(
372+
FSSource,
373+
'//VTK::Color::Dec',
374+
colorDec
375+
).result;
376+
FSSource = vtkShaderProgram.substitute(
377+
FSSource,
378+
'//VTK::Color::Impl',
379+
colorImpl
380+
).result;
381+
318382
shaders.Vertex = VSSource;
319383
shaders.Geometry = GSSource;
320384
shaders.Fragment = FSSource;
@@ -388,7 +452,7 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
388452
).result;
389453
}
390454

391-
if (model.haveCellScalars) {
455+
if (model.renderable.getAreScalarsMappedFromCells()) {
392456
GSSource = vtkShaderProgram.substitute(
393457
GSSource,
394458
'//VTK::PrimID::Impl',
@@ -507,13 +571,42 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
507571
} else {
508572
cellBO.getVAO().removeAttributeArray('tcoordMC');
509573
}
574+
if (
575+
cellBO.getProgram().isAttributeUsed('scalarColor') &&
576+
cellBO.getCABO().getColorComponents()
577+
) {
578+
if (
579+
!cellBO
580+
.getVAO()
581+
.addAttributeArray(
582+
cellBO.getProgram(),
583+
cellBO.getCABO().getColorBO(),
584+
'scalarColor',
585+
cellBO.getCABO().getColorOffset(),
586+
cellBO.getCABO().getColorBOStride(),
587+
model.context.UNSIGNED_BYTE,
588+
4,
589+
true
590+
)
591+
) {
592+
vtkErrorMacro('Error setting scalarColor in shader VAO.');
593+
}
594+
} else {
595+
cellBO.getVAO().removeAttributeArray('scalarColor');
596+
}
510597
if (
511598
model.internalColorTexture &&
512599
cellBO.getProgram().isUniformUsed('texture1')
513600
) {
514-
cellBO
515-
.getProgram()
516-
.setUniformi('texture1', model.internalColorTexture.getTextureUnit());
601+
let texUnit = model.internalColorTexture.getTextureUnit();
602+
if (texUnit > -1) {
603+
cellBO
604+
.getProgram()
605+
.setUniformi(
606+
'texture1',
607+
model.internalColorTexture.getTextureUnit()
608+
);
609+
}
517610
}
518611
const tus = model.openGLActor2D.getActiveTextures();
519612
if (tus) {
@@ -553,9 +646,9 @@ function vtkOpenGLPolyDataMapper2D(publicAPI, model) {
553646
const program = cellBO.getProgram();
554647
const ppty = actor.getProperty();
555648
const opacity = ppty.getOpacity();
649+
program.setUniformf('opacityUniform', opacity);
556650
const dColor = ppty.getColor();
557-
const diffuseColor = [dColor[0], dColor[1], dColor[2], opacity];
558-
program.setUniform4f('diffuseColor', diffuseColor);
651+
program.setUniform3fArray('diffuseColorUniform', dColor);
559652
}
560653
};
561654

0 commit comments

Comments
 (0)