2016-05-20 4 views
0

私は現在、グラフィックスプログラミング/ glslの一部を学んでいます。これは、shader-schoolを使用しています。しかし、私は頂点シェーダについての2回目のレッスンで立ち往生しています。解決策は、YUV色空間の貴様の色相で満たされた三角形を表示するように思われるためシェーダースクール、頂点シェーダー:可変変数

三角形は尋ねた:
YUV-Wheel

私はしかし、私は、それはRGBとYUV間の変換を計算することが可能だということを知っています頂点シェーダまたはフラグメントシェーダの座標空間がどのように機能するかについてはあまりよく分かりません。

マイ頂点シェーダは、次のようになります。

precision highp float; 

attribute vec4 position; 
attribute vec3 color; 

varying vec4 fragPosition; 
void main() { 
    gl_Position = position; 
    fragPosition = position; // send the position to the fragment shader 
} 

私のフラグメントシェーダは、次のようになりながら:

precision highp float; 

varying vec4 fragPosition; // is set by vertex shader 

void main() { 
    gl_FragColor = fragPosition.rgba; 
} 

そしてレンダリング三角形はこのようになります(左の部分は右、解決する問題であり、一部は)これまでのところ私のソリューションです:

shader-school lesson about vertex shaders #2

fragPosition.aは連続的に1.0です。退色はどうして変わるのですか?三角形内の座標空間はどのくらい正確になりますか?私はそれの周りに私の頭をラップすることはできませんし、ブレークポイントや印刷ステートメントなしでは把握するのは簡単ではありません。左下が完全に黒くなっているのはなぜですか?なぜ青い点がありませんか?

答えて

1

OpenGLのデフォルトのスペースはNDCスペースです。その単位立方体は[-1,1]の範囲にあります。 x = -1は画面の左側にあり、x = 1は画面の右側にあり、y = -1、y = + 1、z = -1、z = + 1遠くの平面で。

シェーダで基本的に何をしているのかは、フラグメント座標を色で表示していることです。

座標は[0,1,0,1]のようなもので、色として解釈すると緑色になりますので、三角形の上部は緑色です。三角形の右辺には座標[1、-1,0,1]があり、赤色になります。下は[0、-1,0,1]のようなものです。これは黒です。

Btw実際にはfragment.aが1.0の場合は、gl_FragColor = fragPosition.aaaa;で確認できます。 .aが1.0の場合、.aが〜0.5の場合は白だけが表示され、灰色でなければなりません。

このレッスンでは、代わりにカラー入力(attribute vec3 color;)を使用して、シェーダでrgbaからyuvへの変換を実装すると思います。

1

私は3種類のソリューションを参照してくださいここで

まずFS(フラグメントシェーダ)で全体の計算を行うことです。この種のソリューションは、後処理などには効果的ですが、パフォーマンスに大きな影響を与えます。

デザインアイデア: VS(頂点シェーダ)を介して白い三角形のみを渡し、1つの属性が必要で、位置に基づいてFSのすべての色を実行します。

第2の解決策はVSで色を行い、補間を使用してFSで結果を得ることです。多くの場合、このソリューションは最も高速ですが、すべての種類の問題に単純な補間が含まれているわけではありません。

デザインアイデア: 1つの属性と1つの属性が必要です。 1つの三角形のデータをjsからVSに渡します。そこではコーナーに色を設定し、補間されたカラー値からFSで結果を取得します。

3番目の解決策は、JSの色を初期化することです。各コーナーで1つの色を持つVSに渡し、補間を使用してFSから結果を取得します。この最後の解決策は高いモジュール性を提供し、相互作用を可能にする可能性があります。コストはより長いコードであり、遅くなる可能性があります。

デザインアイデア:2つの属性と1つの可変属性を使用して、位置と色をYUVからVSに変換し、FSの残りの結果と色の補間のみを行います。

私は最後の解決策を単純にコード化しました。あなたはそれを最大限に習得できるからです。

// stackoverflow purposes 
 

 
// initalize canvas and webgl 
 
var canvas = document.getElementById("c"); 
 
var gl = canvas.getContext("webgl"); 
 

 
gl.viewportWidth = canvas.width; 
 
gl.viewportHeight = canvas.height; 
 

 
// create shaders 
 
var vsSource = ` 
 
     precision mediump float; 
 

 
     attribute vec2 a_position; 
 
     attribute vec3 a_color_yuv; 
 

 
     varying vec3 v_color_yuv; 
 
     
 
     void main() { 
 
      v_color_yuv = a_color_yuv; 
 
      gl_Position = vec4(a_position, 0., 1.); 
 
     } 
 
     `; 
 

 
var fsSource = ` 
 
     precision mediump float; 
 

 
     varying vec3 v_color_yuv; // is set by vertex shader 
 

 
     void main() { 
 
      float r = v_color_yuv.x + 1.4075 * (v_color_yuv.z); 
 
      float g = v_color_yuv.x - 0.3455 * (v_color_yuv.y) - (0.7169 * (v_color_yuv.z)); 
 
      float b = v_color_yuv.x + 1.7790 * (v_color_yuv.y); 
 
      
 
      gl_FragColor = vec4(r, g, b, 1.); 
 
     } 
 
     `; 
 

 
var vs = gl.createShader(gl.VERTEX_SHADER); 
 
var fs = gl.createShader(gl.FRAGMENT_SHADER); 
 

 
// replace removes nonascii chars from shaders sources, because I created them with http://es6-features.org/#StringInterpolation 
 
