[英]Three.js shader and window resize
我正在實現Three.js着色器,並且包含ThreeX作為在調整窗口大小時調整場景大小的方法,以處理更改的瀏覽器窗口大小和更改的移動方向。
當窗口寬度變小時,它就像一個飾物。 但是,當窗口的大小(寬度或高度)大於第一次加載時,場景將不會擴展以填充新的空間。 此外,當將窗口的高度調整為較小時,調整大小將完全失敗。 當窗口的高度縮小時,計算出的鼠標位置不會更改為新的地址高度,而是會與實際的鼠標位置錯位。 (請參見屏幕截圖)
救命! 尋找我哪里出錯了。
更新:問題在JSFIDDLE中重現單擊以激活着色器並調整小提琴的大小以查看調整大小的問題。
圖像01:顯示窗口的大小調整得更大,並且着色器沒有擴展到匹配
圖片02:顯示的窗口具有較小的調整高度,並且鼠標/鼠標坐標不匹配(鼠標為白點,色環應在其右側)
<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.