Skip to content
Merged
11 changes: 6 additions & 5 deletions shaders/contour-vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
precision mediump float;
precision highp float;

attribute vec4 uv;
attribute float f;

uniform vec3 objectOffset;
uniform mat3 permutation;
uniform mat4 model, view, projection;
uniform float height, zOffset;
Expand All @@ -16,15 +17,15 @@ varying vec4 vColor;

void main() {
vec3 dataCoordinate = permutation * vec3(uv.xy, height);
vec4 worldPosition = model * vec4(dataCoordinate, 1.0);
worldCoordinate = objectOffset + dataCoordinate;
vec4 worldPosition = model * vec4(worldCoordinate, 1.0);

vec4 clipPosition = projection * view * worldPosition;
clipPosition.z = clipPosition.z + zOffset;
clipPosition.z += zOffset;

gl_Position = clipPosition;
value = f;
value = f + objectOffset.z;
kill = -1.0;
worldCoordinate = dataCoordinate;
planeCoordinate = uv.zw;

vColor = texture2D(colormap, vec2(value, value));
Expand Down
7 changes: 5 additions & 2 deletions shaders/fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
precision mediump float;
precision highp float;

#pragma glslify: beckmann = require(glsl-specular-beckmann)
#pragma glslify: outOfRange = require(glsl-out-of-range)

uniform vec3 objectOffset;
uniform vec3 lowerBound, upperBound;
uniform float contourTint;
uniform vec4 contourColor;
Expand Down Expand Up @@ -32,7 +33,9 @@ void main() {
float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);

//decide how to interpolate color — in vertex or in fragment
vec4 surfaceColor = step(vertexColor, .5) * texture2D(colormap, vec2(value, value)) + step(.5, vertexColor) * vColor;
vec4 surfaceColor =
step(vertexColor, .5) * texture2D(colormap, vec2(value, value)) +
step(.5, vertexColor) * vColor;

vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);

Expand Down
2 changes: 1 addition & 1 deletion shaders/pick.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
precision mediump float;
precision highp float;

#pragma glslify: outOfRange = require(glsl-out-of-range)

Expand Down
6 changes: 4 additions & 2 deletions shaders/vertex.glsl
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
precision mediump float;
precision highp float;

attribute vec4 uv;
attribute vec3 f;
attribute vec3 normal;

uniform vec3 objectOffset;
uniform mat4 model, view, projection, inverseModel;
uniform vec3 lightPosition, eyePosition;
uniform sampler2D colormap;
Expand All @@ -15,7 +16,8 @@ varying vec3 lightDirection, eyeDirection, surfaceNormal;
varying vec4 vColor;

