文档章节

Three.js的绘制流程(三)----地形

李勇2
 李勇2
发布于 2015/03/02 09:38
字数 914
阅读 31
收藏 0
点赞 0
评论 0

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

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的目的。


© 著作权归作者所有

共有 人打赏支持
李勇2

李勇2

粉丝 45
博文 188
码字总数 62209
作品 0
广州
程序员
three.js (四)离散层次细节level of details

LOD 处理比较大的外部地面场景中比较有用, 一般用于绘制地形。 首先通过可视体的切割删除不用的地形块,接着通过LOD 对照相机不同距离的地形块进行层次细节调整。 这里采用最简单的LOD 方法...

李勇2 ⋅ 2012/09/18 ⋅ 0

Three.js的绘制流程(三)----地形

最简单的地形是单一的平面, 这个通过 var geo = new THREE.PlaneGeometry(2, 2, 256, 256) 几何体构建, 可以设定平面的切分块的数量。 var pmesh = new THREE.Mesh(geo, material); 可以为...

李勇2 ⋅ 2012/09/18 ⋅ 0

WebVR开发教程——标准入门

WebVR即web + VR的体验方式,我们可以戴着头显享受沉浸式的网页,新的API标准让我们可以使用js语言来开发。本文将介绍如何快速开发一个WebVR网页,在此之前,我们有必要了解WebVR的体验方式。...

YoneChen ⋅ 01/09 ⋅ 0

Unity3D 游戏引擎之构建3D游戏世界的基本地形(四)

Unity3D 游戏引擎之构建3D游戏的基本地形 雨松MOMO原创文章如转载,请注明:转载自雨松MOMO的博客原文地址:http://blog.csdn.net/xys289187120/article/details/6887687 创建一个3D地形 在上...

彭博 ⋅ 2012/03/09 ⋅ 0

SegmentFault 技术周刊 Vol.35 - WebGL:打开网页看大片

WebGL 可以说是 HTML5 技术生态链中最为令人振奋的标准之一,它把 Web 带入了 3D 的时代。 初识 WebGL 先通过几个使用 WebGL 的网站来认识下 WebGL 的魅力吧~ 温馨提示:浏览以下网页需要浏览...

keke ⋅ 2017/10/19 ⋅ 0

[译文] 如何高效渲染庞大的地形 - Rendering large terrains

翻译:RyuZhihao123 时间:2017/5/16(大三下学期) 原文链接:Render large terrains - pheelicks Rendering large terrains Today we’ll look at how to efficiently render a large terr......

Mahabharata_ ⋅ 2017/05/17 ⋅ 0

微信小游戏three.js开发

如何用three.js开发微信小游戏 首先我们先用微信开发者工具创建一个模块,然后先将里面不需要的内容删除,将three.js放到我们的项目中,并且在main.js都将其引入: 这里我用一个3D游戏中比较...

yidboy ⋅ 04/13 ⋅ 0

腾讯Web前端大会 WebGL&Three.js(MR_LP)

1.前言 本次大会下午场我主要在分会场1 : Web 前沿技术 听各位大牛的分享。 本文主要是来跟大家分享一下听到的关于前端实现 Web AR/VR 的一些信息。 声明: 本文是由 李鹏(MR_LP)全程手打...

mr_lp ⋅ 2017/06/26 ⋅ 0

three.js简介 —— 3D框架

threejs 随着HTML5的普及,网页的表现能力越来越强大,浏览器提供了WebGL接口,可以通过调用对应API进行3D图形的绘制,Three.js在这些基础接口之上又做了一层封装。 原文链接 特点 Three.js...

bestvist ⋅ 2017/12/26 ⋅ 0

Unity3D 游戏引擎之构建游戏地形的基本元素(五)

Unity3D 游戏引擎之构建3D游戏的基本元素 雨松MOMO原创文章如转载,请注明:转载自雨松MOMO的博客原文地址:http://blog.csdn.net/xys289187120/article/details/6891156 我们继续创建一个完美...

彭博 ⋅ 2012/03/09 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

SpringCloud 微服务 (六) 服务通信 RestTemplate

壹 通信的方式主要有两种,Http 和 RPC SpringCloud使用的是Http方式通信, Dubbo的通信方式是RPC 记录学习SpringCloud的restful方式: RestTemplate (本篇)、Feign 贰 RestTemplate 类似 Http...

___大侠 ⋅ 1分钟前 ⋅ 0

React创建组件的三种方式

1.无状态函数式组建 无状态函数式组件,也就是你无法使用State,也无法使用组件的生命周期方法,这就决定了函数组件都是展示性组件,接收Props,渲染DOM,而不关注其他逻辑。 无状态函数式组...

kimyeongnam ⋅ 8分钟前 ⋅ 0

react 判断实例类型

今天在写组件的时候想通过判断内部子元素不同而在父元素上应用不同的class,于是首先要解决的就是如何判断子元素的类型。 这里附上一个讲的很全面的文章: https://www.cnblogs.com/onepixel...

球球 ⋅ 15分钟前 ⋅ 0

Centos7备份数据到百度网盘

一、关于 有时候我们需要进行数据备份,如果能自动将数据备份到百度网盘,那将会非常方便。百度网盘有较大的存储空间,而且不怕数据丢失,安全可靠。下面简单的总结一下如何使用 bypy 实现百...

zctzl ⋅ 28分钟前 ⋅ 0

开启远程SSH

SSH默认没有开启账号密码登陆,需要再配置表中修改: vim /etc/ssh/sshd_configPermitRootLogin yes #是否可以使用root账户登陆PasswordAuthentication yes #是都开启密码登陆ser...

Kefy ⋅ 31分钟前 ⋅ 0

Zookeeper3.4.11+Hadoop2.7.6+Hbase2.0.0搭建分布式集群

有段时间没更新博客了,趁着最近有点时间,来完成之前关于集群部署方面的知识。今天主要讲一讲Zookeeper+Hadoop+Hbase分布式集群的搭建,在我前几篇的集群搭建的博客中已经分别讲过了Zookeep...

海岸线的曙光 ⋅ 39分钟前 ⋅ 0

js保留两位小数方法总结

本文是小编针对js保留两位小数这个大家经常遇到的经典问题整理了在各种情况下的函数写法以及遇到问题的分析,以下是全部内容: 一、我们首先从经典的“四舍五入”算法讲起 1、四舍五入的情况...

孟飞阳 ⋅ 57分钟前 ⋅ 0

python log

python log 处理方式 log_demo.py: 日志代码。 #! /usr/bin/env python# -*- coding: utf-8 -*-# __author__ = "Q1mi""""logging配置"""import osimport logging.config# 定义三种......

inidcard ⋅ 今天 ⋅ 0

mysql 中的信息数据库以及 shell 查询 sql

Information_schema 是 MySQL 自带的信息数据库,里面的“表”保存着服务器当前的实时信息。它提供了访问数据库元数据的方式。 什么是元数据呢?元数据是关于数据的数据,如数据库名或表名,...

blackfoxya ⋅ 今天 ⋅ 0

maven配置阿里云镜像享受飞的感觉

1.在maven目录下的conf/setting.xml中找到mirrors添加如下内容,对所有使用改maven打包的项目生效。 <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.al......

kalnkaya ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部