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.
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:
GL_QUADS
GL_TRIANGLE_FAN
or GL_TRIANGLE_STRIP
glDrawElements
and Stick the rectangles together with 2 triangles and 4 vertices