-->

加载在反馈环路的第一帧文件纹理与three.js所交换缓冲区(loading a file text

2019-10-22 08:07发布

我正在使用一些反馈回路的着色器(纹理乒乓球)three.js所网站上。

当有人访问该网站时,回路应(视时,他/她访问的)从某一点继续。 要做到这一点,我打算在第一帧从服务器加载的图片(如JPEG),使这对我的乒乓缓冲区,并继续从帧2开始我的正常反馈环路。

这里是我的问题的一个精简版,作为反馈功能,我只需在一帧小的值添加到像素的颜色。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>feedbacktest</title>
        <style>canvas { width: 100%; height: 100%; }</style>
    </head>
    <body>
        <!-- Main THREE includes -->
        <script src="js/three.min.js"></script>
        <script src="js/Detector.js"></script>
        <!-------------------->
        <!-- Shaders        -->
        <!-------------------->

                        <!-- no change vertex shader. used for all render stages. -->
        <script id="vs_output" type="x-shader/x-vertex">

            varying vec2 texCoord;

            void main(void)
            {
                texCoord = uv;                              
                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            }
        </script>

        <!-- feedback shader -->
        <script id="fs_feedback" type="x-shader/x-fragment">        
            // switch on high precision floats
            #ifdef GL_ES
            precision highp float;
            #endif      
            uniform sampler2D texture;
            uniform sampler2D texture2;
            varying vec2 texCoord;
            uniform float onOpen;

            void main() 
            {                       
                // sample textures
                vec4 result = texture2D(texture, texCoord);
                vec4 startT = texture2D(texture2, texCoord);                
                result.rgb+=0.001;
                result.rgb = mod(result.rgb, 1.0);
    /*          if (onOpen <=1.0){
                    result.rgb=startT.rgb;
                }*/
                result.a = 1.0;                                 
                gl_FragColor = result;              
            }
        </script>

        <!-- Final pass fragment shader. -->
        <script id="fs_output" type="x-shader/x-fragment">

            uniform sampler2D fb2output;                        
            varying vec2 texCoord;

            void main (void)
            {
                vec4 col = texture2D(fb2output, texCoord);                      
                gl_FragColor = col;
            }
        </script>

                <!-- init shader. -->
        <script id="fs_start" type="x-shader/x-fragment">

            uniform sampler2D texture;                      
            varying vec2 texCoord;

            void main (void)
            {
                vec4 col = texture2D(texture, texCoord);

                gl_FragColor = col;
            }
        </script>

        <!-------------------->
        <!-- Main Logic     -->
        <!-------------------->
        <script>
            if (!Detector.webgl)
            {
                Detector.addGetWebGLMessage();
            }
            //------------------------------------------
            // Globals
            //------------------------------------------
            var cameraLoop, cameraOutput, sceneFeedback, sceneOutput, renderer, sceneStart;
            var feedbackTexture, feedbackTexture2, loadTexture;         
            var feedbackUniforms, mainUniforms, startUniforms;
            var feedbackQuad, screenQuad, startQuad;
            var feedbackMat, screenMat, startMat;
            var loopRes = new THREE.Vector2(64.0, 64.0);
            var outputRes = new THREE.Vector2(512.0, 512.0);

            var doLoad =0.0;
//          var onOpen = 0.0;

            var renderTargetNearestFloatParams = {
                minFilter:THREE.NearestFilter,
                magFilter:THREE.NearestFilter,
                wrapS:THREE.ClampToEdgeWrapping,
                wrapT:THREE.ClampToEdgeWrapping,
                format:THREE.RGBAFormat,
                stencilBuffer:false,
                depthBuffer:false,
                needsUpdate:true,
                type:THREE.FloatType
            };

            //------------------------------------------
            // Main init and loop
            //------------------------------------------
            start();
            update();

            //------------------------------------------
            // Initialization
            //------------------------------------------
            function start() 
            {   

                //setup scenes          
                sceneOutput = new THREE.Scene();
                sceneFeedback = new THREE.Scene();
                sceneStart = new THREE.Scene();

                //setup renderer
                renderer = new THREE.WebGLRenderer({ precision:"highp"});
                renderer.setSize( window.innerWidth, window.innerHeight );
                renderer.setClearColor(0x808080);
                renderer.autoClear = false;
                document.body.appendChild( renderer.domElement );   

                // create buffers
                feedbackTexture = new THREE.WebGLRenderTarget( loopRes.x, loopRes.y, renderTargetNearestFloatParams );              
                feedbackTexture2 = new THREE.WebGLRenderTarget( loopRes.x, loopRes.y, renderTargetNearestFloatParams ); 

                // load a texture, set wrap mode
                var loadTexture = THREE.ImageUtils.loadTexture( "textures/tes2t.jpg" );
                loadTexture.wrapS = THREE.ClampToEdgeWrapping;
                loadTexture.wrapT = THREE.ClampToEdgeWrapping;
                loadTexture.minFilter = THREE.NearestFilter;
                loadTexture.magFilter = THREE.NearestFilter;
                loadTexture.format = THREE.RGBAFormat;
                loadTexture.type = THREE.FloatType;

                // Setup algorithm camera
                cameraLoop = new THREE.OrthographicCamera( loopRes.x / - 2, loopRes.x / 2, loopRes.y / 2, loopRes.y / - 2, -10000, 10000 );

                // Setup sceneOutput camera
                cameraOutput = new THREE.PerspectiveCamera( 60, window.innerWidth/window.innerHeight, 1, 10000 );
                cameraOutput.position.z = 300;

                // feedback shader
                feedbackUniforms = {
                    texture: { type: "t", value: feedbackTexture2 },
                    texture2: { type: "t", value: loadTexture },
                    onOpen: { type: "f", value: 0.0 },
                };
                feedbackMat = new THREE.ShaderMaterial({
                    uniforms: feedbackUniforms,
                    vertexShader: document.getElementById( 'vs_output' ).textContent,
                    fragmentShader: document.getElementById( 'fs_feedback' ).textContent
                });             
                var feedbackGeo = new THREE.PlaneBufferGeometry( loopRes.x, loopRes.y );
                feedbackQuad = new THREE.Mesh( feedbackGeo, feedbackMat );
                feedbackQuad.position.z = -100;
                sceneFeedback.add( feedbackQuad );

                // output shader
                mainUniforms = {
                    fb2output: { type: "t", value: feedbackTexture2 },                  
                };              
                screenMat = new THREE.ShaderMaterial({
                    uniforms: mainUniforms,
                    vertexShader: document.getElementById( 'vs_output' ).textContent,
                    fragmentShader: document.getElementById( 'fs_output' ).textContent,
                });
                var screenGeo = new THREE.PlaneBufferGeometry( outputRes.x, outputRes.y );              
                sceneQuad = new THREE.Mesh( screenGeo , screenMat );
                sceneQuad.position.z = -200;
                sceneOutput.add( sceneQuad );               

                            // init shader
                startUniforms = {
                    texture: { type: "t", value: loadTexture },                 
                };              
                startMat = new THREE.ShaderMaterial({
                    uniforms: startUniforms,
                    vertexShader: document.getElementById( 'vs_output' ).textContent,
                    fragmentShader: document.getElementById( 'fs_start' ).textContent,
                });
                var startGeo = new THREE.PlaneBufferGeometry(  loopRes.x, loopRes.y );              
                startQuad = new THREE.Mesh( startGeo , startMat );
                startQuad.position.z = -100;
                sceneStart.add( startQuad );                
            }           


            //------------------------------------------
            // Main loop
            //------------------------------------------
            function update() 
            {
                requestAnimationFrame( update );
                console.debug(doLoad.toString());
                render();               
            }

            //------------------------------------------
            // Main rendering
            //------------------------------------------
            function render() 
            {
                renderer.clear();

                if (doLoad < 1.0){

                    renderer.render( sceneStart, cameraLoop, feedbackTexture2);

                    doLoad = 1.0;

                } else {

                renderer.render( sceneFeedback, cameraLoop, feedbackTexture);

                var a = feedbackTexture2;
                feedbackTexture2 = feedbackTexture;
                feedbackTexture = a;
                feedbackUniforms.texture.value = feedbackTexture2;
                }

                renderer.render( sceneOutput, cameraOutput );
    //          feedbackUniforms.onOpen.value += 0.5;
            }

        </script>
    </body>
</html>  

正如你可以在渲染功能看到我试图使在第1帧和sceneFeedback sceneStart之后(if / else语句块)。 不幸的是,这是行不通的。 我已经试过各种东西,也做了开关在着色器本身的质地开始(见注释代码),但没有运气。 我发现,当我改线

doLoad = 1.0;

doLoad +=0.4;

或低于0.5任何它会奏效。 所以我的理解是必须写3次到我的反馈缓冲区中,直到正常的循环可以从那里工作....但是为什么呢?

写入在第一帧的反馈信息的纹理也不起作用,因为你可能会建议....

不幸的是,使其为3张是没有我的解决方案,因为它会打破我的参与实际着色器之一,同时也带来了这是所谓的方式要复杂得多装载在第一帧的图片来解决其他问题.....

在阿里纳斯,我怎么能调试three.js所应用的第一个框架? 我知道WebGL的检查,但如果我的帧率有慢下来,然后刷新播放设置都恢复正常......有什么建议?

非常感谢你!

Answer 1:

我敢肯定,你需要等待你开始渲染之前的图像加载。 图片载入异步让你的前几帧不会有尚未加载纹理。

它看起来像你使用THREE.ImageUtils.loadTexture 。 根据该文档 loadTexture需要4个参数( .loadTexture (url, mapping, onLoad, onError) )的第三一个是回调被加载图像时。

你可能不希望渲染,直到图像加载。 在你的代码的开头你有

start();
update();   // delete this line

删除更新行,那么你改变loadTexture线

// load a texture, set wrap mode
var loadTexture = THREE.ImageUtils.loadTexture( 
    "textures/tes2t.jpg", undefined, update );

这样, update图像时完成加载并开始渲染将被调用。



文章来源: loading a file texture in FIRST frame of a feedback loop with swapped buffers in three.js