Skip to content

Commit

Permalink
Merge pull request #630 from Kitware/add_skybox
Browse files Browse the repository at this point in the history
add vtkSkybox class and fix depth comparison issue
  • Loading branch information
jourdain authored Mar 7, 2018
2 parents 6d2ac32 + a854630 commit 8a6ff8d
Show file tree
Hide file tree
Showing 14 changed files with 398 additions and 934 deletions.
Binary file modified Sources/Common/Core/LookupTable/test/testCategoricalColors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions Sources/Rendering/Core/Skybox/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import macro from 'vtk.js/Sources/macro';
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';

// ----------------------------------------------------------------------------
// vtkSkybox methods
// ----------------------------------------------------------------------------

function vtkSkybox(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkSkybox');

publicAPI.getIsOpaque = () => true;

publicAPI.hasTranslucentPolygonalGeometry = () => false;

publicAPI.getSupportsSelection = () => false;
}

// ----------------------------------------------------------------------------
// Object fSkyboxy
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

// Inheritance
vtkActor.extend(publicAPI, model, initialValues);

// Build VTK API

// Object methods
vtkSkybox(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend, 'vtkSkybox');

// ----------------------------------------------------------------------------

export default { newInstance, extend };
2 changes: 2 additions & 0 deletions Sources/Rendering/Core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import vtkRenderer from './Renderer';
import vtkRenderWindow from './RenderWindow';
import vtkRenderWindowInteractor from './RenderWindowInteractor';
import vtkRepresentation from './Representation';
import vtkSkybox from './Skybox';
import vtkSphereMapper from './SphereMapper';
import vtkStickMapper from './StickMapper';
import vtkTexture from './Texture';
Expand Down Expand Up @@ -61,6 +62,7 @@ export default {
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRepresentation,
vtkSkybox,
vtkSphereMapper,
vtkStickMapper,
vtkTexture,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Sources/Rendering/OpenGL/RenderWindow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
gl.ONE,
gl.ONE_MINUS_SRC_ALPHA
);
gl.depthFunc(gl.LEQUAL);
gl.enable(gl.BLEND);
model.initialized = true;
}
Expand Down
215 changes: 215 additions & 0 deletions Sources/Rendering/OpenGL/Skybox/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
import { mat3, mat4 } from 'gl-matrix';

import macro from 'vtk.js/Sources/macro';
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';
import vtkHelper from 'vtk.js/Sources/Rendering/OpenGL/Helper';
import vtkViewNode from 'vtk.js/Sources/Rendering/SceneGraph/ViewNode';
import vtkOpenGLTexture from 'vtk.js/Sources/Rendering/OpenGL/Texture';

import { Representation } from 'vtk.js/Sources/Rendering/Core/Property/Constants';

const { vtkErrorMacro } = macro;

// ----------------------------------------------------------------------------
// vtkOpenGLSkybox methods
// ----------------------------------------------------------------------------

