问题:
我试图从渲染目标中读取像素值,但这些值都以零的形式返回。我做错了什么,或者我使用的版本是否已破坏此功能?
我有什么:
一个重要的注意事项是我使用r76卡住了。我知道,我知道,这也让我感到不安。
以下代码实际上就是我所拥有的一切。只需点击" GO"右上角的按钮,它会产生一个警告,说明整个渲染目标缓冲区是否为零。
我尝试过的事情:
我尝试使用最新的three.js(r86),完全相同的代码正常工作。
我还尝试通过将我的render
函数安排到渲染到画布(工作正常)或渲染目标(仍为全零)来解决任何异步问题,基于我在外面设置的标志渲染循环。
function render() {
light.position.copy(camera.position);
if(doRenderTarget){
toRenderTarget();
doRenderTarget = false;
}
else{
renderer.clear();
renderer.render(scene, camera);
}
controls.update();
}
代码:
使用r76:
var hostDiv, scene, renderer, camera, controls, light;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
var target = new THREE.WebGLRenderTarget();
function toRenderTarget() {
var size = renderer.getSize();
var w = WIDTH;
var h = HEIGHT;
target.setSize(w, h);
renderer.clearTarget(target, true, true, true);
renderer.render(scene, camera, target);
var renderTargetPixelBuffer = new Uint8Array(w * h * 4);
renderer.readRenderTargetPixels(target, 0, 0, w, h, renderTargetPixelBuffer);
var allZeroes = renderTargetPixelBuffer.reduce(function(prev, item) {
return prev && (item === 0.0);
}, true);
if (allZeroes) {
alert("All zeroes!");
} else {
alert("Never mind, the data is okay.");
}
}
document.getElementById("go").addEventListener("click", toRenderTarget);
function init() {
hostDiv = document.createElement('div');
hostDiv.setAttribute('id', 'host');
document.body.appendChild(hostDiv);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(WIDTH, HEIGHT);
hostDiv.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 500;
controls = new THREE.TrackballControls(camera, renderer.domElement);
//controls.rotateSpeed = 5.0;
controls.dynamicDampingFactor = 0.5;
controls.handleResize();
light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);
scene = new THREE.Scene();
scene.add(camera);
scene.add(light);
var cube = new THREE.Mesh(
new THREE.BoxBufferGeometry(50, 50, 50),
new THREE.MeshLambertMaterial({
color: "red"
})
);
scene.add(cube);
animate();
}
function render() {
light.position.copy(camera.position);
renderer.render(scene, camera);
controls.update();
}
function animate() {
requestAnimationFrame(animate);
render();
}
init();
window.onresize = function() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}

body {
position: relative;
}

