zoukankan      html  css  js  c++  java
  • Three.js的绘制流程(三)地形

    最简单的地形是单一的平面, 这个通过

    var geo = new THREE.PlaneGeometry(2, 2, 256, 256) 几何体构建, 可以设定平面的切分块的数量。

    var pmesh = new THREE.Mesh(geo, material);

    可以为平面提供纹理, 从而是地面看起来更真实一些,而纹理坐标在geo中已经自动设定好了。 因此只需要写材质就可以了。

    这里使用ShaderMaterial 用于材质。

    顶点shader:

    varying vec2 vUV; //从定点shader 传递到 片段shader的纹理坐标

    void main()

    {

          vUV = uv; //uv 是默认存在的顶点属性, 用于做纹理坐标

          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);// projectionMatrix 默认存在的投影矩阵 modelViewMatrix默认模型视图矩阵 position定点坐标 
    }

     

    片段shader:

    uniform sampler2D texture_grass;//纹理

    varying vec2 vUV;

    void main()

    {

         gl_FragColor = texture2D(texture_grass, vUV);
    }

    材质则是:

    var mat = new THREE.ShaderMaterial({

         uniforms:{

              texture_grass:{type:'t', value:0,  texture:TRHEE.ImageUtils.loadTexture("texture_grass.png")},//类型纹理, 纹理编号0, 加载图片数据 

        },

         attributes:{},

         vertexShader:text,

         fragmentShader:text,

    });

    var pmesh = new THREE.Mesh(geo, mat);

     

    这样就得到一个添加了纹理的平面, 平面在x,y 平面上, 平面的正方向指向z正向, 可以调整平面x轴逆时针旋转90度, 得到x,z 方向的平面。

     

    现在我们期望能够调整地面的高度, 采用的方式是鼠标点击屏幕位置, 计算实际的地面的位置, 接着调整地面上该点附近的所有定点的高度。

    调整高度有两种方式, 一是调整geo几何体中的vertices 中的y值, 或者在修改shader程序 增加一个顶点属性, displacement 用于记录所有顶点的高度,这样只需要修改这一个数据就可以了,而不需要修改整个定点数组。

    顶点shader调整:

    attribute float displacement;

    varying vec2 vUV;

    void main()

    {

           vUV = uv;

           gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy,  displacement, 1);
    }

    材质调整:

    var mat = new THREE.ShaderMaterial({

          //其它部分相同

           attributes:{

         displacement:{type:'f',  value:[]},

       }

    });

    需要根据平面顶点个数 来初始化displacement值为0

    for(var i = 0; i < geo.vertices.length; i++)

          mat.attributes.displacement.value.push(0);

     

    因为需要动态调整displacement的值 所以需要设定geo是动态更新的

    geo.dynamic = true;

     

    这样现在仍只是看到一个平面;接下来需要设定鼠标点击的时间处理函数。

    var projector = new THREE.Projector(); //计算从屏幕坐标到 世界坐标的工具

     

    renderer.domElement.onmousedown = function(e){

         var mx = e.offsetX;

         var my = e.offsetY;

         //计算相机近平面上的坐标

          mx = 2*mx/SCREEN_WIDTH-1;

         my = 1 - 2*my/SCREEN_HEIGHT;

        var vec = new THREE.Vector3(mx, my, 0);//只有 x y 坐标有意义

         var ray = project.pickingRay(vec, camera);//计算从相机发出的穿过近平面上mx my 点的射线

        var intersects = ray.intersectObject(pmesh); //计算射线和 平面的所有交点 0 或者 1个

         if(intersects.length > 0)

        {

                //存在交点

               updateDisplacement(intersects[0].point); //调整该点附近顶点的高度。

        }

    }

     

    function updateDisplacement(point)

    {

    //平面方位 -1, 1  -1, 1 x轴切分256份, WIDTH= 257,  y轴切分256份 , HEIGHT=257

    //计算交点附近 0.1为边长的矩形框的上下左右范围, 接着计算geo中相应的定点的行和列范围。

    //调整所有顶点的高度, 设定材质中的 mat.attributes.displacement.needsUpdate = true;  设定displacement需要更新

     

        var radius = 0.05;     var left = point.x-radius;    var right = point.x+radius;    var bottom = point.z-radius;    var up = point.z + radius;    var rowGrid = 2/(HEIGHT-1);    var colGrid = 2/(WIDTH-1);        var rowBegin = ~~Math.max((bottom+1)/rowGrid, 0);    var rowEnd = ~~Math.min((up+1)/rowGrid, HEIGHT);    var colBegin = ~~Math.max((left+1)/colGrid, 0);    var colEnd = ~~Math.min((right+1)/colGrid, WIDTH);
        for(var i = rowBegin; i <= rowEnd; i++)    {        for(var j = colBegin; j <= colEnd; j++)        {            var num = ~~(i*WIDTH+j);            //console.log(num);            pmesh.displacement.value[num] += 0.05;            //console.log("new", pmesh.displacement, pmesh.displacement.needsUpdate);        }    }    pmesh.displacement.needsUpdate = true;


    }

     

    结束:

       通过设定几何体可以动态更新,  设定 材质中的属性需要更新, 则实现了调整displacement的目的。

  • 相关阅读:
    关于BehaviorEditorPart 不显示的问题(出自msdn)
    webpart msdn 的位置
    Visual Studio 2008 具有一些新的报表功能和改进之处
    .NET Framework 类库
    Reporting Service 安装 及相关问题如:授予的权限不足解决办法
    单服务器部署&&双服务器部署
    Windows Server 2003安装完毕后汉字都为乱码“方框”,配置域控制器
    Dreamweaver MX显示汉字为乱码的解决方法
    名称以无效字符开头。处理资源 'http://localhost/发布了的/Default.aspx' 时出错。第 1 行,位置: 2
    【随感】my feeling about Long Ying
  • 原文地址:https://www.cnblogs.com/liyonghelpme/p/4273792.html
Copyright © 2011-2022 走看看