简体   繁体   中英

Three.JS — porting a custom vertex shader

I'd like to use this shader with three.js. The vertex shader in this example uses an attribute surfacePosAttrib which is set up in the hosting javascript by the following calls I believe:

surface.positionAttribute = gl.getAttribLocation(currentProgram, "surfacePosAttrib");
gl.enableVertexAttribArray(surface.positionAttribute);

I couldn't find these calls when searching through the webglrenderer source for three.js , so I believe these buffers are not set up in three.js .

Is there a supported way to set these buffers for a custom shader in three.js ?

I see this vertex shader in the source code:

<script id="surfaceVertexShader" type="x-shader/x-vertex">

    attribute vec3 position;
    attribute vec2 surfacePosAttrib;
    varying vec2 surfacePosition;

    void main() {

        surfacePosition = surfacePosAttrib;
        gl_Position = vec4( position, 1.0 );

    }

</script>

The first line of code you provided the method finds the index bound the attribute surfacePosAttrib in the vertex shader inside current program and assigns it to positionAttribute of surface in javascript. The second line is simply enabling it. Javascript buffer names are arbitrary. They have different names in different programs so it's predictable you won't find such buffers in three.js .

I'm guessing (not sure though) that almost all the work is done in fragment shader (like most of similar works done by Iñigo Quílez can be found in his shadertoy page ) and vertex shader is only providing a surface for fragment shader to draw on.

Below simple example uses custom shaders in three.js . It defines a mesh with a 2D plane geometry visible by the camera and defines a custom shader whose vertex shader and fragment shader provided by the user. Note that projectionMatrix and modelViewMatrix are provided automatically by three.js in the vertex shader so you don't need to manually pass them.

<!DOCTYPE html>
<html>
<head>
    <title>Shading #1</title>
    <style>canvas { width: 100%; height: 100% ;}</style>
    <style>
        body {
            margin: 0px;
        }
    </style>
</head>
<body>      
    <script src="https://rawgithub.com/mrdoob/three.js/master/build/three.min.js"></script>

    <script id="vs" type="x-shader/x-vertex">       
        void main()
        {
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
        }           
    </script>

    <script id="fs" type="x-shader/x-fragment">

        uniform float time;
        uniform vec2 resolution;

        void main()
        {               

            gl_FragColor = vec4(0.3, 0.0, 0.0 , 1.0);
        }

    </script>

    <script type="text/javascript">

        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
        var renderer = new THREE.WebGLRenderer({ antialias: true});

        var startTime = Date.now();

        //assignings happen here
        //more info on https://github.com/mrdoob/three.js/wiki/Uniforms-types
        var uniforms = {
            time: {
                type: 'f',
                value: 0
            },
            resolution: {
                type: "v2",
                value: new THREE.Vector2( window.innerWidth, window.innerHeight )
            }
        };          
        var myMaterial = new THREE.ShaderMaterial({
            uniforms: uniforms,
            vertexShader: document.getElementById( 'vs' ).textContent,
            fragmentShader: document.getElementById( 'fs' ).textContent
        });

        camera.position.z = 0.40;
        var itemGeometry = new THREE.PlaneGeometry( window.innerWidth / (window.innerWidth+window.innerHeight), window.innerHeight / (window.innerWidth+window.innerHeight), 0);
        var itemCube = new THREE.Mesh( itemGeometry, myMaterial );
        scene.add( itemCube );

        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );


        function render() {

            requestAnimationFrame(render);
            uniforms.time.value = (Date.now() - startTime)/1000;        
            renderer.render(scene, camera);

        }
        render();
    </script>
</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM