基本的なOpenGL、頂点バッファー、Pyglet
質問
編集:Rotoglupは私のコードで問題を見つけ、削除したシェーダーを追加してソリューションが完成しました。正しいコード(シェーダー付き)については、以下の私の答えを参照してください。
こんにちは、みんな !
モダンなopenglの基本を学ぼうとしています このチュートリアル.
ただし、C ++ではなくPython/Pygletでやりたいと思います。 Pygletは、低レベルのOpenGLの多くを抽象化できることを知っています。しかし、抽象化のレイヤーの後ろに隠すことに移る前に、基本のいくつかを理解したいと思います。
私の問題は非常に単純です。以下のコードは、私が期待している3ではなく、単一のポイントのみを描画します。私のコードは、私が知る限り、チュートリアルのC ++と同じですが、頂点とフラグメントシェーダーの削除を除き( グリートール Pythonで)、それは私の問題に違いをもたらさないようです。
単一のポイントに物事を単純化することは、私が理解していない行動を示しています(最初の座標は何かに影響を与える唯一のものであるように見えます)。または一般的にも3D:p
関連するコードは次のとおりです。
import pyglet
from pyglet.gl import *
window = pyglet.window.Window()
positionBufferObject = GLuint()
vao = GLuint()
vertexPositions = [0.0, 0.0, 0.0,
0.25, 0.0, 0.0,
1.75, 1.75, 0.0]
vertexPositionsGl = (GLfloat * len(vertexPositions))(*vertexPositions)
@window.event
def on_draw():
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0)
glDrawArrays(GL_POINTS, 0, 3)
glDisableVertexAttribArray(0)
glGenBuffers(1, positionBufferObject)
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject)
glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glClearColor(0.0, 0.0, 0.0, 0.0)
pyglet.app.run()
解決
glDrawArrays(GL_POINTS, 0, 1)
チュートリアルでは、1ポイントを描画するように指示します。1は3です。
glDrawArrays(GL_POINTS, 0, 3)
また、頂点の4番目のコンポーネントは0ではなく1である必要があることにも注意してください。
vertexPositions = [0.0, 0.0, 0.0, 1.0,
0.25, 0.0, 0.0, 1.0,
1.75, 1.75, 0.0, 1.0]
または、Wコンポーネントを削除することもできます。
vertexPositions = [0.0, 0.0, 0.0,
0.25, 0.0, 0.0,
1.75, 1.75, 0.0]
次の呼び出しを変更します。
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0)
別のことは、私はPygletの専門家ではありませんが、Glbufferdataは、そのcの対応物のように、要素ではなくバイトでサイズをとる可能性があります。各フロートは4バイトで、試すことができます。
glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW)
他のヒント
私はついにこれを正しくしました!
頂点、gldrawarrays、glvertexattribpointerをいじり、単一のドットが表示されることがあるという事実に惑わされていたようです。これは事故のように思われます。Toglupの答えによって提供される修正により、何も描かれていません。これは、私の元の質問のコードの「正しい」動作です。
それが誰にでも役立つ場合に備えて、私の間違いの目録は次のとおりです。
チュートリアルのクリップスペース変換の説明が完全に欠落しているのではなく、W座標を0に設定します。
glbufferdataにバイトが予想されるときに頂点でバッファーのサイズを与えます。
- 頂点とフラグメントシェーダーを削除します(上記の2つの問題を探している間にコードを簡素化するため)。これにより、何もレンダリングされないことが保証されました...私が時々取得していた(バギー?)シングルドットを除いて。
記録のために、以下のコードには、シェーダーを通過する単一の三角形が表示されます。私が最新の状態になり、OpenGLを修正したいと考えています。要件はピグレットとグレトールです。
import pyglet
from pyglet.gl import *
from gletools import ShaderProgram, FragmentShader, VertexShader
window = pyglet.window.Window()
positionBufferObject = GLuint()
vertexPositions = [0.75, 0.75, 0.0, 1.0,
0.75, -0.75, 0.0, 1.0,
-0.75, -0.75, 0.0, 1.0]
vertexPositionsGl = (GLfloat * len(vertexPositions))(*vertexPositions)
program = ShaderProgram(
FragmentShader('''
#version 330
out vec4 outputColor;
void main()
{
outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}'''),
VertexShader('''
#version 330
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}''')
)
@window.event
def on_draw():
with program:
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0)
glDrawArrays(GL_TRIANGLES, 0, 3)
glDisableVertexAttribArray(0)
glGenBuffers(1, positionBufferObject)
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject)
glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
pyglet.app.run()