Three.js Shader-Texture Blinking

怎甘沉沦 提交于 2019-12-10 17:23:38

问题


I'm new to three.js and think it's great. I'm trying to get a better hold on moving texture data to the shader so I can mostly use GPU. I base my program on Mr. Doob's magic dust example, but I'm not using particles rather loaded models stored in a texture. I'm having an issue currently where I get flickering. The code below is a rough example of the flickering and has some closeness to what I'm doing. If anyone could help me understand what I'm doing wrong or where the flickering is coming from ... I'm pretty sure everything is up-to-date, as in the texture mapping and three.js revision. Thanks a lot

<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Sample Three.js</title>
    </head>

    <div id="container">
    </div>

    <body>
        <script type="text/javascript" src="./Scripts/three.js"></script>

        <script type="text/javascript">

        //
        // as name suggests - utilty functions mostly from Mr.doob from THREE.FBOUtils
        //
        UtilityFuncs = function() {
            this.textureWidth = 0;
            this.textureHeight = 0;
            this.scene = null;
            this.camera = null;
            this.renderer = null;
            this.material = null;
            this.jsonLoader = null;
            this.jsonModel = null;
            this.loadCount = 0;
        }

        UtilityFuncs.prototype.createScene = function( textureWidth, textureHeight, renderer ) {
            var gl = renderer.getContext();

            if( !gl.getExtension( "OES_texture_float" )) {
                    alert( "No OES_texture_float support for float textures!" );
                    return;
            }

            if( gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) == 0) {
                    alert( "No support for vertex shader textures!" );
                    return;
            }

            var camera = new THREE.OrthographicCamera(-textureWidth/2, textureHeight/2,
                                                      textureWidth/2, -textureHeight/2,
                                                      -1000, 1000);
            camera.position.z = 100;

            // Shader Stuff
            var vertex_shader = [
                "varying vec2 vUv;",
                "void main() {",
                "    vUv = vec2(uv.x, 1.0 - uv.y);",
                "    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
                "} "
            ].join("\n");

            var fragment_shader = [
                "varying vec2 vUv;",
                "uniform sampler2D tPositions;",
                "void main() {",
                "    vec4 pos = texture2D( tPositions, vUv );",
                "    gl_FragColor = pos;",
                "}"
            ].join("\n");

            var material = new THREE.ShaderMaterial({
                    uniforms: {
                        tPositions: { type: "t", value: null }
                    },
                    vertexShader: vertex_shader,
                    fragmentShader: fragment_shader,
                    blending: THREE.NoBlending,
                    depthTest: false,
                    depthWrite: false,
                    side: THREE.DoubleSide
            });

            var plane = new THREE.PlaneGeometry(textureWidth, textureHeight);
            var quad = new THREE.Mesh(plane, material);
            quad.position.z = 0;
            var scene = new THREE.Scene();
            scene.add(camera);
            scene.add(quad);

            this.textureWidth = textureWidth;
            this.textureHeight = textureHeight;
            this.scene = scene;
            this.camera = camera;
            this.renderer = renderer;
            this.material = material;
        }

        UtilityFuncs.prototype.createRenderTarget = function(width, height) {
            var rtTexture = new THREE.WebGLRenderTarget(width, height,
                                            {
                                                wrapS:THREE.RepeatWrapping,
                                                wrapT:THREE.RepeatWrapping,
                                                minFilter: THREE.NearestFilter,
                                                magFilter: THREE.NearestFilter,
                                                format: THREE.RGBAFormat,
                                                type:THREE.FloatType,
                                                // renderbuffer defaults to RGB4
                                                // if stencil & depth false! 
                                                // three.js, setupRenderBuffer::24848 
                                                stencilBuffer: false,
                                                depthBuffer: true
                                            });
            rtTexture.generateMipmaps = false;
            return rtTexture;
        }

        UtilityFuncs.prototype.createFloatTextureFromData = function(width, height, data) {
            var texture = new THREE.DataTexture(
                data,
                width,
                height,
                THREE.RGBAFormat,
                THREE.FloatType,
                null,
                THREE.RepeatWrapping,
                THREE.RepeatWrapping,
                THREE.NearestFilter,
                THREE.NearestFilter
            );

            texture.generateMipmaps = false;
            texture.needsUpdate = true;

            return texture;
        };

        UtilityFuncs.prototype.readFramebuffer = function(renderer, framebuffer, width, height) {
                var gl = renderer.getContext();
                gl.flush();
                if (framebuffer != null)
                    gl.bindFramebuffer( gl.FRAMEBUFFER, framebuffer );
                var rdData = new Uint8Array(width*height*4);
                gl.readPixels( 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, rdData );
                return rdData;
        }

        UtilityFuncs.prototype.readFloatFramebuffer = function(renderer, framebuffer, width, height) {
                var gl = renderer.getContext();
                gl.flush();
                if (framebuffer != null)
                    gl.bindFramebuffer( gl.FRAMEBUFFER, framebuffer );
                var rdData = new Float32Array(width*height*4);
                gl.readPixels( 0, 0, width, height, gl.RGBA, gl.FLOAT, rdData );
                return rdData;
        }

        UtilityFuncs.prototype.renderToTexture = function(texture, renderToTexture) {
            this.material.uniforms.tPositions.value = texture;
            this.renderer.render(this.scene, this.camera, renderToTexture, false);
        };

        UtilityFuncs.prototype.render = function(texture) {
            this.material.uniforms.tPositions.value = texture;
            this.renderer.render(this.scene, this.camera);
        };

        //
        // start of main routines
        //
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;
        var texWidth = 4,
            texHeight = 4;
        var container, renderer;
        var start = Date.now();
        var rtTexture, rtTexture2;
        var utilities;
        var rdData, rdData2, ardData, ardData2;

        function launch() {

            container = document.getElementById("container");
            renderer = new THREE.WebGLRenderer({antialias:true});
            renderer.setSize(WIDTH, HEIGHT);
            container.appendChild(renderer.domElement);

            utilities = new UtilityFuncs();

            utilities.createScene( texWidth, texHeight, renderer );

            rtTexture = utilities.createRenderTarget(texWidth, texHeight);
            rtTexture2 = utilities.createRenderTarget(texWidth, texHeight);


            // Create constant color test textures
            var mData = new Float32Array(texWidth*texHeight*4);
            for (var i = 0; i < 8; i++) {
                    mData[4*i] = 1.0; mData[4*i+1] = 0.0; mData[4*i+2] = 1.0; mData[4*i+3] = 1.0;
            }
            magentaTexture = utilities.createFloatTextureFromData(texWidth, texHeight, mData)

            // Create constant color test textures
            var cData = new Float32Array(texWidth*texHeight*4);
            for (var i = 0; i < 8; i++) {
                    cData[4*i] = 0.0; cData[4*i+1] = 1.0; cData[4*i+2] = 1.0; cData[4*i+3] = 1.0;
            }
            cyanTexture = utilities.createFloatTextureFromData(texWidth, texHeight, cData)

            utilities.renderToTexture(cyanTexture, rtTexture);
            rdData = utilities.readFramebuffer(renderer, rtTexture.__webglFramebuffer,
                                               texWidth, texHeight);

            utilities.renderToTexture(magentaTexture, rtTexture2);
            rdData2 = utilities.readFramebuffer(renderer, rtTexture2.__webglFramebuffer,
                                                texWidth, texHeight);

            if (rdData[0] != 0 || rdData[1] != 255 || rdData[2] != 255 || rdData[3] != 255)
                console.log("rtTexture load fail\n");

            if (rdData2[0] != 255 || rdData2[1] != 0 || rdData2[2] != 255 || rdData2[3] != 255)
                console.log("rtTexture2 load fail\n");

            animate();
        }

        var timer = 0;

        function animate() {
            requestAnimationFrame( animate );
            render();
        }

        function render() {
            //
            // copy rtTexture and rtTexture2 between each other
            //

            utilities.renderToTexture(rtTexture, rtTexture2);
            ardData2 = utilities.readFramebuffer(renderer, rtTexture2.__webglFramebuffer,
                                                 texWidth, texHeight);

            utilities.renderToTexture(rtTexture2, rtTexture);
            ardData = utilities.readFramebuffer(renderer, rtTexture.__webglFramebuffer,
                                                   texWidth, texHeight);

            if (timer & 1)
                utilities.render(rtTexture2);
            else
                utilities.render(rtTexture);

            if (ardData[0] != 0 || ardData[1] != 255 || ardData[2] != 255 || ardData[3] != 255)
                console.log("rtTexture fail\n");
            if (ardData2[0] != 0 || ardData2[1] != 255 || ardData2[2] != 255 || ardData2[3] != 255)
                console.log("rtTexture2 fail\n");
            timer++;
        }

        //launch();

        </script>
        <button id="renderButton" onClick="launch()">Render</button>
        <br/>
    </body>
</html>

回答1:


Well the flickering will stop if you change your for loop where you fill the textures from:

for (var i = 0; i < 8; i++) ==>> for (var i = 0; i < texWidth*texHeight*4; i++)

but I keep getting "rtTexture2 fail" both on chrome and firefox.

I spotted another error. Line;

if (ardData2[0] != 0 || ardData2[1] != 255 || ardData2[2] != 255 || ardData2[3] != 255)

should be:

if (ardData2[0] != 255 || ardData2[1] != 0 || ardData2[2] != 255 || ardData2[3] != 255)

but I still cannot get rid of the above error.



来源:https://stackoverflow.com/questions/15077762/three-js-shader-texture-blinking

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!