2017-07-30 9 views
1

私は通常、画面上の位置だけを変更する点を描くつもりです。OpenGL 3.3では、ポイントを描画する効率的で正しい方法がありますか?

通常、色とサイズは変わりません。

は、だから私はpythonで、このクラスPointをした:作成されたポイントのオブジェクトと

class Point2D(): 
    _verts = None 
    _vshader_code = ''' 
     #version 330 

     in vec2 pos; 

     uniform float size; 

     void main() { 
      gl_Position = vec4(pos, 0.0, 1.0); 
      gl_PointSize = size; 
     } 
    ''' 
    _fshader_code = ''' 
     #version 330 

     uniform vec4 col; 

     void main() { 
      gl_FragColor = col; 
     } 
    ''' 

    def __init__(self, size, col): 
     ## CREATE PROGRAM/SHADER ## 
     self.program = GL.glCreateProgram() 

     self.shaders = [ 
      CreateShader(self._vshader_code, GL.GL_VERTEX_SHADER), 
      CreateShader(self._fshader_code, GL.GL_FRAGMENT_SHADER) 
     ] 

     for shader in self.shaders: 
      GL.glAttachShader(self.program, shader) 

     GL.glLinkProgram(self.program) 
     #CheckShaderError(self.program, GL.GL_LINK_STATUS, True, "Error: Program linking failed:") 
     GL.glValidateProgram(self.program) 
     #CheckShaderError(self.program, GL.GL_VALIDATE_STATUS, True, "Error: Program is invalid:") 

     self.unif_size = GL.glGetUniformLocation(self.program, 'size') 
     self.unif_col = GL.glGetUniformLocation(self.program, 'col') 

     GL.glUseProgram(self.program) 
     GL.glUniform1f(self.unif_size, size) 
     GL.glUniform4fv(self.unif_col, 1, col) 

     ## FLAGS ## 
     #GL.glEnable(GL.GL_PROGRAM_POINT_SIZE); 
     GL.glEnable(GL.GL_VERTEX_PROGRAM_POINT_SIZE) 

    def bind_array(self, array): 
     self._verts = array 

     ## BIND BUFFER ## 
     self.vertexArrayObject = GL.glGenVertexArrays(1) 
     GL.glBindVertexArray(self.vertexArrayObject) 

     self.buff = GL.glGenBuffers(1) 
     GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.buff) 

     GL.glBufferData(GL.GL_ARRAY_BUFFER, self._verts.nbytes, self._verts, GL.GL_STATIC_DRAW) 

     self.attr_pos = GL.glGetAttribLocation(self.program, 'pos') 

     GL.glEnableVertexAttribArray(0) 
     GL.glVertexAttribPointer(self.attr_pos, 2, GL.GL_FLOAT, GL.GL_FALSE, 8, None) 

     GL.glBindVertexArray(0) 

    def update_size_and_color(self, size, col): 
     #GL.glPointSize(size) 
     GL.glUseProgram(self.program) 

     GL.glUniform1f(self.unif_size, size) 
     GL.glUniform4fv(self.unif_col, 1, col) 

    def update_elem(self, index, value): 
     GL.glUseProgram(self.program) 

     self._verts[index] = value 
     GL.glBindVertexArray(self.vertexArrayObject) 
     GL.glBufferSubData(GL.GL_ARRAY_BUFFER, index * 8, 8, value) 
     GL.glBindVertexArray(0) 

    def Draw(self): 
     GL.glUseProgram(self.program) 

     GL.glBindVertexArray(self.vertexArrayObject) 
     GL.glDrawArrays(GL.GL_POINTS, 0, len(self._verts)) 
     GL.glBindVertexArray(0) 

    def __del__(self): 
     try: 
      #if the context is alive, you want to try and delete shader/program stuff manually 
      #this could be triggered with e.g. `del Display` 
      for shader in self.shaders: 
       GL.glDetachShader(self.program, shader) 
       GL.glDeleteShader(shader) 
      GL.glDeleteProgram(self.program) 
     except OpenGL.error.NullFunctionError as error: 
      print("context already deleted my shader/program stuff!") 

     GL.glDisable(GL.GL_VERTEX_PROGRAM_POINT_SIZE) 

、次のように私はポイントの描画を行うことができます。

point = Point2D(10.0, numpy.array((1.0, 0.0, 0.0, 1.0), 'f4')) 
point.bind_array(numpy.zeros((2, 2), 'f4')) 

## DRAW ## 
point.update_elem(0, numpy.array((0.5, 0.0), 'f4')) 
point.update_elem(1, numpy.array((-0.5, 0.0), 'f4')) 
point.Draw() 
(...code...) 
point.update_elem(1, numpy.array((0.25, 0.25), 'f4')) 
point.Draw() 

描画が実用的で、一見効率的であり、質問は...:

- 私はそうしていますか?

答えて

3

あなたがやっているやり方はうまくいくでしょう。多くの点(数千から数百万)を描画する場合は、すべての座標を持つ単一の配列を作成し、すべての点の頂点属性を持つ別の配列を作成し、それらの配列を使って1回の描画呼び出しを行うことができます。これにより、描画呼び出しの回数が減り、パフォーマンスの制限要因となる可能性があります。しかし、数十から数百にしか描画していない場合は、おそらく大きな違いに気付かないでしょう。いつものように、あなたのコードをプロファイリングして、推測よりも減速がどこにあるのかを知ることができます。

+0

私はコードを編集し、属性ごとにユニフォームを変更し、異なるポイントのすべての座標を配列にとり、1つまたは複数の –

1

instanced図面を使用する必要があります。ポイントの1つのモデルのみを静的なデータとしてロードし、それらのオブジェクトの位置の配列(他の属性)を使用します。

この方法については多くのチュートリアルがあります。例えば、oneです。

関連する問題