Three+Shader 生成3D地球高度地图

27 篇文章 15 订阅

通过three.js + shader 生成高度地图

使用自定义着色器读取到当前位置信息的颜色值来生成当前高度。
在这里插入图片描述

准备

两张图,一张展示材质,一张生成高度的材质
高度是黑白构成的一张图,通过图片的灰度来生成高度。
在这里插入图片描述

开始

生成地球

生成地球模型

// threejs
const options = {
   radius: 100, // 地球的半径
   segments: 640, // 地球的分段数 数量越高 地球精度越高
   map: './images/earth.jpg', // 地球材质
   bump: './images/earthbump.jpg' // 生成高度材质
};
// 生成球类几何
const geometry = new THREE.SphereBufferGeometry(options.radius, options.segments, options.segments);
// 使用自定义着色器
const material = new THREE.ShaderMaterial({
    uniforms: {
        u_radius: {
            value: options.radius // 半径
        },
        u_height: {
            value: 5 // 生成的高度
        },
        u_map: {
            value: new THREE.TextureLoader().load(options.map) // 贴图
        },
        u_bump: {
            value: new THREE.TextureLoader().load(options.bump) // 高度图
        },
        u_color: {
            value: new THREE.Color('rgb(255, 255, 255)')
        },
        u_opacity: {
            value: 1.0
        }
    },
    transparent: true,
    vertexShader: earthShader.vertexShader, // 顶点着色器
    fragmentShader: earthShader.fragmentShader, // 片元着色器
});
const plane = new THREE.Mesh(geometry, material);


顶点与片元

const earthShader = {
    vertexShader: `
	varying vec4 v_color; // 用来存储当前顶点颜色
	varying vec2 v_uv; // UV
	uniform float u_height; // 生成的高度
	uniform float u_radius; // 半径
    uniform sampler2D u_bump; // 高度图
    // 插值计算
	float lerp(float x, float y, float t) {
		return (1.0 - t) * x + t * y;
    }
    // 获得当前向量与中心点的距离
	float glength(vec3 p) {
		return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
    }
    // 传入当前向量 需要返回的长度
	vec3 setLength(vec3 p, float length) {
		vec3 c_position = p;
		float scale = length / glength(c_position);
		c_position.x *= scale;
		c_position.y *= scale;
		c_position.z *= scale;
		return c_position;
	}
	void main() {
		v_uv = uv; // uv
        v_color = texture2D(u_bump, uv); // 生成当前高度信息
        float c_height = v_color.r * u_height; // 生成当前的高度 当前的灰度r值 * 基础高度
        vec3 vposition = setLength(position, u_radius + c_height); // 生成新的向量 离中心距离为当前基础半径+生成的高度
        // 传递position
		vec4 mPosition = modelViewMatrix * vec4(vposition, 1.0); 
		gl_Position = projectionMatrix * mPosition;
	}
`,
    fragmentShader: `
	uniform float u_opacity; // 透明度
	uniform vec3 u_color; // 基础颜色
	varying vec2 v_uv; // UV
	uniform sampler2D u_map; // 基础材质
	void main() {
		gl_FragColor = vec4(u_color, u_opacity) * texture2D(u_map, v_uv);
	}
`
}
生成

在这里插入图片描述

打个广告:可以进QQ群(1082834010)讨论

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸡饶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值