WebGLUWebGLを䜿甚した䜜業の簡玠化

ブラりザヌの3Dは、以前は倧きな問題でした。 ブラりザで3次元の動的な3次元グラフィックスを䜜成するこずに頌らなかったものSVGでの擬䌌3Dの䜿甚、キャンバスでの構築、フラッシュの䜿甚... 2.0-WebGL。 これはかなり新しい技術であり、1幎ほど前のものです。 ただし、今では、あらゆる皮類のブラりザゲヌムず䟋でそのパワヌを評䟡できたす。



この技術は比范的若いため、䜿甚するためのマニュアルはそれほど倚くありたせん。 圌女ずの仕事に぀いおはこちらをご芧ください  こちら -ロシア語ぞの翻蚳。 ここでは、WebGLの基本に぀いお孊ぶこずができたす。



WebGLでの䜜業を容易にするために、倚くのラむブラリが開発されおいたすただし、それらのほずんどはただかなり粗雑です。 そのうちの1぀であるwebGLUを適甚しお、単䞀の懐䞭電灯で照らされたシンプルなシヌンを圢成したす。 ここで䟋を芋るこずができ、ここから完党なアヌカむブをダりンロヌドしお、マシンで実行できたす。



たず、OpenGLずWebGLの違いを少し思い出しおください。 WebGLはGLESに基づいおいるため、このテクノロゞヌはOpenGLよりも倧幅に劣っおいたす。倚くの䟿利な拡匵機胜ARBなどがなく、組み蟌みのラむティングサポヌトがありたせん。GL_QUADSでさえサポヌトされおいたせん。サヌドパヌティのプラグむンなしでWebに3Dを実装できる人はいたせん。



シェヌダヌは、頂点の䜍眮ず最終画像の色を蚈算するために䜿甚されたす。 3次元シヌンの最も単玔な構築では、シェヌダヌは関連付けられおいる各頂点に察しお呌び出されたす。 しかし、より耇雑なシヌンをこの方法で説明するこずはできたせん。 この堎合、圌らは最終シヌンを圢成するテクスチャを圢成するシェヌダヌを曞くこずに頌りたす䟋はここで芋るこずができたす 。倚分次の蚘事で3次元シヌンを蚘述するこの方法に觊れたす。



WebGLUラむブラリには、わずかなドキュメントずいく぀かの䟋が含たれおいたす。 これは、ラむブラリを完党に操䜜するには䞍十分であるため、゜ヌスコヌドも読む必芁がありたす。 さらに、ラむブラリは非垞に粗雑なので、コヌドを掘り䞋げる必芁がある堎合がありたす。



したがっお、WebGLUでの䜜業を開始するには、webglu.jsスクリプトを接続しお初期化する必芁がありたす。



<script type="text/javascript" src="./src/webglu.js"></script> 
 $W.initialize();
      
      





$ Wは、WebGLU名前空間のメむンオブゞェクトです。 ほずんどの仕事は圌ずやりたす。 このオブゞェクトに加えお、オブゞェクト$ GGameGLU名前空間があり、マりスずキヌボヌドを䜿甚しおシヌンを制埡する䜜業を簡玠化したす。 WebGLUには、いく぀かの実隓的な機胜もありたすたずえば、CrazyGLU-遞択した疑䌌バッファヌず物理孊を操䜜するため。 すべおの゜ヌスファむルは、察応する関数の起動時にWebGLUによっおロヌドされるためuseControlProfiles();



関数などuseControlProfiles();



ファむルをロヌドしたす、webglu.js以倖のスクリプトを手動でロヌドする必芁はありたせん。



WebGLUを初期化した埌、シヌンオブゞェクトの䜜成を開始できたす。 オブゞェクトを䜜成するために、WebGLUはむンタヌフェむス$W.Object(type, flags)



提䟛したす。ここで、typeはオブゞェクトのタむプですOpenGLず同様。





$W.RENDERABLE | $W.PICKABLE



オプションのフラグデフォルトでは、 $W.RENDERABLE | $W.PICKABLE



ただし、 $W.RENDERABLE | $W.PICKABLE



は、子であるオブゞェクトを描画する堎合、 $W.PICKABLE



を明瀺的に$W.PICKABLE



必芁があり$W.PICKABLE



。 最も単玔なケヌスでは、オブゞェクトの各頂点の色を指定する必芁がありたすが、独自のシェヌダヌを自由に䜜成しお次に行いたす、オブゞェクト党䜓に共通の色を指定できたす。



したがっお、たずえば、色座暙軞を䜜成するには、次のようにしたす。



 var originLines = new $W.Object($W.GL.LINES); originLines.vertexCount = 6; originLines.fillArray("vertex", [[0,0,0], [3,0,0], [0,0,0], [0,3,0], [0,0,0], [0,0,3]]); with ($W.constants.colors){ originLines.fillArray("color", [ RED, RED, GREEN, GREEN, BLUE, BLUE]); }
      
      





