質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CPU

CPUは、コンピュータの中心となる処理装置(プロセッサ)で中央処理装置とも呼ばれています。プログラム演算や数値計算、その他の演算ユニットをコントロール。スマホやPCによって内蔵されているCPUは異なりますが、処理性能が早いほど良いとされています。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

WebGL

WebGL(ウェブジーエル)は、ウェブブラウザで 3次元コンピュータグラフィックスを表示させるための標準仕様です。

Q&A

解決済

2回答

5287閲覧

WebGLでアニメーションするとメモリリークする

退会済みユーザー

退会済みユーザー

総合スコア0

CPU

CPUは、コンピュータの中心となる処理装置(プロセッサ)で中央処理装置とも呼ばれています。プログラム演算や数値計算、その他の演算ユニットをコントロール。スマホやPCによって内蔵されているCPUは異なりますが、処理性能が早いほど良いとされています。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

WebGL

WebGL(ウェブジーエル)は、ウェブブラウザで 3次元コンピュータグラフィックスを表示させるための標準仕様です。

0グッド

0クリップ

投稿2019/02/04 13:33

Canvasに対してシェーダープログラムの処理を実行するクラスを自作し、これを利用してアニメーションを実装しようと考えています。

HTML

1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="utf-8"> 5</head> 6<body> 7 <canvas id="sheet"></canvas> 8 <input type="file" id="image"> 9 <script> 10 class Filter{ 11 constructor(shader){ 12 this.canvas=document.createElement("canvas"); 13 this.canvas.width=600; 14 this.canvas.height=600; 15 this.gl=this.canvas.getContext("webgl"); 16 this.gl.viewport(0,0,600,600); 17 this.gl.clearColor(0,0,0,1); 18 let prog=this.gl.createProgram(); 19 let vs=this.gl.createShader(this.gl.VERTEX_SHADER); 20 this.gl.shaderSource(vs,` 21 attribute vec2 position; 22 varying vec2 vTexCoord; 23 24 void main(){ 25 vTexCoord = vec2((position.x + 1.0) / 2.0,(- position.y + 1.0) / 2.0); 26 gl_Position = vec4(position,0.0,1.0); 27 } 28 `); 29 this.gl.compileShader(vs); 30 if (!this.gl.getShaderParameter(vs, this.gl.COMPILE_STATUS)) { 31 console.log(this.gl.getShaderInfoLog(vs)); 32 } 33 this.gl.attachShader(prog,vs); 34 let fs=this.gl.createShader(this.gl.FRAGMENT_SHADER); 35 this.gl.shaderSource(fs,shader); 36 this.gl.compileShader(fs); 37 this.gl.attachShader(prog,fs); 38 this.gl.linkProgram(prog); 39 if (!this.gl.getProgramParameter(prog, this.gl.LINK_STATUS)) { 40 console.log(this.gl.getProgramInfoLog(prog)); 41 } 42 this.prog=prog; 43 } 44 draw(canvas,option={}){ 45 this.gl.useProgram(this.prog); 46 this.gl.clear(this.gl.COLOR_BUFFER_BIT); 47 let vertexPosAttr=this.gl.getAttribLocation(this.prog,"position"); 48 let vertexBuf=this.gl.createBuffer(); 49 let texture=this.gl.createTexture(); 50 if(option.uniform){ 51 Object.keys(option.uniform).forEach((k)=>{ 52 let l=this.gl.getUniformLocation(this.prog,k); 53 switch(option.uniform[k].length){ 54 case 1: 55 this.gl.uniform1f(l,option.uniform[k]); 56 break; 57 case 2: 58 this.gl.uniform2f(l,option.uniform[k]); 59 break; 60 case 3: 61 this.gl.uniform3f(l,option.uniform[k]); 62 break; 63 case 4: 64 this.gl.uniform4f(l,option.uniform[k]); 65 break; 66 } 67 }); 68 } 69 this.gl.bindTexture(this.gl.TEXTURE_2D,texture); 70 71 this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,canvas); 72 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); 73 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); 74 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); 75 this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); 76 this.gl.bindBuffer(this.gl.ARRAY_BUFFER,vertexBuf); 77 this.gl.bufferData(this.gl.ARRAY_BUFFER,new Float32Array([ 78 -1.0,1.0,0.0, 79 1.0,1.0,0.0, 80 -1.0,-1.0,0.0, 81 1.0,-1.0,0.0 82 ]),this.gl.STATIC_DRAW); 83 this.gl.enableVertexAttribArray(vertexPosAttr); 84 this.gl.vertexAttribPointer(vertexPosAttr,3,this.gl.FLOAT,false,0,0); 85 this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4); 86 this.gl.flush(); 87 this.gl.bindTexture(this.gl.TEXTURE_2D,null); 88 return this.canvas; 89 } 90 } 91 let brown=new Filter(` 92 precision mediump float; 93 varying vec2 vTexCoord; 94 uniform sampler2D texture; 95 uniform float time; 96 void main(void){ 97 vec4 color=texture2D(texture,vTexCoord); 98 float interval=1400.0; 99 float speed=time*5.0; 100 float scanLine=max(1.0,sin(vTexCoord.y*interval+speed)*2.0)*1.5; 101 color.rgb*=scanLine; 102 gl_FragColor=color; 103 } 104 `); 105 let image=new Image(); 106 image.onload=()=>{ 107 let canvas=document.querySelector("#sheet"); 108 let ctx=canvas.getContext("2d"); 109 canvas.width=600; 110 canvas.height=600; 111 var start=(new Date()).getTime()/1000; 112 function updateFrame(){ 113 let now=(new Date()).getTime()/1000-start; 114 ctx.clearRect(0,0,600,600); 115 ctx.drawImage(image,0,0,600,600,0,0,600,600); 116 ctx.drawImage(brown.draw(canvas,{uniform:{time:[now]}}),0,0,600,600,0,0,600,600); 117 requestAnimationFrame(updateFrame); 118 } 119 requestAnimationFrame(updateFrame); 120 } 121 document.querySelector("#image").onchange=(e)=>{ 122 image.src=URL.createObjectURL(e.target.files[0]); 123 } 124 </script> 125</body> 126</html>

