【问题标题】:filling shader attributes from webgl context in threejs visualization在threejs可视化中从webgl上下文填充着色器属性
【发布时间】:2018-03-31 16:54:22
【问题描述】:

我正在使用许多现有的 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()
    });
...

【问题讨论】:

    标签: three.js glsl webgl


    【解决方案1】:

    不,这种方法既不推荐也不支持。除了使用原始 WebGL 上下文,您有两个选择:

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

    以下两个基本示例显示了两种材料在最新版本three.js (R91) 中的用法:

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

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

    【讨论】:

    • 我明白了,对此有官方答案很好。但是,在某些情况下,使用 gl 上下文是否是必要且有帮助的?还是不管制服和属性是如何创建的,都必须像示例一样传递给着色器材质(原始或其他)?
    • 没错。如果您使用库的功能,您肯定会编写更少的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 2013-08-27
    • 2014-07-20
    相关资源
    最近更新 更多