function vtkOpenGLSkybox(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkOpenGLSkybox');

// Builds myself.
publicAPI.buildPass = (prepass) => {
if (prepass) {
model.openGLRenderer = publicAPI.getFirstAncestorOfType(
'vtkOpenGLRenderer'
);
model.openGLRenderWindow = model.openGLRenderer.getParent();
model.context = model.openGLRenderWindow.getContext();
model.tris.setOpenGLRenderWindow(model.openGLRenderWindow);
model.openGLTexture.setOpenGLRenderWindow(model.openGLRenderWindow);
const ren = model.openGLRenderer.getRenderable();
model.openGLCamera = model.openGLRenderer.getViewNodeFor(
ren.getActiveCamera()
);
}
};

publicAPI.queryPass = (prepass, renderPass) => {
if (prepass) {
if (!model.renderable || !model.renderable.getVisibility()) {
return;
}
renderPass.incrementOpaqueActorCount();
}
};

publicAPI.opaquePass = (prepass, renderPass) => {
if (prepass) {
publicAPI.updateBufferObjects();

model.openGLRenderWindow.enableDepthMask();

model.openGLRenderWindow
.getShaderCache()
.readyShaderProgram(model.tris.getProgram());

model.openGLTexture.render(model.openGLRenderWindow);

const texUnit = model.openGLTexture.getTextureUnit();
model.tris.getProgram().setUniformi('sbtexture', texUnit);

const ren = model.openGLRenderer.getRenderable();

const keyMats = model.openGLCamera.getKeyMatrices(ren);
const imat = mat4.create();
mat4.invert(imat, keyMats.wcdc);
model.tris.getProgram().setUniformMatrix('IMCDCMatrix', imat);

const camPos = ren.getActiveCamera().getPosition();
model.tris
.getProgram()
.setUniform3f('camPos', camPos[0], camPos[1], camPos[2]);
model.tris.getVAO().bind();

// draw polygons
model.context.drawArrays(
model.context.TRIANGLES,
0,
model.tris.getCABO().getElementCount()
);
model.tris.getVAO().release();

model.openGLTexture.deactivate();
}
};

publicAPI.updateBufferObjects = () => {
if (model.tris.getCABO().getElementCount()) {
return;
}

const ptsArray = new Float32Array(12);
for (let i = 0; i < 4; i++) {
ptsArray[i * 3] = (i % 2) * 2 - 1.0;
ptsArray[i * 3 + 1] = i > 1 ? 1.0 : -1.0;
ptsArray[i * 3 + 2] = 1.0;
}
const points = vtkDataArray.newInstance({
numberOfComponents: 3,
values: ptsArray,
});
points.setName('points');

const cellArray = new Uint16Array(8);
cellArray[0] = 3;
cellArray[1] = 0;
cellArray[2] = 1;
cellArray[3] = 3;
cellArray[4] = 3;
cellArray[5] = 0;
cellArray[6] = 3;
cellArray[7] = 2;
const cells = vtkDataArray.newInstance({
numberOfComponents: 1,
values: cellArray,
});

model.tris.getCABO().createVBO(cells, 'polys', Representation.SURFACE, {
points,
cellOffset: 0,
});

const tmaps = model.renderable.getTextures();
if (!tmaps.length) {
vtkErrorMacro('vtkSkybox requires a texture map');
}
model.openGLTexture.setRenderable(tmaps[0]);

model.tris.setProgram(
model.openGLRenderWindow.getShaderCache().readyShaderProgramArray(
`//VTK::System::Dec
attribute vec3 vertexMC;
varying vec3 TexCoords;
uniform mat4 IMCDCMatrix;
uniform vec3 camPos;
void main () {
gl_Position = vec4(vertexMC.xyz, 1.0);
vec4 wpos = IMCDCMatrix * gl_Position;
TexCoords = normalize(wpos.xyz/wpos.w - camPos);
}`,
`//VTK::System::Dec
//VTK::Output::Dec
varying vec3 TexCoords;
uniform samplerCube sbtexture;
void main () {
gl_FragData[0] = textureCube(sbtexture, TexCoords);
}`,
''
)
);

model.tris.getShaderSourceTime().modified();
model.tris.getVAO().bind();

if (
!model.tris
.getVAO()
.addAttributeArray(
model.tris.getProgram(),
model.tris.getCABO(),
'vertexMC',
model.tris.getCABO().getVertexOffset(),
model.tris.getCABO().getStride(),
model.context.FLOAT,
3,
model.context.FALSE
)
) {
vtkErrorMacro('Error setting vertexMC in shader VAO.');
}
};
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
context: null,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

// Inheritance
vtkViewNode.extend(publicAPI, model, initialValues);

model.openGLTexture = vtkOpenGLTexture.newInstance();
model.tris = vtkHelper.newInstance();

model.keyMatrixTime = {};
macro.obj(model.keyMatrixTime, { mtime: 0 });
model.keyMatrices = {
normalMatrix: mat3.create(),
mcwc: mat4.create(),
};

// Build VTK API
macro.setGet(publicAPI, model, ['context']);

macro.get(publicAPI, model, ['activeTextures']);

// Object methods
vtkOpenGLSkybox(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend);

// ----------------------------------------------------------------------------

export default { newInstance, extend };
104 changes: 104 additions & 0 deletions Sources/Rendering/OpenGL/Skybox/test/testSkybox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import vtkSkybox from 'vtk.js/Sources/Rendering/Core/Skybox';
import vtkHttpDataSetReader from 'vtk.js/Sources/IO/Core/HttpDataSetReader';
import vtkOpenGLRenderWindow from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow';
import vtkTexture from 'vtk.js/Sources/Rendering/Core/Texture';
import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer';
import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow';

import test from 'tape-catch';
import testUtils from 'vtk.js/Sources/Testing/testUtils';

import baseline from './testSkybox.png';

test.onlyIfWebGL('Test vtkOpenGLSkybox Rendering', (t) => {
const gc = testUtils.createGarbageCollector(t);
t.ok('Rendering', 'Filter: OpenGLTexture');

function callBackfunction(loadedTextures) {
// Create come control UI
const container = document.querySelector('body');
const renderWindowContainer = gc.registerDOMElement(
document.createElement('div')
);
container.appendChild(renderWindowContainer);

// Create view
const renderWindow = gc.registerResource(vtkRenderWindow.newInstance());
const renderer = gc.registerResource(vtkRenderer.newInstance());
renderWindow.addRenderer(renderer);

const texture = gc.registerResource(vtkTexture.newInstance());
for (let i = 0; i < 6; i++) {
const scalarName = loadedTextures[i]
.getPointData()
.getArrayByIndex(0)
.getName();
loadedTextures[i].getPointData().setActiveScalars(scalarName);
texture.setInputData(loadedTextures[i], i);
}

const actor = gc.registerResource(vtkSkybox.newInstance());
actor.addTexture(texture);
renderer.addActor(actor);

renderer.getActiveCamera().setViewUp(0, -1, 0);
renderer.getActiveCamera().setFocalPoint(0, 0, 1);
renderer.getActiveCamera().setPosition(0, 0, -50);
renderer.resetCameraClippingRange();

const glwindow = gc.registerResource(vtkOpenGLRenderWindow.newInstance());
glwindow.setContainer(renderWindowContainer);
renderWindow.addView(glwindow);
glwindow.setSize(400, 400);

const image = glwindow.captureImage();
testUtils.compareImages(
image,
[baseline],
'Rendering/OpenGL/Skybox/',
t,
0.5,
gc.releaseResources
);
}

// Recursive function to load texture one by one
function loadTexture(
idTexture,
texturePathList,
textureImageList,
endCallBack
) {
if (idTexture === texturePathList.length) {
if (endCallBack) {
// check if endcallback exists
endCallBack(textureImageList);
}
return;
}

const reader = gc.registerResource(
vtkHttpDataSetReader.newInstance({ fetchGzip: true })
);
reader.setUrl(texturePathList[idTexture]).then(() => {
reader.loadData().then(() => {
textureImageList.push(reader.getOutputData());
const nextID = idTexture + 1;
loadTexture(nextID, texturePathList, textureImageList, endCallBack);
}); // end loadData
}); // end set url
}

const path = `${__BASE_PATH__}/Data/skybox/mountains/`;
const texturePathList = [];
texturePathList.push(`${path}px.vti`);
texturePathList.push(`${path}nx.vti`);
texturePathList.push(`${path}py.vti`);
texturePathList.push(`${path}ny.vti`);
texturePathList.push(`${path}pz.vti`);
texturePathList.push(`${path}nz.vti`);

// It will contains all vtkImageData which will textured the cube
const textures = [];
loadTexture(0, texturePathList, textures, callBackfunction);
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 8a6ff8d

Please sign in to comment.