Roman Cortesは、JavaScriptスクリプトで書かれた赤いバラを持ち込みました。コードで作られたローズは、素晴らしいプログラマーからあなたのガールフレンドに与えられた最高のバレンタインデーの贈り物です! (ヒント:視聴効果と速度は、異なるブラウザで非常に異なります)
画像はコードによって生成され、ユーザーはページを更新して、バラを見るプレゼンテーションプロセスを繰り返すことができます。
3Dローズの実装コードは次のとおりです。
コードコピーは次のとおりですp(a、b、c){if(c> 60)return [s(a*7)*(13+5/(。2+p(b*4,4))) - s(b)*50、b*f+50,625+c(a*7)*(13+ 5/(。2+p(b*4,4)))+b*400、a*1-b/2、a]; a = a*2-1; b = b*2-1; if(a*a+b*b <1){if(c> 37){n =(j = c&1) ?6:4; o = .5/(a+.01)+c(b*125)*3-a*300; w = b*h; return [o*c(n)+w*s(n)+j*610-390、o*s(n)-w*c (n)+550-J*350,1180+C(B+A)*99-J*300、.4-A*.1+P(1-B*B、-H*6)*。 o*(a+1)+(b> 0?w:-w)/25)、30)* a*45-20; w = b*b*h; z = o*s(c)+w*c(c)+620; return [o*c(c)-w*s(c)、28+c(b*.5)*99-b*b*b*60-z/ 2-H、Z、(b*b*.3+p((1-(a*a))、7)*。15+.3)*b、b*.7]} o = a*(2-b)*(80-c*2); w = 99-c(a)*120-c(b)*( - hc*4.9)+c(p(1-b、7))*50+c*2; z = o*s(c)+w*c(c)+700; return [o*c(c)-w*s(c)、b*99-c(p(b、7))*50-c/3-z/1.35+450、z、(1-b/1.2)*。9+a*.1、 p((1-b)、20)/4+.05]}} setinterval( 'for(i = 0; i <1e4; i ++)if(s = p(r()、r()、i%46/.74)){z = s [2]; x = ~~(s [0]*f/zh); y = 〜~(s [1]*f/zh); (!m [q = y*f+x] | m [q]> z)m [q] = z、a.fillstyle = "rgb("+〜(s [3]*h)+"、"+〜(s [4]*h)+"、"+〜(s [3]*s [3]* - 80)+")
もちろん、興味のある人は次の実装プロセスと関連理論を理解できます。
この3次元コードローズのプレゼンテーション効果は、モンテカルロ法を使用し、作成者はモンテカルロ法を高く評価しました。彼は、モンテカルロ法は、機能的な最適化とサンプリングの観点から「信じられないほど強力なツール」であると述べました。 Monte Carloメソッドについては、次のことを参照してください:Monte Carlo Method。
特定の操作:
外観サンプリングレンダリング効果図
複数の異なる形状図を使用してこのコードローズを形成しました。合計31の形状が使用されました:24枚の花びら、4つの片麻状、2つの葉、1つの花の茎が使用され、各形状図がコードに描かれていました。
まず、サンプリング範囲を定義します。
関数表面(a、b){//パラメーターは0から1の範囲としてaとbを使用しています{x:a*50、y:b*50}; //この表面は50x50ユニットのサイズの平方です}次に、形状描写コードを書きます。
var canvas = document.body.appendChild(document.createElement( "canvas"))、context = canvas.getContext( "2d")、a、b、position; //今、私はaおよびbパラメーターについて.1間隔で表面をサンプリングします:for(a = 0; a <1; a += .1) b); context.fillrect(position.x、position.y、1、1);}}
次に、より密度の高いサンプリング間隔を試してください。
サンプリング間隔がより密度が高くなっているため、ポイントが最も密度が高くなっているため、隣接するポイント間の距離は1ピクセル未満であり、肉眼では間隔を見ることができません(0.01を参照)。あまりにも多くの視覚的な違いを引き起こさないために、サンプリング間隔はさらに減少します。この時点で、図面領域は満たされています(比較結果は0.01と0.001です)。
次に、この式を使用して円を描画します。
関数表面(a、b){var x = a * 100、y = b * 100、radius = 50、x0 = 50、y0 = 50; if((x -x0) *(x -x0) +(y -y0) *(y -y0)<radius){// sircreturn {x:x:x、y:y {x、y {/};オーバーフローを防ぐには、サンプリング条件を追加する必要があります。
if(position = surface(a、b)){context.fillrect(position.x、position.y、1、1);}サンプリングの拒否を必要としない円を定義するには、さまざまな方法があります。どちらを使用して円を定義する必要はないので、別の方法を使用して円を定義します。
関数表面(a、b){//極座標を使用した円角度= a * math.pi * 2、radius = 50、x0 = 50、y0 = 50; return {x:math.cos(angle) * radius * b + x0、y:math.sin(angle) * radius * radius * b + y0};};}(この方法では、前の方法と比較して、充填のために密なサンプリングが必要です。)
わかりました、今、円を変形させて、花びらのように見せます。
関数表面(a、b){var x = a * 100、y = b * 100、radius = 50、x0 = 50、y0 = 50; if((x -x0) *(x -x0) +(y -y0) *(y -y0)<radius * radius){return {x:x:x、y:y *(1 + + b) / 2 // demorationこれはバラの花びらのように見えます。ここでは、いくつかの関数値を変更することもできます。多くの興味深い形状が表示されます。
次に、それに色を追加します:
関数表面(a、b){var x = a * 100、y = b * 100、radius = 50、x0 = 50、y0 = 50; if((x -x0) *(x -x0) +(y -y0) *(y -y0)<radius * radius){return {x:x、y:y *(1 + + b) / r gradientg:50、b:50};} else {return null;}} for(a = 0; a <1; a + = .01){for(b = 0; b <1; b + = .001){if(point = surface(a、b)){context.fillstyle = "rgb(" + point.r + " ")"; context.fillrect(point.x、point.y、1、1);}}}}色付きの花びらが現れます。
3D表面および視点投影
たとえば、3次元表面を定義することは、単純です。
関数表面(a、b){var angle = a * math.pi * 2、radius = 100、length = 400; return {x:math.cos(angle) * radius、y:math.sin(angle) * hing nength / 2、//長さ// // 0};}次に、投影の視点を追加します。まず、カメラを定義する必要があります。
上記のように、カメラをx/y平面に(0、0、z)位置とキャンバスに配置します。キャンバスに投影されるサンプリングポイントは次のとおりです。
var px、py、//キャンバスxおよびy coordinatesperspective = 350、halfheight = canvas.height / 2、halfwidth = canvas.width / 2、cameraz = -700; for(a = 0; a <1; a += .001){for(b = 0; b <1; b <1; b += .01){b += .01){ =(point.x * Perspective) /(point.z -cameraz) + halfwidth; py =(point.y * perspective) /(point.z -cameraz) + halfheight; context.fillstyle = "rgb(" + point.r + "、" + point.g + "、" + point.b + ";効果は次のとおりです。
Zバッファー
Zバッファーは、コンピューターグラフィックスで非常に一般的な手法です。シェーディングオブジェクトの場合、「隠された表面除去」作業が実行され、隠されたオブジェクトの背後にある部分が表示されません。
上の写真は、Zバッファーテクノロジーで処理されたバラです。 (あなたはそれがすでに3次元性を持っていることがわかります)
コードは次のとおりです。
var zbuffer = []、zbufferindex; (point.z -cameraz) + halfheight); zbufferindex = py * canvas.width + px; if((typeof zbuffer [zbufferindex] === "undefined")||(point.z <zbuffer [zbufferindex])){zbuffer [zbufferindex] = point = " point.r + "、" + point.g + "、" + point.b + ")"; context.fillrect(px、py、1、1);}}}}}回転します
任意のベクトル回転法を使用できます。コードローズの作成では、Euler Rotationを使用します。次に、以前に書かれた管状オブジェクトを回転させて、y軸の周りを回転させます。
関数表面(a、b){var angle = a * math.pi * 2、radius = 100、length = 400、x = math.cos(angle) * radius、y = math.sin(angle) * radius、z = b * length / 2、yaxisrotationangle = -.4、// in radians!rotatedx = x * math.cos(yaxisrotationange) + z * * Math.sin(yaxisrotationangle)、rotatedz = x * -math.sin(yaxisrotationangle) + z * math.cos(yaxisrotationangle); return {x:rotatedx、y:y、z:rotatedz、r:0、g:math.floor(b * 255)、b:0};};効果:
モンテカルロ法
サンプリング時間に関しては、大きすぎて小さすぎると視覚的な経験が非常に低いため、合理的なサンプリング間隔を設定する必要があり、ここではモンテカルロ法が使用されます。
var i; window.setInterval(function(){for(i = 0; i <10000; i ++){if(point = surface(math.random()、math.random())){px = math.floor((point.x * perspection) /(point.z -cameraz) +halfwidth); halfheight); zbufferindex = py * canvas.width + px; if((typeof zbuffer [zbufferindex] === "undefined")||(point.z <zbuffer [zbufferindex])){zbuffer [zbufferindex] = point.z point.g + "、" + point.b + ")"; context.fillrect(px、py、1、1);}}}}、0);AとBをランダムパラメーターとして設定し、十分なサンプリングで表面充填を完全にします。毎回10000ポイントを描き、画面が更新が完了するのを待ちます。
また、乱数が正しくない場合、表面充填効果が正しくないことにも注意する必要があります。一部のブラウザでは、Math.Randomの実行は線形であり、表面充填効果のエラーにつながる可能性があります。現時点では、エラーを回避するために高品質のPRNGサンプリングを実行するには、Mersenne Twister(乱数アルゴリズム)のようなものを使用する必要があります。
仕上げる
バラの各部分が同時に完了してレンダリングするには、同期の値を返すために各パーツのパラメーターを設定するために機能を追加する必要があります。また、セグメント関数を使用して、バラのさまざまな部分を表します。たとえば、花びら部分では、回転と変形を使用してそれらを作成します。
表面サンプリング方法は、3次元グラフィックを作成するための最も有名で最も古い方法の1つですが、モンテカルロとZバッファーを表面サンプリングに追加するこの方法は一般的ではありません。これは、実際のシナリオ制作ではそれほど創造的ではないかもしれませんが、その単純なコードの実装と小さなサイズはまだ満足のいくものです。
うまくいけば、この記事がコンピューターグラフィックの愛好家にさまざまなプレゼンテーション方法を試してみて、それから楽しむことを願っています。 (ローマコルテス)
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。