zoukankan      html  css  js  c++  java
  • 初识webgl--我的webgl学习第一课(基于threeJs)

    一,我为什么要学习webgl

    一个偶然的机会,在和朋友的聊天过程中,听说了webgl,也许过去也看到过,但是没有特别在意过。原来,JavaScript也可以很好的渲染并在网页上显示三维动画,不用借助插件,听起来是一个很棒的事情。大学的时候,计算机老师让我们课后学习3Dmax,种种原因,并没有听老师的话,但是,却一直希望能够接触一下三维世界。现在,我喜欢的JavaScript也可以实现三维动画效果,当然有点小惊喜,既然如此,何不借此机会,了解webgl的同时,巩固下自己的JavaScript基础呢?

    其二,有句话说的很好,活到老,学到老,更何况,还没有老,那还不赶快多学一学一些很有挑战性的东西,充实下自己的精神生活,不浪费大脑资源。

    二,threeJs基础知识总结

    1.组成三维场景的基本要素:场景,相机,渲染器。

    三维场景,立体空间,和我们生活的现实世界很相似。通过照片或者视频,我们只能看到物体片面的状态,也就是作者想要展示给你看的那个面。但是,现实生活中我们可以手动移动物体,得到一个全面的状态,这就是三维的优点之一吧,我们将拥有更多的控制权。不过,不同于现实生活的是,在threeJs里面,最初的世界是一片空,场景就相当于造物主创造一个新世界,先创造大环境,容纳所有生物,然后按照自己的喜好或者需求添加生物。新世界创造好了,接下来需要一个可以看懂新世界的眼睛,把新世界的点点滴滴传给一个能够理解这个眼睛所传来的图像的大脑,经过一系列处理,把这些图像信息还原为我们人类的眼睛能够看懂的内容,展示给我们。所以,场景可以理解为造物主,相机可以理解为能够看懂场景这个造物主的构成的眼睛,而渲染器呢,就是能够把眼睛看到的新世界展示给我们的那个特殊的大脑。

    总结一下,用threeJs官方的话来说呢就是: render the scene with camera.

    即:我们通过相机来把场景渲染到页面上。

    接下来,看一个具体的例子:

    <!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="utf-8" />
            <title>mytestOne</title>
            <style>
                #scene {width: 400px;height: 400px;margin: 10% auto;}
            </style>
            <script src="js/three.js"></script>
        </head>
    
        <body>
            <button onclick="render()">开始执行</button>
            <div id="scene"></div>
            <script>
                var scene=new THREE.Scene();//定义场景
                var camera=new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);//定义相机
                var renderer=new THREE.WebGLRenderer();
                renderer.setSize(400, 400);//设置渲染器的尺寸
                document.getElementById('scene').append(renderer.domElement);//把场景容器添加到页面,使场景能够被我们看到。
                var geometry=new THREE.CubeGeometry(1,1,1);//定义几何体,将来添加到场景中
                var material=new THREE.MeshBasicMaterial({
                    color: 0xBDC1F4
                });//定义材质,用来渲染几何体
                var cube=new THREE.Mesh(geometry,material);//用几何体和材质,渲染立方体。
                scene.add(cube);//把立方体添加到场景中
                camera.position.z=5;//相机距离的远近,影响了物体的大小
                //渲染函数,让立方体完成旋转的动画。
                function render(){
                    requestAnimationFrame(render);
                    cube.rotation.x+=0.1;
                    cube.rotation.y+=0.1;
                    renderer.render(scene,camera);
                };
            </script>
        </body>
    
    </html>

    单击开始运行时,触发渲染函数,整个立方体就会在场景中动起来。

    上面的写法是一个简单例子的写法,场景,相机还有渲染器都是最基础的,不复杂,所有我们按照顺序写,但是如果是大型场景,很复杂,这样写不利于阅读。也就是代码不友好,我们可以分模块来写,比如,专门的渲染器函数,场景函数,几何体函数等等,把功能按照模块封装起来,最后再统一调用,举个例子:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>mytestTwo</title>
            <script type="text/javascript" src="js/three.js" ></script>
            <style type="text/css">
                #scene-wrap {
                    border: none;
                    cursor: pointer;
                    width: 400px;
                    height: 400px;
                    background-color: #BDC1F4;
                }
            </style>
        </head>
        <body>
            <button onclick="start()">start</button>
            <div id="scene-wrap"></div>
        </body>
        <script>
            var width=document.getElementById('scene-wrap').clientWidth;
            var height=document.getElementById('scene-wrap').clientHeight;
            //定义渲染器,同时设置宽高并把它添加到页面节点中。
            var renderer;
            function initThree(){
                renderer=new THREE.WebGLRenderer({antialias:true});
                renderer.setSize(width,height);
                document.getElementById('scene-wrap').append(renderer.domElement);
                renderer.setClearColor(0x00FF00, 1.0);
            }
            //定义相机
            var camera;
            function initCamera(){
                camera=new THREE.PerspectiveCamera(45,width/height,1,1000);
                camera.position.x=0;
                camera.position.y=1000;
                camera.position.z=0;
                camera.up.x = 0;
                camera.up.y = 0;
                camera.up.z = 1;
                camera.lookAt({
                    x: 0,
                    y: 0,
                    z: 0
                });
            }
            //定义场景
            var scene;
            function initScene(){
                scene=new THREE.Scene();
            }
            //定义灯光
            var light;
            function initLight(){
                light=new THREE.DirectionalLight(0xFF0000, 1.0, 0);
                light.position.set(100,100,200);
                scene.add(light);//给场景添上灯光
            }
            //定义几何体
            var cube;
            function initObject(){
                var geometry=new THREE.Geometry();
                var material=new THREE.LineBasicMaterial({
                    vertexColors:THREE.VertexColors
                });
                var color1=new THREE.Color(0x00ff00);
                var color2=new THREE.Color(0x0000ff);
                var p1=new THREE.Vector3(-100,0,100);
                var p2=new THREE.Vector3(100,0,-100);
                geometry.vertices.push(p1);
                geometry.vertices.push(p2);
                geometry.colors.push(color1,color2);
                var line=new THREE.Line(geometry,material,THREE.LinePieces);
                scene.add(line);//在场景中添加物体
            }
            //定义渲染函数
            function render(){
                renderer.clear();
                renderer.render(scene,camera);//使用相机将渲染的场景展示在浏览器中
                requestAnimationFrame(render);
            }
            //触发函数
            function start(){
                initThree();
                initCamera();
                initScene();
                initLight();
                initObject();
                render();
            }
        </script>
    </html>

    这样,我们只关注于每个模块内部的东西,逻辑就会很清晰。

    好了,回归本小节主体,我们可以发现,如果想要用threeJs创建一个三维场景或者说创造一个新世界,那么我们离不开三个要素,场景,相机还有渲染器。换句话说就是造物主,眼睛还有大脑。O(∩_∩)O哈哈~

     OK,文章太长好像容易让人生烦,欲知后事如何,且听下回分解。

  • 相关阅读:
    getComputedStyle方法获取元素CSS值
    js获得当前元素的样式
    移动端 Retina屏border实现0.5px
    CFA
    LCD驱动
    EPD的驱动
    camera原理
    Perl实战(一)
    Perl的debug小技巧
    Bus memory attribute
  • 原文地址:https://www.cnblogs.com/benxiaohai-microcosm/p/8656466.html
Copyright © 2011-2022 走看看