ThreeJS中使用Alpha纹理实现软/渐变阴影投射的方法咨询
ThreeJS基于Alpha纹理实现渐变透明阴影方案
核心原理是修改深度材质的着色器,将Alpha纹理的灰度值写入深度图的Alpha通道,再修改阴影采样逻辑,用该灰度值动态调整阴影强度,实现半透明表面的渐变阴影效果。
第一步:调整自定义深度材质配置
你之前使用的alphaTest: 1是硬裁切参数,会直接裁掉所有半透明区域的深度写入,首先删除该参数,保留Alpha纹理配置:
var customDepthMaterial = new THREE.MeshDepthMaterial( { depthPacking: THREE.RGBADepthPacking, alphaMap: alphaTex, skinning: true })
第二步:修改深度材质着色器,写入Alpha值
给深度材质添加onBeforeCompile钩子,在深度写入逻辑后插入Alpha纹理采样,将灰度值存入输出颜色的Alpha通道:
customDepthMaterial.onBeforeCompile = (shader) => { shader.fragmentShader = shader.fragmentShader.replace( `#include <depth_frag>`, ` #include <depth_frag> // 采样Alpha纹理取灰度值作为透明度权重 float shadowAlpha = texture2D(alphaMap, vUv).r; // 将透明度写入深度图的Alpha通道 gl_FragColor.a = shadowAlpha; ` ) }
第三步:修改接收阴影材质的着色器,调整阴影强度
所有需要接收阴影的材质都需要添加以下着色器修改逻辑,让阴影计算时读取深度图的Alpha通道调整强度,可和你原有泛光逻辑合并:
receiveShadowMaterial.onBeforeCompile = (shader) => { // 注入Alpha通道读取逻辑 shader.fragmentShader = shader.fragmentShader.replace( `#include <shadowmap_pars_fragment>`, ` #include <shadowmap_pars_fragment> float getShadowAlpha(sampler2D shadowMap, vec2 uv) { return texture2D(shadowMap, uv).a; } ` ) // 修改阴影计算逻辑,用Alpha值调整阴影强度 .replace( `float shadow = getShadow( map, vec4( shadowCoord.xy, shadowCoord.z, shadowMapSize ), shadowBias );`, ` float shadow = getShadow( map, vec4( shadowCoord.xy, shadowCoord.z, shadowMapSize ), shadowBias ); float alphaWeight = getShadowAlpha(map, shadowCoord.xy); // Alpha值越高阴影越深,全透明区域阴影强度为0 shadow = mix(1.0, shadow, alphaWeight); ` ) // 你原有泛光逻辑保留即可,和阴影逻辑互不冲突 shader.uniforms.globalBloom = uniforms.globalBloom; shader.fragmentShader = ` uniform float globalBloom; ${shader.fragmentShader} `.replace( `#include <dithering_fragment>`, `#include <dithering_fragment> if (globalBloom > 0.5){ gl_FragColor = texture2D( emissiveMap, vUv ); } ` ); }
必要配置检查
- 渲染器开启软阴影可获得更自然的渐变效果:
renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap;
- 投射阴影的模型开启
castShadow = true,接收阴影的模型开启receiveShadow = true
内容的提问来源于stack exchange,提问作者Miger
相关产品推荐
相关产品推荐

