三个js纹理边缘像素被拉伸
Three js texture edge pixels being stretched
我正在尝试在球体中显示纹理,其中球体充当遮罩。我的纹理已正确显示,但我无法理解如何删除被拉伸以填充球体的边缘像素。我希望它们是透明的。
这就是正在发生的事情
想法是图像以其默认方面显示,并且在鼠标悬停在球体上时会缩小以遮盖图像的一部分。球体稍后会被修改为其他东西,这只是为了测试,所以用二维形状做同样的事情不是一个选项。
这就是它的设置方式,没什么特别的,只是让您明白了。
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
是默认行为,因此完全没用,我在文档中能找到的唯一其他替代方法是 RepeatWrapping
或 MirroredRepeatWrapping
,两者都不是我想。我也无法创建具有透明边缘的自定义纹理,因为图像将由客户端上传。
我该如何解决这个问题,我能否以某种方式检测我的着色器中的边界?
如果到视图中心的距离大于 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;
// [...]
}
我正在尝试在球体中显示纹理,其中球体充当遮罩。我的纹理已正确显示,但我无法理解如何删除被拉伸以填充球体的边缘像素。我希望它们是透明的。
这就是正在发生的事情
想法是图像以其默认方面显示,并且在鼠标悬停在球体上时会缩小以遮盖图像的一部分。球体稍后会被修改为其他东西,这只是为了测试,所以用二维形状做同样的事情不是一个选项。
这就是它的设置方式,没什么特别的,只是让您明白了。
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
是默认行为,因此完全没用,我在文档中能找到的唯一其他替代方法是 RepeatWrapping
或 MirroredRepeatWrapping
,两者都不是我想。我也无法创建具有透明边缘的自定义纹理,因为图像将由客户端上传。
我该如何解决这个问题,我能否以某种方式检测我的着色器中的边界?
如果到视图中心的距离大于 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;
// [...]
}