debugging - loading a file texture in FIRST frame of a feedback loop with swapped buffers in three.js -
i'm working on website in three.js using several feedback shader loops (texture pingpong).
when visits site, loop should continue point (depending on when he/she visits). achieve intend load picture (eg jpeg) server in first frame, render pingpong buffers , continue normal feedback loop frame 2 onwards.
here's stripped down version of problem, feedback function add small value color of pixel in previous frame.
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>feedbacktest</title> <style>canvas { width: 100%; height: 100%; }</style> </head> <body> <!-- main 3 includes --> <script src="js/three.min.js"></script> <script src="js/detector.js"></script> <!--------------------> <!-- shaders --> <!--------------------> <!-- no change vertex shader. used 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 , 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 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 = feedbacktexture2; feedbacktexture2 = feedbacktexture; feedbacktexture = a; feedbackuniforms.texture.value = feedbacktexture2; } renderer.render( sceneoutput, cameraoutput ); // feedbackuniforms.onopen.value += 0.5; } </script> </body> </html>
as can see in render function i'm trying render scenestart in frame 1 , scenefeedback afterwards (if/else block). unfortunately, doesn't work. i've tried kinds of stuff, doing switch start texture in shader (see commented code), no luck. found out when change line
doload = 1.0;
to
doload +=0.4;
or below 0.5 work. understand has write 3 times feedback buffer until normal loop can work there....but why?
writing both feedback textures in first frame doesn't work, might suggest....
unfortunately, rendering 3 frames no solution me, break 1 of actual shaders involved , brings other issues supposedly way more complicated solve loading picture in first frame.....
on sidenote, how can debug first frames of three.js app? i'm aware of webgl inspector if slow down framerate there , refresh playback settings normal...any suggestions?
thank much!
i'm pretty sure need wait image load before start rendering. images load async first few frames not have texture loaded yet.
it looks you're using three.imageutils.loadtexture
. according docs loadtexture
takes 4 arguments (.loadtexture (url, mapping, onload, onerror)
) 3rd 1 callback when image loaded.
you don't want render until image loaded. @ beginning of code have
start(); update(); // delete line
delete update line, change loadtexture
line to
// load texture, set wrap mode var loadtexture = three.imageutils.loadtexture( "textures/tes2t.jpg", undefined, update );
that way update
called when image finished loading , start rendering.
Comments
Post a Comment