Created
February 6, 2019 15:17
-
-
Save turner/c030fb1a01f6124634390d4d165c0777 to your computer and use it in GitHub Desktop.
Custom Shader Rendering Bug in three.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as THREE from './threejs_es6/three.module.js'; | |
import LineGeometry from './threejs_es6/LineGeometry.js'; | |
import LineMaterial from './threejs_es6/LineMaterial.js'; | |
import Line2 from './threejs_es6/Line2.js'; | |
import OrbitControls from './threejs_es6/orbit-controls-es6.js'; | |
import { appleCrayonNames, appleCrayonColorHexValue, appleCrayonColorThreeJS } from './ei_color.js'; | |
import SequenceManager from './sequenceManager.js'; | |
import BedTrack from './igv/bedTrack.js' | |
import CubicMapManager from "./cubicMapManager.js"; | |
let scene; | |
let renderer; | |
let camera; | |
let orbitControl; | |
let sequenceManager; | |
let cubicMapManager; | |
let sphereGeometry; | |
let cylinderGeometry; | |
let showNormalsMaterial; | |
let showSTMaterial; | |
const genomicChr = "chr21" | |
const genomicStart = 28000071 | |
const genomicStep = 30000 | |
// Compute the segment indexes containing a feature. Quick hack, this is not the right place to do this but | |
// I don't know how to change sphere color after its placed in scene | |
let featureSegmentIndexes = new Set() | |
let initDemoTrack = async (path) => { | |
const bedTrack = new BedTrack(path) | |
const bedFeatures = await bedTrack.getFeatures(genomicChr) | |
for (let feature of bedFeatures) { | |
// Segment index (first sgement is 1) | |
const idx = Math.floor((feature.start - genomicStart) / genomicStep) + 1 | |
if(idx >= 0) { | |
console.log(idx + " " + (genomicStart + (idx-1)*( genomicStep)) + "-" + (genomicStart + idx*genomicStep)) | |
featureSegmentIndexes.add(idx) | |
} | |
} | |
} | |
let main = (threejs_canvas) => { | |
renderer = new THREE.WebGLRenderer({ canvas: threejs_canvas, antialias: true }); | |
renderer.setClearColor(appleCrayonColorHexValue('iron')); | |
renderer.setPixelRatio(window.devicePixelRatio); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
const [ near, far, fov ] = [ 1e-1, 1e5, 35 ]; | |
camera = new THREE.PerspectiveCamera(fov, window.innerWidth / window.innerHeight, near, far); | |
orbitControl = new OrbitControls(camera, renderer.domElement); | |
scene = new THREE.Scene(); | |
scene.background = appleCrayonColorThreeJS('iron'); | |
const cubicMapMaterialConfig = | |
{ | |
textureRoot: 'texture/cubic/diffuse/cap_hill/', | |
suffix: '.png', | |
vertexShaderName: 'diffuse_cube_vert', | |
fragmentShaderName: 'diffuse_cube_frag' | |
}; | |
cubicMapManager = new CubicMapManager(cubicMapMaterialConfig); | |
showNormalsMaterial = new THREE.MeshNormalMaterial(); | |
const showSTMaterialConfig = | |
{ | |
uniforms: {}, | |
vertexShader: document.getElementById( 'show_st_vert' ).textContent, | |
fragmentShader: document.getElementById( 'show_st_frag' ).textContent, | |
depthTest: true | |
}; | |
showSTMaterial = new THREE.ShaderMaterial(showSTMaterialConfig ); | |
// showSTMaterial = new THREE.ShaderMaterial(); | |
setup(scene, renderer, camera, orbitControl); | |
}; | |
let setup = async (scene, renderer, camera, orbitControl) => { | |
const path = 'data/csv/IMR90_chr21-28-30Mb.csv'; | |
sequenceManager = new SequenceManager(); | |
await sequenceManager.loadSequence({ path }); | |
//initDemoTrack('data/tracks/IMR-90_CTCF_27-31.bed') | |
initDemoTrack('data/tracks/IMR-90_RAD21_27-31.bed') | |
const currentKey = '2489'; | |
let currentSegment = sequenceManager.segmentWithName(currentKey) | |
const [ targetX, targetY, targetZ ] = currentSegment.target; | |
const target = new THREE.Vector3(targetX, targetY, targetZ); | |
const [ extentX, extentY, extentZ ] = currentSegment.extent; | |
const [ cameraPositionX, cameraPositionY, cameraPositionZ ] = currentSegment.cameraPosition; | |
camera.position.set(cameraPositionX, cameraPositionY, cameraPositionZ); | |
camera.lookAt( target ); | |
let dimen = 0.5 * Math.max(extentX, extentY, extentZ); | |
dimen = Math.sqrt(dimen*dimen + (2 * dimen*dimen)); | |
camera.near = 0.05 * dimen; | |
camera.far = 4.00 * dimen; | |
orbitControl.screenSpacePanning = false; | |
orbitControl.target = target; | |
orbitControl.update(); | |
orbitControl.addEventListener("change", () => renderer.render(scene, camera)); | |
const groundPlane = new THREE.GridHelper(2 * Math.max(extentX, extentY, extentZ), 16, appleCrayonColorHexValue('steel'), appleCrayonColorHexValue('steel')); | |
groundPlane.position.set(targetX, targetY, targetZ); | |
scene.add( groundPlane ); | |
const sphereRadius = 24; | |
sphereGeometry = new THREE.SphereGeometry(sphereRadius, 32, 16); | |
for(let seg of currentSegment) { | |
const [x, y, z] = seg.xyz; | |
const doSkip = isNaN(x) || isNaN(y) || isNaN(z); | |
if (!doSkip) { | |
sphereForSegment(seg, x, y, z, scene); | |
} | |
} | |
// cylinders | |
const flatColorMaterial = new THREE.MeshBasicMaterial(); | |
flatColorMaterial.color = appleCrayonColorThreeJS('aluminum'); | |
const cylinderRadius = 8; | |
for (let i = 0, j = 1; j < currentSegment.length; ++i, ++j) { | |
const [ x0, y0, z0 ] = currentSegment[i].xyz; | |
const [ x1, y1, z1 ] = currentSegment[j].xyz; | |
const doSkip = isNaN(x0) || isNaN(x1); | |
if (!doSkip) { | |
const cylinderAxis = new THREE.CatmullRomCurve3([ new THREE.Vector3( x0, y0, z0 ), new THREE.Vector3( x1, y1, z1 ) ]); | |
cylinderGeometry = new THREE.TubeGeometry(cylinderAxis, 4, cylinderRadius, 16, false); | |
cylinderWithScene(cylinderGeometry, flatColorMaterial, scene); | |
} | |
} | |
window.addEventListener( 'resize', onWindowResize, false ); | |
renderer.render( scene, camera ); | |
}; | |
let onWindowResize = () => { | |
camera.aspect = window.innerWidth / window.innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
renderer.render( scene, camera ); | |
}; | |
let sphereForSegment = (segment, x, y, z, scene) => { | |
const flatColorMaterial = new THREE.MeshBasicMaterial(); | |
let index | |
// advance past dark crayon color names. | |
// index += 24; | |
// index %= appleCrayonNames.length; | |
// const name = appleCrayonNames[ index ]; | |
// flatColorMaterial.color = new THREE.Color( appleCrayonColor(name) ); | |
// Transition from blue -> red over 60 steps | |
index = segment.segmentIndex; | |
const step = index / 60 | |
const red = Math.floor(Math.min(255, step * 255)) | |
const green = 0 | |
const blue = 255 - red | |
flatColorMaterial.color = new THREE.Color(featureSegmentIndexes.has(segment.segmentIndex) ? 'rgb(0, 255, 0)': `rgb(${red},${green},${blue})`) | |
let sphereMesh = new THREE.Mesh(sphereGeometry, showSTMaterial/*flatColorMaterial*/); | |
sphereMesh.position.set(x, y, z); | |
scene.add(sphereMesh); | |
}; | |
let lineWithLerpedColorBetweenEndPoints = (a, b, aColor, bColor, scene) => { | |
const [ x0, y0, z0 ] = a; | |
const [ x1, y1, z1 ] = b; | |
if (isNaN(x0) || isNaN(x1)) { | |
return; | |
} | |
let positions = []; | |
positions.push( a[0], a[1], a[2] ); | |
positions.push( b[0], b[1], b[2] ); | |
let colors = []; | |
colors.push( aColor.r, aColor.g, aColor.b ); | |
colors.push( bColor.r, bColor.g, bColor.b ); | |
var lineGeometry = new LineGeometry(); | |
lineGeometry.setPositions( positions ); | |
lineGeometry.setColors( colors ); | |
const lineMaterial = new LineMaterial( { color: appleCrayonColorHexValue('snow'), linewidth: 5, vertexColors: THREE.VertexColors, dashed: false } ); | |
let line = new Line2( lineGeometry, lineMaterial ); | |
line.computeLineDistances(); | |
line.scale.set( 1, 1, 1 ); | |
scene.add( line ); | |
}; | |
let cylinderWithScene = (geometry, material, scene) => { | |
scene.add(new THREE.Mesh(geometry, material)); | |
}; | |
export { main }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment