如何让THREE.js中陡峭平面的凸起部分比低洼部分更暗?
问题分析与解决方案
你的核心问题在于片元着色器的颜色计算逻辑完全偏离了“基于高度控制明暗”的目标——原代码用屏幕坐标gl_FragCoord除以顶点传递的test向量,这种计算没有任何物理意义,导致颜色出现异常的强对比度。
下面提供两种简单可行的调整方案,都能实现“低洼更暗、凸起更亮”的自然效果,且对比度可控:
方案一:直接基于高度值映射颜色
这种方法最直观,直接用顶点的z高度值来控制颜色亮度,通过调整映射范围就能控制对比度。
修改后的顶点着色器
varying float vHeight; // 只传递高度值到片元着色器 void main(void) { float amp = 2.5; float z = amp * sin(position.x*0.2) * cos(position.y*0.5); vHeight = z; // 传递高度值 gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, z, 1.0); }
修改后的片元着色器
precision mediump float; varying float vHeight; void main(void) { // 先把高度值归一化到[0,1]范围:z的最小值是-2.5,最大值是2.5 float normalizedHeight = (vHeight + 2.5) / 5.0; // 调整对比度:用pow函数,指数>1会降低暗部亮度,指数<1会提亮暗部 float brightness = pow(normalizedHeight, 1.2); // 指数可根据需求调整,比如1.0是线性映射 // 生成灰度颜色,也可以改成彩色,比如vec3(brightness, 0.5, 1.0 - brightness) gl_FragColor = vec4(vec3(brightness), 1.0); }
调整技巧:
- 如果觉得暗部太亮,增大
pow的指数(比如1.5、2.0) - 如果觉得亮部太暗,减小指数(比如0.8、0.9)
- 也可以用
smoothstep(0.0, 1.0, normalizedHeight)来替代pow,实现更柔和的过渡
方案二:用漫反射光照实现自然明暗
这种方法更接近真实光照效果,通过计算平面的法向量,模拟光源照射产生的明暗,对比度和过渡更自然。
修改后的顶点着色器
varying vec3 vNormal; // 传递法向量到片元着色器 varying vec3 vPosition; // 传递世界空间位置 void main(void) { float amp = 2.5; float z = amp * sin(position.x*0.2) * cos(position.y*0.5); vec3 pos = vec3(position.x, position.y, z); // 计算法向量(基于高度场的数值微分) float delta = 0.1; // 采样步长 float z1 = amp * sin((position.x + delta)*0.2) * cos(position.y*0.5); float z2 = amp * sin(position.x*0.2) * cos((position.y + delta)*0.5); vec3 tangent = vec3(delta, 0.0, z1 - z); vec3 bitangent = vec3(0.0, delta, z2 - z); vNormal = normalize(cross(tangent, bitangent)); vPosition = pos; gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); }
修改后的片元着色器
precision mediump float; varying vec3 vNormal; varying vec3 vPosition; void main(void) { // 定义光源方向(世界空间) vec3 lightDir = normalize(vec3(1.0, 1.0, 2.0)); // 计算漫反射强度 float diff = max(dot(vNormal, lightDir), 0.0); // 基础颜色 + 漫反射亮度,可调整基础色和强度 vec3 color = vec3(0.6, 0.8, 1.0) * (0.3 + diff * 0.7); // 0.3是环境光强度,0.7是漫反射权重 gl_FragColor = vec4(color, 1.0); }
调整技巧:
- 调整
lightDir可以改变光源方向,影响明暗分布 - 修改
0.3(环境光)和0.7(漫反射权重)可以控制整体对比度:环境光越大,暗部越亮,对比度越低;反之则对比度越高 - 替换
vec3(0.6, 0.8, 1.0)可以改变平面的基础颜色
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

