Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save FadedWeiss/f8146a081df797dc06809e0e2e7469cd to your computer and use it in GitHub Desktop.
Save FadedWeiss/f8146a081df797dc06809e0e2e7469cd to your computer and use it in GitHub Desktop.
Animal Crossing: New Horizons Camera & Tilt Shift
<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
"addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
}
}
</script>
//original by @mjurczyk https://codepen.io/mjurczyk/pen/LYNqzxa
import * as THREE from 'three'
import {BokehShader} from 'addons/shaders/BokehShader.js'
import {EffectComposer} from 'addons/postprocessing/EffectComposer.js'
import {RenderPass} from 'addons/postprocessing/RenderPass.js'
import {BokehPass} from 'addons/postprocessing/BokehPass.js'
import {ShaderPass} from 'addons/postprocessing/ShaderPass.js'
import {GLTFLoader} from'addons/loaders/GLTFLoader.js'
import { extendMaterial } from 'https://cdn.jsdelivr.net/gh/forerunrun/extends@main/ExtendMaterial.module.js'
let camera, scene, renderer, composer;
let tree
let player
let gltfLoader = new GLTFLoader()
let mixer, clock;
let action;
const load = ()=>{
gltfLoader.load('https://raw.githubusercontent.com/forerunrun/extends/main/BirchTree_1.glb', (gltf)=>{
tree = gltf.scene
tree.traverse(c=>{
if(c.isMesh){
c.material = new THREE.MeshStandardMaterial({color:0xffffff})
if(c.geometry){
c.geometry.scale(0.1,0.1,0.1)
c.geometry.rotateX(90*Math.PI/180)
c.geometry.translate(0,-9,0)
}
}
})
loadNext()
})
const loadNext = ()=>{
gltfLoader.load('https://raw.githubusercontent.com/forerunrun/extends/main/player_final.glb', (gltf)=>{
player = gltf.scene
player.traverse(c=>{
if(c.isMesh){
c.material = new THREE.MeshStandardMaterial({color:0xffffff})
if(c.geometry){
// c.geometry.scale(0.05,0.05,0.05)
// c.geometry.rotateX(90*Math.PI/180)
// c.geometry.translate(0,-9,0)
}
}
})
const animations = gltf.animations;
mixer = new THREE.AnimationMixer( player );
action = mixer.clipAction( animations[ 4 ] );
action.play();
player.scale.set(0.05,0.05,0.05)
player.rotation.y = 180*Math.PI/180
player.rotation.x = 90*Math.PI/180
afterLoad()
})
}
}
load()
const afterLoad = ()=>{
const foldableShader = `
vec4 vWorld = projectionMatrix * modelViewMatrix * vec4(transformed, 1.0);
vWorld -= cameraPosition.y;
vec3 vShift = vec3(0.0, pow2(vWorld.z) * - 0.15, pow2(vWorld.z) * - 0.3);
transformed += vShift;
`;
function FoldableMaterial(options = {}) {
return extendMaterial(
THREE.MeshStandardMaterial,
{
uniforms: { ...options },
vertex: {
transformEnd: foldableShader
}
}
);
}
const textures = {
grass: new THREE.TextureLoader().load('//cdn.wtlstudio.com/sample.wtlstudio.com/401795a0-590a-4a1b-9b75-36f94b3f4cdf.png', (texture) => {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
}),
wood: new THREE.TextureLoader().load('//cdn.wtlstudio.com/sample.wtlstudio.com/9c275256-9383-4661-b85e-8848d605e465.png', (texture) => {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
}),
sky: new THREE.TextureLoader().load('//cdn.wtlstudio.com/sample.wtlstudio.com/70b211ae-bc58-4b7f-b830-b85e8e63fcb4.png', (texture) => {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
}),
};
const materials = {
greens: FoldableMaterial({ map: textures.grass, side: THREE.FrontSide }),
wood: FoldableMaterial({ map: textures.wood, side: THREE.FrontSide }),
};
function createWorld() {
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(100.0, 100.0, 100, 100),
materials.greens
);
ground.rotation.x -= Math.PI / 2;
ground.position.z = -10.0;
scene.add(ground);
ground.add(player)
player.position.set(0,-9,0)
// camera.lookAt(player.position)
tree.traverse(c=>{
if(c.isMesh){
c.material = materials.wood
}
})
// player.traverse(c=>{
// if(c.isMesh){
// c.material = materials.wood
// }
// })
for (let i = 0; i < 50; i++) {
const treeClone = tree.clone()
treeClone.translateY(-10);
treeClone.translateX(Math.random() * 2.0 - 1.0);
treeClone.translateY(-10 + i * 2.0);
ground.add(treeClone);
}
}
function init() {
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000.0);
camera.position.y = 1.0;
camera.rotation.x -= THREE.MathUtils.degToRad(45);
scene = new THREE.Scene();
scene.background = textures.sky;
scene.add(new THREE.HemisphereLight(0xffffcc, 0x19bbdc, 1));
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
composer = new EffectComposer(renderer);
composer.setSize(window.innerWidth, window.innerHeight);
composer.addPass(new RenderPass(scene, camera));
composer.addPass(new BokehPass(scene, camera, {
focus: 1.25,
aperture: 0.01,
maxblur: 0.01,
width: window.innerWidth,
height: window.innerHeight
}));
createWorld();
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
player.position.y += 0.01
camera.position.z -= 0.01;
mixer.update( 0.01 );
composer.render();
}
init();
animate();
}
body {
margin: 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment