-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
112 lines (95 loc) · 2.68 KB
/
index.ts
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import {
Scene,
PerspectiveCamera,
Mesh,
WebGLRenderer,
ShaderMaterial,
VideoTexture,
GridHelper,
SphereGeometry,
BackSide,
} from "three";
import { VRButton } from "three/addons/webxr/VRButton.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
const canvas = document.getElementById("root")!;
const renderer = new WebGLRenderer({
antialias: true,
canvas,
});
renderer.xr.enabled = true;
document.body.appendChild(VRButton.createButton(renderer));
const camera = new PerspectiveCamera(
90,
window.innerWidth / window.innerHeight,
0.01,
100
);
camera.position.z = 1;
new OrbitControls(camera, canvas);
const scene = new Scene();
scene.add(new GridHelper());
const geometry = new SphereGeometry(1, 1024, 512);
const video = document.createElement("video");
video.loop = true;
window.onclick = () => {
window.onclick = undefined;
const input = document.createElement("input");
input.type = "file";
input.onchange = () => {
const file = input.files[0];
if (file == null) {
return;
}
video.src = URL.createObjectURL(file);
video.play();
};
input.click();
};
const material = new ShaderMaterial({
uniforms: {
map: { value: new VideoTexture(video) },
},
vertexShader: `
varying vec3 vUv;
uniform sampler2D map;
#define M_PI 3.14159
vec2 worldToSpherical(vec3 flatCoord, float r) {
return vec2(
atan(flatCoord.x, flatCoord.z),
acos(-flatCoord.y / r)
) / vec2(2.0 * M_PI, M_PI) + vec2(0.5, 0.0);
}
void main() {
vUv = position;
float d = texture2D(map, vec2(0.5, 1.0) * worldToSpherical(position, 1.0)).r;
float depth = 1.0 + pow(1.0 - d, 5.0) * 20.0;
vec4 modelViewPosition = modelViewMatrix * vec4(position * vec3(depth), 1.0);
gl_Position = projectionMatrix * modelViewPosition;
}`,
fragmentShader: `
#define M_PI 3.14159
varying vec3 vUv;
uniform sampler2D map;
vec2 worldToSpherical(vec3 flatCoord, float r) {
return vec2(
atan(flatCoord.x, flatCoord.z),
acos(-flatCoord.y / r)
) / vec2(2.0 * M_PI, M_PI) + vec2(0.5, 0.0);
}
void main() {
gl_FragColor = texture2D(map, vec2(0.5, 0.0) + vec2(0.5, 1.0) * worldToSpherical(vUv, 1.0));
}`,
});
material.side = BackSide;
const mesh = new Mesh(geometry, material);
mesh.position.y = 1.1;
mesh.scale.setScalar(2);
mesh.frustumCulled = false;
scene.add(mesh);
renderer.setSize(window.innerWidth, window.innerHeight);
window.addEventListener("resize", () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
renderer.setAnimationLoop(() => renderer.render(scene, camera));