在threejs可视化中填充webgl上下文中的着色器属性

时间:2018-03-30 21:02:10

标签: three.js glsl webgl

我正在学习使用大量现有webgl教程的着色器,我希望有一种方法可以将编译后的着色器程序附加到threejs着色器材料上,但我遇到了困难。如果可能的话,使用gl方法设置属性和制服是非常好的,然后在材质上设置着色器程序。这是我尝试过的。

<!doctype html>
<html>
    <head>

        <script src="http://threejs.org/build/three.min.js"></script>
        <meta charset="utf-8" />
        <title>Sample Three.js</title>
        <style>
            #container {
                background: #000;
                width: 400px;
                height: 300px;
            }
        </style>
    </head>
    <body>


    </body>

    <script type="x-shader/x-vertex" id="vertexshader">
        // switch on high precision floats
        #ifdef GL_ES
        precision highp float;
        #endif
        uniform mat4 projectionmyMatrix;
        attribute vec3 vertexPos;
        attribute float displacement;
        uniform float amplitude;

        void main()
        {
            vec3 newPos = vertexPos;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos,1.0);
        }

    </script>

    <script type="x-shader/x-fragment" id="fragmentshader">
        #ifdef GL_ES
        precision highp float;
        #endif

        void main( void ) {

           gl_FragColor = vec4( 1.0,1.0,1.0,1.0);

        }
    </script>

    <!-- End Shaders -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>

    <script type="text/javascript">
    // set the scene size
    var WIDTH = 800,
        HEIGHT = 600;

    // set some camera attributes
    var VIEW_ANGLE = 45,
        ASPECT = WIDTH / HEIGHT,
        NEAR = 1,
        FAR = 1000;

    // get the DOM element to attach to
    // - assume we've got jQuery to hand
    var $container = $('body');

    // create a WebGL renderer, camera
    // and a scene
    var renderer = new THREE.WebGLRenderer();
    var camera = new THREE.PerspectiveCamera(
        VIEW_ANGLE,
    ASPECT,
    NEAR,
    FAR  );
    var scene = new THREE.Scene();

    // the camera starts at 0,0,0 so pull it back
    camera.position.z = 300;

    // start the renderer
    renderer.setSize(WIDTH, HEIGHT);

    // attach the render-supplied DOM element
    $container.append(renderer.domElement);

    // set up the sphere vars
    var radius = 50, segments = 16, rings = 16;


    // create the sphere's material
    var shaderMaterial = new THREE.ShaderMaterial({
        vertexShader:   $('#vertexshader').text(),
        fragmentShader: $('#fragmentshader').text()
    });
    // create a new mesh with sphere geometry -
    // we will cover the sphereMaterial next!
    var sphere = new THREE.Mesh(
       new THREE.SphereGeometry(radius, segments, rings),
       shaderMaterial);

    //filling the attribute vertex array

    // add the sphere and camera to the scene
    scene.add(sphere);
    scene.add(camera);
    renderer.compile(scene,camera)

    var gl = renderer.getContext()
    var sq = createSquare(gl)
    var prg = shaderMaterial.program.program
    var posAttr = gl.getAttribLocation(prg,'vertexPos')


    // set the vertex buffer to be drawn
    gl.bindBuffer(gl.ARRAY_BUFFER, sq.buffer);

    // set the shader to use
    gl.useProgram(prg);

    // connect up the shader parameters: vertex position and projection/model matrices
    gl.vertexAttribPointer(posAttr, sq.vertSize, gl.FLOAT, false, 0, 0);

    renderer.compile(scene,camera)
    // create a rendering loop
    var frame = 0;
    function update() {
        frame += .01
        renderer.render(scene, camera);
        requestAnimationFrame(update)
    }
    requestAnimationFrame(update)

    </script>
</html>

我宁愿不必将教程翻译成下面表示的three.js所使用的制服,属性语法

```

   var attributes = {
  displacement: {
    type: 'f', // a float
    value: [] // an empty array
  }
};
var uniforms = {
  amplitude: {
    type: 'f', // a float
    value: 1
  }
};

var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');

// create the final material
var shaderMaterial =
    new THREE.MeshShaderMaterial({
      uniforms:       uniforms,
      attributes:     attributes,
      vertexShader:   vShader.text(),
      fragmentShader: fShader.text()
    });
...

1 个答案:

答案 0 :(得分:0)

不,这种方法既不推荐也不支持。您可以使用两种方法,而不是使用原始WebGL上下文:

  • 您可以使用THREE.ShaderMaterial作为自定义着色器定义。 three.js会自动提供一些内置属性和制服(例如modelViewMatrixprojectionMatrix),这些属性和制服经常被顶点和片段着色器使用。官方doc page提供了大量信息。
  • THREE.RawShaderMaterial是一个更轻量级的选项,因为three.js没有提供上面提到的内置制服和属性。

以下两个基本示例显示了使用最新版three.jsR91)的两种材料的用法:

https://threejs.org/examples/#webgl_shader https://threejs.org/examples/#webgl_buffergeometry_rawshader

我建议使用这些示例,而不是使用可能过时的教程。例如,属性不再是ShaderMaterial的参数。相反,属性数据是几何体的一部分。