void main() {
worldCoordinate = vec3(uv.zw, f.x);
vec3 localCoordinate = vec3(uv.zw, f.x);
worldCoordinate = objectOffset + localCoordinate;
vec4 worldPosition = model * vec4(worldCoordinate, 1.0);
vec4 clipPosition = projection * view * worldPosition;
gl_Position = clipPosition;
Expand Down
79 changes: 56 additions & 23 deletions surface.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,13 @@ function SurfacePlot (
contourBuffer,
contourVAO,
dynamicBuffer,
dynamicVAO) {
dynamicVAO,
objectOffset) {
this.gl = gl
this.shape = shape
this.bounds = bounds
this.intensityBounds = [];
this.objectOffset = objectOffset
this.intensityBounds = []

this._shader = shader
this._pickShader = pickShader
Expand Down Expand Up @@ -267,6 +269,7 @@ var UNIFORMS = {
contourColor: [0, 0, 0, 1],
permutation: [1, 0, 0, 0, 1, 0, 0, 0, 1],
zOffset: -1e-4,
objectOffset: [0, 0, 0],
kambient: 1,
kdiffuse: 1,
kspecular: 1,
Expand Down Expand Up @@ -295,6 +298,7 @@ function drawCore (params, transparent) {
uniforms.projection = params.projection || IDENTITY
uniforms.lowerBound = [this.bounds[0][0], this.bounds[0][1], this.colorBounds[0] || this.bounds[0][2]]
uniforms.upperBound = [this.bounds[1][0], this.bounds[1][1], this.colorBounds[1] || this.bounds[1][2]]
uniforms.objectOffset = this.objectOffset
uniforms.contourColor = this.contourColor[0]

uniforms.inverseModel = invert(uniforms.inverseModel, uniforms.model)
Expand Down Expand Up @@ -400,7 +404,9 @@ function drawCore (params, transparent) {
if (!this._contourCounts[i][j]) {
continue
}

shader.uniforms.height = this.contourLevels[i][j]

vao.draw(gl.LINES, this._contourCounts[i][j], this._contourOffsets[i][j])
}
}
Expand Down Expand Up @@ -428,6 +434,7 @@ function drawCore (params, transparent) {
}
}
}

vao.unbind()

// Draw dynamic contours
Expand Down Expand Up @@ -485,6 +492,7 @@ var PICK_UNIFORMS = {
lowerBound: [0, 0, 0],
upperBound: [0, 0, 0],
zOffset: 0.0,
objectOffset: [0, 0, 0],
permutation: [1, 0, 0, 0, 1, 0, 0, 0, 1],
lightPosition: [0, 0, 0],
eyePosition: [0, 0, 0]
Expand All @@ -503,6 +511,7 @@ proto.drawPick = function (params) {
uniforms.pickId = this.pickId / 255.0
uniforms.lowerBound = this.bounds[0]
uniforms.upperBound = this.bounds[1]
uniforms.objectOffset = this.objectOffset
uniforms.permutation = DEFAULT_PERM

for (var i = 0; i < 2; ++i) {
Expand Down Expand Up @@ -714,6 +723,8 @@ function handleColor (param) {
proto.update = function (params) {
params = params || {}

this.objectOffset = params.objectOffset || this.objectOffset

this.dirty = true

if ('contourWidth' in params) {
Expand Down Expand Up @@ -922,8 +933,8 @@ proto.update = function (params) {

var tx = this._field[0].get(r + 1, c + 1)
var ty = this._field[1].get(r + 1, c + 1)
f = this._field[2].get(r + 1, c + 1)
var vf = f
f = this._field[2].get(r + 1, c + 1)

nx = normals.get(r + 1, c + 1, 0)
ny = normals.get(r + 1, c + 1, 1)
nz = normals.get(r + 1, c + 1, 2)
Expand All @@ -932,6 +943,10 @@ proto.update = function (params) {
vf = params.intensity.get(r, c)
}

var vf = (params.intensity) ?
params.intensity.get(r, c) :
f + this.objectOffset[2];

tverts[tptr++] = r
tverts[tptr++] = c
tverts[tptr++] = tx
Expand All @@ -943,14 +958,14 @@ proto.update = function (params) {
tverts[tptr++] = ny
tverts[tptr++] = nz

lo[0] = Math.min(lo[0], tx)
lo[1] = Math.min(lo[1], ty)
lo[2] = Math.min(lo[2], f)
lo[0] = Math.min(lo[0], tx + this.objectOffset[0])
lo[1] = Math.min(lo[1], ty + this.objectOffset[1])
lo[2] = Math.min(lo[2], f + this.objectOffset[2])
lo_intensity = Math.min(lo_intensity, vf)

hi[0] = Math.max(hi[0], tx)
hi[1] = Math.max(hi[1], ty)
hi[2] = Math.max(hi[2], f)
hi[0] = Math.max(hi[0], tx + this.objectOffset[0])
hi[1] = Math.max(hi[1], ty + this.objectOffset[1])
hi[2] = Math.max(hi[2], f + this.objectOffset[2])
hi_intensity = Math.max(hi_intensity, vf)

vertexCount += 1
Expand Down Expand Up @@ -1001,6 +1016,11 @@ proto.update = function (params) {
return a - b
})
}
for (i = 0; i < 3; ++i) {
for (j = 0; j < levels[i].length; ++j) {
levels[i][j] -= this.objectOffset[i]
}
}
change_test:
for (i = 0; i < 3; ++i) {
if (levels[i].length !== this.contourLevels[i].length) {
Expand Down Expand Up @@ -1033,6 +1053,7 @@ proto.update = function (params) {

for (i = 0; i < levels.length; ++i) {
var graph = surfaceNets(this._field[dim], levels[i])

levelOffsets.push((contourVerts.length / 5) | 0)
vertexCount = 0

Expand All @@ -1051,35 +1072,41 @@ proto.update = function (params) {
var fy = y - iy

var hole = false
dd_loop:
for (var dd = 0; dd < 3; ++dd) {
parts[dd] = 0.0
var iu = (dim + dd + 1) % 3
axis_loop:
for (var axis = 0; axis < 3; ++axis) {
parts[axis] = 0.0
var iu = (dim + axis + 1) % 3
for (dx = 0; dx < 2; ++dx) {
var s = dx ? fx : 1.0 - fx
r = Math.min(Math.max(ix + dx, 0), shape[0]) | 0
for (dy = 0; dy < 2; ++dy) {
var t = dy ? fy : 1.0 - fy
c = Math.min(Math.max(iy + dy, 0), shape[1]) | 0

if (dd < 2) {
if (axis < 2) {
f = this._field[iu].get(r, c)
} else {
f = (this.intensity.get(r, c) - this.intensityBounds[0]) / (this.intensityBounds[1] - this.intensityBounds[0])
}
if (!isFinite(f) || isNaN(f)) {
hole = true
break dd_loop
break axis_loop
}

var w = s * t
parts[dd] += w * f
parts[axis] += w * f
}
}
}

if (!hole) {
contourVerts.push(parts[0], parts[1], p[0], p[1], parts[2])
contourVerts.push(
parts[0],
parts[1],
p[0],
p[1],
parts[2]
)
vertexCount += 1
} else {
if (k > 0) {
Expand All @@ -1099,6 +1126,7 @@ proto.update = function (params) {
// Store results
this._contourOffsets[dim] = levelOffsets
this._contourCounts[dim] = levelCounts

}

var floatBuffer = pool.mallocFloat(contourVerts.length)
Expand Down Expand Up @@ -1131,14 +1159,16 @@ proto.dispose = function () {
}

proto.highlight = function (selection) {
var i

if (!selection) {
this._dynamicCounts = [0, 0, 0]
this.dyanamicLevel = [NaN, NaN, NaN]
this.highlightLevel = [-1, -1, -1]
return
}

for (var i = 0; i < 3; ++i) {
for (i = 0; i < 3; ++i) {
if (this.enableHighlight[i]) {
this.highlightLevel[i] = selection.level[i]
} else {
Expand All @@ -1152,6 +1182,9 @@ proto.highlight = function (selection) {
} else {
levels = selection.position
}
for (i = 0; i < 3; ++i) {
levels[i] -= this.objectOffset[i]
}
if ((!this.enableDynamic[0] || levels[0] === this.dynamicLevel[0]) &&
(!this.enableDynamic[1] || levels[1] === this.dynamicLevel[1]) &&
(!this.enableDynamic[2] || levels[2] === this.dynamicLevel[2])) {
Expand All @@ -1177,7 +1210,6 @@ proto.highlight = function (selection) {
var f = this._field[d]
var g = this._field[u]
var h = this._field[v]
var intensity = this.intensity

var graph = surfaceNets(f, levels[d])
var edges = graph.cells
Expand Down Expand Up @@ -1295,8 +1327,8 @@ function createSurfacePlot (params) {

var surface = new SurfacePlot(
gl,
[0, 0],
[[0, 0, 0], [0, 0, 0]],
[0, 0], // shape
[[0, 0, 0], [0, 0, 0]], // bounds
shader,
pickShader,
coordinateBuffer,
Expand All @@ -1307,7 +1339,8 @@ function createSurfacePlot (params) {
contourBuffer,
contourVAO,
dynamicBuffer,
dynamicVAO
dynamicVAO,
[0, 0, 0] // objectOffset
)

var nparams = {
Expand Down