importos# For mac... I am using a macimportglfw# We're using this instead of GLUT as we have more flexibilityimportnumpyasnp# We will use numpy for our arrays# Using the API wrapper instead of something mugh higher. Keep in mind that the API is a state machinefromOpenGL.GLimport*fromOpenGL.arraysimport*fromctypesimportc_void_pfromPILimportImageclassHelloWindow():width=800height=640title='Hello Window'window=Noneshader_program=Nonevao=Nonevbo=Nonetexture=Nonevertex_gsl="""
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 3) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main() {
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord);
}
"""fragment_gsl="""
#version 410 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
void main() {
FragColor = texture(texture1, TexCoord);
}
"""def__init__(self):ifnotglfw.init():raiseTypeError('Unable to initalize glfw')self.main()defmain(self):# Set window hintsself.set_window_hints()# Create the windowself.create_window()max_vertex_attributes=glGetIntegerv(GL_MAX_VERTEX_ATTRIBS)print('Maximum number of vertex attributes in a vertex shader is: '+str(max_vertex_attributes))# Keep the window open in a loopself.loop()defset_window_hints(self):glfw.window_hint(glfw.SAMPLES,4)# Using the core version in Mac OS but can be set to something elseglfw.window_hint(glfw.CONTEXT_VERSION_MAJOR,4)glfw.window_hint(glfw.CONTEXT_VERSION_MINOR,1)glfw.window_hint(glfw.OPENGL_PROFILE,glfw.OPENGL_CORE_PROFILE)glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT,True)defcreate_window(self):self.window=glfw.create_window(self.width,self.height,self.title,None,None)ifnotself.window:raiseTypeError('Unable to create the window')glfw.terminate()glfw.make_context_current(self.window)glfw.set_framebuffer_size_callback(self.window,self.frame_buffer_size)### Let's setup our dataverts=np.array([# positions # colors # texture coords[-0.5,0.5,0.0,1.0,0.0,0.0,0.0,1.0],[-0.5,-0.5,0.0,0.0,1.0,0.0,0.0,0.0],[0.5,-0.5,0.0,0.0,0.0,1.0,1.0,0.0],[0.5,0.5,0.0,1.0,1.0,0.0,1.0,1.0]],dtype=np.float32)# OpenGL expects 32 bit data. Not 64 bit if you're on a 64 bit machineindicies=np.array([[0,1,3],[1,2,3]],dtype=np.uint32)self.vao=glGenVertexArrays(1)self.vbo=glGenBuffers(1)self.ebo=glGenBuffers(1)glBindVertexArray(self.vao)glBindBuffer(GL_ARRAY_BUFFER,self.vbo)# Bind the buffer as an array buffer and not an element bufferglBufferData(GL_ARRAY_BUFFER,verts,GL_STATIC_DRAW)glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,self.ebo)glBufferData(GL_ELEMENT_ARRAY_BUFFER,indicies,GL_STATIC_DRAW)glVertexAttribPointer(0,3,GL_FLOAT,False,8*verts.itemsize,None)glEnableVertexAttribArray(0)glVertexAttribPointer(1,3,GL_FLOAT,False,8*verts.itemsize,c_void_p(3*verts.itemsize))glEnableVertexAttribArray(1)glVertexAttribPointer(2,2,GL_FLOAT,False,8*verts.itemsize,c_void_p(6*verts.itemsize))glEnableVertexAttribArray(2)glBindBuffer(GL_ARRAY_BUFFER,0)glBindVertexArray(0)self.setup_shader()self.texture=glGenTextures(1)glBindTexture(GL_TEXTURE_2D,self.texture)glPixelStorei(GL_UNPACK_ALIGNMENT,1)# Set the wrapping texture parameters for x,y equivalentsglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT)glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT)# Set the texture filtering parameters from min to maxglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR)glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)# Load our imageimg=Image.open('../res/container.jpg')img.transpose(Image.FLIP_TOP_BOTTOM)img.convert('RGB')data=np.array(list(img.getdata()),np.uint8)# Set the texture dataglTexImage2D(GL_TEXTURE_2D,0,GL_RGB,img.width,img.height,0,GL_RGB,GL_UNSIGNED_BYTE,data)glGenerateMipmap(GL_TEXTURE_2D)#img.close()defloop(self):whilenotglfw.window_should_close(self.window):glClearColor(0.2,0.3,0.3,1.0)glClear(GL_COLOR_BUFFER_BIT)# We always use this after we clear the color# Maintain aspect ratio (optional)glfw.set_window_aspect_ratio(self.window,self.width,self.height)# Handle inputself.capture_input()# Bind the textureglBindTexture(GL_TEXTURE_2D,self.texture)# Do some renderingglUseProgram(self.shader_program)glBindVertexArray(self.vao)#glEnableVertexAttribArray(0)#glDrawArrays(GL_TRIANGLES, 0, 3)glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,None)glfw.swap_interval(1)glfw.swap_buffers(self.window)glfw.poll_events()glfw.destroy_window(self.window)# Add the vao and vbo to an array so they're deleted. We can use this when creating several vaos and vbosvao_list=np.array([self.vao],dtype=np.uint32)vbo_list=np.array([self.vbo],dtype=np.uint32)glDeleteVertexArrays(1,vao_list)glDeleteBuffers(1,vbo_list)glfw.terminate()defcapture_input(self):ifglfw.get_key(self.window,glfw.KEY_ESCAPE)==glfw.PRESS:# Get the key pressed and check if it is escape keyglfw.set_window_should_close(self.window,True)defframe_buffer_size(self,window,width,height):glViewport(0,0,width,height)defsetup_shader(self):vertex_shader=glCreateShader(GL_VERTEX_SHADER)glShaderSource(vertex_shader,self.vertex_gsl)glCompileShader(vertex_shader)ifnotglGetShaderiv(vertex_shader,GL_COMPILE_STATUS):glGetShaderInfoLog(vertex_shader,512,None)raiseTypeError('vertex_shader did not compile correctly. Check the GSL')fragment_shader=glCreateShader(GL_FRAGMENT_SHADER)glShaderSource(fragment_shader,self.fragment_gsl)glCompileShader(fragment_shader)ifnotglGetShaderiv(fragment_shader,GL_COMPILE_STATUS):glGetShaderInfoLog(fragment_shader,512,None)raiseTypeError('fragment_shader did not compile correctly. Check the GSL')self.shader_program=glCreateProgram()glAttachShader(self.shader_program,vertex_shader)glAttachShader(self.shader_program,fragment_shader)glLinkProgram(self.shader_program)ifnotglGetProgramiv(self.shader_program,GL_LINK_STATUS):glGetProgramInfoLog(self.shader_program,512,None)glDeleteShader(vertex_shader)glDeleteShader(fragment_shader)if__name__=='__main__':hello_window=HelloWindow()