簡體   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