Last active
July 29, 2024 01:24
-
-
Save duhaime/60c7083009bbd49ce50a58c371d8c818 to your computer and use it in GitHub Desktop.
Using canvas textures in three.js
This file contains hidden or 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
<html> | |
<head> | |
<style> | |
html, body { width: 100%; height: 100%; background: #000; } | |
body { margin: 0; overflow: hidden; } | |
canvas { width: 100%; height: 100%; } | |
</style> | |
</head> | |
<body> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js'></script> | |
<script src='TrackballControls.js'></script> | |
<script> | |
/** | |
* Generate scene object with a background color | |
**/ | |
function getScene() { | |
var scene = new THREE.Scene(); | |
scene.background = new THREE.Color(0x111111); | |
return scene; | |
} | |
/** | |
* Generate the camera to be used in the scene. Camera args: | |
* [0] field of view: identifies the portion of the scene | |
* visible at any time (in degrees) | |
* [1] aspect ratio: identifies the aspect ratio of the | |
* scene in width/height | |
* [2] near clipping plane: objects closer than the near | |
* clipping plane are culled from the scene | |
* [3] far clipping plane: objects farther than the far | |
* clipping plane are culled from the scene | |
**/ | |
function getCamera() { | |
var aspectRatio = window.innerWidth / window.innerHeight; | |
var camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 1000); | |
camera.position.set(0, 1, 5); | |
return camera; | |
} | |
/** | |
* Generate the light to be used in the scene. Light args: | |
* [0]: Hexadecimal color of the light | |
* [1]: Numeric value of the light's strength/intensity | |
* [2]: The distance from the light where the intensity is 0 | |
* @param {obj} scene: the current scene object | |
**/ | |
function getLight(scene) { | |
var light = new THREE.PointLight(0xffffff, 1, 0); | |
light.position.set(1, 1, 1); | |
scene.add(light); | |
var ambientLight = new THREE.AmbientLight(0x111111); | |
scene.add(ambientLight); | |
return light; | |
} | |
/** | |
* Generate the renderer to be used in the scene | |
**/ | |
function getRenderer() { | |
// Create the canvas with a renderer | |
var renderer = new THREE.WebGLRenderer({antialias: false}); | |
// Add support for retina displays | |
renderer.setPixelRatio(window.devicePixelRatio); | |
// Specify the size of the canvas | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
// Add the canvas to the DOM | |
document.body.appendChild(renderer.domElement); | |
return renderer; | |
} | |
/** | |
* Generate the controls to be used in the scene | |
* @param {obj} camera: the three.js camera for the scene | |
* @param {obj} renderer: the three.js renderer for the scene | |
**/ | |
function getControls(camera, renderer) { | |
var controls = new THREE.TrackballControls(camera, renderer.domElement); | |
controls.zoomSpeed = 0.4; | |
controls.panSpeed = 0.4; | |
return controls; | |
} | |
/** | |
* Create retina quality canvas | |
**/ | |
var PIXEL_RATIO = (function () { | |
var ctx = document.createElement('canvas').getContext('2d'), | |
dpr = window.devicePixelRatio || 1, | |
bsr = ctx.webkitBackingStorePixelRatio || | |
ctx.mozBackingStorePixelRatio || | |
ctx.msBackingStorePixelRatio || | |
ctx.oBackingStorePixelRatio || | |
ctx.backingStorePixelRatio || 1; | |
return dpr / bsr; | |
})(); | |
createRetinaCanvas = function(w, h, ratio) { | |
if (!ratio) { ratio = PIXEL_RATIO; } | |
var can = document.createElement('canvas'); | |
can.width = w * ratio; | |
can.height = h * ratio; | |
can.style.width = w + 'px'; | |
can.style.height = h + 'px'; | |
can.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0); | |
return can; | |
} | |
function addTexture() { | |
var text = 'cats' | |
//create image | |
var bitmap = createRetinaCanvas(100, 100); | |
var ctx = bitmap.getContext('2d', {antialias: false}); | |
ctx.font = 'Bold 20px Arial'; | |
ctx.beginPath(); | |
ctx.rect(0, 0, 100, 100); | |
ctx.fillStyle = 'red'; | |
ctx.fill(); | |
ctx.fillStyle = 'white'; | |
ctx.fillText(text, 0, 20); | |
ctx.strokeStyle = 'black'; | |
ctx.strokeText(text, 0, 20); | |
// canvas contents will be used for a texture | |
var texture = new THREE.Texture(bitmap) | |
texture.needsUpdate = true; | |
var material = new THREE.MeshBasicMaterial({ map: texture }); | |
var geometry = new THREE.BoxGeometry( 1, 1, 1 ); | |
cube = new THREE.Mesh(geometry, material); | |
scene.add(cube) | |
} | |
// Render loop | |
function render() { | |
requestAnimationFrame(render); | |
renderer.render(scene, camera); | |
controls.update(); | |
cube.rotation.y += 0.01; | |
cube.rotation.z += 0.01; | |
}; | |
var scene = getScene(); | |
var camera = getCamera(); | |
var light = getLight(scene); | |
var renderer = getRenderer(); | |
var controls = getControls(camera, renderer); | |
var cube; | |
addTexture() | |
render(); | |
</script> | |
</body> | |
</html> |
This file contains hidden or 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
THREE.TrackballControls=function(e,t){var o=this,n={NONE:-1,ROTATE:0,ZOOM:1,PAN:2,TOUCH_ROTATE:3,TOUCH_ZOOM_PAN:4};this.object=e,this.domElement=void 0!==t?t:document,this.enabled=!0,this.screen={left:0,top:0,width:0,height:0},this.rotateSpeed=1,this.zoomSpeed=1.2,this.panSpeed=.3,this.noRotate=!1,this.noZoom=!1,this.noPan=!1,this.staticMoving=!1,this.dynamicDampingFactor=.2,this.minDistance=0,this.maxDistance=1/0,this.keys=[65,83,68],this.target=new THREE.Vector3;var s=new THREE.Vector3,c=n.NONE,a=n.NONE,i=new THREE.Vector3,r=new THREE.Vector2,p=new THREE.Vector2,h=new THREE.Vector3,d=0,u=new THREE.Vector2,E=new THREE.Vector2,m=0,l=0,g=new THREE.Vector2,y=new THREE.Vector2;this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.up0=this.object.up.clone();var v={type:"change"},w={type:"start"},T={type:"end"};this.handleResize=function(){if(this.domElement===document)this.screen.left=0,this.screen.top=0,this.screen.width=window.innerWidth,this.screen.height=window.innerHeight;else{var e=this.domElement.getBoundingClientRect(),t=this.domElement.ownerDocument.documentElement;this.screen.left=e.left+window.pageXOffset-t.clientLeft,this.screen.top=e.top+window.pageYOffset-t.clientTop,this.screen.width=e.width,this.screen.height=e.height}};var b,f,O,R,H,L,V,k,N,j,D,A,Y=(b=new THREE.Vector2,function(e,t){return b.set((e-o.screen.left)/o.screen.width,(t-o.screen.top)/o.screen.height),b}),C=(f=new THREE.Vector2,function(e,t){return f.set((e-.5*o.screen.width-o.screen.left)/(.5*o.screen.width),(o.screen.height+2*(o.screen.top-t))/o.screen.width),f});function P(e){!1!==o.enabled&&(window.removeEventListener("keydown",P),a=c,c===n.NONE&&(e.keyCode!==o.keys[n.ROTATE]||o.noRotate?e.keyCode!==o.keys[n.ZOOM]||o.noZoom?e.keyCode!==o.keys[n.PAN]||o.noPan||(c=n.PAN):c=n.ZOOM:c=n.ROTATE))}function X(e){!1!==o.enabled&&(c=a,window.addEventListener("keydown",P,!1))}function M(e){!1!==o.enabled&&(e.preventDefault(),e.stopPropagation(),c===n.NONE&&(c=e.button),c!==n.ROTATE||o.noRotate?c!==n.ZOOM||o.noZoom?c!==n.PAN||o.noPan||(g.copy(Y(e.pageX,e.pageY)),y.copy(g)):(u.copy(Y(e.pageX,e.pageY)),E.copy(u)):(p.copy(C(e.pageX,e.pageY)),r.copy(p)),document.addEventListener("mousemove",Z,!1),document.addEventListener("mouseup",S,!1),o.dispatchEvent(w))}function Z(e){!1!==o.enabled&&(e.preventDefault(),e.stopPropagation(),c!==n.ROTATE||o.noRotate?c!==n.ZOOM||o.noZoom?c!==n.PAN||o.noPan||y.copy(Y(e.pageX,e.pageY)):E.copy(Y(e.pageX,e.pageY)):(r.copy(p),p.copy(C(e.pageX,e.pageY))))}function S(e){!1!==o.enabled&&(e.preventDefault(),e.stopPropagation(),c=n.NONE,document.removeEventListener("mousemove",Z),document.removeEventListener("mouseup",S),o.dispatchEvent(T))}function x(e){if(!1!==o.enabled&&!0!==o.noZoom){switch(e.preventDefault(),e.stopPropagation(),e.deltaMode){case 2:u.y-=.025*e.deltaY;break;case 1:u.y-=.01*e.deltaY;break;default:u.y-=25e-5*e.deltaY}o.dispatchEvent(w),o.dispatchEvent(T)}}function z(e){if(!1!==o.enabled){switch(e.preventDefault(),e.touches.length){case 1:c=n.TOUCH_ROTATE,p.copy(C(e.touches[0].pageX,e.touches[0].pageY)),r.copy(p);break;default:c=n.TOUCH_ZOOM_PAN;var t=e.touches[0].pageX-e.touches[1].pageX,s=e.touches[0].pageY-e.touches[1].pageY;l=m=Math.sqrt(t*t+s*s);var a=(e.touches[0].pageX+e.touches[1].pageX)/2,i=(e.touches[0].pageY+e.touches[1].pageY)/2;g.copy(Y(a,i)),y.copy(g)}o.dispatchEvent(w)}}function _(e){if(!1!==o.enabled)switch(e.preventDefault(),e.stopPropagation(),e.touches.length){case 1:r.copy(p),p.copy(C(e.touches[0].pageX,e.touches[0].pageY));break;default:var t=e.touches[0].pageX-e.touches[1].pageX,n=e.touches[0].pageY-e.touches[1].pageY;l=Math.sqrt(t*t+n*n);var s=(e.touches[0].pageX+e.touches[1].pageX)/2,c=(e.touches[0].pageY+e.touches[1].pageY)/2;y.copy(Y(s,c))}}function q(e){if(!1!==o.enabled){switch(e.touches.length){case 0:c=n.NONE;break;case 1:c=n.TOUCH_ROTATE,p.copy(C(e.touches[0].pageX,e.touches[0].pageY)),r.copy(p)}o.dispatchEvent(T)}}function F(e){!1!==o.enabled&&e.preventDefault()}this.rotateCamera=(R=new THREE.Vector3,H=new THREE.Quaternion,L=new THREE.Vector3,V=new THREE.Vector3,k=new THREE.Vector3,N=new THREE.Vector3,function(){N.set(p.x-r.x,p.y-r.y,0),(O=N.length())?(i.copy(o.object.position).sub(o.target),L.copy(i).normalize(),V.copy(o.object.up).normalize(),k.crossVectors(V,L).normalize(),V.setLength(p.y-r.y),k.setLength(p.x-r.x),N.copy(V.add(k)),R.crossVectors(N,i).normalize(),O*=o.rotateSpeed,H.setFromAxisAngle(R,O),i.applyQuaternion(H),o.object.up.applyQuaternion(H),h.copy(R),d=O):!o.staticMoving&&d&&(d*=Math.sqrt(1-o.dynamicDampingFactor),i.copy(o.object.position).sub(o.target),H.setFromAxisAngle(h,d),i.applyQuaternion(H),o.object.up.applyQuaternion(H)),r.copy(p)}),this.zoomCamera=function(){var e;c===n.TOUCH_ZOOM_PAN?(e=m/l,m=l,i.multiplyScalar(e)):(1!==(e=1+(E.y-u.y)*o.zoomSpeed)&&e>0&&i.multiplyScalar(e),o.staticMoving?u.copy(E):u.y+=(E.y-u.y)*this.dynamicDampingFactor)},this.panCamera=(j=new THREE.Vector2,D=new THREE.Vector3,A=new THREE.Vector3,function(){j.copy(y).sub(g),j.lengthSq()&&(j.multiplyScalar(i.length()*o.panSpeed),A.copy(i).cross(o.object.up).setLength(j.x),A.add(D.copy(o.object.up).setLength(j.y)),o.object.position.add(A),o.target.add(A),o.staticMoving?g.copy(y):g.add(j.subVectors(y,g).multiplyScalar(o.dynamicDampingFactor)))}),this.checkDistances=function(){o.noZoom&&o.noPan||(i.lengthSq()>o.maxDistance*o.maxDistance&&(o.object.position.addVectors(o.target,i.setLength(o.maxDistance)),u.copy(E)),i.lengthSq()<o.minDistance*o.minDistance&&(o.object.position.addVectors(o.target,i.setLength(o.minDistance)),u.copy(E)))},this.update=function(){i.subVectors(o.object.position,o.target),o.noRotate||o.rotateCamera(),o.noZoom||o.zoomCamera(),o.noPan||o.panCamera(),o.object.position.addVectors(o.target,i),o.checkDistances(),o.object.lookAt(o.target),s.distanceToSquared(o.object.position)>1e-6&&(o.dispatchEvent(v),s.copy(o.object.position))},this.reset=function(){c=n.NONE,a=n.NONE,o.target.copy(o.target0),o.object.position.copy(o.position0),o.object.up.copy(o.up0),i.subVectors(o.object.position,o.target),o.object.lookAt(o.target),o.dispatchEvent(v),s.copy(o.object.position)},this.dispose=function(){this.domElement.removeEventListener("contextmenu",F,!1),this.domElement.removeEventListener("mousedown",M,!1),this.domElement.removeEventListener("wheel",x,!1),this.domElement.removeEventListener("touchstart",z,!1),this.domElement.removeEventListener("touchend",q,!1),this.domElement.removeEventListener("touchmove",_,!1),document.removeEventListener("mousemove",Z,!1),document.removeEventListener("mouseup",S,!1),window.removeEventListener("keydown",P,!1),window.removeEventListener("keyup",X,!1)},this.domElement.addEventListener("contextmenu",F,!1),this.domElement.addEventListener("mousedown",M,!1),this.domElement.addEventListener("wheel",x,!1),this.domElement.addEventListener("touchstart",z,!1),this.domElement.addEventListener("touchend",q,!1),this.domElement.addEventListener("touchmove",_,!1),window.addEventListener("keydown",P,!1),window.addEventListener("keyup",X,!1),this.handleResize(),this.update()},THREE.TrackballControls.prototype=Object.create(THREE.EventDispatcher.prototype),THREE.TrackballControls.prototype.constructor=THREE.TrackballControls; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment