js着色器纹理闪烁

js着色器纹理闪烁

本文介绍了Three.js着色器纹理闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是three.js的新手,并且认为它很棒.我试图更好地控制将纹理数据移动到着色器,因此我主要可以使用GPU.我的程序基于Doob先生的魔术之尘示例,但我没有使用粒子,而是使用存储在纹理中的加载模型.我目前遇到一个闪烁的问题.下面的代码是闪烁的粗糙示例,与我在做的事情有些相似.如果有人可以帮助我了解我在做什么错或闪烁是从哪里来的……我很确定所有内容都是最新的,例如纹理映射和three.js版本.非常感谢

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>

推荐答案

如果更改for循环,并在其中填充纹理,则闪烁将停止:

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++)

但是我在chrome和firefox上都一直遇到"rtTexture2失败"的情况.

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)

应该是:

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

但是我仍然无法摆脱上面的错误.

but I still cannot get rid of the above error.

这篇关于Three.js着色器纹理闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 00:18