画像をinputから参照するとcanvasに描画され、そのcanvasがクラスに与えられてwebglで処理され、帰ってきたwebgl用のcanvasをdrawImageでもとのcanvasに再描画するという仕組みです。
これを実行してしばらくするとパソコンが急にカタついて動かなくなってしまったので、システムモニター(Windowsで言うタスクマネージャー)で監視してみると、画像のようにメモリの使用量が右肩上がりになっていました。イメージ説明
領域の回収がうまくいっていないのだと思うのですが、どこが原因でしょうか。
また、WebGLを使っているのでGPUを使っていると思っていたのですが、CPUの使用率が高くなるのは普通でしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

すでに解決されたようなので、蛇足かもしれませんが……参考になればと思って書きます。

WebGL で生成したオブジェクトは、たぶん、単純に GC の対象にならないものがあるような気がします。
いわゆるネイティブな C/C++ の場合と同じように「意図的にメモリやオブジェクトは解放する」という考え方を持ったほうがいいです。

たとえば VBO などのバッファオブジェクトやシェーダオブジェクトは、それを Delete するためのメソッドが用意されていますので、それらを使った解放処理すべきだと思います。

テクスチャも、確か削除するためのメソッド gl.deleteTexture があるので、もし削除しなければならない場合はそういうメソッドで開放処理を行ったほうがいいと思います。削除はせずに使いまわしてやりくりする、という speken00 さんが取られた方法も、今回のようなケースでは正しいアプローチだと思いますね。

WebGL はブラウザのウィンドウ(タブ)が閉じられたらきれいにリセットされてしまうので、あまり細かく解放処理を記述しなくても問題が起こりにくいです。
ただその分、繰り返し何度も描画するようなアプリケーションを作っている場合は、そのあたりの「いわゆる後始末」をお行儀よく行ってやらないと、メモリリーク等が発生しやすいと思いますので、注意するといいかもしれません。

投稿2019/02/05 02:37

doxas

総合スコア112

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

小さなテクスチャをコンストラクタ内で作成して置き、描画時にテクスチャを更新することでメモリが増えなくなりました。どうやらcreateTextureによって作成されたオブジェクトがGCで回収できていなかったようです。

投稿2019/02/04 15:06

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問