2016-09-09 177 views
0

我想寫一個自定義着色器,它用three.js操作我的圖像。 爲此,我想創建一個與圖像作爲紋理的平面。之後我想移動頂點以扭曲圖像。Three.js自定義着色器與紋理

(如果這是一個絕對錯誤的方式來做到這一點,請告訴我)。

首先我有我的着色器:

<script type="x-shader/x-vertex" id="vertexshader"> 
     attribute vec2 a_texCoord; 
     varying vec2 v_texCoord; 

     void main() { 
      // Pass the texcoord to the fragment shader. 
      v_texCoord = a_texCoord; 

      gl_Position = projectionMatrix * 
          modelViewMatrix * 
          vec4(position,1.0); 
     } 
    </script> 

    <script type="x-shader/x-fragment" id="fragmentshader"> 
     uniform sampler2D u_texture; 
     varying vec2 v_texCoord; 

     void main() { 
      vec4 color = texture2D(u_texture, v_texCoord); 
      gl_FragColor = color; 
     } 

    </script> 

在哪裏我真的不明白什麼的Texture2D是幹什麼的,但我發現,在其他的代碼片段。 我想要的是這個示例:只需使用「底層」圖像(=紋理)中的顏色對頂點(gl_FracColor)進行着色即可。

在我的代碼,我已經建立了正常的3個場景飛機:

// set some camera attributes 
    var VIEW_ANGLE = 45, 
     ASPECT = window.innerWidth/window.innerHeight, 
     NEAR = 0.1, 
     FAR = 1000; 

    var scene = new THREE.Scene(); 


    var camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR); 
    camera.position.set(0, 0, 15); 

    var vertShader = document.getElementById('vertexshader').innerHTML; 
    var fragShader = document.getElementById('fragmentshader').innerHTML; 

    var texloader = new THREE.TextureLoader(); 
    var texture = texloader.load("img/color.jpeg"); 

    var uniforms = { 
     u_texture: {type: 't', value: 0, texture: texture}, 

    }; 


    var attributes = { 
     a_texCoord: {type: 'v2', value: new THREE.Vector2()} 
    }; 

    // create the final material 
    var shaderMaterial = new THREE.ShaderMaterial({ 
     uniforms:  uniforms, 
     vertexShader: vertShader, 
     fragmentShader: fragShader 
    }); 

    var renderer = new THREE.WebGLRenderer(); 
    renderer.setSize(window.innerWidth, window.innerHeight); 
    document.body.appendChild(renderer.domElement); 

    var plane = { 
     width: 5, 
     height: 5, 
     widthSegments: 10, 
     heightSegments: 15 
    } 

    var geometry = new THREE.PlaneBufferGeometry(plane.width, plane.height, plane.widthSegments, plane.heightSegments) 

    var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); 
    var plane = new THREE.Mesh(geometry, shaderMaterial); 
    scene.add(plane); 

    plane.rotation.y += 0.2; 

    var render = function() { 
     requestAnimationFrame(render); 

     // plane.rotation.x += 0.1; 

     renderer.render(scene, camera); 
    }; 

    render(); 

不幸的是,在運行該代碼後,我只看到一個黑色窗口。雖然我知道如果在創建網格時使用material作爲材質,我可以清楚地看到它。 所以它必須是着色器材質或着色器。

問題:

  • 我必須定義統一u_texture,在我的着色材料的制服和屬性的屬性 a_texCoord?並且做 他們必須有完全相同的名字?
  • 無論如何有多少個頂點?我會得到圖像中每個像素的頂點嗎?或者這架飛機的每個角落只有4個?
  • a_texCoord有什麼價值?什麼也沒有發生,如果我寫:

    var attributes = { 
        a_texCoord: {type: 'v2', value: new THREE.Vector2(1,1)} 
    }; 
    
  • 還是我必須使用一些映射(內置地圖的東西從三個)?但是,我將如何改變頂點位置?

難道有人會對此事有所瞭解嗎?

回答

1

我把它通過改變這個工作:

var uniforms = { 
     u_texture: {type: 't', value: 0, texture: texture}, 
    }; 

要這樣:

var uniforms = { 
     u_texture: {type: 't', value: texture}, 
    }; 

反正所有其他的問題仍然是開放和答案的高度讚賞。 (順便說一句:爲什麼別人的降級)

1

我必須定義統一u_texture和屬性a_texCoord在我的着色材料的制服和屬性 ?他們是否有 具有完全相同的名稱?

是的,是的。這些制服被定義爲着色器材質的一部分,而屬性在版本72中已經從着色器材質移動到BufferGeometry-class(我假設你使用的是最新版本,所以這裏是你如何做到這一點今天):

var geometry = new THREE.PlaneBufferGeometry(...); 

// first, create an array to hold the a_texCoord-values per vertex 
var numVertices = (plane.widthSegments + 1) * (plane.heightSegments + 1); 
var texCoordBuffer = new Float32Array(2 * numVertices); 

// now register it as a new attribute (the 2 here indicates that there are 
// two values per element (vec2))  
geometry.addAttribute('a_texCoord', new THREE.BufferAttribute(texCoordBuffer, 2)); 

正如你看到的,屬性將只如果有在你的shader代碼指定的確切名稱相同的工作。

我不確切知道你打算如何使用它,但它聽起來很像你想要的uv座標。如果是這樣的話,如果你看看THREE.PlaneBufferGeometry-class,你可以節省很多工作。它已經提供了一個名爲uv的屬性,它可能正是您正在尋找的。所以,你只需要在你的shader代碼更改屬性名稱

attribute vec2 uv; 

反正有多少頂點有哪些?我會爲圖像中的每個 像素獲取一個頂點嗎?或者這架飛機的每個角落只有4個?

根據參數heightSegmentswidthSegments創建頂點。所以如果你設置爲5,那麼將會有(5 + 1)*(5 + 1)= 36個頂點(+1,因爲只有1個線段的線有兩個頂點等)和5 * 5 * 2 = 50個三角形(有150個指數)。

另一件需要注意的是,PlaneBufferGeometry是一個索引幾何。這意味着每個頂點(和其他每個屬性值)只存儲一次,儘管它被多個三角形使用。有一個特殊的索引屬性,其中包含哪些頂點用於創建哪些三角形的信息。

a_texCoord有什麼價值?如果我寫:

我希望以上內容有助於回答這個問題。

還是我必須使用一些映射(內置三個地圖的東西)?

我建議你使用uv屬性如上所述。但你絕對不需要。

但是,我將如何改變頂點位置?

至少有兩種方法可以做到這一點:在頂點着色器或通過JavaScript。後者可以在這裏看到:http://codepen.io/usefulthink/pen/vKzRKr?editors=1010 (更新幾何的相關部分從第84行開始)。