繁体   English   中英

THREE.js-在从TubeGeometry构造的网格上移动纹理

[英]THREE.js - Shifting a texture on a Mesh constructed from a TubeGeometry

我有一个问题,我怀疑答案很简单(一两行),但到目前为止我没有尝试过。 非常感谢您的任何建议。

我所拥有的是我通过画布绘制制作的TubeGeometry和Texture。 然后,我制作一个网格物体(如果有区别,可以使用多种材质的物体),其中一种材质的map属性指定为我的纹理。 我将这种材料称为Mat。

问题在于,我需要一种方法来连续地围绕管旋转纹理(以圆环的形式,围绕子午线而不是赤道)。 有点像揉圆形面包。 以前,我指定偏移量(0-1),并具有一个函数createTexture(offset),用于在画布上重绘纹理以模拟环绕,并不断使用代码

Mat.map = new THREE.Texture( createTexture(offset) ); Mat.map.needsUpdate = true; Mat.needsUpdate = true;

从美学上讲,这很好用...除了画布绘图过于昂贵而且我的表现因此而遭受巨大损失之外。 因此,这不是一个合理的解决方案。

我还尝试弄乱Mat.map.offset属性,但这根本不起作用。 似乎保留了原始纹理并仅覆盖了其中的一部分。 我无法确切地了解发生了什么,并想知道使用TubeGeometry是否存在问题,因为有关此方法的与球有关的stackExchange问​​题已解决。

第三个想法是进入TubeGeometry.faceVertexUvs并移动所有面坐标,将它们修改一个,如下所示:

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和/或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>

定义着色器材质:

_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/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM