【问题标题】:Three js texture edge pixels being stretched三个js纹理边缘像素被拉伸
【发布时间】:2020-01-19 13:53:39
【问题描述】:

我正在尝试在球体充当蒙版的球体中显示纹理。我的纹理正确显示,但我不知道如何去除被拉伸以填充球体的边缘像素。我希望它们是透明的。

这就是正在发生的事情

这个想法是图像以其默认外观显示,并且在鼠标悬停时,球体将缩小以掩盖图像的一部分。球体稍后会被修改为其他东西,这只是为了测试,所以不能对 2d 形状做同样的事情。

这就是它的设置方式,没什么特别的,只是为了让你明白。

    texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping
    texture.minFilter = THREE.LinearFilter

    // uniforms

    const uniforms = {
        texture: {value: texture},
        resolution: {type: 'vec2', value: new THREE.Vector2(window.innnerWidth, window.innerHeight)},
        offset: {type: 'vec2', value: new THREE.Vector2(offset.x, offset.y)},
        size: {type: 'vec2', value: new THREE.Vector2(width, height)},
        scroll: {value: 0}
    }

    // material

    const material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: this.vertex,
        fragmentShader: this.fragment
    })

    const geometry = new THREE.SphereGeometry(5, 32, 32)
    this.mesh = new THREE.Mesh(geometry, material)

还有我的片段着色器

    uniform sampler2D texture;
    uniform vec2 resolution;
    uniform vec2 offset;
    uniform vec2 size;

    void main() {

        vec2 uv = gl_FragCoord.xy / resolution * 2.0 - 1.0;
        uv = uv / 2.0 + 0.5;

        uv.x = (uv.x - offset.x) / size.x;
        uv.y = (uv.y - offset.y - scroll) / size.y + 1.0 ;

        gl_FragColor = texture2D(texture, uv);
    }

我知道texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping 是默认行为,因此完全没用,我可以在文档中找到的唯一其他选择是RepeatWrappingMirroredRepeatWrapping,这两者都不是我想要的。我也无法创建具有透明边缘的自定义纹理,因为图像将由客户端上传。

我将如何解决这个问题,我能以某种方式检测我的着色器中的边界吗?

【问题讨论】:

  • vec2 uv = gl_FragCoord.xy / resolution * 2.0 - 1.0;:if (max(abs(uv.x), abs(uv.y)) > 1.0) discard; 之后可能是这样的?
  • 这就像 4 行代码将图像绘制到稍大的画布上,带有 1 像素的黑色边框,然后使用该画布而不是您的纹理.. 或者您可以执行类似的操作如果 uv.y1.) 丢弃;

标签: three.js glsl shader textures mask


【解决方案1】:

如果到视图中心的距离大于 1.0,您必须遵守纵横比和 discard 片段。按纵横比缩放x分量,计算出向量从中心到当前位置的length

vec2 p = gl_FragCoord.xy / resolution * 2.0 - 1.0;
p.x *= resolution.x / resolution.y;
if (length(p) > 1.0)
    discard;

注意,discard 关键字可以在片段着色器中使用,以放弃对当前片段的操作。此关键字会导致片段被丢弃,并且不会更新任何缓冲区。


请注意,甚至可以在像素坐标中定义一个点和一个半径,并在该点周围显示一个圆形区域。
例如您可以通过当前鼠标位置更新中心点。 由于计算是在像素坐标中进行的,因此不需要将距离的 x 分量按纵横比进行缩放:

uniform vec2  center; // center of the circle in pixel coordinates
uniform float radius; // radius in pixel

void main()
{
   vec2 v = gl_FragCoord.xy - center.xy;
   if (length(v) > radius)
       discard;

   // [...]
}

【讨论】:

  • p.x *= resolution.x / resolution.y; 的好选择!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-21
  • 2021-01-14
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 2013-03-24
相关资源
最近更新 更多