带Displacement Texture的归一化立方体网格法线不连续问题求助
归一化立方体法线不连续问题求助
我在项目中用六个平面网格创建了一个归一化立方体,为提升视觉效果添加了Displacement Texture并计算纹理法线以保证正确光照,但出现了边缘法线不连续的问题,底层立方体结构暴露出来,无法实现类球体的平滑外观。
以下是我的Shader代码:
顶点着色器
varying vec2 vUv; uniform sampler2D u_tex; uniform vec3 wTl; uniform vec3 ps; // 归一化每个平面 vec3 planeToSphere(vec3 p, vec3 localCenter){ return 100.0*normalize(p-localCenter) + localCenter; } varying vec3 v3n; void main() { vUv = uv; vec3 newPosition = planeToSphere(position,wTl); vec3 worldp = (modelMatrix * vec4(newPosition,1.0)).xyz; float n = texture2D(u_tex, vUv).x; // newPosition = newPosition + 1.0*n*normalize(position-wTl); // 启用该注释添加位移 gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0); }
片元着色器
varying vec2 vUv; uniform sampler2D u_tex; varying vec3 v3n; vec4 displacementMapToNormalMap(sampler2D displacementMap, vec2 vUv){ float scale = 0.9; // 控制位移量 float epsilon = 0.01; // 计算梯度的小值 float strength = 1.; float center = texture2D(displacementMap, vUv).r; // 采样位移贴图 float dx = texture2D(displacementMap, vUv + vec2(epsilon, 0.0)).r - center; // 计算X方向梯度 float dy = texture2D(displacementMap, vUv + vec2(0.0, epsilon)).r - center; // 计算Y方向梯度 vec3 normalMap = normalize(vec3(dx * scale, dy * scale, 1.0)); // 计算法向量 normalMap *= strength; // 应用强度 return vec4(normalMap * 0.5 + 0.5, 1.0); // 将法线输出为颜色 } void main() { vec3 lightDirection = normalize(vec3(0.,1.,1.)); vec4 normalMapColor = displacementMapToNormalMap(u_tex, vUv); // 获取法线贴图颜色 float grayscale = dot(normalMapColor.rgb, vec3(0.299, 0.587, 0.114)); // 转换为灰度 vec4 grayColor = vec4(grayscale, grayscale, grayscale, 1.0); float lightIntensity = dot(normalMapColor.rgb, lightDirection); // 计算光照贡献 vec4 finalColor = grayColor * lightIntensity; // 将光照应用到灰度颜色 gl_FragColor = finalColor; // 输出最终颜色 }
我已经为此问题钻研数周但未取得实质性进展。研究时看到相关问题中,有回复建议不使用Three.js提供的切线框架,而是用顶点数据生成切线以对齐接缝,但我对该技术不熟悉,希望得到解释。
2023年7月16日更新
使用dFd函数获取相邻像素值替代epsilon(因像素以2x2批次渲染),这是目前最优方案但仍不完善:
vec4 displacementMapToNormalMap(sampler2D displacementMap, vec2 vUv){ float scale = 0.9; // 控制位移量 float strength = 1.; float center = texture2D(displacementMap, vUv).r; // 采样位移贴图 float dx = texture2D(displacementMap, vUv + dFdx(vUv)).r - center; // 计算X方向梯度 float dy = texture2D(displacementMap, vUv + dFdy(vUv)).r - center; // 计算Y方向梯度 vec3 normalMap = normalize(vec3(dx * scale, dy * scale, 1.0)); // 计算法向量 normalMap *= strength; // 应用强度 return vec4(normalMap * 0.5 + 0.5, 1.0); // 将法线输出为颜色 }
希望能得到解决法线不连续问题、实现带Displacement Texture的归一化立方体平滑外观的指导或建议,感谢帮助。
内容的提问来源于stack exchange,提问作者Memory1
相关产品推荐
相关产品推荐

