forked from Tresjs/lab
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request Tresjs#102 from Tresjs/feat/overlay
feat(overlay): Add example of HTML overlay on TresCanvas
- Loading branch information
Showing
6 changed files
with
416 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
<script setup lang="ts"> | ||
import { ShaderMaterial, SphereGeometry, Vector3, Color, MathUtils } from 'three/src/Three'; | ||
const rgb = (r: number, g: number, b: number) => new Color(r / 255, g / 255, b / 255) | ||
const BG_COLOR_BOTTOM_BLUISH = rgb(170, 215, 217) | ||
const BG_COLOR_TOP_BLUISH = rgb(57, 167, 255) | ||
const BG_COLOR_BOTTOM_ORANGISH = rgb(255, 160, 75) | ||
const BG_COLOR_TOP_ORANGISH = rgb(239, 172, 53) | ||
const SPHERE_COLOR_BOTTOM_BLUISH = rgb(120, 235, 124) | ||
const SPHERE_COLOR_TOP_BLUISH = rgb(0, 167, 255) | ||
const SPHERE_COLOR_BOTTOM_ORANGISH = rgb(235, 170, 0) | ||
const SPHERE_COLOR_TOP_ORANGISH = rgb(255, 120, 0) | ||
const SPHERE_COUNT = 250 | ||
const SPHERE_SCALE_COEFF = 3 | ||
const ORBIT_MIN = SPHERE_SCALE_COEFF + 2 | ||
const ORBIT_MAX = ORBIT_MIN + 10 | ||
const RAND_SEED = 898211544 | ||
const seededRandom = (a: number) => { | ||
return function () { | ||
a |= 0; a = a + 0x9e3779b9 | 0; | ||
var t = a ^ a >>> 16; t = Math.imul(t, 0x21f0aaad); | ||
t = t ^ t >>> 15; t = Math.imul(t, 0x735a2d97); | ||
return ((t = t ^ t >>> 15) >>> 0) / 4294967296; | ||
} | ||
} | ||
const rand = seededRandom(RAND_SEED) | ||
const randRange = (n = 1) => rand() * n | ||
const { PI, cos, sin } = Math; | ||
const PI2 = PI * 2 | ||
const spheres = new Array(SPHERE_COUNT).fill(0).map((_: any, i) => i) | ||
const sizes = new Array(SPHERE_COUNT).fill(0).map(() => randRange(1) * Math.pow(randRange(), 3)) | ||
const orbitRadii = new Array(SPHERE_COUNT).fill(0).map(() => MathUtils.lerp(ORBIT_MIN, ORBIT_MAX, randRange())) | ||
const thetas = new Array(SPHERE_COUNT).fill(0).map(() => randRange(PI2)) | ||
const phis = new Array(SPHERE_COUNT).fill(0).map(() => randRange(PI2)) | ||
const positions: [number, number, number][] = orbitRadii.map((rad, i) => ([rad * cos(thetas[i]) * sin(phis[i]), rad * sin(thetas[i]) * sin(phis[i]), rad * cos(phis[i])])) | ||
const getGradientMaterial = (colorBottomWarm: Color, colorTopWarm: Color, colorBottomCool: Color, colorTopCool: Color) => { | ||
return new ShaderMaterial({ | ||
uniforms: { | ||
colorBottomWarm: { | ||
value: new Color().copy(colorBottomWarm) | ||
}, | ||
colorTopWarm: { | ||
value: new Color().copy(colorTopWarm) | ||
}, | ||
colorBottomCool: { | ||
value: new Color().copy(colorBottomCool) | ||
}, | ||
colorTopCool: { | ||
value: new Color().copy(colorTopCool) | ||
}, | ||
uTemperature: { | ||
value: 0.0 | ||
}, | ||
uTemperatureVariancePeriod: { | ||
value: new Vector3(0.08, 0.1, 0.2) | ||
}, | ||
uElapsedTime: { | ||
value: 0 | ||
} | ||
}, | ||
vertexShader: ` | ||
uniform vec4 uTemperatureVariancePeriod; | ||
uniform float uTemperature; | ||
uniform float uElapsedTime; | ||
varying float topBottomMix; | ||
varying float warmCoolMix; | ||
void main() { | ||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); | ||
topBottomMix = normal.y; | ||
warmCoolMix = 0.6 * uTemperature + | ||
0.4 * (sin( | ||
(uElapsedTime + gl_Position.x) * uTemperatureVariancePeriod.x + | ||
(uElapsedTime + gl_Position.y) * uTemperatureVariancePeriod.y + | ||
(uElapsedTime + gl_Position.z) * uTemperatureVariancePeriod.z) * 0.5 + 0.5); | ||
} | ||
`, | ||
fragmentShader: ` | ||
uniform vec3 colorBottomWarm; | ||
uniform vec3 colorTopWarm; | ||
uniform vec3 colorBottomCool; | ||
uniform vec3 colorTopCool; | ||
varying float topBottomMix; | ||
varying float warmCoolMix; | ||
void main() { | ||
gl_FragColor = vec4(mix( | ||
mix(colorTopCool, colorTopWarm, warmCoolMix), | ||
mix(colorBottomCool, colorBottomWarm, warmCoolMix), | ||
topBottomMix), 1.0); | ||
} | ||
`, | ||
}); | ||
} | ||
const sphereGeometry = new SphereGeometry(SPHERE_SCALE_COEFF); | ||
const sphereMaterial = getGradientMaterial(SPHERE_COLOR_BOTTOM_BLUISH, SPHERE_COLOR_TOP_BLUISH, SPHERE_COLOR_BOTTOM_ORANGISH, SPHERE_COLOR_TOP_ORANGISH) | ||
const bgGeometry = new SphereGeometry(); | ||
bgGeometry.scale(-1, 1, 1) | ||
const bgMaterial = getGradientMaterial(BG_COLOR_BOTTOM_BLUISH, BG_COLOR_TOP_BLUISH, BG_COLOR_BOTTOM_ORANGISH, BG_COLOR_TOP_ORANGISH) | ||
bgMaterial.uniforms.uTemperatureVariancePeriod.value = new Vector3(0, 0, 0.1) | ||
useRenderLoop().onLoop(({ elapsed }) => { | ||
const temperature = sin(elapsed * 0.5) * 0.5 + 0.5 | ||
bgMaterial.uniforms.uTemperature.value = temperature | ||
sphereMaterial.uniforms.uTemperature.value = temperature | ||
bgMaterial.uniforms.uElapsedTime.value = elapsed | ||
sphereMaterial.uniforms.uElapsedTime.value = elapsed | ||
}) | ||
</script> | ||
|
||
<template> | ||
<TresCanvas clear-color="white" :shadows="false"> | ||
<TresMesh :scale="20" :rotation-x="Math.PI * 1.5" :material="bgMaterial" :geometry="bgGeometry"></TresMesh> | ||
<TresPerspectiveCamera :position="[0, 0, 23]" /> | ||
<Levioso :speed="0.7" :float-factor="20"> | ||
<TresGroup :rotation-x="Math.PI * 1.5"> | ||
<TresMesh v-for="i of spheres" :position="positions[i]" :scale="sizes[i]" :material="sphereMaterial" | ||
:geometry="sphereGeometry" /> | ||
</TresGroup> | ||
</Levioso> | ||
</TresCanvas> | ||
</template> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
<script setup lang="ts"> | ||
import Background from './Background.vue'; | ||
</script> | ||
|
||
<template> | ||
<Background /> | ||
<div class="overlay"> | ||
<div class="overlay-center"> | ||
<h1>Hola</h1> | ||
</div> | ||
<div class="top-left"> | ||
<a href="https://tresjs.org" class="logo"> | ||
<img src="./logos/tres_logo_white.svg" alt="TresJS Logo" width="140" /> | ||
</a> | ||
</div> | ||
<div class="bottom-left"> | ||
<div style="display:flex"> | ||
<div style="padding-right:20px; padding-top:5px"> | ||
<img src="./logos/tres_shapes_stack_white.svg" width="25" alt="" /> | ||
</div> | ||
<div> | ||
<a href="https://tresjs.org">TresJS is Vue.js + Three.js</a><br /> | ||
<a href="/">See more experiments and examples</a> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<style> | ||
body { | ||
color: white | ||
} | ||
.overlay { | ||
position: fixed; | ||
width: 100%; | ||
height: 100%; | ||
top: 0; | ||
left: 0; | ||
right: 0; | ||
bottom: 0; | ||
z-index: 2; | ||
} | ||
.overlay a { | ||
pointer-events: auto; | ||
color: #FFF; | ||
transition: color 0.25s; | ||
} | ||
.overlay a:hover { | ||
color: #444; | ||
} | ||
.top-left { | ||
position: absolute; | ||
top: 40px; | ||
left: 60px; | ||
} | ||
.bottom-left { | ||
position: absolute; | ||
bottom: 40px; | ||
left: 60px; | ||
} | ||
.bottom-right { | ||
position: absolute; | ||
bottom: 40px; | ||
right: 60px; | ||
} | ||
.overlay-center { | ||
position: absolute; | ||
top: 50%; | ||
left: 50%; | ||
transform: translate3d(-50%, -50%, 0); | ||
pointer-events: none; | ||
} | ||
h1 { | ||
margin: 0; | ||
padding: 0; | ||
font-size: 15em; | ||
letter-spacing: -0.05em; | ||
text-align: center; | ||
} | ||
/* phone */ | ||
@media (max-width: 599px) { | ||
h1 { | ||
font-size: 6em; | ||
} | ||
} | ||
/* tablet portrait up */ | ||
@media (min-width: 600px) { | ||
h1 { | ||
font-size: 10em; | ||
} | ||
} | ||
/* tablet landscape */ | ||
@media (min-width: 900px) { | ||
h1 { | ||
font-size: 14em; | ||
} | ||
} | ||
/* tablet desktop up */ | ||
@media (min-width: 1200px) { | ||
h1 { | ||
font-size: 18em; | ||
} | ||
} | ||
/* tablet big desktop up */ | ||
@media (min-width: 1800px) { | ||
h1 { | ||
font-size: 24em; | ||
} | ||
} | ||
</style> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.