<!-- r76 -->
<script src="https://cdn.rawgit.com/mrdoob/three.js/6400f2c9b6ee58e01c005a66f00c7cd1113752aa/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/6400f2c9b6ee58e01c005a66f00c7cd1113752aa/examples/js/controls/TrackballControls.js"></script>
<input type="button" id="go" value="GO" style="position: absolute; top: 0; right: 0" ; />
&#13;
使用r86:
var hostDiv, scene, renderer, camera, controls, light;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
var target = new THREE.WebGLRenderTarget();
function toRenderTarget() {
var size = renderer.getSize();
var w = WIDTH;
var h = HEIGHT;
target.setSize(w, h);
renderer.clearTarget(target, true, true, true);
renderer.render(scene, camera, target);
var renderTargetPixelBuffer = new Uint8Array(w * h * 4);
renderer.readRenderTargetPixels(target, 0, 0, w, h, renderTargetPixelBuffer);
var allZeroes = renderTargetPixelBuffer.reduce(function(prev, item) {
return prev && (item === 0.0);
}, true);
if (allZeroes) {
alert("All zeroes!");
} else {
alert("Never mind, the data is okay.");
}
}
document.getElementById("go").addEventListener("click", toRenderTarget);
function init() {
hostDiv = document.createElement('div');
hostDiv.setAttribute('id', 'host');
document.body.appendChild(hostDiv);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(WIDTH, HEIGHT);
hostDiv.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 500;
controls = new THREE.TrackballControls(camera, renderer.domElement);
//controls.rotateSpeed = 5.0;
controls.dynamicDampingFactor = 0.5;
controls.handleResize();
light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);
scene = new THREE.Scene();
scene.add(camera);
scene.add(light);
var cube = new THREE.Mesh(
new THREE.BoxBufferGeometry(50, 50, 50),
new THREE.MeshLambertMaterial({
color: "red"
})
);
scene.add(cube);
animate();
}
function render() {
light.position.copy(camera.position);
renderer.render(scene, camera);
controls.update();
}
function animate() {
requestAnimationFrame(animate);
render();
}
init();
window.onresize = function() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
&#13;
body {
position: relative;
}
&#13;
<!-- r86 -->
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
<input type="button" id="go" value="GO" style="position: absolute; top: 0; right: 0" ; />
&#13;
使用r76并将渲染延迟到下一个动画循环:
var hostDiv, scene, renderer, camera, controls, light;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
var target = new THREE.WebGLRenderTarget();
var doRenderTarget = false;
function go(){
doRenderTarget = true;
}
function toRenderTarget() {
var size = renderer.getSize();
var w = WIDTH;
var h = HEIGHT;
target.setSize(w, h);
renderer.clearTarget(target, true, true, true);
renderer.render(scene, camera, target);
var renderTargetPixelBuffer = new Uint8Array(w * h * 4);
renderer.readRenderTargetPixels(target, 0, 0, w, h, renderTargetPixelBuffer);
var allZeroes = renderTargetPixelBuffer.reduce(function(prev, item) {
return prev && (item === 0.0);
}, true);
if (allZeroes) {
alert("All zeroes!");
} else {
alert("Never mind, the data is okay.");
}
}
document.getElementById("go").addEventListener("click", toRenderTarget);
function init() {
hostDiv = document.createElement('div');
hostDiv.setAttribute('id', 'host');
document.body.appendChild(hostDiv);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(WIDTH, HEIGHT);
hostDiv.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 500;
controls = new THREE.TrackballControls(camera, renderer.domElement);
//controls.rotateSpeed = 5.0;
controls.dynamicDampingFactor = 0.5;
controls.handleResize();
light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);
scene = new THREE.Scene();
scene.add(camera);
scene.add(light);
var cube = new THREE.Mesh(
new THREE.BoxBufferGeometry(50, 50, 50),
new THREE.MeshLambertMaterial({
color: "red"
})
);
scene.add(cube);
animate();
}
function render() {
light.position.copy(camera.position);
if(doRenderTarget){
toRenderTarget();
}
else{
renderer.render(scene, camera);
}
controls.update();
}
function animate() {
requestAnimationFrame(animate);
render();
}
init();
window.onresize = function() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}
&#13;
body {
position: relative;
}
&#13;
<!-- r76 -->
<script src="https://cdn.rawgit.com/mrdoob/three.js/6400f2c9b6ee58e01c005a66f00c7cd1113752aa/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/6400f2c9b6ee58e01c005a66f00c7cd1113752aa/examples/js/controls/TrackballControls.js"></script>
<input type="button" id="go" value="GO" style="position: absolute; top: 0; right: 0" ; />
&#13;
随访:
这里的关键似乎直接从GL上下文中读取,但问题的根本原因要简单得多。我想知道readRenderTargetPixels
如何读取它有什么问题,因为它实际上调用了相同的GL方法。它一直在我面前。阻止_gl.readPixels
来电:
R76:
if ( ( x > 0 && x <= ( renderTarget.width - width ) ) && ( y > 0 && y <= ( renderTarget.height - height ) ) ) {
R86:
if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
r76
中的函数不允许x
或y
为0
,我将两者都设置为零。 r86
函数允许两者都为0
,这就是它工作的原因。
由于r76
超级老,我不打算提交错误报告或修复。感谢@evil professeur帮助突出问题!
答案 0 :(得分:0)
问题是,当您调用该函数时,缓冲区将被清除。你要做的就是在渲染后立即调用它。最简单的方法是在click上设置一个标志,通知渲染函数你想要检索像素,并在渲染后立即调用toRenderTarget。变化看起来像那样:
var getRenderedPixels = false;
function setAwaitFlag() {
getRenderedPixels = true;
}
document.getElementById("go").addEventListener("click", setAwaitFlag);
然后在渲染功能
中function render() {
light.position.copy(camera.position);
renderer.render(scene, camera);
if (getRenderedPixels) {
toRenderTarget();
getRenderedPixels = false;
}
controls.update();
}
除此之外,我使用gl.ReadPixels而不是readRenderTargetPixels,然后单击它。这是改变:
var gl = renderer.getContext(),
pixels = new Uint8Array(w * h * 4);
gl.readPixels(0,0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, renderTargetPixelBuffer);
但是,您应该缩小读取的像素数以提高性能。
我也被困了一会儿。