簡體   English   中英

Three.js着色器和窗口調整大小

[英]Three.js shader and window resize

我正在實現Three.js着色器,並且包含ThreeX作為在調整窗口大小時調整場景大小的方法,以處理更改的瀏覽器窗口大小和更改的移動方向。

當窗口寬度變小時,它就像一個飾物。 但是,當窗口的大小(寬度或高度)大於第一次加載時,場景將不會擴展以填充新的空間。 此外,當將窗口的高度調整為較小時,調整大小將完全失敗。 當窗口的高度縮小時,計算出的鼠標位置不會更改為新的地址高度,而是會與實際的鼠標位置錯位。 (請參見屏幕截圖)

救命! 尋找我哪里出錯了。

更新:問題在JSFIDDLE重現單擊以激活着色器並調整小提琴的大小以查看調整大小的問題。

圖像01:顯示窗口的大小調整得更大,並且着色器沒有擴展到匹配

圖片02:顯示的窗口具有較小的調整高度,並且鼠標/鼠標坐標不匹配(鼠標為白點,色環應在其右側)

圖片01 Image02

<script>
        var scene;
        var camera;
        var renderer;

        function scene_setup(){

            scene = new THREE.Scene();
  scene.background = new THREE.Color( 0xffffff );
            var width = window.innerWidth;
            var height = window.innerHeight;

            camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
            camera.position.z = 2;
 THREEx.WindowResize(renderer, camera);
            renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.getElementById("curse").appendChild( renderer.domElement );

        }

        var bufferScene;
        var textureA;
        var textureB;
        var bufferMaterial;
        var plane;
        var bufferObject;
        var finalMaterial;
        var quad;

        function buffer_texture_setup(){

            bufferScene = new THREE.Scene();

            textureA = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter});
            textureB = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter} );

            bufferMaterial = new THREE.ShaderMaterial( {
                uniforms: {
                 bufferTexture: { type: "t", value: textureA },
                 res : {type: 'v2',value:new THREE.Vector2(window.innerWidth,window.innerHeight)},//Keeps the resolution
                 smokeSource: {type:"v3",value:new THREE.Vector3(0,0,0)},
                 time: {type:"f",value:Math.random()*Math.PI*2+Math.PI}
                },
                fragmentShader: document.getElementById( 'fragS' ).innerHTML
            } );
            plane = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
            bufferObject = new THREE.Mesh( plane, bufferMaterial );
            bufferScene.add(bufferObject);

            //Draw textureB to screen 
            finalMaterial =  new THREE.MeshBasicMaterial({map: textureB});
            quad = new THREE.Mesh( plane, finalMaterial );
            scene.add(quad);
        }


        scene_setup();


        buffer_texture_setup();




        var mouseDown = false;
        function UpdateMousePosition(X,Y){
            var mouseX = X;
            var mouseY = window.innerHeight - Y;
            bufferMaterial.uniforms.smokeSource.value.x = mouseX;
            bufferMaterial.uniforms.smokeSource.value.y = mouseY;
        }
        document.onmousemove = function(event){
            UpdateMousePosition(event.clientX,event.clientY)
        }

        document.onmousedown = function(event){
            mouseDown = true;
            bufferMaterial.uniforms.smokeSource.value.z = 0;
        }
        document.onmouseup = function(event){
            mouseDown = false;
            bufferMaterial.uniforms.smokeSource.value.z = 0.02;
        }

        function render() {

          requestAnimationFrame( render );


          renderer.render(bufferScene,camera,textureB,true);

          var t = textureA;
          textureA = textureB;
          textureB = t;
          quad.material.map = textureB;
          bufferMaterial.uniforms.bufferTexture.value = textureA;


          bufferMaterial.uniforms.time.value += 0.01;


          renderer.render( scene, camera );
        }
        render();

//着色器

      </script>  
<script id="fragS">
        uniform vec2 res;//The width and height of our screen
        uniform sampler2D bufferTexture;//Our input texture
        uniform vec3 smokeSource;//The x,y are the posiiton. The z is the power/density
        uniform float time;
        void main() {
            vec2 pixel = gl_FragCoord.xy / res.xy;
            //Get the distance of the current pixel from the smoke source
            float dist = distance(smokeSource.xy,gl_FragCoord.xy);
            //Get the color of the current pixel
            gl_FragColor = texture2D( bufferTexture, pixel );

            //Generate smoke when mouse is pressed
            gl_FragColor.rgb += smokeSource.z * max(100.0-dist,0.02);


            //Smoke diffuse
            float xPixel = 1.0/res.x;//The size of a single pixel
            float yPixel = 4.0/res.y;
            vec4 rightColor = texture2D(bufferTexture,vec2(pixel.x+xPixel,pixel.y));
            vec4 leftColor = texture2D(bufferTexture,vec2(pixel.x-xPixel,pixel.y));
            vec4 upColor = texture2D(bufferTexture,vec2(pixel.x,pixel.y+yPixel));
            vec4 downColor = texture2D(bufferTexture,vec2(pixel.x,pixel.y-yPixel));
            //Handle the bottom boundary
            if(pixel.y <= yPixel){
                downColor.rgb = vec3(0.0);
            }
            //Diffuse equation
            float factor = 1.0 * 0.020 * (leftColor.r + rightColor.r + downColor.r * 3.0 + upColor.r - 6.0 * gl_FragColor.r);

            //Account for low precision of texels
            float minimum = 0.003;
            if(factor >= -minimum && factor < 0.0) factor = -minimum;

            gl_FragColor.rgb += factor;

         }
    </script>

如果在jsfiddle中,則調試起來會更容易。 您創建一個世界尺寸的平面,並將世界尺寸與屏幕尺寸進行匹配。 即1個世界單位代表一個像素。

plane = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );

窗口大小更改時,相機大小也會更改。 IE瀏覽器。 您調用一次:

var width = window.innerWidth;
var height = window.innerHeight;

camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );

然后,讓您的第三方事物來管理它。 發生這種情況時,這些width值會發生變化。 您的飛機保持不變。

繪制全屏四邊形的簡單解決方法可能是這樣的:

new THREE.PlaneBufferGeometry(2,2,1,1)

然后是頂點着色器

void main(){
  gl_Posiiton = vec4(position.xy,0.,1.);
}

否則,相同的想法適用於節點圖:

new PlaneBufferGeometry(1,1,1,1)

onResize(){
   planeMesh.scale.set(width,height,1)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM