code: def on_initialize(self, event):
      # Build & activate cube program
      self.cube = gl.glCreateProgram()
      vertex = gl.glCreateShader(gl.GL_VERTEX_SHADER)
      fragment = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)
      gl.glShaderSource(vertex, cube_vertex)
      gl.glShaderSource(fragment, cube_fragment)
      gl.glCompileShader(vertex)
      gl.glCompileShader(fragment)
      gl.glAttachShader(self.cube, vertex)
      gl.glAttachShader(self.cube, fragment)
      gl.glLinkProgram(self.cube)
      gl.glDetachShader(self.cube, vertex)
      gl.glDetachShader(self.cube, fragment)
      gl.glUseProgram(self.cube)
  
      # Get data & build cube buffers
      vcube_data, self.icube_data = makecube()
      vcube = gl.glCreateBuffer()
      gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vcube)
      gl.glBufferData(gl.GL_ARRAY_BUFFER, vcube_data, gl.GL_STATIC_DRAW)
      icube = gl.glCreateBuffer()
      gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, icube)
      gl.glBufferData(
          gl.GL_ELEMENT_ARRAY_BUFFER, self.icube_data, gl.GL_STATIC_DRAW
      )
  
      # Bind cube attributes
      stride = vcube_data.strides[0]
      offset = 0
      loc = gl.glGetAttribLocation(self.cube, "a_position")
      gl.glEnableVertexAttribArray(loc)
      gl.glVertexAttribPointer(
          loc, 3, gl.GL_FLOAT, False, stride, offset
      )
  
      offset = vcube_data.dtype["a_position"].itemsize
      loc = gl.glGetAttribLocation(self.cube, "a_texcoord")
      gl.glEnableVertexAttribArray(loc)
      gl.glVertexAttribPointer(
          loc, 2, gl.GL_FLOAT, False, stride, offset
      )
  
      # Create & bind cube texture
      crate = checkerboard()
      texture = gl.glCreateTexture()
      gl.glTexParameterf(
          gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR
      )
      gl.glTexParameterf(
          gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR
      )
      gl.glTexParameterf(
          gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE
      )
      gl.glTexParameterf(
          gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE
      )
      gl.glTexImage2D(
          gl.GL_TEXTURE_2D,
          0,
          gl.GL_LUMINANCE,
          gl.GL_LUMINANCE,
          gl.GL_UNSIGNED_BYTE,
          crate.shape[:2],
      )
      gl.glTexSubImage2D(
          gl.GL_TEXTURE_2D,
          0,
          0,
          0,
          gl.GL_LUMINANCE,
          gl.GL_UNSIGNED_BYTE,
          crate,
      )
      loc = gl.glGetUniformLocation(self.cube, "u_texture")
      gl.glUniform1i(loc, texture)
      gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
  
      # Create & bind cube matrices
      view = np.eye(4, dtype=np.float32)
      model = np.eye(4, dtype=np.float32)
      projection = np.eye(4, dtype=np.float32)
      translate(view, 0, 0, -7)
      self.phi, self.theta = 60, 20
      rotate(model, self.theta, 0, 0, 1)
      rotate(model, self.phi, 0, 1, 0)
      loc = gl.glGetUniformLocation(self.cube, "u_model")
      gl.glUniformMatrix4fv(loc, 1, False, model)
      loc = gl.glGetUniformLocation(self.cube, "u_view")
      gl.glUniformMatrix4fv(loc, 1, False, view)
      loc = gl.glGetUniformLocation(self.cube, "u_projection")
      gl.glUniformMatrix4fv(loc, 1, False, projection)
  
      # OpenGL initalization
      gl.glClearColor(0.30, 0.30, 0.35, 1.00)
      gl.glEnable(gl.GL_DEPTH_TEST)
      self._resize(*(self.size + self.physical_size))
      self.timer = app.Timer("auto", self.on_timer, start=True)
  
file_path: vispy/examples/gloo/gl/cube.py
imports: import math
  import numpy
  from vispy import app
  from vispy.gloo import gl
label_desc: Use image node_id 2 for calling the Canvas obj's underlying member method code with example usage: obj.on_initialize(event) without return types