0

プログラムで独自の頂点シェーダーとフラグメント シェーダーを作成しようとしています (これは基本的に、VBO で三角形を表示する非常に単純なプログラムです)。ただし、実行しようとすると、常に何も表示されない黒い画面が表示されます。コンパイルログを確認しましたが、エラーなしで返されます。私は自分のカスタム シェーダーでプログラムをまだ実行していないので、ここで何か間違ったことをしているのではないかと思います。OpenGL 3.2 および GLSL 1.5 でコードを実行しています

以下は、現在実行しようとしているコードです


GLuint vbo;

GLfloat data[] = {0.0, 0.0, -5.0,
                  1.0, 0.0, -5.0,
                  1.0, 1.0, -5.0
};

const char *vertexShader = "\n\
#version 150\n\
\n\
layout (location=0) in vec4 position;\n\
void main()\n\
{\n\
gl_Position = position;\n\
}\n\
";

const char *fragmentShader = "\n\
#version 150\n\
\n\
out vec4 outColor;\n\
\n\
void main()\n\
{\n\
    outColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
}";


- (void)drawRect:(NSRect)dirtyRect
{
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    glUseProgram(programId);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableClientState(GL_VERTEX_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, 0);

    glDrawArrays(GL_TRIANGLES, 0, sizeof(data));

    glFlush();


    glDisableClientState(GL_VERTEX_ARRAY);

}

-(void)reshape
{
    glViewport(0, 0, w, h);
    gluPerspective(45.0,                  //The camera angle
                   (double)w / (double)h, //The width-to-height ratio
                   1.0,                   //The near z clipping coordinate
                   200.0); 
}

-(void)prepareOpenGL
{
    glEnable(GL_DEPTH_TEST);  

    glGenBuffersARB(1, &vbo);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);


    vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderId, 1, &vertexShader, NULL);

    glCompileShader(vertexShaderId);

    GLint completed;
    glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &completed);

    if (!completed)
    {
        GLint length;
        GLchar *log;
        glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &length);

        log = (GLchar *)malloc(length);
        glGetShaderInfoLog(vertexShaderId, length, &length, log);
        fprintf(stderr, "Vertex compile log = '%s'\n", log);
    }



    fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL);
    glCompileShader(fragmentShaderId);

    GLint complete;

    glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &complete);

    if (!complete)
    {
        GLint length;
        GLchar *log;
        glGetShaderiv(fragmentShaderId, GL_INFO_LOG_LENGTH, &length);

        log = (GLchar *)malloc(length);
        glGetShaderInfoLog(fragmentShaderId, length, &length, log);
        fprintf(stderr, "fragment compile log = '%s'\n", log);
    }

    programId = glCreateProgram();

    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);

    glLinkProgram(programId);

    glUseProgram(programId);
}
4

1 に答える 1

9

ここにはいくつかの問題があります。上から下まで:


GLfloat data[] = {0.0, 0.0, -5.0,
                  1.0, 0.0, -5.0,
                  1.0, 1.0, -5.0
};

Z 値が表示ボリューム [-1, 1] の外にあるため、このデータは表示されません。代わりに 0.0 を使用してみてください。


#version 150\n\
\n\
layout (location=0) in vec4 position;

layout(location=0)次の 2 つの状況での頂点シェーダー入力に対してのみ有効です。

  1. GLSL バージョン 3.30 以降を使用しています。あなたのシェーダーは言い#version 150ます。
  2. ARB_explicit_attrib_location 拡張機能を使用しています。その場合、#extensionシェーダーでアクティブ化するための宣言が必要になります。さらに、OSX の GL 3.2 サポートがこの拡張機能を提供していないことも知っています。

したがって、昔ながらの方法で行う必要がありますglBindAttribLocationプログラムをリンクする前に、この関数を使用してください。


glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);

これは不必要であるだけでなく、レンダリングしようとすると OpenGL エラーが発生するなどの原因となるため、実行しようとしているものを積極的に破壊します。

汎用属性を使用している場合、古いスタイルの属性は必要ありません。


glDrawArrays(GL_TRIANGLES, 0, sizeof(data));

sizeof(data)配列のバイト単位のサイズです。dataほとんどのマシンでは、それは 36 になります。36 の頂点をレンダリングしているのではありません。あなたは3つをレンダリングしています。したがって、これは次のようになります。

glDrawArrays(GL_TRIANGLES, 0, 3);

gluPerspective(45.0,                  //The camera angle
               (double)w / (double)h, //The width-to-height ratio
               1.0,                   //The near z clipping coordinate
               200.0); 

これはまったく無意味な問題ではありません。シェーダーでレンダリングしており、組み込みのマトリックスを使用していません。これは何もしませ


glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);

これもおそらく「問題」ではありませんが、問題になる可能性があります。「ARB」で終わる関数と列挙子は、OpenGL 拡張機能を表します。したがって、ARB_vertex_buffer_object 拡張によって公開された関数を使用しています。

この拡張機能は GL 1.4 以降のコアです。実際、拡張機能を一貫して使用していません(ここで問題が発生する可能性があります)。ARB 拡張機能を使用してバッファーのデータを設定していますが、レンダリング時にコア関数を使用しています。

ARB 拡張機能を捨てて、コア機能を使用するだけです。


    log = (GLchar *)malloc(length);
    glGetShaderInfoLog(vertexShaderId, length, &length, log);
    fprintf(stderr, "Vertex compile log = '%s'\n", log);

これでバグが発生することはありませんが... への呼び出しはfreeどこですか?


glLinkProgram(programId);
glUseProgram(programId);

シェーダーをコンパイルした後、またはプログラムをリンクした後は、常に エラーをチェックする必要があります。


あなたのコードは、ある種のフランケンシュタインのプログラムを形成するために、さまざまなソースから一緒にコピー アンド ペーストされているようです。あなたの問題のほとんどは、あなたが計画している使用方法とは異なる方法で動作するさまざまなコードから生じています。これが実際にどのように機能するかを実際に調査する必要があります。そうすれば、これらの問題に遭遇することはありません。

于 2012-04-21T16:52:55.470 に答える