回転マニピュレータ用の glsl シェーダを作成しています。私はAutodesk Mayaスタイルを目指しています。xyとzの回転のそれぞれに3つの軸があり、カメラの前方軸に沿った回転に1つの軸が4に等しいです。
ユーザーは、ビューポートで直接選択することにより、操作の結果を特定の軸に制限することができます。
オブジェクトの選択を有効にするために、レンダー ターゲットとして 2 つのテクスチャがアタッチされたカスタム フレームバッファを使用しています。1 つは色用、もう 1 つはセレクション ID 用です。
問題は、これらの 4 つの軸を GL_LINES モードで描画すると、ユーザーにとって問題が発生することです。線が細くきれいに描かれている場合、ユーザーはそれらを非常に正確にクリックして特定の軸をアクティブにする必要があります。これは、軸の適切な object_id を持つピクセルを正確に選択する必要があるためです。2 つの別々の図面を作成することで、彼の生活を楽にしたいと考えています。カラー出力用の細い線と objectid 出力テクスチャ用の 3 倍の幅の線。
私はopenGLの初心者です。今、私の単純なロジックは、フラグメント シェーダーにカラーまたは objectid バッファーのどちらに描画するかを指示するブール値のユニフォームを渡しています。
渡されたrender_targetセレクターを使用した描画コマンドは次のとおりです
GLfloat lw;
glGetFloatv(GL_LINE_WIDTH,&lw);
glUniform1ui(7,0);//render to RGB
glDrawArrays(GL_POINTS,0,1);
glUniform1ui(7,1);//render to OBJECTID
glLineWidth(10);
glDrawArrays(GL_POINTS,0,1);
glLineWidth(lw);
そして、ここにフラグメントシェーダーがあります:
#version 450
//inputs
layout(location=6) uniform uint manipulator_selected_axis;
layout(location=7) uniform uint render_to_selection_buffer;
//outputs
layout(location=0) out vec4 out_color;
layout(location=1) out float out_objectid;
void main(void)
{
if (render_to_selection_buffer==1)
{
switch (gl_PrimitiveID)
{
case 0: //CAMERA FORWARD
out_objectid=float(253)/256;
break;
case 1: //X
out_objectid=float(250)/256;
break;
case 2: //Y
out_objectid=float(251)/256;
break;
case 3: //Z
out_objectid=float(252)/256;
break;
}
out_color=vec4(0,0,0,0);
}
else
{
vec4 active_axis_color=vec4(1.0,1.0,0.0,1.0);
switch(gl_PrimitiveID)
{
case 0: //CAMERA FORWARD
if(manipulator_selected_axis==0)
out_color=active_axis_color;
else
out_color =vec4(1.0,0.5,1.0,1.0);
break;
case 1: //X
if(manipulator_selected_axis==1)
out_color=active_axis_color;
else
out_color =vec4(1.0,0.0,0.0,1.0);
break;
case 2: //Y
if(manipulator_selected_axis==2)
out_color=active_axis_color;
else
out_color =vec4(0.0,1.0,0.0,1.0);
break;
case 3: //Z
if(manipulator_selected_axis==3)
out_color=active_axis_color;
else
out_color =vec4(0.0,0.0,1.0,1.0);
break;
case 4:
out_color =vec4(0.6,0.6,0.6,1.0);
break;
}
out_objectid=0;
}
}
そのために使用しているロジックは、見苦しく最適化されていないように見えるので、本当に好きではありません。まず、シェーダーを 2 回実行する必要があり、かなり複雑なジオメトリ シェーダーがあり、そこで円を生成するためです。2 つ目は、私のフラグメント シェーダーには多数の if else があり、gpu は分岐を好まないと言われたためです。
質問 1 同じことを行うシェーダーを作成する別の適切な方法は何ですか? 質問 2 はより技術的なものです。

ここでは、これら 2 つの glDrawArrays 呼び出しで得られるもののスクリーンショットを提供します。ご覧のとおり、カラーバッファーに黒い輪郭があります。問題は、framgent シェーダーが out_objectid ターゲットのレンダー コードを実行するときに、下の図のようにいくつかのダーティ ランダム情報を out_color に書き込むため、out_color=vec4(0,0,0,0 で上書きする必要があったことです。 )。少なくともそれはきれいな黒を与えます。
質問 2. 私の間違いはどこですか? objectid ブロックが out_color に書き込まれないようにするにはどうすればよいですか? ありがとう更新:提案されたことに従って、この種の効果が得られました。openGL の内部で何が起こっているのかわかりません。まだ GL_DEPTH_COMPONENT に書き込み、そのような結果につながる未定義の深さテストを行っているようです。マニピュレータは常に上にあるため、この描画呼び出し中に深度書き込みは必要ありません。追加のアドバイスをいただけるかもしれません。
描画コード
glBindBuffer(GL_ARRAY_BUFFER,0);
glUseProgram(program_id_ctl_manip_color);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
glUniform4f(0,0,0,0,1);
glUniform1f(5,0.67);
glUniform1ui(6,manipulator_axis_highlight);
glUniformMatrix4fv(10,1,GL_TRUE,cam.matrix_view.m);
glUniformMatrix4fv(14,1,GL_TRUE,cam.matrix_projection_ortho.m);
glUniformMatrix4fv(18,1,GL_TRUE,cam.matrix_camera.m);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glDrawArrays(GL_POINTS,0,1);
GLfloat lw;
glGetFloatv(GL_LINE_WIDTH,&lw);
glLineWidth(6);
glUseProgram(program_id_ctl_manip_objectid);
glUniform4f(0,0,0,0,1);
glUniform1f(5,0.67);
glUniform1ui(6,manipulator_axis_highlight);
glUniformMatrix4fv(10,1,GL_TRUE,cam.matrix_view.m);
glUniformMatrix4fv(14,1,GL_TRUE,cam.matrix_projection_ortho.m);
glUniformMatrix4fv(18,1,GL_TRUE,cam.matrix_camera.m);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glDrawArrays(GL_POINTS,0,1);
GLenum buffers[2]={GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1};
glDrawBuffers(2,buffers);
glLineWidth(lw);