THREE.js - 在由 TubeGeometry 构造的网格上移动纹理
THREE.js - Shifting a texture on a Mesh constructed from a TubeGeometry
我有一个问题,我怀疑答案很简单(一两行),但到目前为止我尝试过的都没有用。非常感谢您的任何建议。
我拥有的是通过 canvas 绘图制作的 TubeGeometry 和纹理。然后我制作了一个网格(多 material 对象,如果有区别的话),其中一个 material 将贴图 属性 指定为我的纹理。我将其称为 material Mat。
问题是我需要一种方法来围绕管子连续旋转纹理(在圆环方面,围绕子午线,而不是赤道)。有点像揉圆形面包。以前我指定了一个偏移量 (0-1) 并有一个函数 createTexture(offset) 用于重绘 canvas 上的纹理以模拟环绕,不断使用代码
Mat.map = new THREE.Texture( createTexture(offset) );
Mat.map.needsUpdate = true;
Mat.needsUpdate = true;
从美学上讲,这很好用...只是 canvas 绘图太贵了,我的表现因此受到很大影响。所以这不是一个合理的解决方案。
我也试过摆弄 Mat.map.offset
属性,但这根本不起作用。似乎要保留原始纹理并仅覆盖其中的一部分。我无法准确辨别那里发生了什么,想知道使用 TubeGeometry 是否有问题,因为有关 Spheres 的相关 stackExchange 问题已通过此方法解决。
第三个想法是进入 TubeGeometry.faceVertexUvs
并移动所有面部坐标,修改为 1,如:
function transform(n){
var faceVertexUvs = tubeGeometry.faceVertexUvs[0];
for (var i =0; i < faceVertexUvs.length; i++){
for (var j=0; j< 3; j++){
faceVertexUvs[i][j].y = ((faceVertexUvs[i][j].y + n) % 1);
}
}
tubeGeometry.uvsNeedUpdate = true;
}
这太接近工作了,但总是留下一条赤道线,在那里一切都出错了。纹理看起来很糟糕,就像它遇到了巨大的优柔寡断危机,我正在做的光线投射在这个地方也很疯狂。虽然 99% 的效果都很好......也许有办法挽救最后一次尝试?
不过,我不偏爱任何一种方法。特别感谢最大效率!
再次感谢您的帮助!
接缝由 % 1 创建。删除 % 1 并在纹理上启用环绕 (map.wrapS = THREE.RepeatWrapping and/or map.wrapT)。这将允许您不断增加 UV,并且纹理将自行包裹。您也可以尝试更改 map.offset,这可能会为您偏移纹理。
您可以使用片段着色器执行此操作:
<script id="fs" type="x-shader/x-fragment">
uniform float iGlobalTime;
uniform sampler2D iChannel0;
varying vec2 vUv;
void main() {
vec2 uv = vUv;
uv.y = uv.y + iGlobalTime;
if (uv.y > 1.)
uv.y = uv.y - 1.;
gl_FragColor = texture2D( iChannel0, vec2(uv.x, uv.y));
}
</script>
定义着色器 material:
_uniforms = {
iGlobalTime: { type: 'f', value: 0.1 },
iChannel0: { type: 't', value: THREE.ImageUtils.loadTexture( 'textures/cat.png') },
};
newMaterial = new THREE.ShaderMaterial( {
uniforms: _uniforms,
vertexShader: document.getElementById( 'vs' ).textContent,
fragmentShader: document.getElementById( 'fs' ).textContent,
} );
然后在渲染循环中设置 iGlobalTime:
_uniforms.iGlobalTime.value += clock.getDelta();
while (_uniforms.iGlobalTime.value > 1.)
_uniforms.iGlobalTime.value -= 1.;
这里是完整的工作示例:http://rwoodley.org/MyContent/SO/01/
我有一个问题,我怀疑答案很简单(一两行),但到目前为止我尝试过的都没有用。非常感谢您的任何建议。
我拥有的是通过 canvas 绘图制作的 TubeGeometry 和纹理。然后我制作了一个网格(多 material 对象,如果有区别的话),其中一个 material 将贴图 属性 指定为我的纹理。我将其称为 material Mat。
问题是我需要一种方法来围绕管子连续旋转纹理(在圆环方面,围绕子午线,而不是赤道)。有点像揉圆形面包。以前我指定了一个偏移量 (0-1) 并有一个函数 createTexture(offset) 用于重绘 canvas 上的纹理以模拟环绕,不断使用代码
Mat.map = new THREE.Texture( createTexture(offset) );
Mat.map.needsUpdate = true;
Mat.needsUpdate = true;
从美学上讲,这很好用...只是 canvas 绘图太贵了,我的表现因此受到很大影响。所以这不是一个合理的解决方案。
我也试过摆弄 Mat.map.offset
属性,但这根本不起作用。似乎要保留原始纹理并仅覆盖其中的一部分。我无法准确辨别那里发生了什么,想知道使用 TubeGeometry 是否有问题,因为有关 Spheres 的相关 stackExchange 问题已通过此方法解决。
第三个想法是进入 TubeGeometry.faceVertexUvs
并移动所有面部坐标,修改为 1,如:
function transform(n){
var faceVertexUvs = tubeGeometry.faceVertexUvs[0];
for (var i =0; i < faceVertexUvs.length; i++){
for (var j=0; j< 3; j++){
faceVertexUvs[i][j].y = ((faceVertexUvs[i][j].y + n) % 1);
}
}
tubeGeometry.uvsNeedUpdate = true;
}
这太接近工作了,但总是留下一条赤道线,在那里一切都出错了。纹理看起来很糟糕,就像它遇到了巨大的优柔寡断危机,我正在做的光线投射在这个地方也很疯狂。虽然 99% 的效果都很好......也许有办法挽救最后一次尝试?
不过,我不偏爱任何一种方法。特别感谢最大效率!
再次感谢您的帮助!
接缝由 % 1 创建。删除 % 1 并在纹理上启用环绕 (map.wrapS = THREE.RepeatWrapping and/or map.wrapT)。这将允许您不断增加 UV,并且纹理将自行包裹。您也可以尝试更改 map.offset,这可能会为您偏移纹理。
您可以使用片段着色器执行此操作:
<script id="fs" type="x-shader/x-fragment">
uniform float iGlobalTime;
uniform sampler2D iChannel0;
varying vec2 vUv;
void main() {
vec2 uv = vUv;
uv.y = uv.y + iGlobalTime;
if (uv.y > 1.)
uv.y = uv.y - 1.;
gl_FragColor = texture2D( iChannel0, vec2(uv.x, uv.y));
}
</script>
定义着色器 material:
_uniforms = {
iGlobalTime: { type: 'f', value: 0.1 },
iChannel0: { type: 't', value: THREE.ImageUtils.loadTexture( 'textures/cat.png') },
};
newMaterial = new THREE.ShaderMaterial( {
uniforms: _uniforms,
vertexShader: document.getElementById( 'vs' ).textContent,
fragmentShader: document.getElementById( 'fs' ).textContent,
} );
然后在渲染循环中设置 iGlobalTime:
_uniforms.iGlobalTime.value += clock.getDelta();
while (_uniforms.iGlobalTime.value > 1.)
_uniforms.iGlobalTime.value -= 1.;
这里是完整的工作示例:http://rwoodley.org/MyContent/SO/01/