▶ 実 行
▶ 実行
クリア
跳ねるボール(WebGL版)
by てぃふと@うぇいく
# ボールが跳ねる !「https://n3s.nadesi.com/plain/565.nako3」を取り込む # # 設定 ボール総数を20000に定める。 最大速度を1に定める。 ボール色を[ [255, 0, 0], [255,255, 0], [ 0, 0,255] ]に定める。 重力を[0, 0]に定める。 自由角度フラグをオンに定める。 フルカラーをオンに定める。 # 重力の符号方向は、Xは右が+、Yは上が+。真下方向にかけるなら、[0,-1]等。 # 自由角度をオフにすると初期の移動が8方向になる。初期以降は制限されない。 # フルカラーをオンにした場合、ボール色の配列に色指定は使われません。 # 高精度優先:高精度優先で自動選択。両方使用できない場合はエラーで停止 # 低精度優先:低精度優先で自動選択。両方使用できない場合はエラーで停止 # 高精度:高精度を利用。使用できない場合はエラーで停止 # 低精度:低精度を利用。使用できない場合はエラーで停止 データテクスチャ利用は「低精度優先」 # # WEBGL更新表示ためのワークエリア WEBGL用キャンバンスは空 テクスチャ幅は0 テクスチャ高は0 色半径テクスチャは空 表示プログラムは空 TEX表示プログラムは空 更新プログラムは空 全体頂点情報バッファは空 インデックスバッファは空 FBリストは空配列 低精度浮動小数点数テクスチャ利用はオフ 低精度浮動小数点数テクスチャは空 表FBは0 裏FBは1-表FB 画面幅は0 画面高は0 # # メイン処理 初期化処理する REQIDは「アニメーション」を画面更新時実行 # # 共通処理(初期化とメインループ) ●初期化処理とは 画面幅は描画中キャンバス["width"] 画面高は描画中キャンバス["height"] WEBGL用キャンバンスは追加キャンバス準備 WEBGL用キャンバンスからGLコンテキスト作成 WEBGLシェーダ準備する FBリスト[表FB]にボール初期化する FBリスト[表FB]をボール表示 ここまで ●(タイムスタンプで)アニメーションとは ターン更新表示 WEBGL用キャンバンスを[0,0]へ画像描画 REQIDは「アニメーション」を画面更新時実行 ここまで # # # ●追加キャンバス準備とは CANVASは"#webgl_cv"をDOM要素取得 もし、CANVASでなければ、 CANVASは「CANVAS」のDOM要素作成 CANVAS["id"]は"webgl_cv" 描画中キャンバス["parentNode"]にCANVASをDOM子要素追加 ここまで CANVAS["width"]は画面幅 CANVAS["height"]は画面高 CANVAS["style"]["display"]は「none」 CANVASで戻る ここまで # データの保存に必要なテクスチャのサイズを求める ●WEBGLシェーダ準備とは # データの保存に必要なテクスチャのサイズを求める 基本底数は2で(ボール総数の平方根)のLOGNを切り上げ テクスチャ幅は2の(基本底数)乗 第二底数は2で(ボール総数÷テクスチャ幅)のLOGNを切り上げ テクスチャ高は2の(第二底数)乗 「TEX=({テクスチャ幅},{テクスチャ高})」を表示 # WEBGLの拡張機能のチェックと限界数の表示を行う VTF数は"MAX_VERTEX_TEXTURE_IMAGE_UNITS"のGLパラメータ取得 もし、VTF数=0ならば、 「この環境ではVTFを利用できません」でエラー発生 ここまで 「利用可能なVTF数={VTF数}」を表示 VATTR数は"MAX_VERTEX_ATTRIBS"のGLパラメータ取得 「利用可能なV属性数={VATTR数}」を表示 点サイズは"ALIASED_POINT_SIZE_RANGE"のGLパラメータ取得 「利用可能な点の大きさ={点サイズ[0]}-{点サイズ[1]}」を表示 浮動小数点数テクスチャは"OES_texture_float"のGL拡張機能取得 もし、浮動小数点数テクスチャ=NULLならば、 「この環境では浮動小数点数テクスチャを利用できません」でエラー発生 ここまで # 高精度または高精度優先の場合の高精度の試行 もし、データテクスチャ利用=「高精度優先」または、データテクスチャ利用=「高精度」ならば、 浮動小数点数カラーバッファはGL浮動小数点数カラーバッファ拡張 もし、浮動小数点数カラーバッファでなければ、 もし、データテクスチャ利用=「高精度」ならば、 「この環境では高精度浮動小数点数カラーバッファは利用できません」でエラー発生 ここまで # 高精度のカラーバッファに未対応ならば低精度を試みる データテクスチャ利用は「低精度」 ここまで ここまで # 低精度または低精度優先もしくは、高精度優先で高精度に失敗した場合の低精度 もし、データテクスチャ利用=「低精度優先」または、データテクスチャ利用=「低精度」ならば、 低精度浮動小数点数テクスチャは"OES_texture_half_float"のGL拡張機能取得 もし、低精度浮動小数点数テクスチャ=NULLならば、 もし、データテクスチャ利用=「低精度」ならば、 「この環境では低精度浮動小数点数テクスチャを利用できません」でエラー発生 ここまで データテクスチャ利用は「高精度」 違えば、 低精度浮動小数点数カラーバッファは"EXT_color_buffer_half_float"のGL拡張機能取得 # NULLでも利用可能な環境もあるためここでの拡張失敗は無視する もし、低精度浮動小数点数カラーバッファ=NULLならば、 もし、データテクスチャ利用=「低精度」ならば、 「低精度浮動小数点数カラーバッファは利用できません」でエラー発生 ここまで データテクスチャ利用は「高精度」 違えば、 低精度浮動小数点数テクスチャ利用はオン ここまで ここまで ここまで # 低精度優先で、低精度に失敗した場合の高精度の試行 もし、データテクスチャ利用=「高精度」ならば、 浮動小数点数カラーバッファはGL浮動小数点数カラーバッファ拡張 もし、浮動小数点数カラーバッファでなければ、 「この環境では高精度浮動小数点数カラーバッファは利用できません」でエラー発生 ここまで ここまで # 画面表示の際に利用する頂点シェーダ # 属性で連番を受け取り、連番に対応したボールの情報を # テクスチャから読み取って、座標と色と半径を設定する。 表示用頂点シェーダは『attribute float aIndex; uniform sampler2D uTex; uniform sampler2D uTexColorRadius; uniform vec2 uTexSize; uniform vec2 uViewSize; varying vec4 vColor; varying float vRadius; vec2 index2uv(float index) { vec2 scale = 1.0 / uTexSize; vec2 halfScale = scale * 0.5; return vec2(mod(index, uTexSize.x), floor(index / uTexSize.x)) * scale + halfScale; } void main() { vec2 scale = 2.0 / uViewSize; vec2 halfScale = scale * 0.5; vec2 uv = index2uv(aIndex); vec4 t = texture2D(uTex, uv); vec4 rgba = texture2D(uTexColorRadius, uv); vec2 xy = t.xy * scale + halfScale - 1.0; float r = floor(rgba.w * 255.0 + 0.5); gl_Position = vec4(xy, 0.0, 1.0); gl_PointSize = r; vColor = vec4(rgba.rgb, 1.0); vRadius = r; }』から"頂点"のGLシェーダ作成 # 画面表示の際に利用するフラグメントシェーダ # vColor(色)とvRadius(丸の半径)を受け取る。 表示シェーダは『precision mediump float; varying vec4 vColor; varying float vRadius; void main() { vec2 p = gl_PointCoord - 0.5; // slide 0.0 - 1.0 to -0.5 - 0.5 float l = length(p); if (l > 0.51) discard; gl_FragColor = l > 0.5 - 1.0 / vRadius ? vec4(0.3, 0.3, 0.3, 1.0) : vColor; }』から"フラグメント"のGLシェーダ作成 # テクスチャからテクスチャに複製する際に利用する頂点シェーダ # 頂点とテクスチャ座標を受け取り、そのままフラグメントシェーダに渡すだけ。 TEX頂点シェーダは『attribute vec2 aPos; attribute vec2 aTexCoord; varying vec2 vTexCoord; void main() { vTexCoord = aTexCoord; gl_Position = vec4(aPos, 0.0, 1.0); }』から"頂点"のGLシェーダ作成 # テクスチャからテクスチャに複製する際に利用するフラグメントシェーダ # テクスチャとテクスチャ座標を受け取り、指定箇所のテクスチャの内容を渡す。 TEX表示シェーダは『precision mediump float; uniform sampler2D uTex; varying vec2 vTexCoord; void main() { gl_FragColor = texture2D(uTex, vTexCoord); }』から"フラグメント"のGLシェーダ作成 # ボールの情報の更新をする際に利用するフラグメントシェーダ # 元とテクスチャで受け取り、更新結果を渡す。 更新シェーダは『precision mediump float; uniform sampler2D uTex; uniform vec2 uViewSize; uniform vec2 uGravity; varying vec2 vTexCoord; void main() { vec4 t = texture2D(uTex, vTexCoord); vec2 v = t.zw + uGravity; vec4 n = vec4(t.xy + v, 0.0, 0.0); n.z = ( n.x < 0.0 || n.x > uViewSize.x ) ? 0.0 - v.x : v.x; n.w = ( n.y < 0.0 || n.y > uViewSize.y ) ? 0.0 - v.y : v.y; n.x = n.x < 0.0 ? 0.0 - n.x : n.x; n.y = n.y < 0.0 ? 0.0 - n.y : n.y; n.x = n.x > uViewSize.x ? uViewSize.x * 2.0 - n.x : n.x; n.y = n.y > uViewSize.y ? uViewSize.y * 2.0 - n.y : n.y; gl_FragColor = n; }』から"フラグメント"のGLシェーダ作成 もし、表示用頂点シェーダ=NULLまたは、表示シェーダ=NULLならば、 「シェーダのコンパイルに失敗しました」でエラー発生 ここまで もし、TEX頂点シェーダ=NULLまたは、TEX表示シェーダ=NULLまたは、更新シェーダ=NULLならば、 「シェーダのコンパイルに失敗しました」でエラー発生 ここまで PGMは表示用頂点シェーダと表示シェーダからGLプログラム作成 表示プログラムは{ PROGRAM: PGM, PARAM: { インデックス: { TYPE: "ATTR", NAME: 「aIndex」 }, テクスチャ: { TYPE: "1i", NAME: 「uTex」 }, テクスチャサイズ: { TYPE: "2fv", NAME: 「uTexSize」 }, 色半径テクスチャ: { TYPE: "1i", NAME: 「uTexColorRadius」 }, 表示サイズ: { TYPE: "2fv", NAME: 「uViewSize」 } } } 表示プログラムのパラメータロケーション情報更新 PGMはTEX頂点シェーダとTEX表示シェーダからGLプログラム作成 TEX表示プログラムは{ PROGRAM: PGM, PARAM: { 頂点: { TYPE: "ATTR", NAME: 「aPos」 }, UV: { TYPE: "ATTR", NAME: 「aTexCoord」 }, テクスチャ: { TYPE: "1i", NAME: 「uTex」 } } } TEX表示プログラムのパラメータロケーション情報更新 PGMはTEX頂点シェーダと更新シェーダからGLプログラム作成 更新プログラムは{ PROGRAM: PGM, PARAM: { 頂点: { TYPE: "ATTR", NAME: 「aPos」 }, UV: { TYPE: "ATTR", NAME: 「aTexCoord」 }, テクスチャ: { TYPE: "1i", NAME: 「uTex」 }, 表示サイズ: { TYPE: "2fv", NAME: 「uViewSize」 }, 加速度: { TYPE: "2fv", NAME: 「uGravity」 } } } 更新プログラムのパラメータロケーション情報更新 # X,Y,U,Vの順 全体頂点情報リストは[ -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, -1.0, 1.0, 0.0 ] 全体頂点情報バッファは{ BUF: 全体頂点情報リストからGL静的配列バッファ作成, STRIDE: 16, NUM: 4, TYPE: "TRIANGLE_STRIP", PARAM: { 頂点: { OFFSET: 0, NUM: 2 }, UV: { OFFSET: 8, NUM: 2 } } } インデックスリストは[] (ボール総数)回繰り返す インデックスリスト[回数-1]は回数-1 ここまで インデックスバッファは{ BUF: インデックスリストからGL静的配列バッファ作成, STRIDE: 0, NUM: ボール総数, TYPE: "POINTS", PARAM: { インデックス: { OFFSET: 0, NUM: 1 }, } } 0をGLテクスチャ枠指定 型は"FLOAT" もし、低精度浮動小数点数テクスチャ利用ならば、 型は低精度浮動小数点数テクスチャ["HALF_FLOAT_OES"] ここまで 2回繰り返す TEXは型でNULLから[テクスチャ幅,テクスチャ高]のGLテクスチャ作成 FBリスト[回数-1]は{ FB: ({COLOR: TEX}のGLフレームバッファ作成), TEX: TEX, W: テクスチャ幅, H: テクスチャ高 } ここまで ここまで ●TEX用初期化データ作成とは PIは"Math.PI"をJS実行 初期データは[] 初期データ["length"]はテクスチャ幅×テクスチャ高×4 色半径データは[] 色半径データ["length"]はテクスチャ幅×テクスチャ高×4 Iは0 (テクスチャ高)回繰り返す TYは回数-1 (テクスチャ幅)回繰り返す TXは回数-1 もし、I<ボール総数ならば Xは画面幅の乱数 Yは画面高の乱数 Vは((2の乱数)×最大速度+3) もし、自由角度フラグならば、 DIRは360の乱数 違えば、 DIRは(8の乱数)×45 ここまで Rは(4+(5の乱数))*2 もし、フルカラーならば、 Cは[255の乱数, 255の乱数, 255の乱数] 違えば、 Cはボール色[3の乱数] ここまで 初期データ[I*4+0]はX 初期データ[I*4+1]はY 初期データ[I*4+2]は(DIRをDEG2RADのCOS)×V 初期データ[I*4+3]は(DIRをDEG2RADのSIN)×V 色半径データ[I*4+0]はC[0] 色半径データ[I*4+1]はC[1] 色半径データ[I*4+2]はC[2] 色半径データ[I*4+3]はR 違えば 初期データ[I*4+0]は0 初期データ[I*4+1]は0 初期データ[I*4+2]は0 初期データ[I*4+3]は0 色半径データ[I*4+0]は0 色半径データ[I*4+1]は0 色半径データ[I*4+2]は0 色半径データ[I*4+3]は0 ここまで IはI+1 ここまで ここまで 全データは{ 座標速度データ: 初期データ, 色半径データ: 色半径データ } 全データで戻る ここまで # 高精度浮動小数点数テクスチャを利用して初期化データを設定する # 合わせて、色と半径の情報を持つテクスチャも作成する(R/Oなので1枚のみ) ●(FBに)ボール初期化とは TEXデータはTEX用初期化データ作成 TEXデータF32はTEXデータ["座標速度データ"]のF32配列 TEXは"FLOAT"でTEXデータF32から[テクスチャ幅,テクスチャ高]のGLテクスチャ作成 TEXをFBにTEXボール複製 TEXをGLテクスチャ削除 TEXデータUI8はTEXデータ["色半径データ"]のUI8配列 色半径テクスチャはTEXデータUI8から[テクスチャ幅,テクスチャ高]のGLテクスチャ作成 ここまで # ボールの情報の更新と表示を行う ●ターン更新表示とは FBリスト[表FB]からFBリスト[裏FB]にボール更新する # FB0とFB1を交換 表FBは1-表FB 裏FBは1-表FB FBリスト[表FB]をボール表示 ここまで ●(FBを)ボール表示とは FB["TEX"]を色半径テクスチャでTEXボール表示する ここまで ●(TEXをTEXCRで)TEXボール表示とは 現PGMは表示プログラム 現PGM["PROGRAM"]をGLプログラム使用 NULLをGLフレームバッファ設定 パラメータ情報は{ 属性: [インデックスバッファ], 共有データ: { テクスチャサイズ: [テクスチャ幅, テクスチャ高], 表示サイズ: [画面幅, 画面高] }, テクスチャ: { テクスチャ: TEX, 色半径テクスチャ: TEXCR } } 使用リソースはパラメータ情報で現PGMにシェーダプログラムパラメータ設定 [0,0,画面幅,画面高]にGLビューポート設定 [1.0, 1.0, 1.0, 1.0]にGLクリア色設定 {COLOR:オン}でGLクリア インデックスバッファ["TYPE"]でインデックスバッファ["NUM"]をGL配列描画 GLフラッシュする 使用リソースをシェーダプログラムパラメータ解放 ここまで ●(TEXをFBに)TEXボール複製とは 現PGMはTEX表示プログラム 現PGM["PROGRAM"]をGLプログラム使用 FB["FB"]をGLフレームバッファ設定 パラメータ情報は{ 属性: [全体頂点情報バッファ], 共有データ: {}, テクスチャ: { テクスチャ: TEX } } 使用リソースはパラメータ情報で現PGMにシェーダプログラムパラメータ設定 [0,0,テクスチャ幅,テクスチャ高]にGLビューポート設定 [0.0, 0.0, 0.0, 1.0]にGLクリア色設定 {COLOR:オン}でGLクリア 全体頂点情報バッファ["TYPE"]で全体頂点情報バッファ["NUM"]をGL配列描画 GLフラッシュする 使用リソースをシェーダプログラムパラメータ解放 ここまで ●(FBSからFBDに)ボール更新とは FBS["TEX"]からFBDにTEXボール更新 ここまで ●(TEXからFBに)TEXボール更新とは 現PGMは更新プログラム 現PGM["PROGRAM"]をGLプログラム使用 FB["FB"]をGLフレームバッファ設定 パラメータ情報は{ 属性: [全体頂点情報バッファ], 共有データ: { 表示サイズ: [画面幅, 画面高], 加速度: 重力 }, テクスチャ: { テクスチャ: TEX } } 使用リソースはパラメータ情報で現PGMにシェーダプログラムパラメータ設定 [0,0,テクスチャ幅,テクスチャ高]にGLビューポート設定 [0.0, 0.0, 0.0, 1.0]にGLクリア色設定 {COLOR:オン}でGLクリア 全体頂点情報バッファ["TYPE"]で全体頂点情報バッファ["NUM"]をGL配列描画 GLフラッシュする 使用リソースをシェーダプログラムパラメータ解放 ここまで # 数学関数群 ●(AのN)乗とは 『(function (a,b) {return Math.pow(a,b)})』を[A,N]でJS関数実行で戻る ここまで