diff --git a/src/mol-geo/representation/volume/direct-volume.ts b/src/mol-geo/representation/volume/direct-volume.ts index db1cc6544c5dd503704fd326e213cd2cda2e5cd9..8574b8671b8150f6c636a76929a20f3307b540ab 100644 --- a/src/mol-geo/representation/volume/direct-volume.ts +++ b/src/mol-geo/representation/volume/direct-volume.ts @@ -134,8 +134,9 @@ function createVolumeTexture3d(volume: VolumeData) { let i = 0 for (let z = 0; z < depth; ++z) { + for (let y = 0; y < height; ++y) { for (let x = 0; x < width; ++x) { - for (let y = 0; y < height; ++y) { + array[i + 3] = ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255 i += 4 } diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index 55dcdec498fed1fe9c9ff131a39bdde9f53d1cfb..93b419807a9fe3cd7ea298a5c3d00a2da58a7365 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -126,12 +126,16 @@ export const GlobalUniformSchema = { uModelView: UniformSpec('m4'), uInvModelView: UniformSpec('m4'), uProjection: UniformSpec('m4'), + uInvProjection: UniformSpec('m4'), + uModelViewProjection: UniformSpec('m4'), + uInvModelViewProjection: UniformSpec('m4'), // uLightPosition: Uniform('v3'), uLightColor: UniformSpec('v3'), uLightAmbient: UniformSpec('v3'), uPixelRatio: UniformSpec('f'), uViewportHeight: UniformSpec('f'), + uViewport: UniformSpec('v4'), uHighlightColor: UniformSpec('v3'), uSelectColor: UniformSpec('v3'), diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index 3e58b1994c8a5889fddda9b2b16bf504890ea596..35a940f89178885396d31114922b72f86d9056f4 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -10,7 +10,7 @@ import { Camera } from 'mol-view/camera/base'; import Scene from './scene'; import { Context, createImageData } from './webgl/context'; -import { Mat4, Vec3 } from 'mol-math/linear-algebra'; +import { Mat4, Vec3, Vec4 } from 'mol-math/linear-algebra'; import { Renderable } from './renderable'; import { Color } from 'mol-util/color'; import { ValueCell } from 'mol-util'; @@ -54,6 +54,7 @@ namespace Renderer { let { clearColor, viewport: _viewport } = { ...DefaultRendererProps, ...props } const viewport = Viewport.clone(_viewport) + const viewportVec4 = Viewport.toVec4(Vec4.zero(), viewport) // const lightPosition = Vec3.create(0, 0, -100) const lightColor = Vec3.create(1.0, 1.0, 1.0) @@ -72,6 +73,9 @@ namespace Renderer { const invView = Mat4.invert(Mat4.identity(), view) const modelView = Mat4.clone(camera.view) const invModelView = Mat4.invert(Mat4.identity(), modelView) + const invProjection = Mat4.invert(Mat4.identity(), camera.projection) + const modelViewProjection = Mat4.mul(Mat4.identity(), modelView, camera.projection) + const invModelViewProjection = Mat4.invert(Mat4.identity(), modelViewProjection) const globalUniforms: GlobalUniformValues = { uModel: ValueCell.create(Mat4.identity()), @@ -79,10 +83,14 @@ namespace Renderer { uInvView: ValueCell.create(invView), uModelView: ValueCell.create(modelView), uInvModelView: ValueCell.create(invModelView), + uInvProjection: ValueCell.create(invProjection), uProjection: ValueCell.create(Mat4.clone(camera.projection)), + uModelViewProjection: ValueCell.create(modelViewProjection), + uInvModelViewProjection: ValueCell.create(invModelViewProjection), uPixelRatio: ValueCell.create(ctx.pixelRatio), uViewportHeight: ValueCell.create(viewport.height), + uViewport: ValueCell.create(viewportVec4), uLightColor: ValueCell.create(Vec3.clone(lightColor)), uLightAmbient: ValueCell.create(Vec3.clone(lightAmbient)), @@ -143,6 +151,9 @@ namespace Renderer { ValueCell.update(globalUniforms.uModelView, Mat4.mul(modelView, scene.view, camera.view)) ValueCell.update(globalUniforms.uInvModelView, Mat4.invert(invModelView, modelView)) ValueCell.update(globalUniforms.uProjection, camera.projection) + ValueCell.update(globalUniforms.uInvProjection, Mat4.invert(invProjection, camera.projection)) + ValueCell.update(globalUniforms.uModelViewProjection, Mat4.mul(modelViewProjection, modelView, camera.projection)) + ValueCell.update(globalUniforms.uInvModelViewProjection, Mat4.invert(invModelViewProjection, modelViewProjection)) ValueCell.update(globalUniforms.uFogFar, camera.fogFar) ValueCell.update(globalUniforms.uFogNear, camera.fogNear) @@ -171,6 +182,7 @@ namespace Renderer { Viewport.set(viewport, x, y, width, height) gl.viewport(x, y, width, height) ValueCell.update(globalUniforms.uViewportHeight, height) + ValueCell.update(globalUniforms.uViewport, Vec4.set(viewportVec4, x, y, width, height)) }, getImageData: () => { const { width, height } = viewport diff --git a/src/mol-gl/shader/direct-volume.frag b/src/mol-gl/shader/direct-volume.frag index 54b80b2fb79b5fc60d76c8b3cf36717b273a6bfc..86754cb969f73a4e407312b77f7de68eb57603f0 100644 --- a/src/mol-gl/shader/direct-volume.frag +++ b/src/mol-gl/shader/direct-volume.frag @@ -17,12 +17,7 @@ varying vec3 origPos; uniform float uAlpha; uniform mat4 uInvView; -uniform mat4 uModelView; -uniform mat4 uInvModelView; uniform float uIsoValue; -uniform vec3 uBboxMin; -uniform vec3 uBboxMax; -uniform vec3 uBboxSize; uniform vec3 uGridDim; uniform sampler2D tTransferTex; @@ -33,56 +28,6 @@ uniform sampler2D tTransferTex; uniform sampler3D tGridTex; #endif -// float uIsoValue = exp(-1.5); -// float uIsoValue = 0.7; - -varying vec4 vNearPos; -varying vec4 vFarPos; -varying vec3 vPosition; - -#pragma glslify: transpose = require(./utils/transpose.glsl) - -vec3 extractCameraPos(const in mat4 modelView) { - // Get the 3 basis vector planes at the camera origin and transform them into model space. - // - // NOTE: Planes have to be transformed by the inverse transpose of a matrix - // Nice reference here: http://www.opengl.org/discussion_boards/showthread.php/159564-Clever-way-to-transform-plane-by-matrix - // - // So for a transform to model space we need to do: - // inverse(transpose(inverse(MV))) - // This equals : transpose(MV) - see Lemma 5 in http://mathrefresher.blogspot.com.au/2007/06/transpose-of-matrix.html - // - // As each plane is simply (1,0,0,0), (0,1,0,0), (0,0,1,0) we can pull the data directly from the transpose matrix. - // - mat4 modelViewT = transpose(modelView); - - // Get plane normals - vec3 n1 = vec3(modelViewT[0]); - vec3 n2 = vec3(modelViewT[1]); - vec3 n3 = vec3(modelViewT[2]); - - // Get plane distances - float d1 = modelViewT[0].w; - float d2 = modelViewT[1].w; - float d3 = modelViewT[2].w; - - // Get the intersection of these 3 planes - // (uisng math from RealTime Collision Detection by Christer Ericson) - vec3 n2n3 = cross(n2, n3); - float denom = dot(n1, n2n3); - - vec3 top = (n2n3 * d1) + cross(n1, (d3 * n2) - (d2 * n3)); - return top / -denom; -} - -vec3 palette(in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d) { - return a + b * cos(6.28318 * (c * t + d)); -} - -vec3 palette1(in float t) { - return palette(t, vec3(0.5,0.5,0.5),vec3(0.5,0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.0,0.10,0.20)); -} - #if defined(dGridTexType_2d) // TODO workaround due to some kind of GPU bug float myMod(float a, float b) { @@ -121,48 +66,31 @@ vec4 transferFunction(float value) { const float gradOffset = 0.5; const vec3 color = vec3(0.45, 0.55, 0.8); -vec4 raymarch(vec3 cameraPos) { - vec3 pos = unitCoord; +vec4 raymarch(vec3 startLoc, vec3 step, vec3 viewDir) { + vec3 scaleVol = vec3(1.0) / uGridDim; + vec3 pos = startLoc + scaleVol * 0.5; float prevValue = -127.0; float value = 0.0; - // float MAX_STEPS_F = max(max(uGridDim.x, uGridDim.y), uGridDim.z); - // int MAX_STEPS = 2 * int(length(vec3(imgresx, imgresy, imgresz))); - float stepSize = 1.0 / float(dMaxSteps); vec4 src = vec4(0.0); vec4 dst = vec4(0.0); - vec3 rayDir = normalize(origPos - cameraPos); - // rayDir = normalize(vec3(1.0, 1.0, 0.0)); - // return vec4(rayDir, 0.5); - vec3 isoPos; - float tmp; - vec3 gradient = vec3(1.0); - vec3 step = rayDir * (1.0 / uGridDim) * 0.5; + #if defined(dRenderMode_isosurface) + vec3 isoPos; + float tmp; - vec3 scaleVol = vec3(1.0) / uGridDim; - vec3 dx = vec3(gradOffset * scaleVol.x, 0.0, 0.0); - vec3 dy = vec3(0.0, gradOffset * scaleVol.y, 0.0); - vec3 dz = vec3(0.0, 0.0, gradOffset * scaleVol.z); - - // dst = vec4(textureVal(vec3(pos.xy, 0.6)).xyz, 0.5); - // vec2 foo = (vec2(5.0 * uGridDim.x, 5.0 * uGridDim.y) + (pos.xy * uGridDim.xy)) / uGridTexDim; - // dst = texture2D(tGridTex, foo); - // dst = texture2D(tGridTex, unitCoord.xy); - // dst.xyz = pos; - // return mix(dst, vec4(1.0, 0.0, 0.0, 1.0), 0.5); + vec3 gradient = vec3(1.0); + vec3 dx = vec3(gradOffset * scaleVol.x, 0.0, 0.0); + vec3 dy = vec3(0.0, gradOffset * scaleVol.y, 0.0); + vec3 dz = vec3(0.0, 0.0, gradOffset * scaleVol.z); + #endif for(int i = 0; i < dMaxSteps; ++i){ - if( pos.x <= 1.0 && pos.y <= 1.0 && pos.z <= 1.0 && pos.x >= 0.0 && pos.y >= 0.0 && pos.z >= 0.0) { - value = textureVal(pos).a; // current voxel value - } else { + value = textureVal(pos).a; // current voxel value + if(pos.x > 1.01 || pos.y > 1.01 || pos.z > 1.01 || pos.x < -0.01 || pos.y < -0.01 || pos.z < -0.01) break; - } #if defined(dRenderMode_volume) - // src = texture1D(transferRGBASampler, scalarData); src = transferFunction(value); - // src.rgb = palette1(value); - // src.a = 1.0 - pow(1.0 - src.a, 0.5); src.rgb *= src.a; dst = (1.0 - dst.a) * src + dst; // standard blending #endif @@ -181,10 +109,10 @@ vec4 raymarch(vec3 cameraPos) { gradient.z = textureVal(isoPos - dz).a - textureVal(isoPos + dz).a; gradient = normalize(gradient); - float d = float(dot(gradient, normalize(cameraPos)) > 0.0); + float d = float(dot(gradient, viewDir) > 0.0); gradient = (2.0 * d - 1.0) * gradient; - src.rgb = color.rgb * abs(dot(gradient, normalize(cameraPos))); + src.rgb = color.rgb * abs(dot(gradient, viewDir)); src.a = uAlpha; // draw interior darker @@ -208,56 +136,14 @@ vec4 raymarch(vec3 cameraPos) { void main () { vec3 cameraPos = uInvView[3].xyz / uInvView[3].w; - // vec3 cameraPos = extractCameraPos(uModelView); - // vec3 cameraPos = vec3(10.0, 0.0, 0.0); - gl_FragColor = raymarch(cameraPos); + + vec3 rayDir = normalize(origPos - cameraPos); + vec3 startLoc = unitCoord; + vec3 step = rayDir * (1.0 / uGridDim) * 0.5; + + gl_FragColor = raymarch(startLoc, step, normalize(cameraPos)); if (length(gl_FragColor.rgb) < 0.00001) discard; #if defined(dRenderMode_volume) gl_FragColor.a = uAlpha; #endif - // gl_FragColor = vec4(unitCoord, 1.0); - // gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5); -} - - -// const float relativeStepSize = 1.0; -// vec3 u_size = uGridDim; - -// void main () { -// // Normalize clipping plane info -// vec3 farPos = vFarPos.xyz / vFarPos.w; -// vec3 nearPos = vNearPos.xyz / vNearPos.w; -// // Calculate unit vector pointing in the view direction through this fragment. -// vec3 viewRay = normalize(nearPos.xyz - farPos.xyz); - -// // Compute the (negative) distance to the front surface or near clipping plane. -// // v_position is the back face of the cuboid, so the initial distance calculated in the dot -// // product below is the distance from near clip plane to the back of the cuboid -// float distance = dot(nearPos - vPosition, viewRay); -// distance = max(distance, min((-0.5 - vPosition.x) / viewRay.x, (u_size.x - 0.5 - vPosition.x) / viewRay.x)); -// distance = max(distance, min((-0.5 - vPosition.y) / viewRay.y, (u_size.y - 0.5 - vPosition.y) / viewRay.y)); -// distance = max(distance, min((-0.5 - vPosition.z) / viewRay.z, (u_size.z - 0.5 - vPosition.z) / viewRay.z)); -// // Now we have the starting position on the front surface -// vec3 front = vPosition + viewRay * distance; -// // Decide how many steps to take -// int nsteps = int(-distance / relativeStepSize + 0.5); -// // if (nsteps < 1) -// // discard; -// // Get starting location and step vector in texture coordinates -// vec3 step = ((vPosition - front) / u_size) / float(nsteps); -// vec3 startLoc = front / u_size; -// // For testing: show the number of steps. This helps to establish -// // whether the rays are correctly oriented -// gl_FragColor = vec4(0.0, float(nsteps) / 1.0 / u_size.x, 1.0, 1.0); -// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); -// return; - -// // if (u_renderstyle == 0) -// // cast_mip(startLoc, step, nsteps, viewRay); -// // else if (u_renderstyle == 1) -// // cast_iso(start_loc, step, nsteps, view_ray); - - -// if (gl_FragColor.a < 0.05) -// discard; -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/mol-gl/shader/direct-volume.vert b/src/mol-gl/shader/direct-volume.vert index 0ae3cd9f7a420410e03deb4522f2ea1cceea9dc3..7ab9edae8c130aeadf0e3db00943600e66f4a3d9 100644 --- a/src/mol-gl/shader/direct-volume.vert +++ b/src/mol-gl/shader/direct-volume.vert @@ -15,41 +15,13 @@ varying vec3 origPos; uniform vec3 uBboxSize; uniform vec3 uBboxMin; uniform vec3 uBboxMax; -uniform mat4 uTransform; -uniform mat4 uInvView; uniform mat4 uModelView; -uniform mat4 uInvModelView; -uniform mat4 uProjection, uView, uModel; - -varying vec4 vNearPos; -varying vec4 vFarPos; -varying vec3 vPosition; +uniform mat4 uProjection; void main() { unitCoord = aPosition + vec3(0.5); - vec4 mvPosition = uView * uModel * vec4(unitCoord * uBboxSize + uBboxMin, 1.0); - // vec4 mvPosition = vec4(unitCoord * uBboxSize + uBboxMin, 1.0); - // origPos = mvPosition.xyz; + vec4 mvPosition = uModelView * vec4(unitCoord * uBboxSize + uBboxMin, 1.0); origPos = unitCoord * uBboxSize + uBboxMin; gl_Position = uProjection * mvPosition; -} - -// void main() { -// // Project local vertex coordinate to camera position. Then do a step -// // backward (in cam coords) to the near clipping plane, and project back. Do -// // the same for the far clipping plane. This gives us all the information we -// // need to calculate the ray and truncate it to the viewing cone. -// vec3 position = aPosition * uBboxSize + uBboxMin; -// vec4 position4 = vec4(position, 1.0); -// vec4 posInCam = uView * position4; -// // Intersection of ray and near clipping plane (z = -1 in clip coords) -// posInCam.z = -posInCam.w; -// vNearPos = uInvView * posInCam; -// // Intersection of ray and far clipping plane (z = +1 in clip coords) -// posInCam.z = posInCam.w; -// vFarPos = uInvView * posInCam; -// // Set varyings and output pos -// vPosition = position; -// gl_Position = uProjection * uModelView * position4; -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/mol-view/camera/util.ts b/src/mol-view/camera/util.ts index 11c77e70db107fb6c41e74befed0a58aa1231348..1fdb476a94e65293298fa5c2e7dd0545385edd07 100644 --- a/src/mol-view/camera/util.ts +++ b/src/mol-view/camera/util.ts @@ -30,6 +30,14 @@ export namespace Viewport { viewport.height = height return viewport } + + export function toVec4(v4: Vec4, viewport: Viewport): Vec4 { + v4[0] = viewport.x + v4[1] = viewport.y + v4[2] = viewport.width + v4[3] = viewport.height + return v4 + } } const tmpVec3 = Vec3.zero()