使用WebGL API,有没有办法计算给定画布中渲染的顶点数?我已经看到一些试图完成这项任务的工具,但有些工具却给出了奇怪的结果(例如,Three.js'renderer.info.render
报告我的场景有10,134.3个三角形)。
使用原始WebGL API计算渲染顶点数(以及理想情况下,点和线)的任何帮助都将非常感激。
答案 0 :(得分:4)
WebGL无法为您执行此操作,但您可以添加自己的扩充。
最明显的方法是跟踪自己的使用情况。而不是致电commentIdList.map(commentId => ({ [commentId]: comments[commentId] })
致电gl.drawXXX
并自行跟踪这些值。
您还可以扩充WebGL上下文。实施例
functionThatTracksDrawingCountsXXX

// copy this part into a file like `augmented-webgl.js`
// and include it in your page
(function() {
// NOTE: since WebGL constants are um, constant
// we could statically init this.
let primMap;
function addCount(ctx, type, count) {
const ctxInfo = ctx.info;
const primInfo = primMap[type];
ctxInfo.vertCount += count;
ctxInfo.primCount[primInfo.ndx] += primInfo.fn(count);
}
WebGLRenderingContext.prototype.drawArrays = (function(oldFn) {
return function(type, offset, count) {
addCount(this, type, count);
oldFn.call(this, type, offset, count);
};
}(WebGLRenderingContext.prototype.drawArrays));
WebGLRenderingContext.prototype.drawElements = (function(oldFn) {
return function(type, count, indexType, offset) {
addCount(this, type, count);
oldFn.call(this, type, count, indexType, offset);
};
}(WebGLRenderingContext.prototype.drawElements));
HTMLCanvasElement.prototype.getContext = (function(oldFn) {
return function(type, ...args) {
const ctx = oldFn.call(this, type, args);
if (ctx && type === "webgl") {
if (!primMap) {
primMap = {};
primMap[ctx.POINTS] = { ndx: 0, fn: count => count, };
primMap[ctx.LINE_LOOP] = { ndx: 1, fn: count => count, };
primMap[ctx.LINE_STRIP]= { ndx: 1, fn: count => count - 1, };
primMap[ctx.LINES] = { ndx: 1, fn: count => count / 2 | 0, };
primMap[ctx.TRIANGLE_STRIP] = { ndx: 2, fn: count => count - 2, };
primMap[ctx.TRIANGLE_FAN] = { ndx: 2, fn: count => count - 2, };
primMap[ctx.TRIANGLES] = { ndx: 2, fn: count => count / 3 | 0, };
};
ctx.info = {
vertCount: 0,
primCount: [0, 0, 0],
};
}
return ctx;
}
}(HTMLCanvasElement.prototype.getContext));
}());
// ---- cut above ----
const $ = document.querySelector.bind(document);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({canvas: $('canvas')});
const geometry = new THREE.BoxGeometry(1, 1, 1);
const items = [];
for (let i = 0; i < 50; ++i) {
let item;
switch(rand(0, 3) | 0) {
case 0:
case 1:
const material = new THREE.MeshBasicMaterial({
color: rand(0xFFFFFF) | 0,
wireframe: rand(0, 3) > 2,
});
item = new THREE.Mesh(geometry, material);
break;
case 2:
const pmat = new THREE.PointsMaterial({
color: rand(0xFFFFFF) | 0,
});
item = new THREE.Points(geometry, pmat);
break;
default:
throw "oops";
}
item.position.x = rand(-10, 10);
item.position.y = rand(-10, 10);
item.position.z = rand( 0, -50);
scene.add(item);
items.push(item);
}
camera.position.z = 5;
const countElem = $('#count');
function render(time) {
time *= 0.001;
resize();
// animate the items
items.forEach((items, ndx) => {
items.rotation.x = time * 1.2 + ndx * 0.01;
items.rotation.y = time * 1.1;
});
// turn on/off a random items
items[rand(items.length) | 0].visible = Math.random() > .5;
renderer.render(scene, camera);
// get the current counts
const info = renderer.context.info;
countElem.textContent = ` VERTS: ${info.vertCount}
POINTS: ${info.primCount[0]}
LINES: ${info.primCount[1]}
TRIANGLES: ${info.primCount[2]}`;
// zero out the count
renderer.context.info.vertCount = 0;
renderer.context.info.primCount = [0, 0, 0];
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function rand(min, max) {
if (max === undefined) {
max = min;
min = 0;
}
return Math.random() * (max - min) + min;
}
function resize() {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
if (canvas.width !== width || canvas.height !== height) {
renderer.setSize(width, height, false);
camera.aspectRatio = width / height;
camera.updateProjectionMatrix();
}
}
&#13;
body { border: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
#ui { position: absolute; left: 1em; top: 1em; background: rgba(0,0,0,.5); color: white; padding: .5em; width: 10em; }
&#13;
当然,您可能希望添加对drawArraysInstanced等的支持...以及对WebGL2的支持。
答案 1 :(得分:1)
我们从renderer.info.render
中删除了已处理顶点的数量,因为重要的测量值是数量或渲染的图元(所以三角形,点,线)。有关更多信息,请阅读https://github.com/mrdoob/three.js/pull/13404以及相关问题/ PR。如果您仍想知道处理了多少个顶点,则需要手动计算。 WebGL无法为您做到这一点。