シェヌダヌはデフォルトで次の配列を䜿甚しお、オブゞェクトの各頂点を特城付けたす。



同様にむンデックスを陀く、シェヌダヌの察応する倉数に名前が付けられたすシェヌダヌの個々の頂点を特城付ける倉数には属性attribute



があるこずを思い出しattribute



。



シェヌダヌずWebGLの接続は、 Material



メ゜ッドを䜿甚しお実装されたす。 このメ゜ッドの唯䞀の匕数は、JSONシェヌダヌ蚘述ファむルぞのパスです。 たずえば、照明シェヌダヌは次のように接続されおいたす。



 var lights = new $W.Material({path:$W.paths.materials + "light.json"});
      
      





light.jsonファむル自䜓は次のようになりたす。



 { name: "light", program: { name: "light", shaders: [ {name:"light_vs", path:$W.paths.shaders+"light.vert"}, {name:"light_fs", path:$W.paths.shaders+"light.frag"} ] } }
      
      





ここで、名前は「材料」の䞀般名です。 プログラム→名前-明らかにプログラムの名前を特城付けるおそらく、WebGLの䜜成者は、1぀のマテリアルに耇数のプログラムを䜿甚できるず瀺唆したが、このパラメヌタヌは特別な圹割を果たさない。 シェヌダヌ-シェヌダヌぞのパスを瀺すシェヌダヌを䜿甚。



各オブゞェクトたたはシステム党䜓共通属性を持぀に共通の倉数は、 setUniformAction(n, f)



オブゞェクトのsetUniformAction(n, f)



メ゜ッドを䜿甚しお、察応するJavaScript倉数に関連付けられたす。 このメ゜ッドの匕数の意味は次のずおりです。n-シェヌダヌ内の倉数の名前メ゜ッドでは文字列ずしお瀺されたす。 fは、関数function(u, o, m)



関数です。ここで、uはuniformオブゞェクト、oはオブゞェクト自䜓、mはマテリアルです。 たずえば、「color」パラメヌタヌのオブゞェクトの色ぞのバむンドは、次のように実行されたす。



 lights.setUniformAction('color', function(uniform, object, material){ $W.GL.uniform4fv(uniform.location, object.color); });
      
      







非暙準のマテリアルをオブゞェクトに蚭定するには、 setMaterial(mat)



オブゞェクトのプロパティをsetMaterial(mat)



。ここで、matは必芁なマテリアルです。 JavaScriptを䜿甚するず、定矩枈みのオブゞェクトにその堎でプロパティを远加できるため、オブゞェクトを簡単に倉曎しおシェヌダヌず調敎できたす。



WebGLUを䜿甚しお、このシヌンを䜜成したしょう。







ここでは、オブゞェクトの継承が䜿甚されたす。メむンの垂盎シリンダヌは、2番目のシリンダヌず䞊の円を継承したす。 これは、䞋の円ず、2぀の円の間の平面にランダムに配眮されたサむズの異なる耇数色の球のセットを継承したす。 シヌン党䜓が1぀の指向性光源オレンゞ色の「懐䞭電灯」で照らされ、小さなオレンゞ色の球䜓で瀺されたす。



ラむティングを䜿甚するには、「むルミネヌタ」シェヌダによっお凊理されるすべおの頂点の法線を正しく蚈算する必芁がありたす。 genSphere(n1,n2,rad)



ラむブラリのgenSphere(n1,n2,rad)



関数を䜿甚しお球を描画できたすが、シリンダヌを自分で描画する必芁がありたす。 これを行う最も簡単な方法は、接続された䞉角圢で円柱の偎面を埋めるこずです。



 function drawCylinder(R, H, n, flags){ var v = [], norm = []; var C = new $W.Object($W.GL.TRIANGLE_STRIP, flags); C.vertexCount = n * 2+2; for(var i = -1; i < n; i++){ var a = _2PI/n*i; var cc = Math.cos(a), ss = Math.sin(a); v = v.concat([R*cc, R*ss,0.]); v = v.concat([R*cc, R*ss,H]); norm = norm.concat([-cc, -ss, 0.]); norm = norm.concat([-cc, -ss, 0.]); } C.fillArray("vertex", v); C.fillArray("normal", norm); return C; }
      
      





埌で芋るように、この方法はかなり原始的です䞡端の間に円柱の衚面に頂点を配眮しないずいう事実により、その照明は誀っお蚈算されたす「ランプ」が円柱の衚面の䞭倮のみを照らし、その端をキャプチャしない堎合、円柱点灯しおいたせん。 円柱を正しく描画するには、远加の䞭間頂点を远加し、䞉角圢の正しい衚瀺のためにむンデックスの配列を埋める必芁がありたす。 別のオプションは、それぞれが䞉角圢のセットで構成されるいく぀かの長方圢から、子オブゞェクトを含むオブゞェクト耇合を描画するこずです。



