1

いくつかのプリミティブ(線、円など)を描画するために、OpenGLを使用してCでプログラムを作成しています。バッファオブジェクトを使用してプリミティブの頂点を格納することに成功しました。したがって、それらを描画することに成功しました。でも、色の設定方法がわからないので、今は行き詰まっているようです。プログラムの一部は私の先生から提供されたので、色の属性は次の構造を使用して指定する必要があることを知っています。

typedef struct {
    float r;
    float g;
    float b;
    float a;
} vec4;

色の値を格納するためにvec4配列を使用することになっているので、そのような変数を1つ宣言しました。1つ目は、プリミティブ頂点を格納するために使用されるvec2配列です。

vec2 vertices[10000];
vec4 colours[10000];

(私が理解しているように)頂点バッファーの制限を設定するために使用される関数は、次のようになります。

void initShaders(void) 
{
    GLuint buffer;
    GLuint loc;
    GLuint vao;

    /*Create and initialize a program object with shaders */ 
  idProgram = initProgram("ass1vshader.glsl", "ass1fshader.glsl");

    /*installs the program object as part of current rendering state */ 
   glUseProgram(idProgram);

   /*Creat a vertex array object */ 
   glGenVertexArrays(1, &vao);
   glBindVertexArray(vao);

    /*Create buffer in the shared display list space and */ 
     /* bind it as GL_ARRAY_BUFFER */ 
    glGenBuffers( 1, &buffer);
    glBindBuffer( GL_ARRAY_BUFFER, buffer);
    glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)+sizeof(colours), NULL,GL_STATIC_DRAW);

    /*Initialize attribute vPosition in program */ 
    loc = glGetAttribLocation( idProgram, "vPosition");
    glEnableVertexAttribArray(loc);
    glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)BUFFER_OFFSET(0));

    /*Get location of the uniform attribute 'u_proj_matrix' */ 
    idProjection = glGetUniformLocation(idProgram, "u_proj_matrix");

    /*Set graphics attributes */ 
    glLineWidth(3.0);
    glPointSize(1.0);
    glClearColor(1.0, 1.0, 1.0, 1.0);

}

ご覧のとおり、頂点バッファサイズを「vertex」と「colors」の合計サイズに初期化しました。

また、フラグメントシェーダーがカラーリングプロセスで重要な役割を果たしていることも理解できます。次のようになります。

#version 140

in vec4 color;
out vec4  fColor;

void
main()
{    
    fColor = color;
}

プリミティブに色を付ける方法を教えてもらえますか?私が提供した情報が十分であることを願っています。

4

2 に答える 2

1

これを行う1つの方法は、カラー配列を使用することです。glColorPointer()これは、の場合と同じ方法で呼び出すことで実行できますglVertexPointer()

また、これが単なるタイプミスなのか、それとも実際にこのエラーが発生したのかはわかりませんが、次のように書いています。

glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)+sizeof(colours), NULL,GL_STATIC_DRAW);

ただし、頂点配列の名前は「vertex」ではなく「vertices」です(少なくとも以前のステートメントによると)。コンパイルが正常であれば、頂点という名前の別の変数またはデータ構造があることを意味している可能性がありますが、思ったとおりに動作していません。

また、データはインターリーブされていないため(頂点とカラーのデータが別々になっている)、それらに別々のバッファーを使用することをお勧めします。それらが1つの構造にある場合は、単一の配列を使用してストライドを適切に設定できますが、インターリーブされていないため、実行しようとしていることが機能するかどうかはわかりません。

于 2012-04-19T04:42:50.157 に答える
0

まず、頂点シェーダーを表示していません。頂点シェーダーは、頂点ごとの色を受け取り、プリミティブを補間してフラグメントシェーダーに送信するために出力します。私はそれが次のように見える(または見えるはずです)と思います:

uniform mat4 u_proj_matrix;

in vec4 vPosition;
in vec4 vColor;

out color;

void main()
{
    gl_Position = u_proj_matrix * vPosition;
    color = vColor;
}

したがって、属性vColorに対して行ったのと同じ方法で、ソースを指定する必要がある追加の頂点ごとの属性がありvPositionます。

loc = glGetAttribLocation(idProgram, "vColor");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, 
                      (GLvoid*)BUFFER_OFFSET(sizeof(vertices)));

これは、すべての10000頂点の座標の後に、バッファに格納されるすべての10000頂点の色を指定します。


ただし、user1118321ですでに説明したように、単一の頂点の座標と色を一緒に保存して、属性をインターリーブする方がよい場合があります(可能なのは1つだけではありません)。この場合、次のような構造になります。

typedef struct {
    vec2 coords;
    vec4 color;
} vertex;

そしてそれらの単一の配列:

vertex vertices[10000];

ただし、この場合、次のストライドパラメータとオフセットパラメータを使用してデータがインターリーブされていることをOpenGLに通知する必要がありますglVertexAttribPointer

//for position:
glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 
                      sizeof(vertex), (GLvoid*)offsetof(vertex, coords));

//for color:
glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 
                      sizeof(vertex), (GLvoid*)offsetof(vertex, color));

これにより、OpenGLは、2つの連続する頂点の属性値間のストライド(1から次へのオフセット)がカスタム構造体のサイズであることを通知します。ある頂点の座標データの先頭から次の頂点の座標データに移動するという意味は、sizeof(vertex)バイト(おそらくsizeof(vec2)+sizeof(vec4) = 24)を「ジャンプオーバー」する必要があり、同様に色も同様です。

さらに、頂点データは最初の頂点の座標メンバーのオフセットで始まり(おそらく0)、カラーデータは最初の頂点のカラーメンバーのオフセットで始まる(おそらく)ことをGLに伝えsizeof(vec2) = 8ます。

于 2012-04-19T08:37:24.470 に答える