Skip to content

Commit

Permalink
Merge pull request Tresjs#102 from Tresjs/feat/overlay
Browse files Browse the repository at this point in the history
feat(overlay): Add example of HTML overlay on TresCanvas
  • Loading branch information
andretchen0 authored Feb 12, 2024
2 parents 97f8255 + 80982e8 commit 13c0d45
Show file tree
Hide file tree
Showing 6 changed files with 416 additions and 0 deletions.
129 changes: 129 additions & 0 deletions components/content/overlay/Background.vue
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>
124 changes: 124 additions & 0 deletions components/content/overlay/index.vue
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>
105 changes: 105 additions & 0 deletions components/content/overlay/logos/tres_logo_white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 13c0d45

Please sign in to comment.