You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Three.js中基于顶点绘制抗锯齿圆形点的实现问题

Three.js无纹理实现平滑圆形点方案

问题根源

你当前的实现用硬距离判断做圆形边缘,且未将gl_PointSize传递到片元着色器,无法根据点的屏幕像素尺寸做适配性抗锯齿,导致点缩放时要么边缘模糊、要么直接消失。

解决思路

  1. 将顶点着色器中的gl_PointSize传递到片元着色器,获取点的屏幕像素尺寸
  2. 基于像素尺寸计算抗锯齿过渡范围,用smoothstep替代硬条件判断,实现跨尺寸的平滑边缘
  3. 直接利用视图/裁剪空间的深度值实现距离衰减

修改后的着色器代码

顶点着色器

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:07:20