【发布时间】:2019-03-01 09:39:31
【问题描述】:
我正在实现 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>
【问题讨论】:
-
我没有看到你的着色器,也没有你的调整大小逻辑(什么是三倍?)但是你有没有更新你的
uniforms.res.value? -
@pailhead 实际的着色器视觉效果不是问题,所以我省略了它以免混淆这一点。 ThreeX 是一行 three.js 代码,它告诉渲染器和相机随窗口调整大小。不太确定在这种情况下更新 uniforms.res.value 对我有什么作用。如果您不介意解释……我将不胜感激!
-
如果没有着色器,很难判断着色器应该做什么 :) 我刚刚注意到一个名为
res的东西,并注意到您确实在其上设置了窗口值。这些值会发生变化。当它们发生变化时,您是否更新您的res.value向量?如果你可以删除三倍,或者修改它,尝试添加另一行,基本上只是bufferMaterial.uniforms.res.value.set(window.innerWidth,window.innerHeight) -
为了进一步说明,图像的位置可以由您的顶点着色器或片段着色器控制。关于你是如何到达那里的,有无数种排列。根据这段代码,我猜
res可能与它有关,使用着色器我可以准确地告诉你发生了什么。 -
如果你只有红蓝等,我也会换掉这些渐变和混合,以便更清楚地了解发生了什么,几何结束等。
标签: javascript three.js window-resize