What’s on our mind?

Collection of articles, design, site, and resources made by designers and publisher @Menu View

** index32
// 화면 
let scene = new THREE.Scene();

// 카메라
let camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);

// 렌더링
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
document.body.appendChild(renderer.domElement);

// 화면 사이즈
window.addEventListener("resize", () => {
    camera.aspect = innerWidth / innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(innerWidth, innerHeight);
    bloomComposer.setSize(innerWidth, innerHeight);
    finalComposer.setSize(innerWidth, innerHeight);
    rt.setSize(innerWidth, innerHeight);
    globalUniforms.aspect.value = camera.aspect;
})

// 컨트롤
let controls = new OrbitControls(camera, renderer.domElement);
controls.enableZoom = false;
controls.enablePan = false;
controls.enableDamping = true;
controls.autoRotate = true;
controls.autoRotateSpeed *= 0.25;

let cubeMap = createCubeMap();

// 조명
let light = new THREE.DirectionalLight(0xffffff, 1.75);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.25));

let globalUniforms = {
    bloom: {
        value: 0
    },
    time: {
        value: 0
    },
    aspect: {
        value: innerWidth / innerHeight
    }
}

// 객체 설정
let g = new THREE.IcosahedronGeometry(1, 70);
let localUniforms = {
    color1: {value: new THREE.Color(0xff3232)},
    color2: {value: new THREE.Color(0x0032ff)}
}
let m = new THREE.MeshStandardMaterial({
    roughness: 0.125,
    metalness: 0.875,
    envMap: cubeMap,
    onBeforeCompile: shader => {
        shader.uniforms.bloom = globalUniforms.bloom;
        shader.uniforms.time = globalUniforms.time;
        shader.uniforms.color1 = localUniforms.color1;
        shader.uniforms.color2 = localUniforms.color2;
        shader.vertexShader = `
            uniform float time;
            varying vec3 rPos;
            ${document.getElementById( 'noiseFS' ).textContent}
            float noise(vec3 p){
                return cnoise(vec4(p, time));
            }
            vec3 getPos(vec3 p){
                return p * (4. + noise(p * 3.) * 2.);
            }
            ${shader.vertexShader}
            `.replace(
                `#include <beginnormal_vertex>`,
                `#include <beginnormal_vertex>

            vec3 p0 = getPos(position);

            float theta = .1; 
            vec3 vecTangent = normalize(cross(p0, vec3(1.0, 0.0, 0.0)) + cross(p0, vec3(0.0, 1.0, 0.0)));
            vec3 vecBitangent = normalize(cross(vecTangent, p0));
            vec3 ptTangentSample = getPos(normalize(p0 + theta * normalize(vecTangent)));
            vec3 ptBitangentSample = getPos(normalize(p0 + theta * normalize(vecBitangent)));
            
            objectNormal = normalize(cross(ptBitangentSample - p0, ptTangentSample - p0));
            `
            )
            .replace(
                `#include <begin_vertex>`,
                `#include <begin_vertex>
                    transformed = p0;
                    rPos = transformed;
                `
            );
        //console.log(shader.vertexShader);
        shader.fragmentShader = `
            #define ss(a, b, c) smoothstep(a, b, c)
            uniform float bloom;
            uniform vec3 color1;
            uniform vec3 color2;
            varying vec3 rPos;
            ${shader.fragmentShader}
        `.replace(
            `vec4 diffuseColor = vec4( diffuse, opacity );`,
            `vec3 col = mix(color1, color2, ss(2., 6., length(rPos)));
            vec4 diffuseColor = vec4( col, opacity );
            `)
            .replace(
                `#include <dithering_fragment>`,
                `#include <dithering_fragment>

                float coord = length(rPos) * 4.;
                float line = abs(fract(coord - 0.5) - 0.5) / fwidth(coord) / 1.25;
                float grid = 1.0 - min(line, 1.0);

                gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0), bloom);
                gl_FragColor.rgb = mix(gl_FragColor.rgb, col * 2., grid);
            `
        );
    }
});
let o = new THREE.Mesh(g, m);
scene.add(o);

// BLOOM
const params = {
    exposure: 1,
    bloomStrength: 1,
    bloomThreshold: 0,
    bloomRadius: 0
};

const renderScene = new RenderPass(scene, camera);

const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;

const bloomComposer = new EffectComposer(renderer);
bloomComposer.renderToScreen = false;
bloomComposer.addPass(renderScene);
bloomComposer.addPass(bloomPass);

const finalPass = new ShaderPass(
    new THREE.ShaderMaterial({
        uniforms: {
            baseTexture: {
                value: null
            },
            bloomTexture: {
                value: bloomComposer.renderTarget2.texture
            }
        },
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        defines: {}
    }), 'baseTexture'
);
finalPass.needsSwap = true;

const finalComposer = new EffectComposer(renderer);
finalComposer.addPass(renderScene);
finalComposer.addPass(finalPass);

// 백그라운드 설정
let rt = new THREE.WebGLRenderTarget(innerWidth, innerHeight);
scene.background = rt.texture;
let bCam = new THREE.Camera();
let bScn = new THREE.Scene();
let bQuad = new THREE.Mesh(
    new THREE.PlaneGeometry(2, 2),
    new THREE.ShaderMaterial({
        uniforms: {
            time: globalUniforms.time,
            aspect: globalUniforms.aspect,
            baseColor: {
                value: new THREE.Color(0x160832)
            }
        },
        vertexShader: `
            varying vec2 vUv;
            void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
        }`,
        fragmentShader: `
            #define ss(a, b, c) smoothstep(a, b, c)
            uniform float time;
            uniform float aspect;
            uniform vec3 baseColor;
            varying vec2 vUv;
            ${document.getElementById( 'noiseFS2' ).textContent}
            void main() {
                vec2 uv = (vUv - 0.5) * vec2(aspect, 1.);
                float n = noise(vec3(normalize(uv) * 6., time * 5.));
                float backCircle = length(uv * (1. - n * 0.25)) ;
                vec3 blueish = vec3(0.5, 0.5, 1) * 0.125;
                vec3 col = mix(baseColor * 0.5 + blueish, baseColor * 0.5, ss(0.5 + n * 0.1, 0.75 - n * 0.05, backCircle));
                gl_FragColor = vec4( col, 1.0 );
            }`
    })
);
bScn.add(bQuad);

//애니메이션 
let clock = new THREE.Clock();

renderer.setAnimationLoop(() => {
    let t = clock.getElapsedTime();
    controls.update();
    globalUniforms.time.value = t * 0.1;
    renderer.setRenderTarget(rt);
    renderer.render(bScn, bCam);
    renderer.setRenderTarget(null);
    scene.background = null;
    globalUniforms.bloom.value = 1;
    bloomComposer.render();
    scene.background = rt.texture;
    globalUniforms.bloom.value = 0;
    finalComposer.render();
    renderer.render(scene, camera);
});

function createCubeMap() {
    let images = [];

    let c = document.createElement("canvas");
    c.width = 4;
    c.height = c.width;
    let ctx = c.getContext("2d");
    for (let i = 0; i < 6; i++) {
        ctx.fillStyle = "#fff";
        ctx.fillRect(0, 0, c.width, c.height);

        for (let j = 0; j < (c.width * c.height) / 2; j++) {
            ctx.fillStyle = Math.random() < 0.5 ? "#a8a9ad" : "#646464";
            ctx.fillRect(
                Math.floor(Math.random() * c.width),
                Math.floor(Math.random() * c.height),
                2,
                1
            );
        }
        images.push(c.toDataURL());
    }
    return new THREE.CubeTextureLoader().load(images);
}