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

如何在fragment shader中实现像素间隔拉伸而非像素变形的效果

像素艺术像素间隔拉伸Shader实现需求

我目前正在开发一款Shader以实现像素艺术图像的像素“拉开”效果,核心需求为拉伸像素之间的空隙,而非让像素本身发生形变,类似桌面上拂过沙子的效果:沙粒本身尺寸不变,仅沙粒之间的间距变大。

现有实现情况

  • 目前已实现平滑扭曲效果:距离图像中心越远拉伸程度越高,但该方案为连续的平滑变形,所有像素始终保持相连,会出现挤压、smear等不符合需求的问题
  • 使用modulo运算实现了近似效果,但该方案会丢弃一半的图像内容,不符合预期

效果参考

  • 目标效果示意图:目标效果示意图
  • 现有modulo方案效果示意图:现有modulo方案效果示意图

现有核心代码

var fragmentShader = `
precision mediump float;

varying vec2 vTextureCoord;

uniform sampler2D uSampler;
uniform highp vec4 inputSize;
uniform float time;

vec2 mapCoord( vec2 coord )
{
    coord *= inputSize.xy;
    coord += inputSize.zw;

    return coord;
}

vec2 unmapCoord( vec2 coord )
{
    coord -= inputSize.zw;
    coord /= inputSize.xy;

    return coord;
}

void main(void)
{
    vec2 coord = mapCoord(vTextureCoord);
    float dist = distance(coord.x, inputSize.x/2.);
    coord.x += dist/4.;
    coord = unmapCoord(coord);
    gl_FragColor = texture2D(uSampler, coord);
}`

实现方案

你要实现的效果核心是保持每个原始像素的采样范围不变,仅偏移每个像素块的整体位置,不要对UV做连续的平滑偏移,按以下步骤修改即可:

  1. 首先把UV按原始像素尺寸做离散化分块,拆分出「像素块索引」和「块内相对偏移」两部分,块内偏移始终保持不变就能保证像素本身不会发生形变
  2. 仅对每个像素块的中心坐标做拉伸偏移计算,偏移规则沿用你现有逻辑即可
  3. 最后把偏移后的像素块位置和原始块内偏移合并,换算为最终的采样UV
  4. 额外需要把纹理的过滤模式设置为NEAREST邻近过滤,避免采样时出现插值模糊,保证像素边缘清晰

修改后的核心Shader代码如下:

void main(void)
{
    // 拆分像素块索引和块内偏移
    vec2 pixelGrid = vTextureCoord * inputSize.xy;
    vec2 originalPixelIdx = floor(pixelGrid);
    vec2 offsetInPixel = fract(pixelGrid);

    // 仅对像素块的中心做拉伸偏移
    vec2 pixelCenter = originalPixelIdx + 0.5;
    float dist = distance(pixelCenter.x, inputSize.x / 2.0);
    pixelCenter.x += dist / 4.0;

    // 合并得到最终采样UV
    vec2 finalCoord = (pixelCenter + offsetInPixel - 0.5) / inputSize.xy;
    gl_FragColor = texture2D(uSampler, finalCoord);
}

你之前用modulo出现内容丢失的问题,是因为直接对连续偏移的坐标取模,没有先做离散分块处理,按上述方案分块后所有原始像素都会保留,空隙位置会自动显示为透明或者你设置的背景色,不会出现内容丢失的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:48:02