processScene = (scene, parameters) => {
let flattenedScene = prepareForGPU(scene)
const translateVector = [parameters.mx, parameters.my, parameters.mz, 0]
const wtMatrix = worldTransformMatrixFn(parameters)
const apMatrices = anaglyphPerspectiveMatricesFn(parameters)
const processChunk = (chunk) => {
const translationKernel = gpu.createKernel(function(points, translate) {
let sum = 0;
sum += points[this.thread.y][this.thread.x] + translate[this.thread.x]
return sum;
})
.setPipeline(true)
.setOutput([4, chunk.length]);
const worldTransformKernel = gpu.createKernel(function(points, worldTransformMatrix) {
let sum = 0;
for (let i = 0; i < 4; i++) {
sum += points[this.thread.y][i] * worldTransformMatrix[i][this.thread.x];
}
return sum;
})
.setPipeline(true)
.setOutput([4, chunk.length]);
const eyeShiftKernel = gpu.createKernel(function(points, shift, cameraOffset) {
let sideShift = (this.thread.x === 0) ? shift[this.thread.y] : 0
let cOffset = (this.thread.x === 2) ? -cameraOffset : 0
return points[this.thread.z][this.thread.x] + sideShift + cOffset
})
.setPipeline(true)
.setOutput([4, 2, chunk.length])
const anaglyphPerspectiveKernel = gpu.createKernel(function(points, anaglyphPerspectiveMatrices) {
let sum = 0;
for (let i = 0; i < 4; i++) {
sum += points[this.thread.z][this.thread.y][i] * anaglyphPerspectiveMatrices[this.thread.y][i][this.thread.x]
}
return sum;
})
.setPipeline(true)
.setOutput([4, 2, chunk.length])
const divisionKernel = gpu.createKernel(function(points, scale) {
const factor = (this.thread.x <= 1) ? scale / points[this.thread.z][this.thread.y][3] : 1
return points[this.thread.z][this.thread.y][this.thread.x] * factor
}).setOutput([3, 2, chunk.length])
return divisionKernel(anaglyphPerspectiveKernel(eyeShiftKernel(worldTransformKernel(translationKernel(chunk, translateVector), wtMatrix), [-parameters.eyeGap / 2, parameters.eyeGap / 2], parameters.cameraOffset), apMatrices), parameters.scale)
}
const maxTextureSize = 16384
const numOfChunks = Math.ceil(flattenedScene.length / maxTextureSize)
const chunks = d3.range(numOfChunks).map((i) => {
return flattenedScene.splice(0, maxTextureSize)
})
.map(processChunk)
let flatResults = [].concat.apply([], chunks);
const results = scene.map((entity) => {
const anaglyphPoints = flatResults.splice(0, entity.length)
Object.keys(entity).forEach((key) => {
if (!Number.isInteger(parseInt(key))) {
anaglyphPoints[key] = entity[key]
}
})
return anaglyphPoints
})
return results
}