関数を䜿甚しお円を描きたす



 function drawCircle(R, n, w, flags){ var v = []; var C = new $W.Object($W.GL.LINE_LOOP, flags); C.vertexCount = n; for(var i = 0; i < n; i++){ var a = _2PI/n*i; v = v.concat([R*Math.cos(a), R*Math.sin(a),0.]); } C.fillArray("vertex", v); if(typeof(w) != "undefined") C.WD = w; else C.WD = 1.; C.draw = function(){ //       var oldw = $W.GL.getParameter($W.GL.LINE_WIDTH); $W.GL.lineWidth(this.WD); this.drawAt( this.animatedPosition().elements, this.animatedRotation().matrix(), this.animatedScale().elements ); $W.GL.lineWidth(oldw); }; return C; }
      
      





円を描く線の倪さを倉曎できるようにするには、このオブゞェクトのdraw()



関数を再定矩する必芁がありたす関数$W.GL.lineWidth(w)



は、この関数の次の呌び出したで、線の倪さをグロヌバルに蚭定するためです。 このオブゞェクトの$W.GL.LINE_LOOP



を$W.GL.LINE_LOOP



に倉曎するず、円はドットで描画されたす。 ポむントのサむズは、「マテリアル」ポむントを䜿甚するずいう事実により、オブゞェクトのWD



プロパティに䟝存したす。

  gl_PointSize = WD;
      
      



ここでは、さたざたなサむズのポむントを衚瀺するためのフラグメントシェヌダヌコヌドを芋るこずができ、 ここでは頂点シェヌダヌを芋るこずができたす。



そこで、オブゞェクトを䜜成したした。 照明を蚈算するためにシェヌダヌを䜜成する番でした。 耇数の光源で照らされたずきの頂点の最終的な色を蚈算するためのOpenGLハンドブックには、次の匏がありたす。



  result_Color = mat_emission + lmodel_ambient * mat_ambient Sum_i(D * S * [l_ambient * mat_ambient + max{dot(L,n),0}*l_diffuse*mat_diffuse + max{dot(s,n),0}^mat_shininess * l_specular * mat_specular )
      
      





ここに



通垞、マテリアルの拡散色ず背景色が䞀臎し、スポットラむトの背景色が䞀般的な背景照明の拡散色ず䞀臎し、定数枛衰係数ず線圢枛衰係数が省略できるずいう事実を考慮するず、この匏を簡略化できたす。 その結果、 このようなフラグメントシェヌダヌを取埗したす。 頂点衚瀺の座暙の蚈算に加えお、頂点シェヌダヌは、珟圚のモデル固有のマトリックスに基づいお、空間内の頂点の䜍眮ずその法線の方向も再蚈算する必芁がありたす各オブゞェクトを移動、スケヌリング、回転できるため、これを行う必芁がありたす。



ここで、「懐䞭電灯」の特性を刀断する必芁がありたす。



  light = { position: [0.,2.,1.5], target: [0.,0.,-2.], color: [1.,.5,0.,1.], fieldAngle: 60., exponent: 5., distanceFalloffRatio: .02 };
      
      





setUniformAction(
)



を䜿甚しお、「ランタン」プロパティずオブゞェクトプロパティをシェヌダヌ倉数setUniformAction(
)



関連付け、この「マテリアル」を䜿甚しお各オブゞェクトの個々のプロパティを蚭定したす。



これをすべお行った埌、 $W.start(T);



関数を䜿甚しおシヌンをアニメヌション化したす$W.start(T);



ここで、Tはシヌンレンダリング間の最小間隔です。 シヌンが耇雑すぎる堎合は、関数$W.util.defaultUpdate();



を䜿甚しお、倉曎するたびに手動で描画する必芁があり$W.util.defaultUpdate();



および$W.util.defaultDraw();



。 これらの関数はシェヌダヌのコンパむルには圱響したせんシェヌダヌ自䜓に倧幅な倉曎を行う堎合にのみ実行する必芁がありたす。したがっお、シヌンは初期読み蟌み時初期化䞭にのみ「フリヌズ」し、りィンドりのサむズが倉曎されるず少し遅くなりたす。



最埌に、WebGLUからのシヌンの回転正確には、シヌンの呚りでのカメラの移動機胜はあたり䟿利ではないため、独自の移動機胜を定矩する必芁がありたす。 ここ および最初に瀺した䟋のアドレスで、最終的なhtmlファむルがどのように芋えるかを確認できたす。







遞択バッファヌの操䜜マりスクリックでオブゞェクトを識別する必芁がある堎合、ミキシング時にオブゞェクトを衚瀺するオブゞェクトの色の透明床コンポヌネントを䜿甚するために必芁、および「戻る」をクリッピングするこずに぀いおは蚀及しなかったにもかかわらず、蚘事は非垞に倧きくなりたした衚面圢状など。 これが私のWebGLの蚘事が最埌ではないこずを願っおいたすあるいは、誰かが私の仕事を続けるでしょう。











UPD遞択肢を提䟛するために、crazyglu.jsファむルのgetObjectIDAtおよびusePicking関数を䜿甚しようずしたしたが、これらの詊みは倱敗したした。ラむブラリヌは湿っおいたす。 したがっお、関数は独立しお䜜成されたした。



だから、遞択バッファを実装するために必芁なもの。



たず、 $W.start(p)



関数を䜿甚できたせん。そうしないず、遞択バッファヌに曞き蟌むずきにタむマヌむメヌゞの曎新が "実行"されるリスクがありたす。 したがっお、シヌンを倉曎するたびにシヌンをレンダリングする必芁がありたす。



次に、遞択バッファの「グロヌバルマテリアル」 MatPick



を䜜成しお初期化し、バッファ自䜓を初期化する必芁がありたす。



  //  ""    MatPick = new $W.Material({path:$W.paths.materials + "pick.json"}); MatPick.setUniformAction('pickColor', function(uniform, object, material){ var colr = [0.,0.,0.,0.]; var id = object.id; for(var i = 0; i < 4; i++){ colr[i] = (id & 0xff)/256.; id >>= 8; } $W.GL.uniform4fv(uniform.location, colr); } ); //    try{ $W.pickBuffer = new $W.Framebuffer(); $W.pickBuffer.attachTexture($W.GL.RGBA, $W.canvas.width, $W.canvas.height, $W.GL.COLOR_ATTACHMENT0); $W.pickBuffer.attachRenderbuffer($W.GL.DEPTH_COMPONENT16, $W.canvas.width, $W.canvas.height, $W.GL.DEPTH_ATTACHMENT); }catch (e) { console.error(e); }
      
      







暙準スキヌムに埓っお遞択を行いたすオブゞェクト識別子32ビット敎数、できれば正、負、ただし-1に等しくないはバむトに分割され、浮動小数点数オブゞェクトの色成分に倉換されたす。 floatは、䞞め誀差がランダム誀差を蚱容しないこずを保蚌したす識別子aが±1に倉換される堎合。 遞択バッファヌを衚瀺するためのシェヌダヌは非垞に単玔なので、ここではそれらを説明したせん。



3番目に、Objects.jsファむルのコヌドを若干倉曎する必芁がありたすデフォルトで識別子を初期化するため、およびUtil.js画面にコンテンツを衚瀺した埌に描画バッファヌの内容を保存するため、そうしないず遞択は機胜したせん。



最埌に、オブゞェクトを遞択バッファヌに描画し、カヌ゜ルの䞋の色の倀を取埗する遞択関数を䜜成する必芁がありたす。 これを行うには、すべおのオブゞェクトを衚瀺した埌、それらの「マテリアル」をoldmat



配列に保存したす。遞択バッファヌを描画するずきは、䞀時的にすべおの「マテリアル」をMatPick



に倉曎し、バッファヌを埋めお、適切なポむントでカラヌ倀を取埗したす。 そしお、すでに色の倀によっお、オブゞェクトの識別子を決定したすたたはid ==-1の堎合、オブゞェクトの欠劂。



 function pick(X,Y){ //  var ccolr = $W.GL.getParameter($W.GL.COLOR_CLEAR_VALUE); var blend = $W.GL.getParameter($W.GL.BLEND); if(blend) $W.GL.disable($W.GL.BLEND); $W.GL.clearColor(1., 1., 1., 1.); //    "-1" $W.pickBuffer.bind(); //  ""  $W.util.defaultUpdate(); $W.util.clear(); $W.util.setupMatrices(); for (var i = 0; i < $W.objects.length; i++) { $W.objects[i].material = MatPick; //  "" } $W.util.defaultDraw(); //   for (var i = 0; i < $W.objects.length; i++) { $W.objects[i].material = oldmat[i]; //  "" } var pix = new Uint8Array(4); $W.GL.readPixels(X,$W.canvas.height-Y,1,1,$W.GL.RGBA, $W.GL.UNSIGNED_BYTE, pix); $W.pickBuffer.unbind(); //   if(blend) $W.GL.enable($W.GL.BLEND); $W.GL.clearColor(ccolr[0],ccolr[1],ccolr[2],ccolr[3]); var id = pix[0]+(pix[1]<<8)+(pix[2]<<16)+(pix[3]<<24); delete pix; var str = "X=" + X + ", Y=" + Y+ ", ID="+id; alert(str); } </code> <br><br>   :           . <br><br> :  google-chrome     (     ).
      
      






All Articles