Search code examples
pythonopenglgraphicspygame

Drawing rectangle analysis


I decided to print out a rectangle on the screen of a PyGame window.In my previous question I asked how to draw a Triangle and this answer helped me actually print out a triangle.

I tried to do the same for a rectangle so lets dive in the analysis:

The Shape class shouldnt change since:

class Shape:



    def __init__(self,vertices:tuple,counter:int):

        self.shapeid:int = len(vertices)/6

        self.vertices = np.array(vertices,dtype=np.float32)



        self.vao = glGenVertexArrays(counter)

        glBindVertexArray(self.vao)

        self.vbo = glGenBuffers(counter)

        glBindBuffer(GL_ARRAY_BUFFER,self.vbo)

        glBufferData(GL_ARRAY_BUFFER,self.vertices.nbytes,self.vertices,GL_STATIC_DRAW)

        glEnableVertexAttribArray(0)

        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,24,ctypes.c_void_p(0))

        glEnableVertexAttribArray(1)

        glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,24,ctypes.c_void_p(12))

a rectangle is still a list of vertices and the structure of each vertex shouldnt change since it is still specified by the same 6 floating type numbers (x,y,z,r,g,b).

So any changes should be made in the Window class:

class Window:

    shapes:list[Shape] = []

    def __init__(self,width:int,height:int):

        display = (width,height)

        pg.display.set_mode(display,DOUBLEBUF|OPENGL)

        glClearColor(0.0,0.0,0.0,1)

        self.shader = self.createShader("Shaders/vertex.txt","Shaders/fragment.txt")

        glUseProgram(self.shader)



    def loop(self):

        while True:

            for event in pg.event.get():

                if event.type==pg.QUIT:

                    pg.quit()

                    quit()



            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

            for i in self.shapes:

                glBindVertexArray(i.vao)

                if i.shapeid==3:

                    glDrawArrays(GL_TRIANGLES,0,3)

                elif i.shapeid==4:

                    glDrawArrays(GL_TEXTURE_RECTANGLE,0,4)







            pg.display.flip()















    def createShader(self,vertexShederFileName:str,fragmentShederFileName:str):

        with open(vertexShederFileName,'r') as v:

            vertex_src = v.readlines()


        with open(fragmentShederFileName,'r') as f:

            fragment_src = f.readlines()

        shader = compileProgram(compileShader(vertex_src,GL_VERTEX_SHADER),compileShader(fragment_src,GL_FRAGMENT_SHADER))

        return shader


    def addShape(self,shape:Shape):

        self.shapes  = self.shapes + [shape]

Since now we have 4 vertices we have set the 3rd parameter of glDrawArrays() =4.I checked out if there was a issue with the number of elements in the rectangle

pg.init()

win = Window(720,360)






rectangle = (0.0,0.0,0.0,1.0,1.0,1.0,

        0.0,0.5,0.0,1.0,1.0,1.0,

        0.5,0.5,0.0,1.0,1.0,1.0,

        0.5,0.0,0.0,1.0,1.0,1.0

        )

shape1 = Shape(rectangle,1)



win.addShape(shape1)

win.loop()






since if for example len(rectangle)=23 then self.shapeid:int = len(vertices)/6 returns 3 and obviously the code doesnt work but I think the elements of rectange are 24 so I dont know why this code doesnt work.


Solution

  • GL_TEXTURE_RECTANGLE cannot be used with glDrawArrays. This enum constant has no meaning in connection with glDrawArrays and causes an OpenGL error (glGetError).
    The valid primitive types are GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY, GL_LINES_ADJACENCY, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_TRIANGLE_STRIP_ADJACENCY, GL_TRIANGLES_ADJACENCY, GL_PATCHES and the deprecated (still avalaibel with a compatibility profile OpenGL Context) GL_QUADS GL_QUAD_STRIP, and GL_POLYGON.

    So if you want to draw a rectangle you have 4 options:

    1. Use a compatibility OpenGL Context and GL_QUADS
    2. Draw 1 singe rectangle with GL_TRIANGLE_FAN or GL_TRIANGLE_STRIP
    3. Stick the rectangles together with 2 triangles and 6 vertices
    4. Use an index buffer and glDrawElements and Stick the rectangles together with 2 triangles and 4 vertices