├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── README.md ├── pom.xml ├── src └── main │ └── java │ ├── def │ └── threejs_ext │ │ └── three │ │ ├── Globals.java │ │ └── package-info.java │ └── org │ └── jsweet │ └── examples │ └── threejs │ ├── WebglInteractiveCubes.java │ └── WebglMaterialsNormalMap.java └── webapp ├── libs ├── Detector.js ├── postprocessing │ ├── EffectComposer.js │ ├── MaskPass.js │ ├── RenderPass.js │ └── ShaderPass.js ├── shaders │ ├── BleachBypassShader.js │ ├── ColorCorrectionShader.js │ ├── CopyShader.js │ └── FXAAShader.js ├── stats.min.js └── three.min.js ├── logo.png ├── obj └── leeperrysmith │ ├── Infinite-Level_02_Tangent_SmoothUV.jpg │ ├── LeePerrySmith.js │ ├── Map-COL.jpg │ ├── Map-SPEC.jpg │ └── Thumbs.db ├── webgl_interactive_cubes.html └── webgl_materials_normalmap.html /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.jsweet/ 3 | /.ts/ 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | jsweet-examples-threejs 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.8 6 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSweet Examples (threejs framework) 2 | 3 | Some examples to demonstrate using the awesome http://threejs.org framework (WebGL powered 3D) from Java thanks to the [JSweet tranpiler](https://github.com/cincheo/jsweet). 4 | 5 | - [`webgl_interactive_cubes.html`] An example showing cubes, which you can highlight by clicking. [[browse](http://examples.jsweet.org/jsweet-examples-threejs/webapp/webgl_interactive_cubes.html)] 6 | - [`webgl_materials_normalmap.html`] An example showing Lee Perry-Smith (Infinite-Realities). [[browse](http://examples.jsweet.org/jsweet-examples-threejs/webapp/webgl_materials_normalmap.html)] 7 | 8 | These examples are direct translations to JSweet of some of the JavaScript examples taken from the threejs web site. Of course, copyrights fully remain to the original authors. 9 | 10 | Check out more [JSweet examples](https://github.com/cincheo/jsweet). 11 | 12 | ## Usage 13 | 14 | ``` 15 | > git clone https://github.com/cincheo/jsweet-examples-threejs.git 16 | > cd jsweet-examples-threejs 17 | > mvn generate-sources 18 | > firefox webapp/${example}.html 19 | ``` 20 | 21 | ## Prerequisites 22 | 23 | The `node` and `npm` executables must be in the path (https://nodejs.org). 24 | Install Maven (https://maven.apache.org/install.html). 25 | 26 | ## Note on strict mode 27 | 28 | These examples compile with JSweet in strict mode: `jsweet-core-strict` must be placed first (before the JDK) in the classpath. 29 | In strict mode, JavaScript APIs replace Java APIs even on java.lang objects. In strict mode, it is not possible to compile regular Java code (using regular Java APIs) at all. 30 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.jsweet 5 | jsweet-examples-threejs 6 | 2.0.0-SNAPSHOT 7 | JSweet ThreeJS example 8 | A ThreeJS examples to illustrate JSweet 9 | 10 | 11 | rpawlak 12 | Renaud Pawlak 13 | renaud.pawlak@gmail.com 14 | 15 | 16 | 17 | 18 | The Apache Software License, Version 2.0 19 | http://www.apache.org/licenses/LICENSE-2.0.txt 20 | repo 21 | 22 | 23 | 24 | 25 | jsweet-central 26 | libs-release 27 | http://repository.jsweet.org/artifactory/libs-release-local 28 | 29 | 30 | 31 | jsweet-snapshots 32 | libs-snapshot 33 | http://repository.jsweet.org/artifactory/libs-snapshot-local 34 | 35 | 36 | 37 | 38 | 39 | maven-compiler-plugin 40 | 3.1 41 | 42 | 1.8 43 | 1.8 44 | true 45 | 46 | 47 | 48 | maven-antrun-plugin 49 | 1.8 50 | 51 | 52 | generate-js 53 | generate-sources 54 | 55 | run 56 | 57 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 86 | 87 | org.eclipse.m2e 88 | lifecycle-mapping 89 | 1.0.0 90 | 91 | 92 | 93 | 94 | 95 | 96 | org.apache.maven.plugins 97 | 98 | 99 | maven-antrun-plugin 100 | 101 | 102 | [1.8,) 103 | 104 | 105 | run 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | org.jsweet 122 | jsweet-core 123 | 5-20170726 124 | 125 | 126 | org.jsweet.candies 127 | threejs 128 | 75-20171101 129 | 130 | 131 | org.jsweet.candies 132 | stats 133 | 0.17.0-20171101 134 | 135 | 136 | org.jsweet 137 | jsweet-transpiler 138 | 2.0.0 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /src/main/java/def/threejs_ext/three/Globals.java: -------------------------------------------------------------------------------- 1 | package def.threejs_ext.three; 2 | 3 | import def.threejs.three.Shader; 4 | 5 | public class Globals { 6 | 7 | public static Shader BleachBypassShader; 8 | 9 | public static Shader ColorCorrectionShader; 10 | 11 | public static Shader FXAAShader; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/def/threejs_ext/three/package-info.java: -------------------------------------------------------------------------------- 1 | 2 | @jsweet.lang.Name("THREE") 3 | package def.threejs_ext.three; -------------------------------------------------------------------------------- /src/main/java/org/jsweet/examples/threejs/WebglInteractiveCubes.java: -------------------------------------------------------------------------------- 1 | package org.jsweet.examples.threejs; 2 | 3 | import static def.dom.Globals.document; 4 | import static def.dom.Globals.requestAnimationFrame; 5 | import static def.dom.Globals.window; 6 | import static jsweet.util.Lang.union; 7 | 8 | import def.stats.Stats; 9 | import def.threejs.three.BoxGeometry; 10 | import def.threejs.three.Color; 11 | import def.threejs.three.DirectionalLight; 12 | import def.threejs.three.Geometry; 13 | import def.threejs.three.Intersection; 14 | import def.threejs.three.Light; 15 | import def.threejs.three.Mesh; 16 | import def.threejs.three.MeshLambertMaterial; 17 | import def.threejs.three.MeshLambertMaterialParameters; 18 | import def.threejs.three.PerspectiveCamera; 19 | import def.threejs.three.Raycaster; 20 | import def.threejs.three.Raycaster.Coords; 21 | import def.threejs.three.Scene; 22 | import def.threejs.three.Vector2; 23 | import def.threejs.three.WebGLRenderer; 24 | import def.dom.Event; 25 | import def.dom.HTMLElement; 26 | import def.dom.MouseEvent; 27 | import def.js.Math; 28 | import jsweet.util.StringTypes; 29 | 30 | // WARNING: this example compiles with JSweet in strict mode 31 | // jsweet-core-strict must be place first (before the JDK) in the classpath 32 | 33 | public class WebglInteractiveCubes { 34 | 35 | static HTMLElement container; 36 | static Stats stats; 37 | static PerspectiveCamera camera; 38 | static Scene scene; 39 | static Raycaster raycaster; 40 | static WebGLRenderer renderer; 41 | 42 | static Vector2 mouse = new Vector2(); 43 | static Mesh INTERSECTED; 44 | 45 | static double radius = 100; 46 | static double theta = 0; 47 | 48 | public static void main(String[] args) { 49 | init(); 50 | animate(0); 51 | } 52 | 53 | public static void init() { 54 | 55 | container = document.createElement("div"); 56 | document.body.appendChild(container); 57 | 58 | HTMLElement info = document.createElement("div"); 59 | info.style.position = "absolute"; 60 | info.style.top = "10px"; 61 | info.style.width = "100%"; 62 | info.style.textAlign = "center"; 63 | info.innerHTML = "three.js webgl - interactive cubes"; 64 | container.appendChild(info); 65 | 66 | camera = new PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000); 67 | 68 | scene = new Scene(); 69 | 70 | Light light = new DirectionalLight(0xffffff, 1); 71 | light.position.set(1, 1, 1).normalize(); 72 | scene.add(light); 73 | 74 | Geometry geometry = new BoxGeometry(20, 20, 20); 75 | 76 | for (int i = 0; i < 2000; i++) { 77 | 78 | Mesh object = new Mesh(geometry, new MeshLambertMaterial(new MeshLambertMaterialParameters() { 79 | { 80 | color = union(Math.random() * 0xffffff); 81 | } 82 | })); 83 | 84 | object.position.x = Math.random() * 800 - 400; 85 | object.position.y = Math.random() * 800 - 400; 86 | object.position.z = Math.random() * 800 - 400; 87 | 88 | object.rotation.x = Math.random() * 2 * Math.PI; 89 | object.rotation.y = Math.random() * 2 * Math.PI; 90 | object.rotation.z = Math.random() * 2 * Math.PI; 91 | 92 | object.scale.x = Math.random() + 0.5; 93 | object.scale.y = Math.random() + 0.5; 94 | object.scale.z = Math.random() + 0.5; 95 | 96 | scene.add(object); 97 | 98 | } 99 | 100 | raycaster = new Raycaster(); 101 | 102 | renderer = new WebGLRenderer(); 103 | renderer.setClearColor(0xf0f0f0); 104 | renderer.setPixelRatio(window.devicePixelRatio); 105 | renderer.setSize(window.innerWidth, window.innerHeight); 106 | renderer.sortObjects = false; 107 | container.appendChild(renderer.domElement); 108 | 109 | stats = new Stats(); 110 | stats.domElement.style.position = "absolute"; 111 | stats.domElement.style.top = "0px"; 112 | container.appendChild(stats.domElement); 113 | 114 | document.addEventListener(StringTypes.mousemove, WebglInteractiveCubes::onDocumentMouseMove, false); 115 | 116 | // 117 | 118 | window.addEventListener("resize", WebglInteractiveCubes::onWindowResize, false); 119 | 120 | } 121 | 122 | public static Object onWindowResize(Event event) { 123 | 124 | camera.aspect = window.innerWidth / window.innerHeight; 125 | camera.updateProjectionMatrix(); 126 | 127 | renderer.setSize(window.innerWidth, window.innerHeight); 128 | 129 | return null; 130 | } 131 | 132 | public static Object onDocumentMouseMove(MouseEvent event) { 133 | 134 | event.preventDefault(); 135 | 136 | mouse.x = (event.clientX / window.innerWidth) * 2 - 1; 137 | mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; 138 | 139 | return null; 140 | } 141 | 142 | // 143 | 144 | public static void animate(double time) { 145 | 146 | requestAnimationFrame(WebglInteractiveCubes::animate); 147 | 148 | render(); 149 | stats.update(); 150 | 151 | } 152 | 153 | public static void render() { 154 | 155 | theta += 0.1; 156 | 157 | camera.position.x = radius * Math.sin(def.threejs.three.Math.degToRad(theta)); 158 | camera.position.y = radius * Math.sin(def.threejs.three.Math.degToRad(theta)); 159 | camera.position.z = radius * Math.cos(def.threejs.three.Math.degToRad(theta)); 160 | camera.lookAt(scene.position); 161 | 162 | camera.updateMatrixWorld(true); 163 | 164 | // find intersections 165 | 166 | raycaster.setFromCamera(new Coords() { 167 | { 168 | x = mouse.x; 169 | y = mouse.y; 170 | } 171 | }, camera); 172 | 173 | Intersection[] intersects = raycaster.intersectObjects(scene.children); 174 | 175 | if (intersects.length > 0) { 176 | 177 | if (INTERSECTED != intersects[0].object) { 178 | 179 | // This part is horrible partially because there is a mistake in the definition file (emissive is a color) 180 | if (INTERSECTED != null) { 181 | ((Color) (Object) ((MeshLambertMaterial) INTERSECTED.material).emissive) 182 | .setHex((double) INTERSECTED.$get("currentHex")); 183 | } 184 | INTERSECTED = (Mesh) intersects[0].object; 185 | INTERSECTED.$set("currentHex", 186 | ((Color) (Object) ((MeshLambertMaterial) INTERSECTED.material).emissive).getHex()); 187 | ((Color) (Object) ((MeshLambertMaterial) INTERSECTED.material).emissive).setHex(0xff0000); 188 | 189 | } 190 | 191 | } else { 192 | 193 | if (INTERSECTED != null) { 194 | ((Color) (Object) ((MeshLambertMaterial) INTERSECTED.material).emissive) 195 | .setHex((double) INTERSECTED.$get("currentHex")); 196 | } 197 | INTERSECTED = null; 198 | 199 | } 200 | 201 | renderer.render(scene, camera); 202 | 203 | } 204 | 205 | } 206 | -------------------------------------------------------------------------------- /src/main/java/org/jsweet/examples/threejs/WebglMaterialsNormalMap.java: -------------------------------------------------------------------------------- 1 | package org.jsweet.examples.threejs; 2 | 3 | import static def.dom.Globals.document; 4 | import static def.dom.Globals.requestAnimationFrame; 5 | import static def.dom.Globals.window; 6 | import static jsweet.util.Lang.object; 7 | import static jsweet.util.Lang.union; 8 | import static def.threejs.Globals.Detector; 9 | import static def.threejs_ext.three.Globals.BleachBypassShader; 10 | import static def.threejs_ext.three.Globals.ColorCorrectionShader; 11 | import static def.threejs_ext.three.Globals.FXAAShader; 12 | 13 | import def.dom.Event; 14 | import def.dom.HTMLElement; 15 | import def.dom.MouseEvent; 16 | import def.dom.TouchEvent; 17 | import def.stats.Stats; 18 | import def.threejs.three.AmbientLight; 19 | import def.threejs.three.DirectionalLight; 20 | import def.threejs.three.EffectComposer; 21 | import def.threejs.three.Euler; 22 | import def.threejs.three.Geometry; 23 | import def.threejs.three.ImageUtils; 24 | import def.threejs.three.JSONLoader; 25 | import def.threejs.three.Material; 26 | import def.threejs.three.Mesh; 27 | import def.threejs.three.MeshPhongMaterial; 28 | import def.threejs.three.MeshPhongMaterialParameters; 29 | import def.threejs.three.PerspectiveCamera; 30 | import def.threejs.three.PointLight; 31 | import def.threejs.three.RenderPass; 32 | import def.threejs.three.Scene; 33 | import def.threejs.three.ShaderPass; 34 | import def.threejs.three.Vector2; 35 | import def.threejs.three.WebGLRenderer; 36 | import def.threejs.three.WebGLRendererParameters; 37 | import jsweet.util.StringTypes; 38 | 39 | // WARNING: this example compiles with JSweet in strict mode 40 | // jsweet-core-strict must be place first (before the JDK) in the classpath 41 | 42 | public class WebglMaterialsNormalMap { 43 | 44 | static double SCREEN_WIDTH, SCREEN_HEIGHT; 45 | 46 | static boolean statsEnabled = true; 47 | 48 | static HTMLElement container; 49 | static Stats stats; 50 | static JSONLoader loader; 51 | 52 | static PerspectiveCamera camera; 53 | static Scene scene; 54 | static WebGLRenderer renderer; 55 | 56 | static Mesh mesh, zmesh, lightMesh, geometry; 57 | static Mesh mesh1; 58 | 59 | static AmbientLight ambientLight; 60 | static DirectionalLight directionalLight; 61 | static PointLight pointLight; 62 | 63 | static double mouseX = 0; 64 | static double mouseY = 0; 65 | 66 | static double windowHalfX = window.innerWidth / 2; 67 | static double windowHalfY = window.innerHeight / 2; 68 | 69 | static ShaderPass effectFXAA; 70 | static EffectComposer composer; 71 | 72 | public static void main(String[] args) { 73 | if (!Detector.webgl) 74 | Detector.addGetWebGLMessage(); 75 | 76 | init(); 77 | animate(0); 78 | } 79 | 80 | public static void init() { 81 | 82 | container = document.createElement("div"); 83 | document.body.appendChild(container); 84 | 85 | camera = new PerspectiveCamera(27, window.innerWidth / window.innerHeight, 1, 10000); 86 | camera.position.z = 1200; 87 | 88 | scene = new Scene(); 89 | 90 | // LIGHTS 91 | 92 | ambientLight = new AmbientLight(0x444444); 93 | scene.add(ambientLight); 94 | 95 | pointLight = new PointLight(0xffffff, 1.25, 1000); 96 | pointLight.position.set(0, 0, 600); 97 | 98 | scene.add(pointLight); 99 | 100 | directionalLight = new DirectionalLight(0xffffff); 101 | directionalLight.position.set(1, -0.5, -1); 102 | scene.add(directionalLight); 103 | 104 | Material material = new MeshPhongMaterial(new MeshPhongMaterialParameters() { 105 | { 106 | color = union(0xdddddd); 107 | specular = 0x222222; 108 | shininess = 35; 109 | map = ImageUtils.loadTexture("obj/leeperrysmith/Map-COL.jpg"); 110 | specularMap = ImageUtils.loadTexture("obj/leeperrysmith/Map-SPEC.jpg"); 111 | normalMap = ImageUtils.loadTexture("obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg"); 112 | normalScale = new Vector2(0.8, 0.8); 113 | } 114 | }); 115 | 116 | loader = new JSONLoader(); 117 | loader.load("obj/leeperrysmith/LeePerrySmith.js", (geometry, materials) -> { 118 | createScene(geometry, 100, material); 119 | }); 120 | 121 | renderer = new WebGLRenderer(new WebGLRendererParameters() { 122 | { 123 | antialias = false; 124 | } 125 | }); 126 | renderer.setClearColor(0x111111); 127 | renderer.setPixelRatio(window.devicePixelRatio); 128 | renderer.setSize(window.innerWidth, window.innerHeight); 129 | container.appendChild(renderer.domElement); 130 | 131 | // 132 | 133 | renderer.gammaInput = true; 134 | renderer.gammaOutput = true; 135 | 136 | // 137 | 138 | if (statsEnabled) { 139 | 140 | stats = new Stats(); 141 | stats.domElement.style.position = "absolute"; 142 | stats.domElement.style.top = "0px"; 143 | stats.domElement.style.zIndex = "100"; 144 | container.appendChild(stats.domElement); 145 | 146 | } 147 | 148 | // COMPOSER 149 | 150 | renderer.autoClear = false; 151 | 152 | RenderPass renderModel = new RenderPass(scene, camera); 153 | 154 | ShaderPass effectBleach = new ShaderPass(BleachBypassShader); 155 | ShaderPass effectColor = new ShaderPass(ColorCorrectionShader); 156 | effectFXAA = new ShaderPass(FXAAShader); 157 | 158 | ((Euler) object(object(effectFXAA.$get("uniforms")).$get("resolution")).$get("value")) 159 | .set(1 / window.innerWidth, 1 / window.innerHeight, 0); 160 | 161 | object(object(effectBleach.$get("uniforms")).$get("opacity")).$set("value", 0.4); 162 | 163 | ((Euler) object(object(effectColor.$get("uniforms")).$get("powRGB")).$get("value")).set(1.4, 1.45, 1.45); 164 | ((Euler) object(object(effectColor.$get("uniforms")).$get("mulRGB")).$get("value")).set(1.1, 1.1, 1.1); 165 | 166 | effectFXAA.renderToScreen = true; 167 | 168 | composer = new EffectComposer(renderer); 169 | 170 | composer.addPass(renderModel); 171 | 172 | composer.addPass(effectBleach); 173 | composer.addPass(effectColor); 174 | composer.addPass(effectFXAA); 175 | 176 | // EVENTS 177 | 178 | document.addEventListener(StringTypes.mousemove, WebglMaterialsNormalMap::onDocumentMouseMove, false); 179 | document.addEventListener(StringTypes.touchmove, WebglMaterialsNormalMap::onDocumentTouchMove, false); 180 | window.addEventListener("resize", WebglMaterialsNormalMap::onWindowResize, false); 181 | 182 | } 183 | 184 | public static void createScene(Geometry geometry, double scale, Material material) { 185 | 186 | mesh1 = new Mesh(geometry, material); 187 | 188 | mesh1.position.y = -50; 189 | mesh1.scale.x = mesh1.scale.y = mesh1.scale.z = scale; 190 | 191 | scene.add(mesh1); 192 | 193 | } 194 | 195 | // 196 | 197 | public static void onWindowResize(Event event) { 198 | 199 | SCREEN_WIDTH = window.innerWidth; 200 | SCREEN_HEIGHT = window.innerHeight; 201 | 202 | renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); 203 | 204 | camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; 205 | camera.updateProjectionMatrix(); 206 | 207 | composer.reset(); 208 | 209 | ((Euler) object(object(effectFXAA.$get("uniforms")).$get("resolution")).$get("value")).set(1 / SCREEN_WIDTH, 210 | 1 / SCREEN_HEIGHT, 0); 211 | 212 | } 213 | 214 | public static Object onDocumentMouseMove(MouseEvent event) { 215 | 216 | mouseX = (event.clientX - windowHalfX) * 10; 217 | mouseY = (event.clientY - windowHalfY) * 10; 218 | 219 | return null; 220 | } 221 | 222 | public static Object onDocumentTouchMove(TouchEvent event) { 223 | 224 | mouseX = (event.touches.$get(0).clientX - windowHalfX) * 10; 225 | mouseY = (event.touches.$get(0).clientY - windowHalfY) * 10; 226 | 227 | return null; 228 | } 229 | 230 | // 231 | 232 | public static void animate(double time) { 233 | 234 | requestAnimationFrame(WebglMaterialsNormalMap::animate); 235 | 236 | render(); 237 | if (statsEnabled) 238 | stats.update(); 239 | 240 | } 241 | 242 | public static void render() { 243 | 244 | double ry = mouseX * 0.0003, rx = mouseY * 0.0003; 245 | 246 | if (mesh1 != null) { 247 | 248 | mesh1.rotation.y = ry; 249 | mesh1.rotation.x = rx; 250 | 251 | } 252 | 253 | // renderer.render( scene, camera ); 254 | composer.render(); 255 | 256 | } 257 | 258 | } 259 | -------------------------------------------------------------------------------- /webapp/libs/Detector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author mr.doob / http://mrdoob.com/ 4 | */ 5 | 6 | var Detector = { 7 | 8 | canvas: !! window.CanvasRenderingContext2D, 9 | webgl: ( function () { 10 | 11 | try { 12 | 13 | var canvas = document.createElement( 'canvas' ); return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); 14 | 15 | } catch ( e ) { 16 | 17 | return false; 18 | 19 | } 20 | 21 | } )(), 22 | workers: !! window.Worker, 23 | fileapi: window.File && window.FileReader && window.FileList && window.Blob, 24 | 25 | getWebGLErrorMessage: function () { 26 | 27 | var element = document.createElement( 'div' ); 28 | element.id = 'webgl-error-message'; 29 | element.style.fontFamily = 'monospace'; 30 | element.style.fontSize = '13px'; 31 | element.style.fontWeight = 'normal'; 32 | element.style.textAlign = 'center'; 33 | element.style.background = '#fff'; 34 | element.style.color = '#000'; 35 | element.style.padding = '1.5em'; 36 | element.style.width = '400px'; 37 | element.style.margin = '5em auto 0'; 38 | 39 | if ( ! this.webgl ) { 40 | 41 | element.innerHTML = window.WebGLRenderingContext ? [ 42 | 'Your graphics card does not seem to support WebGL.
', 43 | 'Find out how to get it here.' 44 | ].join( '\n' ) : [ 45 | 'Your browser does not seem to support WebGL.
', 46 | 'Find out how to get it here.' 47 | ].join( '\n' ); 48 | 49 | } 50 | 51 | return element; 52 | 53 | }, 54 | 55 | addGetWebGLMessage: function ( parameters ) { 56 | 57 | var parent, id, element; 58 | 59 | parameters = parameters || {}; 60 | 61 | parent = parameters.parent !== undefined ? parameters.parent : document.body; 62 | id = parameters.id !== undefined ? parameters.id : 'oldie'; 63 | 64 | element = Detector.getWebGLErrorMessage(); 65 | element.id = id; 66 | 67 | parent.appendChild( element ); 68 | 69 | } 70 | 71 | }; 72 | 73 | // browserify support 74 | if ( typeof module === 'object' ) { 75 | 76 | module.exports = Detector; 77 | 78 | } 79 | -------------------------------------------------------------------------------- /webapp/libs/postprocessing/EffectComposer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.EffectComposer = function ( renderer, renderTarget ) { 6 | 7 | this.renderer = renderer; 8 | 9 | if ( renderTarget === undefined ) { 10 | 11 | var pixelRatio = renderer.getPixelRatio(); 12 | 13 | var width = Math.floor( renderer.context.canvas.width / pixelRatio ) || 1; 14 | var height = Math.floor( renderer.context.canvas.height / pixelRatio ) || 1; 15 | var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false }; 16 | 17 | renderTarget = new THREE.WebGLRenderTarget( width, height, parameters ); 18 | 19 | } 20 | 21 | this.renderTarget1 = renderTarget; 22 | this.renderTarget2 = renderTarget.clone(); 23 | 24 | this.writeBuffer = this.renderTarget1; 25 | this.readBuffer = this.renderTarget2; 26 | 27 | this.passes = []; 28 | 29 | if ( THREE.CopyShader === undefined ) 30 | console.error( "THREE.EffectComposer relies on THREE.CopyShader" ); 31 | 32 | this.copyPass = new THREE.ShaderPass( THREE.CopyShader ); 33 | 34 | }; 35 | 36 | THREE.EffectComposer.prototype = { 37 | 38 | swapBuffers: function() { 39 | 40 | var tmp = this.readBuffer; 41 | this.readBuffer = this.writeBuffer; 42 | this.writeBuffer = tmp; 43 | 44 | }, 45 | 46 | addPass: function ( pass ) { 47 | 48 | this.passes.push( pass ); 49 | 50 | }, 51 | 52 | insertPass: function ( pass, index ) { 53 | 54 | this.passes.splice( index, 0, pass ); 55 | 56 | }, 57 | 58 | render: function ( delta ) { 59 | 60 | this.writeBuffer = this.renderTarget1; 61 | this.readBuffer = this.renderTarget2; 62 | 63 | var maskActive = false; 64 | 65 | var pass, i, il = this.passes.length; 66 | 67 | for ( i = 0; i < il; i ++ ) { 68 | 69 | pass = this.passes[ i ]; 70 | 71 | if ( ! pass.enabled ) continue; 72 | 73 | pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive ); 74 | 75 | if ( pass.needsSwap ) { 76 | 77 | if ( maskActive ) { 78 | 79 | var context = this.renderer.context; 80 | 81 | context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff ); 82 | 83 | this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta ); 84 | 85 | context.stencilFunc( context.EQUAL, 1, 0xffffffff ); 86 | 87 | } 88 | 89 | this.swapBuffers(); 90 | 91 | } 92 | 93 | if ( pass instanceof THREE.MaskPass ) { 94 | 95 | maskActive = true; 96 | 97 | } else if ( pass instanceof THREE.ClearMaskPass ) { 98 | 99 | maskActive = false; 100 | 101 | } 102 | 103 | } 104 | 105 | }, 106 | 107 | reset: function ( renderTarget ) { 108 | 109 | if ( renderTarget === undefined ) { 110 | 111 | renderTarget = this.renderTarget1.clone(); 112 | 113 | var pixelRatio = this.renderer.getPixelRatio(); 114 | 115 | renderTarget.width = Math.floor( this.renderer.context.canvas.width / pixelRatio ); 116 | renderTarget.height = Math.floor( this.renderer.context.canvas.height / pixelRatio ); 117 | 118 | } 119 | 120 | this.renderTarget1.dispose(); 121 | this.renderTarget1 = renderTarget; 122 | this.renderTarget2.dispose(); 123 | this.renderTarget2 = renderTarget.clone(); 124 | 125 | this.writeBuffer = this.renderTarget1; 126 | this.readBuffer = this.renderTarget2; 127 | 128 | }, 129 | 130 | setSize: function ( width, height ) { 131 | 132 | this.renderTarget1.setSize( width, height ); 133 | this.renderTarget2.setSize( width, height ); 134 | 135 | } 136 | 137 | }; 138 | -------------------------------------------------------------------------------- /webapp/libs/postprocessing/MaskPass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.MaskPass = function ( scene, camera ) { 6 | 7 | this.scene = scene; 8 | this.camera = camera; 9 | 10 | this.enabled = true; 11 | this.clear = true; 12 | this.needsSwap = false; 13 | 14 | this.inverse = false; 15 | 16 | }; 17 | 18 | THREE.MaskPass.prototype = { 19 | 20 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 21 | 22 | var context = renderer.context; 23 | 24 | // don't update color or depth 25 | 26 | context.colorMask( false, false, false, false ); 27 | context.depthMask( false ); 28 | 29 | // set up stencil 30 | 31 | var writeValue, clearValue; 32 | 33 | if ( this.inverse ) { 34 | 35 | writeValue = 0; 36 | clearValue = 1; 37 | 38 | } else { 39 | 40 | writeValue = 1; 41 | clearValue = 0; 42 | 43 | } 44 | 45 | context.enable( context.STENCIL_TEST ); 46 | context.stencilOp( context.REPLACE, context.REPLACE, context.REPLACE ); 47 | context.stencilFunc( context.ALWAYS, writeValue, 0xffffffff ); 48 | context.clearStencil( clearValue ); 49 | 50 | // draw into the stencil buffer 51 | 52 | renderer.render( this.scene, this.camera, readBuffer, this.clear ); 53 | renderer.render( this.scene, this.camera, writeBuffer, this.clear ); 54 | 55 | // re-enable update of color and depth 56 | 57 | context.colorMask( true, true, true, true ); 58 | context.depthMask( true ); 59 | 60 | // only render where stencil is set to 1 61 | 62 | context.stencilFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1 63 | context.stencilOp( context.KEEP, context.KEEP, context.KEEP ); 64 | 65 | } 66 | 67 | }; 68 | 69 | 70 | THREE.ClearMaskPass = function () { 71 | 72 | this.enabled = true; 73 | 74 | }; 75 | 76 | THREE.ClearMaskPass.prototype = { 77 | 78 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 79 | 80 | var context = renderer.context; 81 | 82 | context.disable( context.STENCIL_TEST ); 83 | 84 | } 85 | 86 | }; 87 | -------------------------------------------------------------------------------- /webapp/libs/postprocessing/RenderPass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) { 6 | 7 | this.scene = scene; 8 | this.camera = camera; 9 | 10 | this.overrideMaterial = overrideMaterial; 11 | 12 | this.clearColor = clearColor; 13 | this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 1; 14 | 15 | this.oldClearColor = new THREE.Color(); 16 | this.oldClearAlpha = 1; 17 | 18 | this.enabled = true; 19 | this.clear = true; 20 | this.needsSwap = false; 21 | 22 | }; 23 | 24 | THREE.RenderPass.prototype = { 25 | 26 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 27 | 28 | this.scene.overrideMaterial = this.overrideMaterial; 29 | 30 | if ( this.clearColor ) { 31 | 32 | this.oldClearColor.copy( renderer.getClearColor() ); 33 | this.oldClearAlpha = renderer.getClearAlpha(); 34 | 35 | renderer.setClearColor( this.clearColor, this.clearAlpha ); 36 | 37 | } 38 | 39 | renderer.render( this.scene, this.camera, readBuffer, this.clear ); 40 | 41 | if ( this.clearColor ) { 42 | 43 | renderer.setClearColor( this.oldClearColor, this.oldClearAlpha ); 44 | 45 | } 46 | 47 | this.scene.overrideMaterial = null; 48 | 49 | } 50 | 51 | }; 52 | -------------------------------------------------------------------------------- /webapp/libs/postprocessing/ShaderPass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | */ 4 | 5 | THREE.ShaderPass = function ( shader, textureID ) { 6 | 7 | this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse"; 8 | 9 | this.uniforms = THREE.UniformsUtils.clone( shader.uniforms ); 10 | 11 | this.material = new THREE.ShaderMaterial( { 12 | 13 | defines: shader.defines || {}, 14 | uniforms: this.uniforms, 15 | vertexShader: shader.vertexShader, 16 | fragmentShader: shader.fragmentShader 17 | 18 | } ); 19 | 20 | this.renderToScreen = false; 21 | 22 | this.enabled = true; 23 | this.needsSwap = true; 24 | this.clear = false; 25 | 26 | 27 | this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); 28 | this.scene = new THREE.Scene(); 29 | 30 | this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null ); 31 | this.scene.add( this.quad ); 32 | 33 | }; 34 | 35 | THREE.ShaderPass.prototype = { 36 | 37 | render: function ( renderer, writeBuffer, readBuffer, delta ) { 38 | 39 | if ( this.uniforms[ this.textureID ] ) { 40 | 41 | this.uniforms[ this.textureID ].value = readBuffer; 42 | 43 | } 44 | 45 | this.quad.material = this.material; 46 | 47 | if ( this.renderToScreen ) { 48 | 49 | renderer.render( this.scene, this.camera ); 50 | 51 | } else { 52 | 53 | renderer.render( this.scene, this.camera, writeBuffer, this.clear ); 54 | 55 | } 56 | 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /webapp/libs/shaders/BleachBypassShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] 5 | * - based on Nvidia example 6 | * http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass 7 | */ 8 | 9 | THREE.BleachBypassShader = { 10 | 11 | uniforms: { 12 | 13 | "tDiffuse": { type: "t", value: null }, 14 | "opacity": { type: "f", value: 1.0 } 15 | 16 | }, 17 | 18 | vertexShader: [ 19 | 20 | "varying vec2 vUv;", 21 | 22 | "void main() {", 23 | 24 | "vUv = uv;", 25 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 26 | 27 | "}" 28 | 29 | ].join( "\n" ), 30 | 31 | fragmentShader: [ 32 | 33 | "uniform float opacity;", 34 | 35 | "uniform sampler2D tDiffuse;", 36 | 37 | "varying vec2 vUv;", 38 | 39 | "void main() {", 40 | 41 | "vec4 base = texture2D( tDiffuse, vUv );", 42 | 43 | "vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );", 44 | "float lum = dot( lumCoeff, base.rgb );", 45 | "vec3 blend = vec3( lum );", 46 | 47 | "float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );", 48 | 49 | "vec3 result1 = 2.0 * base.rgb * blend;", 50 | "vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );", 51 | 52 | "vec3 newColor = mix( result1, result2, L );", 53 | 54 | "float A2 = opacity * base.a;", 55 | "vec3 mixRGB = A2 * newColor.rgb;", 56 | "mixRGB += ( ( 1.0 - A2 ) * base.rgb );", 57 | 58 | "gl_FragColor = vec4( mixRGB, base.a );", 59 | 60 | "}" 61 | 62 | ].join( "\n" ) 63 | 64 | }; 65 | -------------------------------------------------------------------------------- /webapp/libs/shaders/ColorCorrectionShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * Color correction 5 | */ 6 | 7 | THREE.ColorCorrectionShader = { 8 | 9 | uniforms: { 10 | 11 | "tDiffuse": { type: "t", value: null }, 12 | "powRGB": { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, 13 | "mulRGB": { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }, 14 | "addRGB": { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) } 15 | 16 | }, 17 | 18 | vertexShader: [ 19 | 20 | "varying vec2 vUv;", 21 | 22 | "void main() {", 23 | 24 | "vUv = uv;", 25 | 26 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 27 | 28 | "}" 29 | 30 | ].join( "\n" ), 31 | 32 | fragmentShader: [ 33 | 34 | "uniform sampler2D tDiffuse;", 35 | "uniform vec3 powRGB;", 36 | "uniform vec3 mulRGB;", 37 | "uniform vec3 addRGB;", 38 | 39 | "varying vec2 vUv;", 40 | 41 | "void main() {", 42 | 43 | "gl_FragColor = texture2D( tDiffuse, vUv );", 44 | "gl_FragColor.rgb = mulRGB * pow( ( gl_FragColor.rgb + addRGB ), powRGB );", 45 | 46 | "}" 47 | 48 | ].join( "\n" ) 49 | 50 | }; 51 | -------------------------------------------------------------------------------- /webapp/libs/shaders/CopyShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * Full-screen textured quad shader 5 | */ 6 | 7 | THREE.CopyShader = { 8 | 9 | uniforms: { 10 | 11 | "tDiffuse": { type: "t", value: null }, 12 | "opacity": { type: "f", value: 1.0 } 13 | 14 | }, 15 | 16 | vertexShader: [ 17 | 18 | "varying vec2 vUv;", 19 | 20 | "void main() {", 21 | 22 | "vUv = uv;", 23 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 24 | 25 | "}" 26 | 27 | ].join( "\n" ), 28 | 29 | fragmentShader: [ 30 | 31 | "uniform float opacity;", 32 | 33 | "uniform sampler2D tDiffuse;", 34 | 35 | "varying vec2 vUv;", 36 | 37 | "void main() {", 38 | 39 | "vec4 texel = texture2D( tDiffuse, vUv );", 40 | "gl_FragColor = opacity * texel;", 41 | 42 | "}" 43 | 44 | ].join( "\n" ) 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /webapp/libs/shaders/FXAAShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author davidedc / http://www.sketchpatch.net/ 4 | * 5 | * NVIDIA FXAA by Timothy Lottes 6 | * http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html 7 | * - WebGL port by @supereggbert 8 | * http://www.glge.org/demos/fxaa/ 9 | */ 10 | 11 | THREE.FXAAShader = { 12 | 13 | uniforms: { 14 | 15 | "tDiffuse": { type: "t", value: null }, 16 | "resolution": { type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) } 17 | 18 | }, 19 | 20 | vertexShader: [ 21 | 22 | "void main() {", 23 | 24 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 25 | 26 | "}" 27 | 28 | ].join( "\n" ), 29 | 30 | fragmentShader: [ 31 | 32 | "uniform sampler2D tDiffuse;", 33 | "uniform vec2 resolution;", 34 | 35 | "#define FXAA_REDUCE_MIN (1.0/128.0)", 36 | "#define FXAA_REDUCE_MUL (1.0/8.0)", 37 | "#define FXAA_SPAN_MAX 8.0", 38 | 39 | "void main() {", 40 | 41 | "vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;", 42 | "vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;", 43 | "vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;", 44 | "vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;", 45 | "vec4 rgbaM = texture2D( tDiffuse, gl_FragCoord.xy * resolution );", 46 | "vec3 rgbM = rgbaM.xyz;", 47 | "vec3 luma = vec3( 0.299, 0.587, 0.114 );", 48 | 49 | "float lumaNW = dot( rgbNW, luma );", 50 | "float lumaNE = dot( rgbNE, luma );", 51 | "float lumaSW = dot( rgbSW, luma );", 52 | "float lumaSE = dot( rgbSE, luma );", 53 | "float lumaM = dot( rgbM, luma );", 54 | "float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );", 55 | "float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );", 56 | 57 | "vec2 dir;", 58 | "dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));", 59 | "dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));", 60 | 61 | "float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );", 62 | 63 | "float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );", 64 | "dir = min( vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),", 65 | "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),", 66 | "dir * rcpDirMin)) * resolution;", 67 | "vec4 rgbA = (1.0/2.0) * (", 68 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (1.0/3.0 - 0.5)) +", 69 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (2.0/3.0 - 0.5)));", 70 | "vec4 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (", 71 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (0.0/3.0 - 0.5)) +", 72 | "texture2D(tDiffuse, gl_FragCoord.xy * resolution + dir * (3.0/3.0 - 0.5)));", 73 | "float lumaB = dot(rgbB, vec4(luma, 0.0));", 74 | 75 | "if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {", 76 | 77 | "gl_FragColor = rgbA;", 78 | 79 | "} else {", 80 | "gl_FragColor = rgbB;", 81 | 82 | "}", 83 | 84 | "}" 85 | 86 | ].join( "\n" ) 87 | 88 | }; 89 | -------------------------------------------------------------------------------- /webapp/libs/stats.min.js: -------------------------------------------------------------------------------- 1 | // stats.js - http://github.com/mrdoob/stats.js 2 | var Stats=function(){function f(a,e,b){a=document.createElement(a);a.id=e;a.style.cssText=b;return a}function l(a,e,b){var c=f("div",a,"padding:0 0 3px 3px;text-align:left;background:"+b),d=f("div",a+"Text","font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px;color:"+e);d.innerHTML=a.toUpperCase();c.appendChild(d);a=f("div",a+"Graph","width:74px;height:30px;background:"+e);c.appendChild(a);for(e=0;74>e;e++)a.appendChild(f("span","","width:1px;height:30px;float:left;opacity:0.9;background:"+ 3 | b));return c}function m(a){for(var b=c.children,d=0;dr+1E3&&(d=Math.round(1E3* 5 | t/(a-r)),u=Math.min(u,d),v=Math.max(v,d),A.textContent=d+" FPS ("+u+"-"+v+")",p(B,d/100),r=a,t=0,void 0!==h)){var b=performance.memory.usedJSHeapSize,c=performance.memory.jsHeapSizeLimit;h=Math.round(9.54E-7*b);y=Math.min(y,h);z=Math.max(z,h);E.textContent=h+" MB ("+y+"-"+z+")";p(F,b/c)}return a},update:function(){k=this.end()}}};"object"===typeof module&&(module.exports=Stats); 6 | -------------------------------------------------------------------------------- /webapp/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cincheo/jsweet-examples-threejs/50fbc75b225f67efedcc0b451cbb14f703f6be09/webapp/logo.png -------------------------------------------------------------------------------- /webapp/obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cincheo/jsweet-examples-threejs/50fbc75b225f67efedcc0b451cbb14f703f6be09/webapp/obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg -------------------------------------------------------------------------------- /webapp/obj/leeperrysmith/Map-COL.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cincheo/jsweet-examples-threejs/50fbc75b225f67efedcc0b451cbb14f703f6be09/webapp/obj/leeperrysmith/Map-COL.jpg -------------------------------------------------------------------------------- /webapp/obj/leeperrysmith/Map-SPEC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cincheo/jsweet-examples-threejs/50fbc75b225f67efedcc0b451cbb14f703f6be09/webapp/obj/leeperrysmith/Map-SPEC.jpg -------------------------------------------------------------------------------- /webapp/obj/leeperrysmith/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cincheo/jsweet-examples-threejs/50fbc75b225f67efedcc0b451cbb14f703f6be09/webapp/obj/leeperrysmith/Thumbs.db -------------------------------------------------------------------------------- /webapp/webgl_interactive_cubes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | three.js webgl - interactive cubes 6 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /webapp/webgl_materials_normalmap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | three.js webgl - materials - normal map [Lee Perry-Smith] 6 | 7 | 8 | 43 | 44 | 45 | 46 |
47 | three.js - webgl normalmap demo. 48 | Lee Perry-Smith head. 49 | 50 |
displacement mapping needs vertex textures (GPU with Shader Model 3.0)
51 | on Windows use Chrome --use-gl=desktop or Firefox 4
52 | please star this Chrome issue to get ANGLE support 53 |
54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | --------------------------------------------------------------------------------