<script >
let tex1 = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAwSURBVBhXY2D4z8DQgIGAgigcOBuIUDjICJ0PRyCMZgiEi0UIghAsNIRuDgT9ZwAADnoj+YsyPEwAAAAASUVORK5CYII=`;
let tex2=`data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAC9JREFUGFdj+N/g0ODAgIaAguh8OBuLEIQN5WAiEMZqDQoHogLFKExN2M353+AAAB6YOvZpRxb+AAAAAElFTkSuQmCC`;
</script>
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
import {ImprovedNoise} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/math/ImprovedNoise";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 5, 20).setLength(40);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", event => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
})
let controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(8, 0, 8);
controls.update();
let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let texMap1 = new THREE.TextureLoader().load(tex1);
let texMap2 = new THREE.TextureLoader().load(tex2);
let g = new THREE.BoxGeometry(1, 1, 1);
let m = new THREE.MeshLambertMaterial({
onBeforeCompile: shader => {
shader.uniforms.map = {value: [texMap1,texMap2]};
shader.vertexShader = `
attribute float texIdx;
varying float vTexIdx;
${shader.vertexShader}
`.replace(
`void main() {`,
`void main() {
vTexIdx = texIdx;
`
);
//console.log(shader.vertexShader);
shader.fragmentShader = `
uniform sampler2D map[2];
varying float vTexIdx;
${shader.fragmentShader}
`.replace(
`#include <map_fragment>`,
`#include <map_fragment>
//vec4 blockColor = texture(texAtlas, blockUv);
if(vTexIdx==0.0){ diffuseColor *=texture2D(map[0],vUv); }
if(vTexIdx==1.0){ diffuseColor *=texture2D(map[1],vUv); }
`
);
//console.log(shader.fragmentShader);
}
});
m.defines = {"USE_UV" : ""};
let blocks = new THREE.InstancedMesh(g, m, 10240);
let perlin = new ImprovedNoise();
let vecUV = new THREE.Vector2();
let dummy = new THREE.Object3D();
let texIdx = new Float32Array(10240).fill(0);
let instIdx = 0;
for(let x = 0; x < 16; x++){
for(let z = 0; z < 16; z++){
vecUV.set(x,z).divideScalar(16).multiplyScalar(2.5);
let h = Math.floor(perlin.noise(vecUV.x, vecUV.y, 100) * 4) + 32;
for(let y = 0; y < h; y++){
dummy.position.set(x, y - 32, z);
dummy.updateMatrix();
blocks.setMatrixAt(instIdx, dummy.matrix);
texIdx[instIdx] = y < (h - 1) ? 0 : 1;
instIdx++;
}
}
}
g.setAttribute("texIdx", new THREE.InstancedBufferAttribute(texIdx,1));
scene.add(blocks);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.