2016-09-09 130 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行开始)。