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

实现Photoshop风格点画效果的GLSL算法咨询

实现Photoshop风格点画效果的GLSL方案

我尝试用以下GLSL代码实现点画效果,但输出不符合预期,想要达到Photoshop中的点画效果,求对应的实现算法和GLSL代码。

我的代码:

float rand(vec2 co) {
    return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // 归一化像素坐标(0到1)
    vec2 uv = fragCoord/iResolution.xy;
    
    float iDotSize = 0.01;       // 归一化点大小(0到1)
    float iMaxDotDistance = iDotSize * 2.0;

    // 计算带随机偏移的点位置
    float dotOffset = (rand(uv) * 2.0 - 1.0) * iMaxDotDistance;
    vec2 dotPosition = uv + dotOffset;

    // 根据期望半径计算点大小
    float dotSize = iDotSize * iResolution.x;

    // 在点位置采样输入图像颜色
    vec3 dotColor = texture(iChannel0, dotPosition).rgb;

    // 绘制点
    if (distance(uv, dotPosition) < dotSize) {
        fragColor = vec4(dotColor, 1.0);
    } else {
        // 绘制背景
        fragColor = vec4(0.0);
    }
}

效果对比:

  • 预期效果(Photoshop点画):规则排列的网点,暗部区域网点大,亮部区域网点小,整体呈现均匀的半色调质感
  • 当前输出效果:随机分布的点,大小固定,无明暗对应关系,不符合预期

正确算法:Photoshop点画本质是半色调(Halftone)网点效果,核心逻辑是:

  • 将图像转换为灰度亮度值,亮度越高(越亮),对应网点越小;亮度越低(越暗),对应网点越大
  • 采用规则网格排列网点(而非随机),每个网格单元对应一个网点中心
  • 计算当前像素到所在网格单元中心的距离,对比基于亮度计算的网点半径,决定是否填充该像素

实现代码:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // 归一化坐标
    vec2 uv = fragCoord / iResolution.xy;
    // 采样原图颜色
    vec4 texColor = texture(iChannel0, uv);
    // 计算灰度亮度(ITU-R BT.601标准)
    float luminance = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));
    
    // 网点网格大小(控制点密度,值越小点越密)
    float gridSize = 16.0;
    // 计算当前像素所在的网格单元中心
    vec2 gridPos = floor(fragCoord / gridSize) * gridSize + gridSize * 0.5;
    vec2 gridUV = gridPos / iResolution.xy;
    
    // 计算网点半径:亮度越高,半径越小(暗部大网点,亮部小网点)
    // 最大半径取网格大小的一半,最小半径为0
    float maxRadius = gridSize * 0.45;
    float dotRadius = maxRadius * (1.0 - luminance);
    
    // 计算当前像素到网格中心的距离
    float dist = distance(fragCoord, gridPos);
    
    // 绘制网点:距离小于半径则取原图颜色,否则取背景色(这里用黑色)
    if (dist < dotRadius) {
        fragColor = texColor;
    } else {
        fragColor = vec4(0.0, 0.0, 0.0, 1.0);
    }
}

代码说明:

  • gridSize:控制网点的密度,数值越小,网点越密集
  • 亮度计算采用标准的灰度转换公式,保证亮度判断准确
  • 网点半径和亮度成反比,完美匹配Photoshop点画的明暗对应关系
  • 规则网格排列保证网点分布均匀,符合半色调效果的视觉特征

内容的提问来源于stack exchange,提问作者ZeroOneZeroR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 18:21:28