본문 바로가기
카테고리 없음

바빌론JS - 그라운드 배경

지난 게시글에서는 HDRI를 큐브맵으로 전환, 가상공간 배경으로 활용해보았는데요.

https://itadventure.tistory.com/712

 

바빌론JS - 배경 만들기 / HDRI => CUBEMAP

HDRI 텍스쳐는 가상공간에서 360도 전 방향의 배경을 표현하는 텍스쳐인데요.3차원 공간 배경으로 자주 활용됩니다.바빌론 JS에서 바로 hdri 배경을 사용하는 방법이 있긴 하나 워낙 속도가 느리더

itadventure.tistory.com

좀 아쉬운 부분이 있습니다.
이를테면 자동차같은 물체를 바닥에 배치해보고 싶지만 땅바닥 방향으로도 거리가 무한대이기 때문에
물체가 허공에 붕 뜨게 됩니다. 카메라를 돌려보면 확인할 수가 있지요.

어디선가 멋진 자동차와 어울어진 배경공간을 본 적이 있는데 바빌론JS에도 그 기술이 없을까 찾아보니,
있더라구요 ! 오늘은 그 부분을 공유드리겠습니다.


광활한 배경이어야 해

우선 그라운드(Ground) 배경을 사용하려면 건물이 근처에 없어야 합니다.
도드라진 지형물들이 너무 가까우면 이상하게 비쳐보이는 문제가 있거든요.

바닥의 중심부 근처는 텅텅 비어 있는게 좋습니다.
그래서 HDRI 해븐 사이트의 다른 배경을 적용해보았습니다.

※ 배경을 큐브맵 변환하는건 지난 게시글을 참조해 주세요.

카메라를 돌려도 바닥에 딱 붙어있는걸 볼 수 있지요.

위와 같은 배경을 다운받았다면 이제 소스를 구성래보죠.


소스코드

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>Babylon.js sample code</title>

        <!-- Babylon.js -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
        <script src="https://assets.babylonjs.com/generated/Assets.js"></script>
        <script src="../snapshot/recast.js"></script>
        <script src="../snapshot/ammo.js"></script>
        <script src="../snapshot/havok/HavokPhysics_umd.js"></script>
        <script src="../snapshot/cannon.js"></script>
        <script src="../snapshot/Oimo.js"></script>
        <script src="../snapshot/earcut.min.js"></script>
        <script src="../snapshot/babylon.js"></script>
        <script src="../snapshot/materialsLibrary/babylonjs.materials.min.js"></script>
        <script src="../snapshot/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
        <script src="../snapshot/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
        <script src="../snapshot/loaders/babylonjs.loaders.js"></script>
        <script src="../snapshot/serializers/babylonjs.serializers.min.js"></script>
        <script src="../snapshot/gui/babylon.gui.min.js"></script>
        <script src="../snapshot/inspector/babylon.inspector.bundle.js"></script>

        <style>
            html, body {
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }

            #renderCanvas {
                width: 100%;
                height: 100%;
                touch-action: none;
            }
            
            #canvasZone {
                width: 100%;
                height: 100%;
            }
        </style>
    </head>
<body>
    <div id="canvasZone"><canvas id="renderCanvas"></canvas></div>
    <script>
        var canvas = document.getElementById("renderCanvas");

        var startRenderLoop = function (engine, canvas) {
            engine.runRenderLoop(function () {
                if (sceneToRender && sceneToRender.activeCamera) {
                    sceneToRender.render();
                }
            });
        }

        var engine = null;
        var scene = null;
        var sceneToRender = null;
        var createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true,  disableWebGL2Support: false}); };

</script>
        <script src="./main.js"></script>
<script>
                window.initFunction = async function() {
                    
                    
                    
                    var asyncEngineCreation = async function() {
                        try {
                        return createDefaultEngine();
                        } catch(e) {
                        console.log("the available createEngine function failed. Creating the default engine instead");
                        return createDefaultEngine();
                        }
                    }

                    window.engine = await asyncEngineCreation();
        if (!engine) throw 'engine should not be null.';
        startRenderLoop(engine, canvas);
        window.scene = createScene();};
        initFunction().then(() => {scene.then(returnedScene => { sceneToRender = returnedScene; });
                            
        });

        // Resize
        window.addEventListener("resize", function () {
            engine.resize();
        });
    </script>
</body>
</html>

main.js

var createScene = async function () {
    // Create a scene
    var scene = new BABYLON.Scene(engine);

    scene.environmentTexture = new BABYLON.CubeTexture("skybox", scene);

    // Our built-in 'sphere' shape.
    var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 1, segments: 32 }, scene);

    // Move the sphere upward 1/2 its height
    sphere.position.y = 0.5;

    let camera = scene.createDefaultCamera(1,1,1);
    //camera.lowerRadiusLimit = 0.5;
    //camera.upperRadiusLimit = 2;

    var pbr = new BABYLON.PBRMaterial("pbr", scene);
    sphere.material = pbr;

    pbr.albedoColor = new BABYLON.Color3(0.9, 0.9, 0.9);
    pbr.metallic = 1.0; // set to 1 to only use it from the metallicRoughnessTexture
    pbr.roughness = 0.0; // set to 1 to only use it from the metallicRoughnessTexture

    // Create a skydome
    const skydome = BABYLON.MeshBuilder.CreateBox("sky", { size: 1000, sideOrientation: BABYLON.Mesh.BACKSIDE }, scene);
    skydome.position.y = 500;
    skydome.isPickable = false;
    skydome.receiveShadows = true;

    // Sets the skydome in ground projection mode
    const sky = new BABYLON.BackgroundMaterial("skyMaterial", scene);
    sky.reflectionTexture = scene.environmentTexture.clone();
    sky.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
    sky.enableGroundProjection = true;
    sky.projectedGroundRadius = 20;
    sky.projectedGroundHeight = 3;
    skydome.material = sky;
    
    // Setup a Light to cast shadows
    const light = new BABYLON.DirectionalLight("light0", new BABYLON.Vector3(-8, -14, -10), scene);
    light.intensity = 0.7;
    light.shadowMinZ = 15;
    light.shadowMaxZ = 30;
    light.diffuse = new BABYLON.Color3(1, 0.9, 0.6);

    // And the shadow generator
    const shadowGenerator = new BABYLON.ShadowGenerator(512, light);
    shadowGenerator.usePercentageCloserFiltering = true;
    shadowGenerator.darkness = 0.2;

    // And register it to the shadow generator
    shadowGenerator.addShadowCaster(sphere);

    return scene;
}

실습이 어려우신 분은 크레이가 준비한 웹사이트를 참조해 주세요.

http://dreamplan7.cafe24.com/babylon/ex25/


마무~리

그라운드 배경편 유용하게 봏셨나 모르겠습니다:)
오늘도 방문해주신 모든 분들께 감사드립니다.


다음 게시글 : https://itadventure.tistory.com/714

 

바빌론js - 360 영상 배경

지난 그라운드 배경에 이어서,https://itadventure.tistory.com/713 바빌론JS - 그라운드 배경지난 게시글에서는 HDRI를 큐브맵으로 전환, 가상공간 배경으로 활용해보았는데요.https://itadventure.tistory.com/712 C

itadventure.tistory.com