Part2おそらくそもそもLoader、AsyncTaskLoaderとは?から来た人が多いと思うので説明は不要でしょうが、この記事はLoader、AsyncTaskLoaderについての記事の番外編です。非同期処理はAsyncTaskで十分じゃないの?さて、Androidで非同期処理をする方法の1つにAndroidが用意しているAsyncTaskを使用するというものがあります。非同期処理の仕組みを用意してるのになぜわざわざLoader、AsyncTaskLoaderを後から用意したのでしょう?いくつか理由があるようですが、私が思う1番の理由はActivityやFragmentのライフサイクルに対応していないということだと思います。解決できると思うので私は問題というほどではないと思ってます。ActivityやFragmentのライフサイクルに対応していないと何が問題なのでしょうか?ActivityやFragmentのライフサイクルに対応してないことで発生する問題ActivityやFragmentが破棄された後もonPostExecuteが呼ばれる例えば以下のパターンを見てみいきましょう。Log.d(_TAG,"onDestroy");}onCreateメソッド内でAsyncTaskを実行し、そのまますぐActivityを終了させてます。onDestroyメソッド内でログを出力させています。Log.d(_TAG,"onPostExecute");}doInBackgroundメソッド内、つまり非同期で処理をするところでは、ログを出力し、今のスレッドを3秒間ストップさせてます。onPostExecuteメソッド内、つまり非同期処理が終了した時に実行するメソッドでもログを出力しています。これを実際に実行してみると下記のようなログが出力されます。doInBackgroundonDestroyonPostExecuteこれを見るとonDestroy・・・つまりActivityが破棄された後も処理が続き、onPostExecuteが呼ばれているということがわかります。下記コードのようにonPostExecuteでDialog.dismissメソッドを呼んでいるとします。下記エラーでアプリケーションがクラッシュします。2.3未満)によってはonDestroyの時にAsyncTaskのcancelメソッドを呼んでもonPostExecuteが実行されてしまうというバグがあります。Changeが発生した(例えば端末を傾けて画面を回転させた)場合、Activityは一旦破棄された後、再度生成されます。onDestroyが呼ばれるわけですがそうなるとさっき言ったようにDialogなどの操作をonPostExecuteで行っているとクラッシュする可能性があります。onCreateに書いてある非同期処理を何度もされるのは都合が悪い時があります。何度も送信されると2重3重にデータが登録されたりします。画面回転をさせなければいい。新しいSIMを装着したりしても発生します。標準フォントサイズは一応抑制できますが、外部キーボードや新しいSIMに関してはソフトウェアから抑制はできません。まとめAsyncTaskはシンプルなコードで非同期処理を行うことができます。ActivityやFragmentのライフサイクルにきちんと対応したコードを書くのは結構大変です。非同期処理の最中にユーザがBackボタンを押したり、Homeボタンを押したり、端末を回転させたりと様々なイベントが起きる可能性があります。それら全てを自前でキャッチして対処するのはかなりAndroidに精通してないとなかなか大変でしょう。Part1おそらくそもそもLoader、AsyncTaskLoaderとは?から来た人が多いと思うので説明は不要でしょうが、この記事はLoader、AsyncTaskLoaderについての記事の番外編です。Java標準Threadクラスを基本的にAndroidで使用しないほうがいいのか?さて、Androidで非同期処理をする方法の1つにJava標準のThreadクラスを使用するというものがありますが、なぜ使用しないほうがいいのでしょう?この方法には以下の欠点があります。AndroidにはViewを操作したい場合はUIスレッドからしか行えないという制限があるThreadクラスにはデフォルトで安全にキャンセルする方法がないThreadクラスにはデフォルトでプールがない詳しく説明していきましょう。AndroidにはViewを操作したい場合はUIスレッドからしか行えないという制限があるまず、1.ですが、これはAndroid自体の制限で、Viewを操作するにはUIスレッドからしか行えない。いうルールがあります。故に自分でスレッドを生成し、処理結果を元に自分で生成したスレッド内でViewを操作しようとすると下記のようなエラーになります。views.しかし、この問題に関して言えばHanderというものを使えばその問題を解決できます。}});というコードを自分で生成したスレッド内に書けばそのスレッドからUIスレッドに「こういう処理をしてね」とお願いすることができます。2.や3.に関しては自前で頑張るしかありません。Threadクラスにはデフォルトで安全にキャンセルする方法がないさて、2.のキャンセルに関してですが、Threadクラスにはぱっと見stopやsuspend、resumeというメソッドがあるので、一見できそうです。・・・がこれらのメソッドは非推奨になっています。これに関しては正式にわざわざアナウンスされております。Deprecated?スレッドを止める方法がないとActivityなどが破棄されスレッドの結果を受け取る先がなくなった際に、すでに結果を返却する場所がないのに処理を続けてしまうという事になったりします。非同期処理のたびに「スレッドを生成し、処理が終了すると破棄する」という動作をさせると、スレッドの生成や破棄のコスト(時間的にもCPUやメモリのリソース)もなかなか高くなります。それが短い時間で何度も行われるとかなりの負荷になり得ます。そこでうまくスレッドを再利用して無駄を減らすという仕組みをプールといいますが、これを自前で作って管理するのもなかなか大変です。まとめ上記などの理由によってAndroidではThreadで非同期処理はしないほうがいいと思います。基本的にはThreadクラスの使用は避けたほうが無難でしょう。Part1皆さんLoader、AsyncTaskLoaderをご存知ですか?知らない人のために簡単にだけ説明すると、Androidで非同期処理を行うための仕組みです。Androidで非同期処理をする方法Androidで非同期処理をする方法はいくつかあります。通常ActivityやFragmentなどで非同期処理をするときは主に上記の3つだと思います。その中でわざわざLoader、AsyncTaskLoaderを使用しなければいけないのでしょう・・・?Androidが用意した最新の仕組みだからそっちのほうがなんとなくいい・・・ただそれだけの理由で使ってる人も案外いらっしゃるんじゃないでしょうか?実際1.と2.にはいくつか問題があります。Java標準のThreadクラスやAsyncTaskの問題点それぞれを詳しく解説すると結構長くなってしまうので別途下記リンクにまとめました。Java標準Threadクラスを基本的にAndroidで使用しないほうがいいのか?非同期処理はAsyncTaskで十分じゃないの?ThreadクラスやAsyncTaskの問題を解決し、更に便利な機能をつけた非同期処理の仕組みとしてLoader、AsyncTaskLoaderが提供されました。Change発生後、Loaderを再設定すれば再処理することなく最終結果を取得できるLoaderはデータソースを監視してるため、内容が変更された際に新しい結果を取得できるまず1.に関してはJava標準のThreadクラスやAsyncTaskの問題点のところにあったリンクを参照するとどういう問題があるのかわかるでしょう。基本的にLoader、AsyncTaskLoaderはこれらの問題を解決しています。Loader、AsyncTaskLoaderってほんとうに便利なの?これらだけ見ると何だかメリットばっかりで是が非でも使うべきみたいに見えますよね?でも、実際に使ってみると・・・非常に使いづらい・・・。メソッド名が紛らわしい、わかりづらいドキュメントの説明が紛らわしい、わかりづらい意外と詳しく解説しているサイトがない(特に日本語)という情報面で色々苦労します。Changeが発生(画面回転など)した時はどういう動作をするのか?など、どんな時にどんな挙動するのかを把握し正しく使用しないと特定の場合のみ起こるバグに繋がったりします。まとめ使いづらいし、どういう動作をするかきちんと把握しないとバグにつながる。使いこなせれば他の手法にはないメリットもあります。正しい使用方法を理解すればこの上ない武器になります。Android4.2以上でaddJavascriptInterfaceに制限がついたAndroidではJavaとJavaScriptの連携が非常に簡単にできる。AndroidAPI(),"API");とするだけでWebViewのJavaScriptからAndroidAPIというクラスのメソッドにアクセスできるようになる。後はJavaScriptのオブジェクトとしてアクセスできる。そのためそのオブジェクトのメソッドを呼ぶことができる。S4などのAndroid4.2以上を搭載している端末では、オブジェクトはできているがメソッドが定義されていないというエラーがJavaScript側で出てしまう。DevelopersのaddJavascriptInterfaceを見てみると、4.2以上からは@JavascriptInterfaceがついているpublicメソッドのみアクセスできるとなっている。無事にJavaScriptからメソッドが呼び出せるようになる。ちなみに@JavascriptInterfaceはandroid.webkit.JavascriptInterfaceをimportすれば使えるようになる。ちなみに4.2未満の場合は(継承されているクラスも含め)publicなメソッドであればすべてアクセスできていた。これでも問題ないように思うかもしれないがJavaにはリフレクションがあるため、その気になればprivateなメンバやメソッドにもアクセスできてしまう。privateメソッドなんかの名前はapkファイルをデコンパイルすれば難読化されてない限り簡単に調べることができる。故に公開したクラスの中にcontextを持っているとJavaScriptからcontextを取得できてしまい、アプリケーションの権限によっては電話帳などの情報にもアクセスできてしまう。そんな状態のアプリケーションが公開されXSS(クロスサイトスクリプティング)攻撃の恐れがあるサイトにWebViewでアクセスされると個人情報が抜き取られる恐れがある。故にこのような仕様変更が起こったのであろう。可能なら4.2未満の端末ではaddJavascriptInterfaceを使わないのが望ましい。WebGLで遊んでみる(3点の描画)第2回では点の描画を通してシェーダやプログラムの使い方をやった。点の位置を変えたり移動したりすることができない。そこで今回はJavaScriptから点の座標をシェーダに渡し、3つの点を描画してみる。描画結果(画像)3つの点が描画されている。</body></html>canvasをHTMLで用意しておく。JavaScript側。checkGLError('disableVertexAttribArray');};シェーダなどは第2回で説明しているので、もし不安があれば見なおしてみてほしい。第2回からの変更点を見ていこう。8行目~15行目に書かれている頂点シェーダのソースコード。a_Position;というのがある。これは、a_Positionという名前でvec4型のattribute変数を定義している。今回はまさに頂点の座標の値を渡すためattribute変数を使う。main関数の中をみてみると、gl_Positionにa_Positionを代入している。なんとこれだけで、頂点ごとに異なる座標を指定する頂点シェーダが出来上がる。フラグメントシェーダは変化なしなので、JavaScript側のmain関数内の変更点を見よう。次の行の-0.5が2つ目の頂点のx座標、-0.5がy座標、3行目の0.5が3つ目の頂点のx座標、-0.5がy座標という風に並べて代入している。65行目~66行目にcreateBufferという関数が使われている。buffer=createBuffer(vertex);引数に先ほどの頂点座標を渡している。中で何をしているかを見るために273行目~295行目を見てみる。*/};具体的に何をしているかを少しずつ見ていこう。275行目~278行目。buffer=gl.createBuffer();//createBufferメソッドのエラーチェックcheckGLError('createBuffer');createBufferメソッドを使ってバッファを作成している。実はバッファなしでも頂点座標を渡すことが出来る。バッファが必要かというと、キャラクタのポリゴンなどを描画しようと思うと何万もの頂点座標が必要になったりする。描画するたびにJavaScriptからWebGLにコピーして渡すのは非常に非効率で低速なので、WebGLのバッファに予め頂点座標の値を渡しておき、バッファを描画の時に使うようにすることによって高速な描画が可能になる。次に279行目~284行目。null;}バッファが作成できなかった場合は、コンソールにメッセージを出してnullを返している。285行目~286行目。//バッファをバインドするbindBuffer(buffer);bindBufferという関数を呼び出しバッファを渡している。bindBufferは297行目~303行目に定義されている。checkGLError('bindBuffer');};bindBufferメソッドを呼び出し、ARRAY_BUFFER定数と引数で受け取ったバッファを渡している。これは、WebGLのARRAY_BUFFERに渡されたバッファをひもづけるという効果がある。287行目~290行目に戻り更に見ていこう。Float32Array(value),gl.STATIC_DRAW);//bufferDataメソッドのエラーチェックcheckGLError('bufferData');bufferDataメソッドを呼び出している。引数をみてみると先ほど登場したARRAY_BUFFERが再び登場している。第2引数をよくみてみると、createBuffer関数で受け取った値を引数としてFloat32Arrayというクラスのインスタンスを作っている。これはJavaScriptの型付き配列と呼ばれるものだ。JavaScriptは型が柔軟な言語だがWebGLは型が厳密なので、そのままの値を渡されると都合が悪い。そのため、何の型の値なのかを明示的に伝えるべく型付き配列で渡すことになっている。第3引数はこのデータの使われ方をヒントとしてWebGLに教えるためのものだ。基本的にSTATIC_DRAW定数で問題ないと思う。結果バッファに値が書き込まれることになる。291行目~292行目。//バッファをアンバインドするunbindBuffer();unbindBufferという関数を呼び出している。unbindBufferの定義は305行目~311行目にある。checkGLError('bindBuffer');};bindBufferメソッドを呼び出し、ARRAY_BUFFER定数とnullを渡している。みbindBuffer関数と同じに見えるが、第2引数にnullを渡しているところが異なる。nullを渡すことによってARRAY_BUFFERとバッファのひもづけを切る効果がある最後に293行目~294行目。buffer;値が書き込まれたバッファを返している。JavaScriptのmain関数に戻り67行目~71行目。return;}バッファが作成できなかった場合は、returnしてmain関数を抜けている。72行目~73行目でgetAttributeという関数が呼ばれている。position=getAttribute(program,'a_Position');引数としてプログラムとattribute変数の名前を渡している。321行目~335行目にある定義を見てみよう。*/};では中で何をしているかを見ていこう。323行目~326行目。渡された名前のattribute変数(厳密にはattribute変数が格納されている場所)が取得できる。取得できなかった時には-1が返ってくるようになっている。327行目~332行目で取得できたかチェックする。return;}attribute変数が取得できなかった場合は、コンソールにメッセージを出してnullを返している。最後に333行目~334行目。location;attribute変数を返している。74行目~78行目に戻ろう。return;}attribute変数が取得できなかった場合は、returnしてmain関数を抜けている。次に79行目~80行目。//attribute変数にバッファをひもづけて有効にするbindAttribute(position,buffer,2);第1引数にattribute変数、第2引数にバッファ、第3引数に頂点あたりの値の数(1~4)を渡している。今回はx座標とy座標を頂点に渡すので頂点あたりの値の数は2である。bindAttributeの定義は337行目~351行目にある。*/};では具体的に見ていこう。339行目~340行目。//バッファをバインドするbindBuffer(buffer);再びbindBuffer関数を呼び出している。341行目~342行目で実際にattribute変数にバッファをひもづけている。第6引数にバッファのどこから値が始まるかを渡す。第5引数については第8回で説明する。345行目~346行目。//バッファをアンバインドするunbindBuffer();unbindBuffer関数もきちんと呼んでおく。347行目~350行目で実際にひもづけが有効になる。//バッファのひもづけを有効にするgl.enableVertexAttribArray(location);//enableVertexAttribArrayメソッドのエラーチェックcheckGLError('enableVertexAttribArray');enableVertexAttribArrayメソッドにattribute変数を渡すことによって、attribute変数にひもづけられたバッファが有効になる。91行目~94行目でdrawArraysメソッドを呼び実際に描画する。今回は3つの点を描画するので3を指定する。以上で3つの点が描画される。95行目~96行目で後片付けをしている。//attribute変数とバッファのひもづけを無効にするunbindAttribute(position);attribute変数とバッファのひもづけを無効化しておく。353行目~359行目にそのunbindAttributeの定義がある。checkGLError('disableVertexAttribArray');};disableVertexAttribArrayメソッドにattribute変数を渡すことによって、ひもづいているバッファを無効化することが出来る。次に97行目~98行目。//バッファ削除deleteBuffer(buffer);バッファも使い終わったら削除してしまう。deleteBufferが定義されてある313行目~319行目を見てみる。checkGLError('deleteBuffer');};deleteBufferメソッドにバッファを渡すことによってそのバッファを削除することが出来る。今回はバッファとattribute変数の使い方を説明した。これを使いこなすことによって自在に好きな座標に描画することが出来るようになる。バッファの作成をまとめてみると。(createBuffer)バッファをバインドする。(bindBuffer)バッファに値を書き込む。(bufferData)バッファをアンバインドする。(bindBuffer)要点はこれだけ。同様にattribute変数もまとめてみると。attribute変数を取得する。(getAttribLocation)バッファをバインドする。(bindBuffer)attribute変数とバッファをひもづける。(vertexAttribPointer)バッファをアンバインドする。(bindBuffer)attribute変数とバッファのひもづけを有効にする。複雑に感じるが実際はこれだけである。WebGLで遊んでみる(点の描画)第1回は描画領域クリアまで説明した。今回は最も簡単な図形・・・点の描画を説明していこうと思う。今回からもっとも重要な要素の1つシェーダが登場する。描画結果(画像)真ん中に青い点が表示されている。これだけだが、シェーダが登場するため、ソースコードは少し長い。</body></html>まぁ、第1回と同じなので特に解説は要らないであろう。canvasを用意しておくだけである。JavaScript側。checkGLError('deleteShader');};では、第1回から変わったところを詳しく見ていこう。8行目~13行目になにやら怪しいソースコードのようなものが書かれている。今回は描画する点の座標についての処理を定義している。シェーダはGLSLという言語を用いて書く必要がある。新しい言語覚えるのかぁ・・・と思う必要もなく、そこまで特殊な文法は存在しない。基本文法はC言語と似ていて、JavaScriptがわかるならある程度読み解けるだろう。わからないことがあれば必要に応じて調べて覚えていく程度でもなんとかなるだろう。実際ここではvertexShaderSource変数に頂点シェーダのソースコードを文字列として代入している。ソースコードは最初にmain関数を定義している。これはGLSLもCと同じくmain関数から始まるという決まりがあるからだ。main関数内ではgl_Positionにvec4(0.0,0.0,0.0,1.0);を代入している。簡単に説明すると、x座標0.0、y座標0.0、z座標0.0、wに1.0を指定したvec4型を作り、それを表示座標に代入している。x座標、y座標、z座標はなんとなくわかるが、wはあんまりピンと来ない。行列計算の時にあると便利だからついてる。今はそのぐらいの認識でもいいと思う。vec4型とはfloat型が4つ入る型。言えば4つのfloat型によって表されるベクトルの値が入る型である。次に、gl_PointSizeに10.0を代入しているが、これは点の大きさを定義しているだけだ。文字列中の各行末にある「\(バックスラッシュ、環境によっては円マーク)」はJavaScriptで複数行文字列リテラルを扱うために必要な物だ。15行目~19行目も同様にフラグメントシェーダのソースコードがかかれている。gl_FragColor=vec4(0.0,0.0,1.0,1.0);\}';頂点シェーダと同様にフラグメントシェーダもGLSLで書かれている。頂点・・・はまぁ、なんとなくわかるが、フラグメントってなに?と思うだろうが、ざっくりといえば頂点で結ばれた線の内側の一つ一つのピクセル(厳密にはピクセルではないが)ぐらいの認識でいいと思う。3つの頂点を定義し三角形を作ったとしたらその三角形の内部全てにこのフラグメントシェーダが適応される。頂点シェーダと同様にフラグメントシェーダでもmain関数を定義している。その中でgl_FragColorにvec4(0.0,0.0,1.0,1.0)を代入している。これは、このフラグメントの色をRGBAの順に指定したvec4型を作り代入している。今回は青色でフラグメントを描画する。次にJavaScript側のmain関数で行なっている処理を見ていこう。返り値をgl変数で受け取っている。getContextが定義してある92行目~121行目を見てみると。gl;};やってることは第1回と一緒でWebGLのコンテキストを取得しているだけである。それを関数の返り値として返している。return;}WebGLのコンテキストが取得できなかった場合はreturnしてmain関数を終了している。32行目~33行目にcreateShaderという関数が使われている。vertexShader=createShader(gl.VERTEX_SHADER,vertexShaderSource);引数にWebGLの定数と上部で定義したvertexShaderSourceを渡している。中で何をしているかは123行目~167行目に書いてある。*/};具体的に何をしているかを少しずつ見ていこう。125行目~128行目。shader=gl.createShader(type);//createShaderメソッドのエラーチェックcheckGLError('createShader');WebGLのコンテキストにあるcreateShaderメソッドに第1引数で渡ってきたtypeという変数を渡している。上記でも少し触れたがシェーダは頂点シェーダとフラグメントシェーダがあるため、どっちのシェーダを作るのかを指定するためにtypeを渡してもらう必要がある。33行目ではgl.VERTEX_SHADERを渡しているので、頂点シェーダを作ることになる。その下の行では第1回説明したとおり返り値や例外でエラーをキャッチできないので、エラーチェック用の関数を定義し呼んでいる。次に129行目~134行目。null;}シェーダが作成できなかった場合は、コンソールにメッセージを出してnullを返している。135行目~138行目。//シェーダとソースコードをひもづけるgl.shaderSource(shader,source);//shaderSourceメソッドのエラーチェックcheckGLError('shaderSource');shaderSourceメソッドを使いではシェーダにソースコードをひもづけている。139行目~164行目。null;}compileShaderメソッドを使いひもづけられているソースコードをコンパイルする。コンパイルはC言語やJavaをやったことがある人にとっては馴染み深い言葉だが、JavaScriptやPHPなどしかしたことない人にとっては初めて見る言葉かもしれない。いえばソースコードをコンピュータが理解しやすい形式(一般的にはバイナリコード)に変換することだ。ソースコードの文法に誤りがあったりした際にはコンパイルが失敗する。そのため、getShaderParameterメソッドにシェーダとgl.COMPILE_STATUSを渡し、コンパイルが成功したかどうかをチェックしている。返り値がfalseのときはコンパイルに失敗しているため、getShaderInfoLogメソッドを呼び、ログの取得を試みる。最後に165行目~166行目。shader;すべての手順が成功した際にシェーダを返している。JavaScriptのmain関数に戻り35行目~38行目。return;}シェーダが作成できなかった場合は、returnしてmain関数を抜けている。39行目~45行目で今度はフラグメントシェーダを作成する。引数にgl.FRAGMENT_SHADERとフラグメントシェーダのソースコードを渡しているところが異なる。作成に失敗したときは同様にreturnでmain関数を抜けている。program=createProgram(vertexShader,fragmentShader);今まで作った頂点シェーダとフラグメントシェーダを渡し、createProgramという関数を呼んでいる。createProgram関数の定義は169行目~215行目にある。*/}createProgram関数は頂点シェーダとフラグメントシェーダを受け取り、プログラムを返すようになってる。簡単にいえばシェーダを管理する入れ物のようなもので、プログラムにシェーダをひもづけることによって初めてシェーダが使えるようになる。createProgram関数がどうやってプログラムを作っているか見てみよう。最初に171行目~172行目。program=gl.createProgram();WebGLのコンテキストにあるcreateProgramメソッドを呼ぶことによりプログラムが作られる。次に173行目~178行目。null;}プログラムが作成できなかった場合は、コンソールにメッセージを出してnullを返している。179行目~186行目。//頂点シェーダをプログラムにひもづけるgl.attachShader(program,vertexShader);//attachShaderメソッドのエラーチェックcheckGLError('attachShader');//フラグメントシェーダをプログラムにひもづけるgl.attachShader(program,fragmentShader);//attachShaderメソッドのエラーチェックcheckGLError('attachShader');attachShaderメソッドにプログラムとシェーダを渡すことによってその2つをひもづけることができる。プログラムには必ず頂点シェーダとフラグメントシェーダをひもづけなければならないので、それぞれに対してattachShaderメソッドを呼んであげる。187行目~212行目。null;}linkProgramメソッドを使うと頂点シェーダとフラグメントシェーダでリンクさせるのに必要なチェックが行われる。頂点シェーダとフラグメントシェーダでの整合性や、使用上限を超えてないかなどがチェックされる。attribute変数は第3回、uniform変数は第4回、varying変数は第5回に説明する。返り値がfalseのときはリンクに失敗しているため、getProgramInfoLogメソッドを呼び、ログの取得を試みる。最後に213行目~214行目。program;すべての手順が成功した際にプログラムを返している。JavaScriptのmain関数に戻り48行目~52行目。return;}プログラムが作成できなかった場合は、returnしてmain関数を抜けている。53行目~58行目では第1回でもやったようにカラーバッファをクリアしている。//RGBAの順番にカラーバッファをクリアする色を指定するgl.clearColor(0.5,0.5,0.5,1.0);//カラーバッファをクリアするgl.clear(gl.COLOR_BUFFER_BIT);//clearメソッドのエラーチェックcheckGLError('clear');今回も灰色でクリアする。59行目~62行目で作成したプログラムを使ってる。//使用するプログラムをWebGLに設定するgl.useProgram(program);//useProgramメソッドのエラーチェックcheckGLError('useProgram');useProgramメソッドを呼ぶことによってWebGLにこれから使用するプログラムを教えてあげる。63行目~66行目によって実際に描画される。//描画するgl.drawArrays(gl.POINTS,0,1);//drawArraysメソッドのエラーチェックcheckGLError('drawArrays');drawArraysメソッドの第1引数にどういう方法で描画するかを指定する。今回は点を描画するのでgl.POINTSを指定している。drawArraysと複数形になってるだけありJavaScriptから座標を渡してあげると、このメソッドは複数の頂点を同時に描画できる。第3引数で何個描画するかを指定する。第2引数には何を指定したとしても変わらない。点を1個描画するので、第3引数は1になっている。このメソッドを呼ぶことによって実際に画面に描画される。//プログラム削除deleteProgram(program,vertexShader,fragmentShader);つかい終わったらいらないものは削除しておいたほうがいい。deleteProgram関数にプログラムと頂点シェーダ、フラグメントシェーダを渡している。deleteProgramが定義されてある217行目~231行目を見てみる。checkGLError('deleteProgram');};detacheShaderメソッドにプログラムとシェーダを渡すと、ひもづけを切ることができる。頂点シェーダとフラグメントシェーダ両方を切らなければいけないので、それぞれを引数に渡しdetachShaderメソッドを呼んでいる。deleteProgramメソッドにプログラムを渡すことでそのプログラムを削除している。69行目~72行目では今度はシェーダを削除している。//頂点シェーダ削除deleteShader(vertexShader);//フラグメントシェーダ削除deleteShader(fragmentShader);もちろん頂点シェーダもフラグメントシェーダも削除するので、それぞれを引数に渡して呼び出す。定義は233行目~239行目にある。checkGLError('deleteShader');};やってることは単純でdeleteShaderメソッドにシェーダを渡してあげるだけである。