gl.shaderSource(vs, vsSource.replace(/[^\x00-\x7F]/g, "")); 
 
gl.shaderSource(fs, fsSource.replace(/[^\x00-\x7F]/g, "")); 
 

 
gl.compileShader(vs); 
 
gl.compileShader(fs); 
 

 
// create webgl program 
 
var shaderProgram = gl.createProgram(); 
 

 
gl.attachShader(shaderProgram, vs); 
 
gl.attachShader(shaderProgram, fs); 
 

 
gl.linkProgram(shaderProgram); 
 

 
gl.useProgram(shaderProgram); 
 

 
// set uniform and attribute locations 
 
var a_position = gl.getAttribLocation(shaderProgram, "a_position"); 
 
gl.enableVertexAttribArray(a_position); 
 

 
var a_color_yuv = gl.getAttribLocation(shaderProgram, "a_color_yuv"); 
 
gl.enableVertexAttribArray(a_color_yuv); 
 

 
// set attribute buffers 
 
var trianglePositionBuffer = gl.createBuffer(); 
 
gl.bindBuffer(gl.ARRAY_BUFFER, trianglePositionBuffer); 
 
var positions = [ 
 
    -1.0, -1.0, 
 
    1.0, -1.0, 
 
    1.0, 1.0 
 
]; 
 
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); 
 
trianglePositionBuffer.itemSize = 2; 
 

 
var triangleColorYUVBuffer = gl.createBuffer(); 
 
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorYUVBuffer); 
 
// modify this 
 
var colorsYUV = [ 
 
    0.5, -0.5, -0.5, 
 
    0.5, 0.0, 0.0, 
 
    0.5, -0.5, 0.5 
 
]; 
 
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorsYUV), gl.STATIC_DRAW); 
 
triangleColorYUVBuffer.itemSize = 3; 
 

 
var bufferSize = 3; 
 

 
// final draw 
 
gl.clearColor(0.0, 0.0, 0.0, 1.0); 
 
gl.enable(gl.DEPTH_TEST); 
 

 
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); 
 
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 

 
gl.bindBuffer(gl.ARRAY_BUFFER, trianglePositionBuffer); 
 
gl.vertexAttribPointer(a_position, trianglePositionBuffer.itemSize, gl.FLOAT, false, 0, 0); 
 

 
gl.bindBuffer(gl.ARRAY_BUFFER, triangleColorYUVBuffer); 
 
gl.vertexAttribPointer(a_color_yuv, triangleColorYUVBuffer.itemSize, gl.FLOAT, false, 0, 0); 
 

 
gl.drawArrays(gl.TRIANGLES, 0, bufferSize);
<canvas id="c" style="border: none;" width="500" height="500"></canvas>

Explinations

fragPosition.a連続的に1.0です。退色はどうして変わるのですか?

左の画像がYUVの色であると想像すれば、右下隅に灰色があるので、Yはおそらく0.5です。

これはフェージングとは関係ありませんが、Yは常に0です。これは黒色でグレーではありません。そして色は暗くなります。

三角形内の座標空間はどのくらい正確になりますか?

Yおよび< -0.5,0.5> Iは範囲< 0,1にYUV色を使用すると言うことができます> UおよびV

ため

反復trhu三角形のすべてのコーナーをします。

  • 左下隅から開始します。
  • このコーナーにはどのような座標がありますか? -1、-1
  • どのような色がありますか?緑
  • YUVでこの色は何ですか?まあ、Y>が範囲< 0,1のどこかにあるかもしれない(しかし、私はその0.5を推測)、Uは-0.5でなければならず、Vは-0.5

は、次に行くことができますする必要があります。右下コーナー

  • このコーナーにはどのような座標がありますか? 1、-1
  • どのような色がありますか?グレー
  • YUVでこの色は何ですか?座標何

    • は、このコーナーである:Yは右上、0.5

    最終コーナーである一方、UおよびVは、両方とも0でなければなりませんか? 1、1

  • どのような色がありますか?オレンジ
  • YUVのこの色は何ですか? Uは、あなたのシェーダコードで

(私はその0.5を推測するが、)Vが0.5であり、Yは範囲< 0,1にあるとき> -0.5しなければならない、あなたは色として位置を使用しようとしています。さて、我々はYUVの色を持っていると言うことができます。そして私たちはXYポジションを持っています。 Yを定数として設定します(0を使用しましたが、0.5にする必要があります)。しかし、XY!=定数* UV +定数(定数に関係なく)は、所望の三角形がYUVカラーシステムからカラーシステムをねじれているためです。左下は緑色で、これは大丈夫です。しかし、右下に青色の代わりに灰色があります。右上はオレンジで、紫色ではありません。そして、私たちが知りませんトップを左に、私たちは気にしません。 これには2つの解決策があります。各コーナーにカラーを割り当てるカラーバッファを作成するか、オーウェンカラーシステムを作成します(フラグメントシェーダで)。私は最初の解決法を使用したので、古典的なYUVシステムを維持しました。

なぜあなたが使用左下隅真っ黒

がある、色、ので、あなたのgl_FragColor.rgba=position.xyzwとして座標れます[-1、-1、0、1]左下隅に、 [0,0,0,1] =黒の色に変身

なぜ左画像には青いスポット

がない、著者はおそらく行います欲しい。あなたの写真では、青はあなたのためのZ座標です。これは時間全体で0です。青はどこにもありません。

関連する問題