gpt4 book ai didi

javascript - 三.js内存管理着色器 Material

转载 作者:行者123 更新时间:2023-11-28 04:33:28 25 4
gpt4 key购买 nike

我正在尝试创建文本标签。我需要使用着色器 Material 来在渲染过程中更好地控制标签。

我注意到即使我清理了旧标签,内存仍在不断增加。

我创建了一个 jsfiddle 示例,它与:https://threejs.org/examples/#webgl_test_memory 没有什么不同。

以下代码使用 Canvas 对象生成纹理,其中包含要描绘为标签的文本:

请小心,这些计算量很大,并且会使选项卡非常无响应。

var container;

var camera, scene, renderer;

var labels;

var canvas;

init();
animate();

function init() {

container = document.createElement( 'div' );
document.body.appendChild( container );

camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 200;

scene = new THREE.Scene();

renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

labels = new THREE.Object3D();

canvas = document.createElement('canvas');
var context = canvas.getContext('2d');

// get text metrics
var fontface = 'Arial';
var fontSize = 60;
context.font = fontSize + "px " + fontface;

var width = context.measureText(text).width;

// add text
var text = 'abcdef';
canvas.width = width;
canvas.height = fontSize*1.3;
context.textAlign = "center";
context.font = fontSize + "px " + fontface;
context.fillStyle = "white";
context.fillText(text, canvas.width / 2, canvas.height / 2);
}

function createLabels() {
for(var i = 0; i < 10000 ; i++) {
createTextMesh();
}

scene.add( labels );
}

function createTextMesh() {
// canvas contents will be used for a texture
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;

var uniforms = {
text: {
type: 't',
value: texture
}
};

var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: document.getElementById( 'vertex-shader' ).textContent,
fragmentShader: document.getElementById( 'fragment-shader' ).textContent
} );

var geometry = new THREE.PlaneBufferGeometry(15, 15);

var label = new THREE.Mesh( geometry, material );

labels.add(label);
}

function clearLabels() {
for(var i = 0; i < labels.children.length; i++) {
var label = labels.children[i];

if(label.material.uniforms) {
label.material.uniforms.text.value.dispose();
}
label.material.dispose();
label.geometry.dispose();

labels.remove(label);
}

scene.remove( labels );
}

function animate() {
requestAnimationFrame( animate );
render();
}

function render() {
// build GL objects
createLabels();

renderer.render( scene, camera );

// clean up
clearLabels();
}
body {
margin:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script>					
<script id="fragment-shader" type="x-shader/x-fragment">
uniform sampler2D text;

varying vec2 vUv;

void main() {
vec4 finalColor = texture2D(text, vUv);
gl_FragColor = finalColor;
}
</script>
<script id="vertex-shader" type="x-shader/x-fragment">
varying vec2 vUv;

void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<canvas></canvas>

您可以使用 chrome 开发工具来评估感知内存利用率的增加。

我建议使用 Windows 自己的任务管理器之类的东西来查看内存的增加。

您可以降低标签创建速度,尽管这自然意味着选项卡会花费更长的时间来耗尽内存。

我是否错误地进行了资源清理?

干杯

最佳答案

不要每次tick创建1000次新的网格,而是将它们集中起来。不要创建 1000 个全部位于同一平面的几何图形。这可能是这里最大的罪魁祸首。只创建一个,然后将其传递给网格。纹理,我对此不太确定。我认为您不应该从 Canvas 上下文创建新纹理,创建一次并更新 Canvas 。

这将随着更改而消失,但值得注意的是,为了提高性能,您也希望避免在循环中创建制服对象。

编辑

你确实创造了很多东西。标签的宽度为 263,如果要信任 3 的控制台日志,则将其大小调整为 256x64。因此,您最终会得到 480mb 的数据,但如果使用 alpha channel ,数据可能会达到 600mb。我假设你的演示甚至从未到达处置部分。它只是让我的浏览器崩溃了。

Three 还提示纹理是 NPOT,因此它尝试写出一万条控制台日志。

关于javascript - 三.js内存管理着色器 Material ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44432537/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com