在Three.js中基于顶点绘制抗锯齿圆形点的实现问题
Three.js无纹理实现平滑圆形点方案
问题根源
你当前的实现用硬距离判断做圆形边缘,且未将gl_PointSize传递到片元着色器,无法根据点的屏幕像素尺寸做适配性抗锯齿,导致点缩放时要么边缘模糊、要么直接消失。
解决思路
- 将顶点着色器中的
gl_PointSize传递到片元着色器,获取点的屏幕像素尺寸 - 基于像素尺寸计算抗锯齿过渡范围,用
smoothstep替代硬条件判断,实现跨尺寸的平滑边缘 - 直接利用视图/裁剪空间的深度值实现距离衰减
修改后的着色器代码
顶点着色器
uniform float particleSize; varying float vPointSize; void main() { vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); gl_Position = projectionMatrix * mvPosition; // 计算点的屏幕尺寸,保留原始的距离衰减逻辑 gl_PointSize = particleSize / gl_Position.z; // 将点尺寸传递到片元着色器 vPointSize = gl_PointSize; }
片元着色器
varying float vPointSize; uniform vec3 pointColor; void main() { // 计算片元到点中心的相对距离 vec2 coord = gl_PointCoord - vec2(0.5); float dist = length(coord); // 计算单个像素在点坐标空间中的占比,以此作为抗锯齿过渡范围 float pixelScale = 1.0 / vPointSize; // smoothstep实现平滑的边缘过渡:从0.5-pixelScale到0.5,透明度从1降到0 float edgeSmooth = smoothstep(0.5 - pixelScale, 0.5, dist); // 实现距离衰减:基于裁剪空间z值调整透明度,公式可按需修改 float distanceAttenuation = 1.0 / (1.0 + gl_Position.z * gl_Position.z * 0.001); // 最终颜色 = 基础颜色 * (1-边缘过渡值) * 距离衰减系数 gl_FragColor = vec4(pointColor, (1.0 - edgeSmooth) * distanceAttenuation); }
Three.js材质配置示例
const shaderMaterial = new THREE.ShaderMaterial({ uniforms: { particleSize: { value: 20.0 }, pointColor: { value: new THREE.Color(0x333333) } }, vertexShader: // 上述顶点着色器代码字符串, fragmentShader: // 上述片元着色器代码字符串, transparent: true, blending: THREE.NormalBlending, depthWrite: false // 可选:如果点重叠较多,关闭深度写入优化显示 });
关键说明
- 抗锯齿逻辑基于点的实际屏幕像素尺寸,不管点放大或缩小,边缘过渡始终保持1个像素宽度,避免模糊或消失问题
smoothstep函数替代硬条件判断,消除阶梯状边缘,实现自然的透明过渡- 距离衰减公式可根据需求调整:比如用视图空间的
mvPosition.z(顶点着色器中可传递vViewZ = -mvPosition.z到片元),衰减效果会更直观
内容的提问来源于stack exchange,提问作者w41g87
相关产品推荐
相关产品推荐

