Skip to main content
Notice removed Draw attention by N3RDIUM
Bounty Ended with the_Demongod's answer chosen by N3RDIUM
Rollback to Revision 1
Source Link
Vaillancourt
  • 16.4k
  • 17
  • 56
  • 61

Python GLFW and PyOpenGL: How to update a VBO from a thread while rendering at the same time?

I'm really new to this community. I'm sorry for any mistakes in advance.I'm making a game like minecraft with GLFW and OpenGL. The problem is, itI just renders two faces correctly and the other faces havecan't render a wierd glitchVBO while I update it from another thread. Here is my code:

# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from terrain import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
# glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 303)
glFogf(GL_FOG_END, 10010)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

world = World(renderer, player)
world.generate()

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3dupdate_on_resize():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 

    _update_3dupdate_on_resize()

    _setup_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    rendererplayer.render_translate()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()
 
# imports
import glfw, numpy
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *
import threading
import numpy as np

glfw.init()

class TerrainRendererVBOManager:
    def __init__(self, windowrenderer):
        self.event = threading.Event()
        self.to_add = []
        self._len = 0

        self.parent = window

        self.vertices = []
        self.texCoordsrenderer = []

        self.create_vbo(window)
renderer
        self.texture_manager = TextureAtlas()

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientStaterun(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY)


    def shared_contextrun(self, window):
        glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
       for window2i =in glfwself.create_window(500,500, "Window 2", None, window)
        glfwrenderer.make_context_current(window2)
        to_add[:self.event.set()

        while not glfwrenderer.window_should_close(window)to_add_count]:
            if len(self.to_addrenderer.vertices.extend(i[0]) > 0:
                i = self.to_addrenderer.poptexCoords.extend(0i[1])

                bytes_vertices_ = np.array(i[0]).nbytesi
                bytes_texCoords = npself.arrayrenderer.to_add.remove(i[1]i).nbytes

                glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo)
                glBufferSubData(GL_ARRAY_BUFFER, len(self._lenrenderer.vertices), bytes_verticeslen(_[0]) * 4, (c_floatGLfloat * len(i[0]_[0]))(*i[0]*_[0]))
                glVertexPointer glFlush(3, GL_FLOAT, 0, None)
             glVertexPointer(3, GL_FLOAT, 0, glFlush(None)
             glTexCoordPointer(3, GL_FLOAT, 0, None)
                glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo_1)
                glBufferSubData(GL_ARRAY_BUFFER,  len(self._lenrenderer.texCoords), bytes_texCoordslen(_[1]) * 4, (c_floatGLfloat * len(i[1]_[1]))(*i[1])*_[1])
                glTexCoordPointer(2, GL_FLOAT, 0, None)
                glFlush()

          class TerrainRenderer:
    def glVertexPointer__init__(3, GL_FLOAT, 0self, Nonewindow):
                glTexCoordPointer(3, GL_FLOAT,self.window 0,= None)window

                self.vertices +== i[0][]
                self.texCoords +== i[1][]
     
        self.to_add = []
  
       self.to_add_count = 256

        self._len +=vbo, bytes_vertices

self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, glfwself.poll_events(vbo)
        glBufferData(GL_ARRAY_BUFFER, 12 * 4, glfw.swap_buffers(window2None, GL_STATIC_DRAW)
        glfwself.terminate()

   vbo_manager def= create_vboVBOManager(self, window): 

        self.vbo, self.vbo_1texture_manager = glGenBuffers TextureAtlas(2) 

        glBindBufferglEnable(GL_ARRAY_BUFFER, self.vboGL_TEXTURE_2D)
        glBufferDataglEnable(GL_ARRAY_BUFFER, 64000000, None, GL_STATIC_DRAWGL_BLEND)
        glBindBufferglBlendFunc(GL_ARRAY_BUFFERGL_SRC_ALPHA, self.vbo_1GL_ONE_MINUS_SRC_ALPHA)
        glBufferDataglEnableClientState(GL_ARRAY_BUFFER, 64000000, None, GL_STATIC_DRAWGL_TEXTURE_COORD_ARRAY)
 
        glfw.make_context_currentglEnableClientState (NoneGL_VERTEX_ARRAY) 

    def load_assets_from(self, other_renderer):
  thread = threading.Thread(target=self.shared_context, args=[window], daemon=True)
  self.texture_manager = other_renderer.texture_manager

    thread.startdef render(self):
        self.event.wait()try:
        glfw    self.make_context_currentvbo_manager.run(window)
 
    def add(self, vertices, texCoords) except RuntimeError:
        self.to_add.append((tuple(vertices), tuple(texCoords)))

    def render(self):pass

        glClear (GL_COLOR_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)

        glDrawArrays (GL_QUADS, 0, len(self._lenvertices))
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)

    def add(self, posList, texCoords):
        self.to_add.append((numpy.array(posList), numpy.array(texCoords)))

    def update_vbo(self):
        pass

Output

It is expected that all faces of the above cube are lime.

Right now, it shows no errors, but it does not render the cube properly. The attached GIF explains what I mean.

When I use this code in rendererworld.py, it works just fine!

# imports
import glfw, numpy
from OpenGL.GLterrain import *
from ctypesplayer import *
from core.texture_managerrenderer import *
import threading
import random
import glfw

def execute_with_delay(func, delay):
    threading.initTimer(delay, func).start()

class VBOManagerThreadedChunkGenerator():
    def __init__(self, rendererworld):
        self.rendererthread = rendererthreading.Thread(target=self.run, daemon=True)
        self.run()world = world
    
     defself.event run= threading.Event(self):
        forself.event.wait()
 i in self.renderer     glfw.to_add[:make_context_current(self.rendererworld.to_add_count]:parent.window)

    def run(self,):
        selfglfw.rendererwindow_hint(glfw.verticesVISIBLE, glfw.extend(i[0]FALSE)
        window2 = glfw.create_window(300, 300, "Window 2", None, self.rendererworld.texCoordsparent.extend(i[1]window)
 
        glfw.make_context_current(window2)
        self.renderer.to_addevent.removeset(i)

        glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo = TerrainRenderer(window2)
        glBufferData(GL_ARRAY_BUFFER, lenrenderer.load_assets_from(self.rendererworld.verticesparent) 
 * 4, (c_float * len(self.renderer.vertices))(*self.renderer.vertices), GL_STATIC_DRAW)  while True:
        glFlush    for i in range(self.world.to_generate):
        glVertexPointer(3, GL_FLOAT, 0, None)
     chunk = i
 glTexCoordPointer(3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER,    renderer = self.rendererworld.vbo_1)parent

        glBufferData(GL_ARRAY_BUFFER, len(self       chunk.generate(renderer.texCoords) 
 * 4, (c_float * len(           self.renderer.texCoords))(*selfworld.renderer.texCoords), GL_STATIC_DRAW)= renderer

        glFlush()    self.world.to_generate = []

class TerrainRendererWorld:
    def __init__(self, windowrenderer, player):
        self.windowparent = window
renderer
        self.verticeschunks = []{}
        self.texCoordsblocks = []
{}
        self.to_addposition = [](0 * 16, 0 * 16)
        self.to_add_countrender_distance = 256
1
        self.vbo,infgen_threshold = 1
        self.vbo_1block_types = glGenBuffers all_blocks(2renderer)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
 to_generate = []
     glBufferData(GL_ARRAY_BUFFER, 12 * 4,self.player None,= GL_STATIC_DRAW)player

        self.vbo_managerthread = VBOManagerThreadedChunkGenerator(self)
        self.thread.start()
        self.texture_managerevent = TextureAtlas()
self.thread.event
        glEnableself.event.wait(GL_TEXTURE_2D)
    
    def glEnableblock_exists(GL_BLENDself, position):
        glBlendFuncreturn position in self.blocks

    def _add_chunk(GL_SRC_ALPHAself, GL_ONE_MINUS_SRC_ALPHAposition):
        glEnableClientStateself.chunks[position] = Chunk(GL_TEXTURE_COORD_ARRAYself.parent, self, position)

    def add_chunk(self, position):
        glEnableClientStateexecute_with_delay(lambda: self._add_chunk(GL_VERTEX_ARRAYposition), random.randrange(1, 2))

    def rendergenerate(self):
        tryfor i in range(self.position[0] - self.render_distance, self.position[0] + self.render_distance + 1):
            for j in range(self.vbo_managerposition[1] - self.run(render_distance, self.position[1] + self.render_distance + 1):
        except RuntimeError:
       if (i, j) not in pass
self.chunks:
        glClear            self.add_chunk(GL_COLOR_BUFFER_BIT(i, j))

    def update_infgen(self, position):
   glEnable     player_pos = (GL_TEXTURE_2Dposition[0] // 16, position[2] // 16) 

        glEnable(GL_BLEND)if player_pos[0] - self.position[0] > self.infgen_threshold:
        glBlendFunc    self.position = (GL_SRC_ALPHAself.position[0] + 2, GL_ONE_MINUS_SRC_ALPHAself.position[1])
        glBindBuffer (GL_ARRAY_BUFFER,   self.vbogenerate()
        glVertexPointerelif (3,player_pos[0] GL_FLOAT,- 0,self.position[0] None)< -self.infgen_threshold:
        glBindBuffer    self.position = (GL_ARRAY_BUFFERself.position[0] - 2, self.vbo_1position[1])
        glTexCoordPointer(2, GL_FLOAT, 0, None self.generate()
 
        glDrawArraysif (GL_QUADS,player_pos[1] 0,- len(self.vertices))position[1] > self.infgen_threshold:
        glDisable    self.position = (GL_TEXTURE_2Dself.position[0], self.position[1] + 2)
        glDisable    self.generate(GL_BLEND)
 
    def add(   elif player_pos[1] - self,.position[1] posList,< texCoords)-self.infgen_threshold:
            self.to_add.append(position = (numpyself.array(posList)position[0], numpyself.array(texCoords)position[1] - 2)
            self.generate()

    def update_vborender(self):
        passself.parent.render()
        self.update_infgen(self.player.pos)
                    

Why does this code work and not the previous one? Have I missed something?

Right now, it shows no errors, just hangs the window before it even starts rendering. Any help will be highly appreciated.

Python GLFW and PyOpenGL: How to update a VBO from a thread while rendering at the same time?

I'm really new to this community. I'm sorry for any mistakes in advance.I'm making a game like minecraft with GLFW and OpenGL. The problem is, it just renders two faces correctly and the other faces have a wierd glitch. Here is my code:

# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 30)
glFogf(GL_FOG_END, 100)

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    _update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    renderer.render()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()
 
# imports
import glfw
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *
import threading
import numpy as np

glfw.init()

class TerrainRenderer:
    def __init__(self, window):
        self.event = threading.Event()
        self.to_add = []
        self._len = 0

        self.parent = window

        self.vertices = []
        self.texCoords = []

        self.create_vbo(window)

        self.texture_manager = TextureAtlas()

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY)


    def shared_context(self, window):
        glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
        window2 = glfw.create_window(500,500, "Window 2", None, window)
        glfw.make_context_current(window2)
        self.event.set()

        while not glfw.window_should_close(window):
            if len(self.to_add) > 0:
                i = self.to_add.pop(0)

                bytes_vertices = np.array(i[0]).nbytes
                bytes_texCoords = np.array(i[1]).nbytes

                glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
                glBufferSubData(GL_ARRAY_BUFFER, self._len, bytes_vertices, (c_float * len(i[0]))(*i[0]))
                glVertexPointer (3, GL_FLOAT, 0, None)
                glFlush()
                
                glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
                glBufferSubData(GL_ARRAY_BUFFER, self._len, bytes_texCoords, (c_float * len(i[1]))(*i[1]))
                glTexCoordPointer(2, GL_FLOAT, 0, None)
                glFlush()

                glVertexPointer(3, GL_FLOAT, 0, None)
                glTexCoordPointer(3, GL_FLOAT, 0, None)

                self.vertices += i[0]
                self.texCoords += i[1]
                
                 self._len += bytes_vertices

            glfw.poll_events()
            glfw.swap_buffers(window2)
        glfw.terminate()

    def create_vbo(self, window):
        self.vbo, self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, 64000000, None, GL_STATIC_DRAW)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glBufferData(GL_ARRAY_BUFFER, 64000000, None, GL_STATIC_DRAW)
 
        glfw.make_context_current(None)
        thread = threading.Thread(target=self.shared_context, args=[window], daemon=True)
        thread.start()
        self.event.wait()
        glfw.make_context_current(window)
 
    def add(self, vertices, texCoords):
        self.to_add.append((tuple(vertices), tuple(texCoords)))

    def render(self):
        glClear (GL_COLOR_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)

        glDrawArrays (GL_QUADS, 0, self._len)
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)

Output

It is expected that all faces of the above cube are lime.

Right now, it shows no errors, but it does not render the cube properly. The attached GIF explains what I mean.

When I use this code in renderer.py, it works just fine!

# imports
import glfw, numpy
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *

glfw.init()

class VBOManager:
    def __init__(self, renderer):
        self.renderer = renderer
        self.run()
    
     def run(self):
        for i in self.renderer.to_add[:self.renderer.to_add_count]:
            self.renderer.vertices.extend(i[0])
            self.renderer.texCoords.extend(i[1])
 
            self.renderer.to_add.remove(i)

        glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo)
        glBufferData(GL_ARRAY_BUFFER, len(self.renderer.vertices) * 4, (c_float * len(self.renderer.vertices))(*self.renderer.vertices), GL_STATIC_DRAW)
        glFlush()
        glVertexPointer(3, GL_FLOAT, 0, None)
        glTexCoordPointer(3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo_1)
        glBufferData(GL_ARRAY_BUFFER, len(self.renderer.texCoords) * 4, (c_float * len(self.renderer.texCoords))(*self.renderer.texCoords), GL_STATIC_DRAW)
        glFlush()

class TerrainRenderer:
    def __init__(self, window):
        self.window = window

        self.vertices = []
        self.texCoords = []

        self.to_add = []
        self.to_add_count = 256

        self.vbo, self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, 12 * 4, None, GL_STATIC_DRAW)
        self.vbo_manager = VBOManager(self)

        self.texture_manager = TextureAtlas()

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY)

    def render(self):
        try:
            self.vbo_manager.run()
        except RuntimeError:
            pass

        glClear (GL_COLOR_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)
 
        glDrawArrays (GL_QUADS, 0, len(self.vertices))
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)
 
    def add(self, posList, texCoords):
        self.to_add.append((numpy.array(posList), numpy.array(texCoords)))

    def update_vbo(self):
        pass

Why does this code work and not the previous one? Have I missed something?

Any help will be highly appreciated.

Python GLFW and PyOpenGL: How to update a VBO from a thread while rendering at the same time

I'm really new to this community. I'm sorry for any mistakes in advance.I'm making a game like minecraft with GLFW and OpenGL. The problem is, I just can't render a VBO while I update it from another thread. Here is my code:

# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from terrain import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
# glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 3)
glFogf(GL_FOG_END, 10)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

world = World(renderer, player)
world.generate()

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def update_on_resize():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 

    update_on_resize()

    _setup_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    player._translate()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()
# imports
import glfw, numpy
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *

glfw.init()

class VBOManager:
    def __init__(self, renderer):
        self.renderer = renderer
        self.run()
    
    def run(self):
        for i in self.renderer.to_add[:self.renderer.to_add_count]:
            self.renderer.vertices.extend(i[0])
            self.renderer.texCoords.extend(i[1])

            _ = i
            self.renderer.to_add.remove(i)

            glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo)
            glBufferSubData(GL_ARRAY_BUFFER, len(self.renderer.vertices), len(_[0]) * 4, (GLfloat * len(_[0]))(*_[0]))
            glFlush()
            glVertexPointer(3, GL_FLOAT, 0, None)
            glTexCoordPointer(3, GL_FLOAT, 0, None)
            glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo_1)
            glBufferSubData(GL_ARRAY_BUFFER,  len(self.renderer.texCoords), len(_[1]) * 4, (GLfloat * len(_[1]))(*_[1]))
            glFlush()

class TerrainRenderer:
    def __init__(self, window):
        self.window = window

        self.vertices = []
        self.texCoords = []
 
        self.to_add = []
        self.to_add_count = 256

        self.vbo, self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, 12 * 4, None, GL_STATIC_DRAW)
        self.vbo_manager = VBOManager(self) 

        self.texture_manager = TextureAtlas() 

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY) 

    def load_assets_from(self, other_renderer):
        self.texture_manager = other_renderer.texture_manager

    def render(self):
        try:
            self.vbo_manager.run()
        except RuntimeError:
            pass

        glClear (GL_COLOR_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)

        glDrawArrays (GL_QUADS, 0, len(self.vertices))
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)

    def add(self, posList, texCoords):
        self.to_add.append((numpy.array(posList), numpy.array(texCoords)))

    def update_vbo(self):
        pass

world.py

from terrain import *
from player import *
from core.renderer import *
import threading
import random
import glfw

def execute_with_delay(func, delay):
    threading.Timer(delay, func).start()

class ThreadedChunkGenerator():
    def __init__(self, world):
        self.thread = threading.Thread(target=self.run, daemon=True)
        self.world = world
        self.event = threading.Event()
        self.event.wait()
        glfw.make_context_current(self.world.parent.window)

    def run(self,):
        glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
        window2 = glfw.create_window(300, 300, "Window 2", None, self.world.parent.window)
        glfw.make_context_current(window2)
        self.event.set()

        renderer = TerrainRenderer(window2)
        renderer.load_assets_from(self.world.parent) 
        while True:
            for i in range(self.world.to_generate):
                chunk = i
                renderer = self.world.parent

                chunk.generate(renderer) 
                self.world.renderer = renderer

            self.world.to_generate = []

class World:
    def __init__(self, renderer, player):
        self.parent = renderer
        self.chunks = {}
        self.blocks = {}
        self.position = (0 * 16, 0 * 16)
        self.render_distance = 1
        self.infgen_threshold = 1
        self.block_types = all_blocks(renderer)
        self.to_generate = []
        self.player = player

        self.thread = ThreadedChunkGenerator(self)
        self.thread.start()
        self.event = self.thread.event
        self.event.wait()
 
    def block_exists(self, position):
        return position in self.blocks

    def _add_chunk(self, position):
        self.chunks[position] = Chunk(self.parent, self, position)

    def add_chunk(self, position):
        execute_with_delay(lambda: self._add_chunk(position), random.randrange(1, 2))

    def generate(self):
        for i in range(self.position[0] - self.render_distance, self.position[0] + self.render_distance + 1):
            for j in range(self.position[1] - self.render_distance, self.position[1] + self.render_distance + 1):
                if (i, j) not in self.chunks:
                    self.add_chunk((i, j))

    def update_infgen(self, position):
        player_pos = (position[0] // 16, position[2] // 16) 

        if player_pos[0] - self.position[0] > self.infgen_threshold:
            self.position = (self.position[0] + 2, self.position[1])
            self.generate()
        elif player_pos[0] - self.position[0] < -self.infgen_threshold:
            self.position = (self.position[0] - 2, self.position[1])
            self.generate()
        if player_pos[1] - self.position[1] > self.infgen_threshold:
            self.position = (self.position[0], self.position[1] + 2)
            self.generate()
        elif player_pos[1] - self.position[1] < -self.infgen_threshold:
            self.position = (self.position[0], self.position[1] - 2)
            self.generate()

    def render(self):
        self.parent.render()
        self.update_infgen(self.player.pos)
                    

Right now, it shows no errors, just hangs the window before it even starts rendering. Any help will be highly appreciated.

deleted 61 characters in body
Source Link
#################################################################
#  ______   __  __   ______   ______     __     ______   ______ *
# |  __  |  \ \/ /  |  ____| |  __  |   /__\   /  ____| |__  __|*
# | |__| |   \  /   | |      | |__| |  //__\\ | |__       |  |  *
# |  ____|    ||    | |      |______| / ____ \|  __|      |  |  *
# | |         ||    | |____  | |\ \  / /    \ | |         |  |  *
# |_|         ||    |______| |_| \_\/_/      \|_|         |__|  *
#################################################################


# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 330)
glFogf(GL_FOG_END, 10100)

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    _update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    renderer.render()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate() 

#################################################################
# imports
import ______glfw
from OpenGL.GL import __*
from ctypes __import *
from core.texture_manager ______import *
import threading
import ______numpy as np

glfw.init()

class TerrainRenderer:
  __  def __init__(self, window):
    ______   ______ *self.event = threading.Event()
# |  __  |  \ \/self.to_add /= []
 |  ____| |  __  |self._len = 0

 /__\   /  ____| |__ self.parent = __|*window
# 
 | |__| |   \  /self.vertices = []
 | |      |self.texCoords |__|= |[]

  //__\\ | |__    self.create_vbo(window)

   |  |  * self.texture_manager = TextureAtlas()
# 
 |  ____|    || glEnable(GL_TEXTURE_2D)
   | |    glEnable(GL_BLEND)
  |______| / ____ \|  __| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    |  |  *glEnableClientState(GL_TEXTURE_COORD_ARRAY)
# | |      glEnableClientState (GL_VERTEX_ARRAY)


  ||  def shared_context(self, |window):
 |____  | |\ \  / /glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
   \ | |   window2 = glfw.create_window(500,500, "Window 2", None, |window)
  |  *    glfw.make_context_current(window2)
# |_|       self.event.set()

  ||    |______| |_| \_\/_/while not glfw.window_should_close(window):
    \|_|        if |__|len(self.to_add) > *
#################################################################

0:
# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

ifi not= glfwself.initto_add.pop(0): 

    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer bytes_vertices = TerrainRenderernp.array(windowi[0]).nbytes
player                bytes_texCoords = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_managernp.savearray("atlas.png"i[1])
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)nbytes
glCullFace(GL_BACK)
glEnable                glBindBuffer(GL_FOGGL_ARRAY_BUFFER, self.vbo)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))             glBufferSubData(0.5GL_ARRAY_BUFFER, 0self.69_len, 1.0bytes_vertices, 10(c_float * len(i[0]))
glHint(GL_FOG_HINT, GL_DONT_CARE*i[0]))
glFogi                glVertexPointer (GL_FOG_MODE3, GL_LINEAR)
glFogf(GL_FOG_STARTGL_FLOAT, 3)
glFogf(GL_FOG_END0, 10None)
 
# get window size
def get_window_size():
    width, height = glfw.get_window_size     glFlush(window)
    return width, height

def _setup_3d():         
    w, h = get_window_size         glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
 
    glMatrixMode            glBufferSubData(GL_PROJECTION)
GL_ARRAY_BUFFER, self._len, bytes_texCoords, (c_float glLoadIdentity* len(i[1]))(*i[1]))
    gluPerspective(70, w / h         glTexCoordPointer(2, GL_FLOAT, 0.1, 1000None)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity        glFlush()

def _update_3d():
    _setup_3d()
    glViewport       glVertexPointer(03, GL_FLOAT, 0, *get_window_size()None)
 
def add_cube               glTexCoordPointer(x3, yGL_FLOAT, z0, None): 

    X, Y, Z = x + 1, y + 1, z + 1self.vertices += i[0]
    renderer            self.add((x,texCoords Y,+= Z,i[1]
  X, Y, Z,  X, Y, z,  x, Y, z), renderer   
                self.texture_manager_len += bytes_vertices

            glfw.get_texturepoll_events("grass"))
    renderer        glfw.add(swap_buffers(x,window2)
 y, z, X, y, z, X, y, Z,glfw.terminate()

 x, y  def create_vbo(self, Zwindow),:
 renderer       self.texture_managervbo, self.get_texturevbo_1 = glGenBuffers ("grass")2)
    renderer.add(    glBindBuffer(xGL_ARRAY_BUFFER, y,self.vbo)
 z,  x, y, Z,  x glBufferData(GL_ARRAY_BUFFER, Y64000000, ZNone, GL_STATIC_DRAW)
 x, Y, z)     glBindBuffer(GL_ARRAY_BUFFER, renderer.texture_managerself.get_texture("grass")vbo_1)
    renderer.add((X, y, Z,  XglBufferData(GL_ARRAY_BUFFER, y64000000, zNone, GL_STATIC_DRAW)

 X, Y, z,  X, Y, Z), renderer.texture_managerglfw.get_texturemake_context_current("grass")None)
    renderer    thread = threading.add(Thread(xtarget=self.shared_context, yargs=[window], Z,daemon=True)
  X, y, Z,  X, Y, Z,thread.start()
  x, Y, Z), renderer   self.texture_managerevent.get_texturewait("grass"))
    renderer    glfw.add(make_context_current(X,window)

 y, z,  x,def yadd(self, zvertices, texCoords):
 x, Y, z,  X, Y, z), rendererself.texture_managerto_add.get_textureappend("grass"))

add_cube(0, 0tuple(vertices), -2tuple(texCoords)))

# mainloop
while not glfw.window_should_close def render(windowself):
        glClear (GL_COLOR_BUFFER_BIT)

 | GL_DEPTH_BUFFER_BIT      glEnable(GL_TEXTURE_2D)
    _update_3d    glEnable(GL_BLEND)
    glClearColor    glBlendFunc(0.5GL_SRC_ALPHA, 0GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.7vbo)
        glVertexPointer (3, 1GL_FLOAT, 1.0, None)
 
    player.update    glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
    renderer.render    glTexCoordPointer(2, GL_FLOAT, 0, None)

    glfw.poll_events    glDrawArrays (GL_QUADS, 0, self._len)
    glfw.swap_buffers    glDisable(windowGL_TEXTURE_2D)
 
glfw.terminate        glDisable(GL_BLEND)

Right now, it shows no errors, but it does not render the cube properly. The attached GIF explains what I mean.

When I use this code in renderer.py, it works just fine!

# imports
import glfw, numpy
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *

glfw.init()

class VBOManager:
    def __init__(self, renderer):
        self.renderer = renderer
        self.run()
    
    def run(self):
        for i in self.renderer.to_add[:self.renderer.to_add_count]:
            self.renderer.vertices.extend(i[0])
            self.renderer.texCoords.extend(i[1])

            self.renderer.to_add.remove(i)

        glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo)
        glBufferData(GL_ARRAY_BUFFER, len(self.renderer.vertices) * 4, (c_float * len(self.renderer.vertices))(*self.renderer.vertices), GL_STATIC_DRAW)
        glFlush()
        glVertexPointer(3, GL_FLOAT, 0, None)
        glTexCoordPointer(3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo_1)
        glBufferData(GL_ARRAY_BUFFER, len(self.renderer.texCoords) * 4, (c_float * len(self.renderer.texCoords))(*self.renderer.texCoords), GL_STATIC_DRAW)
        glFlush()

class TerrainRenderer:
    def __init__(self, window):
        self.window = window

        self.vertices = []
        self.texCoords = []

        self.to_add = []
        self.to_add_count = 256

        self.vbo, self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, 12 * 4, None, GL_STATIC_DRAW)
        self.vbo_manager = VBOManager(self)

        self.texture_manager = TextureAtlas()

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY)

    def render(self):
        try:
            self.vbo_manager.run()
        except RuntimeError:
            pass

        glClear (GL_COLOR_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)

        glDrawArrays (GL_QUADS, 0, len(self.vertices))
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)

    def add(self, posList, texCoords):
        self.to_add.append((numpy.array(posList), numpy.array(texCoords)))

    def update_vbo(self):
        pass

Why does this code work and not the previous one? Have I missed something?

Any help will be highly appreciated.

#################################################################
#  ______   __  __   ______   ______     __     ______   ______ *
# |  __  |  \ \/ /  |  ____| |  __  |   /__\   /  ____| |__  __|*
# | |__| |   \  /   | |      | |__| |  //__\\ | |__       |  |  *
# |  ____|    ||    | |      |______| / ____ \|  __|      |  |  *
# | |         ||    | |____  | |\ \  / /    \ | |         |  |  *
# |_|         ||    |______| |_| \_\/_/      \|_|         |__|  *
#################################################################


# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 3)
glFogf(GL_FOG_END, 10)

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    _update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    renderer.render()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()
#################################################################
#  ______   __  __   ______   ______     __     ______   ______ *
# |  __  |  \ \/ /  |  ____| |  __  |   /__\   /  ____| |__  __|*
# | |__| |   \  /   | |      | |__| |  //__\\ | |__       |  |  *
# |  ____|    ||    | |      |______| / ____ \|  __|      |  |  *
# | |         ||    | |____  | |\ \  / /    \ | |         |  |  *
# |_|         ||    |______| |_| \_\/_/      \|_|         |__|  *
#################################################################


# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 3)
glFogf(GL_FOG_END, 10)
 
# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()
 
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())
 
def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    _update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)
 
    player.update()
    renderer.render()

    glfw.poll_events()
    glfw.swap_buffers(window)
 
glfw.terminate()

Right now, it shows no errors, but it does not render the cube properly. The attached GIF explains what I mean. Any help will be highly appreciated.

# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 30)
glFogf(GL_FOG_END, 100)

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    _update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    renderer.render()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate() 

# imports
import glfw
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *
import threading
import numpy as np

glfw.init()

class TerrainRenderer:
    def __init__(self, window):
        self.event = threading.Event()
        self.to_add = []
        self._len = 0

        self.parent = window
 
        self.vertices = []
        self.texCoords = []

        self.create_vbo(window)

        self.texture_manager = TextureAtlas()
 
        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY)


    def shared_context(self, window):
        glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
        window2 = glfw.create_window(500,500, "Window 2", None, window)
        glfw.make_context_current(window2)
        self.event.set()

        while not glfw.window_should_close(window):
            if len(self.to_add) > 0:
                i = self.to_add.pop(0) 

                bytes_vertices = np.array(i[0]).nbytes
                bytes_texCoords = np.array(i[1]).nbytes

                glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
                glBufferSubData(GL_ARRAY_BUFFER, self._len, bytes_vertices, (c_float * len(i[0]))(*i[0]))
                glVertexPointer (3, GL_FLOAT, 0, None)
                glFlush()
                
                glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
                glBufferSubData(GL_ARRAY_BUFFER, self._len, bytes_texCoords, (c_float * len(i[1]))(*i[1]))
                glTexCoordPointer(2, GL_FLOAT, 0, None)
                glFlush()

                glVertexPointer(3, GL_FLOAT, 0, None)
                glTexCoordPointer(3, GL_FLOAT, 0, None) 

                self.vertices += i[0]
                self.texCoords += i[1]
                
                self._len += bytes_vertices

            glfw.poll_events()
            glfw.swap_buffers(window2)
        glfw.terminate()

    def create_vbo(self, window):
        self.vbo, self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, 64000000, None, GL_STATIC_DRAW)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glBufferData(GL_ARRAY_BUFFER, 64000000, None, GL_STATIC_DRAW)

        glfw.make_context_current(None)
        thread = threading.Thread(target=self.shared_context, args=[window], daemon=True)
        thread.start()
        self.event.wait()
        glfw.make_context_current(window)

    def add(self, vertices, texCoords):
        self.to_add.append((tuple(vertices), tuple(texCoords)))

    def render(self):
        glClear (GL_COLOR_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)

        glDrawArrays (GL_QUADS, 0, self._len)
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)

Right now, it shows no errors, but it does not render the cube properly. The attached GIF explains what I mean.

When I use this code in renderer.py, it works just fine!

# imports
import glfw, numpy
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *

glfw.init()

class VBOManager:
    def __init__(self, renderer):
        self.renderer = renderer
        self.run()
    
    def run(self):
        for i in self.renderer.to_add[:self.renderer.to_add_count]:
            self.renderer.vertices.extend(i[0])
            self.renderer.texCoords.extend(i[1])

            self.renderer.to_add.remove(i)

        glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo)
        glBufferData(GL_ARRAY_BUFFER, len(self.renderer.vertices) * 4, (c_float * len(self.renderer.vertices))(*self.renderer.vertices), GL_STATIC_DRAW)
        glFlush()
        glVertexPointer(3, GL_FLOAT, 0, None)
        glTexCoordPointer(3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo_1)
        glBufferData(GL_ARRAY_BUFFER, len(self.renderer.texCoords) * 4, (c_float * len(self.renderer.texCoords))(*self.renderer.texCoords), GL_STATIC_DRAW)
        glFlush()

class TerrainRenderer:
    def __init__(self, window):
        self.window = window

        self.vertices = []
        self.texCoords = []

        self.to_add = []
        self.to_add_count = 256

        self.vbo, self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, 12 * 4, None, GL_STATIC_DRAW)
        self.vbo_manager = VBOManager(self)

        self.texture_manager = TextureAtlas()

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY)

    def render(self):
        try:
            self.vbo_manager.run()
        except RuntimeError:
            pass

        glClear (GL_COLOR_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)

        glDrawArrays (GL_QUADS, 0, len(self.vertices))
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)

    def add(self, posList, texCoords):
        self.to_add.append((numpy.array(posList), numpy.array(texCoords)))

    def update_vbo(self):
        pass

Why does this code work and not the previous one? Have I missed something?

Any help will be highly appreciated.

Notice added Draw attention by N3RDIUM
Bounty Started worth 50 reputation by N3RDIUM
deleted 1746 characters in body; edited title
Source Link

Python GLFW and PyOpenGL: How to update a VBO from a thread while rendering at the same time?

I'm really new to this community. I'm sorry for any mistakes in advance.I'm making a game like minecraft with GLFW and OpenGL. The problem is, Iit just can't renderrenders two faces correctly and the other faces have a VBO while I update it from another threadwierd glitch. Here is my code:

#################################################################
#  ______   __  __   ______   ______     __     ______   ______ *
# |  __  |  \ \/ /  |  ____| |  __  |   /__\   /  ____| |__  __|*
# | |__| |   \  /   | |      | |__| |  //__\\ | |__       |  |  *
# |  ____|    ||    | |      |______| / ____ \|  __|      |  |  *
# | |         ||    | |____  | |\ \  / /    \ | |         |  |  *
# |_|         ||    |______| |_| \_\/_/      \|_|         |__|  *
#################################################################


# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from terrain import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
# glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 3)
glFogf(GL_FOG_END, 10)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

world = World(renderer, player)
world.generate()

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def update_on_resize_update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    update_on_resize()
 
    _setup_3d_update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    playerrenderer._translaterender()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()
# imports#################################################################
import# glfw, numpy
from______ OpenGL.GL import *
from__ ctypes import *
from__ core.texture_manager import *

glfw.init()

class______ VBOManager:
  ______  def __init__(self, renderer):
 __     ______  self.renderer =______ renderer*
  # |  __  | self.run()
 \ \/ / 
  |  ____| def| run(self):
 __  |   /__\  for i/ in self.renderer.to_add[:self.renderer.to_add_count]:
____| |__  __|*
# | |__| |   \  / self.renderer.vertices.extend(i[0])
  | |      | |__| | self.renderer.texCoords.extend(i[1])

 //__\\ | |__       |  _| = i*
  # |  ____|    ||   self.renderer.to_add.remove(i)

 | |      |______| / ____ \| glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo)
__|      |  |  *
# | glBufferSubData(GL_ARRAY_BUFFER,| len(self.renderer.vertices), len(_[0]) * 4, (GLfloat * len(_[0]))(*_[0]))
  ||    | |____  | |\ \ glFlush()
 / /    \ | |    glVertexPointer(3, GL_FLOAT, 0, None)
  |  |  *
# |_|     glTexCoordPointer(3, GL_FLOAT, 0, None)
 ||    |______| |_| \_\/_/     glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo_1)
\|_|         |__|  *
#################################################################


# glBufferSubData(GL_ARRAY_BUFFER,imports
import glfw
from len(self.rendererOpenGL.texCoords),GL len(_[1])import *
from 4,OpenGL.GLU (GLfloatimport * len(_[1]))(*_[1]))
    
# internal imports
from core.renderer import *
from player import glFlush()*

class TerrainRenderer:
   if defnot __init__glfw.init(self, window):
     raise Exception("glfw can self.windownot =be windowinitialized!")

  window = glfw.create_window(800, 500, "PyCraft", None, selfNone)
glfw.verticesmake_context_current(window)
renderer = []TerrainRenderer(window)
        self.texCoordsplayer = []Player(window)

        selfrenderer.to_add = []texture_manager.add_from_folder("assets/textures/block/")
        selfrenderer.to_add_count = 256texture_manager.save("atlas.png")
renderer.texture_manager.bind()

     glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * selfint(8))(0.vbo5, self0.vbo_1 =69, glGenBuffers1.0, (210))
        glBindBufferglHint(GL_ARRAY_BUFFERGL_FOG_HINT, self.vboGL_DONT_CARE)
        glBufferDataglFogi(GL_ARRAY_BUFFERGL_FOG_MODE, 12 * 4GL_LINEAR)
glFogf(GL_FOG_START, None3)
glFogf(GL_FOG_END, GL_STATIC_DRAW10) 

# get window size
def get_window_size():
    width, self.vbo_managerheight = VBOManagerglfw.get_window_size(selfwindow)
 
       return self.texture_managerwidth, =height

def TextureAtlas_setup_3d()
 :
     w, h = glEnableget_window_size(GL_TEXTURE_2D) 

    glMatrixMode(GL_PROJECTION)
    glEnableglLoadIdentity(GL_BLEND)
    gluPerspective(70, w / h, glBlendFunc(GL_SRC_ALPHA0.1, GL_ONE_MINUS_SRC_ALPHA1000)
        glEnableClientStateglMatrixMode(GL_TEXTURE_COORD_ARRAYGL_MODELVIEW)
        glEnableClientState glLoadIdentity(GL_VERTEX_ARRAY)

    def load_assets_from_update_3d(self, other_renderer):
    _setup_3d()
    self.texture_managerglViewport(0, =0, other_renderer.texture_manager*get_window_size())

    def renderadd_cube(selfx, y, z):
    X, Y, Z = try:
x + 1, y + 1, z + 1
    self.vbo_managerrenderer.runadd()
(x, Y, Z,  X, Y, Z,  exceptX, RuntimeError:
Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, pass

X, y, z, X, y, Z, x, y, glClearZ), renderer.texture_manager.get_texture(GL_COLOR_BUFFER_BIT"grass")
 )
    renderer.add((x, y, z,  x, y, Z, glEnable(GL_TEXTURE_2D)
 x, Y, Z,  x, Y, z), glEnablerenderer.texture_manager.get_texture(GL_BLEND"grass"))
    renderer.add((X, y, Z,  glBlendFunc(GL_SRC_ALPHAX, GL_ONE_MINUS_SRC_ALPHA)
y, z,  X, Y, z,  X, glBindBufferY, (GL_ARRAY_BUFFERZ), selfrenderer.vbotexture_manager.get_texture("grass"))
     renderer.add((x, y, Z, glVertexPointer (3X, GL_FLOATy, 0Z, None)
  X, Y, Z,  x, Y, glBindBuffer(GL_ARRAY_BUFFERZ), selfrenderer.vbo_1texture_manager.get_texture("grass"))
        glTexCoordPointerrenderer.add(2(X, GL_FLOATy, 0z, None)

 x, y, z,  x, Y, z, glDrawArrays (GL_QUADSX, 0Y, len(selfz), renderer.verticestexture_manager.get_texture("grass"))
   
add_cube(0, 0, -2)

# mainloop
while not glDisableglfw.window_should_close(GL_TEXTURE_2Dwindow):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glDisable_update_3d(GL_BLEND)
 
    def addglClearColor(self0.5, posList0.7, texCoords1, 1.0):
     
    self.to_add.append((numpyplayer.arrayupdate(posList), 
 numpy   renderer.arrayrender(texCoords)))

    def update_vboglfw.poll_events(self):
        passglfw.swap_buffers(window)

glfw.terminate()

world.pyOutput

from terrain import *
from player import *
from core.renderer import *
import threading
import random
import glfw

def execute_with_delay(func, delay):
    threading.Timer(delay, func).start()

class ThreadedChunkGenerator():
    def __init__(self, world):
        self.thread = threading.Thread(target=self.run, daemon=True)
        self.world = world
        self.event = threading.Event()
        self.event.wait()
        glfw.make_context_current(self.world.parent.window)

    def run(self,):
        glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
        window2 = glfw.create_window(300, 300, "Window 2", None, self.world.parent.window)
        glfw.make_context_current(window2)
        self.event.set()

        renderer = TerrainRenderer(window2)
        renderer.load_assets_from(self.world.parent)
        while True:
            for i in range(self.world.to_generate):
                chunk = i
                renderer = self.world.parent

                chunk.generate(renderer)
                self.world.renderer = renderer

            self.world.to_generate = []

class World:
    def __init__(self, renderer, player):
        self.parent = renderer
        self.chunks = {}
        self.blocks = {}
        self.position = (0 * 16, 0 * 16)
        self.render_distance = 1
        self.infgen_threshold = 1
        self.block_types = all_blocks(renderer)
        self.to_generate = []
        self.player = player

        self.thread = ThreadedChunkGenerator(self)
        self.thread.start()
        self.event = self.thread.event
        self.event.wait()

    def block_exists(self, position):
        return position in self.blocks

    def _add_chunk(self, position):
        self.chunks[position] = Chunk(self.parent, self, position)

    def add_chunk(self, position):
        execute_with_delay(lambda: self._add_chunk(position), random.randrange(1, 2))

    def generate(self):
        for i in range(self.position[0] - self.render_distance, self.position[0] + self.render_distance + 1):
            for j in range(self.position[1] - self.render_distance, self.position[1] + self.render_distance + 1):
                if (i, j) not in self.chunks:
                    self.add_chunk((i, j))

    def update_infgen(self, position):
        player_pos = (position[0] // 16, position[2] // 16)

        if player_pos[0] - self.position[0] > self.infgen_threshold:
            self.position = (self.position[0] + 2, self.position[1])
            self.generate()
        elif player_pos[0] - self.position[0] < -self.infgen_threshold:
            self.position = (self.position[0] - 2, self.position[1])
            self.generate()
        if player_pos[1] - self.position[1] > self.infgen_threshold:
            self.position = (self.position[0], self.position[1] + 2)
            self.generate()
        elif player_pos[1] - self.position[1] < -self.infgen_threshold:
            self.position = (self.position[0], self.position[1] - 2)
            self.generate()

    def render(self):
        self.parent.render()
        self.update_infgen(self.player.pos)
                    

It is expected that all faces of the above cube are lime.

Right now, it shows no errors, just hangs the window beforebut it even starts renderingdoes not render the cube properly. The attached GIF explains what I mean. Any help will be highly appreciated.

Python GLFW and PyOpenGL: How to update a VBO from a thread while rendering at the same time

I'm really new to this community. I'm sorry for any mistakes in advance.I'm making a game like minecraft with GLFW and OpenGL. The problem is, I just can't render a VBO while I update it from another thread. Here is my code:

# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from terrain import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
# glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 3)
glFogf(GL_FOG_END, 10)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

world = World(renderer, player)
world.generate()

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def update_on_resize():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    update_on_resize()
 
    _setup_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    player._translate()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()
# imports
import glfw, numpy
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *

glfw.init()

class VBOManager:
    def __init__(self, renderer):
        self.renderer = renderer
        self.run()
    
     def run(self):
        for i in self.renderer.to_add[:self.renderer.to_add_count]:
            self.renderer.vertices.extend(i[0])
            self.renderer.texCoords.extend(i[1])

            _ = i
            self.renderer.to_add.remove(i)

            glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo)
            glBufferSubData(GL_ARRAY_BUFFER, len(self.renderer.vertices), len(_[0]) * 4, (GLfloat * len(_[0]))(*_[0]))
            glFlush()
            glVertexPointer(3, GL_FLOAT, 0, None)
            glTexCoordPointer(3, GL_FLOAT, 0, None)
            glBindBuffer(GL_ARRAY_BUFFER, self.renderer.vbo_1)
            glBufferSubData(GL_ARRAY_BUFFER,  len(self.renderer.texCoords), len(_[1]) * 4, (GLfloat * len(_[1]))(*_[1]))
            glFlush()

class TerrainRenderer:
    def __init__(self, window):
        self.window = window

        self.vertices = []
        self.texCoords = []

        self.to_add = []
        self.to_add_count = 256

        self.vbo, self.vbo_1 = glGenBuffers (2)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
        glBufferData(GL_ARRAY_BUFFER, 12 * 4, None, GL_STATIC_DRAW)
        self.vbo_manager = VBOManager(self)
 
        self.texture_manager = TextureAtlas()
 
        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        glEnableClientState (GL_VERTEX_ARRAY)

    def load_assets_from(self, other_renderer):
        self.texture_manager = other_renderer.texture_manager

    def render(self):
        try:
            self.vbo_manager.run()
        except RuntimeError:
            pass

        glClear (GL_COLOR_BUFFER_BIT)
 
        glEnable(GL_TEXTURE_2D)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBindBuffer (GL_ARRAY_BUFFER, self.vbo)
        glVertexPointer (3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
        glTexCoordPointer(2, GL_FLOAT, 0, None)

        glDrawArrays (GL_QUADS, 0, len(self.vertices))
        glDisable(GL_TEXTURE_2D)
        glDisable(GL_BLEND)
 
    def add(self, posList, texCoords):
        self.to_add.append((numpy.array(posList), numpy.array(texCoords)))

    def update_vbo(self):
        pass

world.py

from terrain import *
from player import *
from core.renderer import *
import threading
import random
import glfw

def execute_with_delay(func, delay):
    threading.Timer(delay, func).start()

class ThreadedChunkGenerator():
    def __init__(self, world):
        self.thread = threading.Thread(target=self.run, daemon=True)
        self.world = world
        self.event = threading.Event()
        self.event.wait()
        glfw.make_context_current(self.world.parent.window)

    def run(self,):
        glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
        window2 = glfw.create_window(300, 300, "Window 2", None, self.world.parent.window)
        glfw.make_context_current(window2)
        self.event.set()

        renderer = TerrainRenderer(window2)
        renderer.load_assets_from(self.world.parent)
        while True:
            for i in range(self.world.to_generate):
                chunk = i
                renderer = self.world.parent

                chunk.generate(renderer)
                self.world.renderer = renderer

            self.world.to_generate = []

class World:
    def __init__(self, renderer, player):
        self.parent = renderer
        self.chunks = {}
        self.blocks = {}
        self.position = (0 * 16, 0 * 16)
        self.render_distance = 1
        self.infgen_threshold = 1
        self.block_types = all_blocks(renderer)
        self.to_generate = []
        self.player = player

        self.thread = ThreadedChunkGenerator(self)
        self.thread.start()
        self.event = self.thread.event
        self.event.wait()

    def block_exists(self, position):
        return position in self.blocks

    def _add_chunk(self, position):
        self.chunks[position] = Chunk(self.parent, self, position)

    def add_chunk(self, position):
        execute_with_delay(lambda: self._add_chunk(position), random.randrange(1, 2))

    def generate(self):
        for i in range(self.position[0] - self.render_distance, self.position[0] + self.render_distance + 1):
            for j in range(self.position[1] - self.render_distance, self.position[1] + self.render_distance + 1):
                if (i, j) not in self.chunks:
                    self.add_chunk((i, j))

    def update_infgen(self, position):
        player_pos = (position[0] // 16, position[2] // 16)

        if player_pos[0] - self.position[0] > self.infgen_threshold:
            self.position = (self.position[0] + 2, self.position[1])
            self.generate()
        elif player_pos[0] - self.position[0] < -self.infgen_threshold:
            self.position = (self.position[0] - 2, self.position[1])
            self.generate()
        if player_pos[1] - self.position[1] > self.infgen_threshold:
            self.position = (self.position[0], self.position[1] + 2)
            self.generate()
        elif player_pos[1] - self.position[1] < -self.infgen_threshold:
            self.position = (self.position[0], self.position[1] - 2)
            self.generate()

    def render(self):
        self.parent.render()
        self.update_infgen(self.player.pos)
                    

Right now, it shows no errors, just hangs the window before it even starts rendering. Any help will be highly appreciated.

Python GLFW and PyOpenGL: How to update a VBO from a thread while rendering at the same time?

I'm really new to this community. I'm sorry for any mistakes in advance.I'm making a game like minecraft with GLFW and OpenGL. The problem is, it just renders two faces correctly and the other faces have a wierd glitch. Here is my code:

#################################################################
#  ______   __  __   ______   ______     __     ______   ______ *
# |  __  |  \ \/ /  |  ____| |  __  |   /__\   /  ____| |__  __|*
# | |__| |   \  /   | |      | |__| |  //__\\ | |__       |  |  *
# |  ____|    ||    | |      |______| / ____ \|  __|      |  |  *
# | |         ||    | |____  | |\ \  / /    \ | |         |  |  *
# |_|         ||    |______| |_| \_\/_/      \|_|         |__|  *
#################################################################


# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 3)
glFogf(GL_FOG_END, 10)

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size()

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    _update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)

    player.update()
    renderer.render()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()
#################################################################
#  ______   __  __   ______   ______     __     ______   ______ *
# |  __  |  \ \/ /  |  ____| |  __  |   /__\   /  ____| |__  __|*
# | |__| |   \  /   | |      | |__| |  //__\\ | |__       |  |  *
# |  ____|    ||    | |      |______| / ____ \|  __|      |  |  *
# | |         ||    | |____  | |\ \  / /    \ | |         |  |  *
# |_|         ||    |______| |_| \_\/_/      \|_|         |__|  *
#################################################################


# imports
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *

# internal imports
from core.renderer import *
from player import *

if not glfw.init():
    raise Exception("glfw can not be initialized!")

window = glfw.create_window(800, 500, "PyCraft", None, None)
glfw.make_context_current(window)
renderer = TerrainRenderer(window)
player = Player(window)

renderer.texture_manager.add_from_folder("assets/textures/block/")
renderer.texture_manager.save("atlas.png")
renderer.texture_manager.bind()

glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * int(8))(0.5, 0.69, 1.0, 10))
glHint(GL_FOG_HINT, GL_DONT_CARE)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 3)
glFogf(GL_FOG_END, 10) 

# get window size
def get_window_size():
    width, height = glfw.get_window_size(window)
    return width, height

def _setup_3d():
    w, h = get_window_size() 

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(70, w / h, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

def _update_3d():
    _setup_3d()
    glViewport(0, 0, *get_window_size())

def add_cube(x, y, z):
    X, Y, Z = x + 1, y + 1, z + 1
    renderer.add((x, Y, Z,  X, Y, Z,  X, Y, z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z, X, y, z, X, y, Z, x, y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass"))
    renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass"))

add_cube(0, 0, -2)

# mainloop
while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    _update_3d()
    glClearColor(0.5, 0.7, 1, 1.0)
 
    player.update() 
    renderer.render()

    glfw.poll_events()
    glfw.swap_buffers(window)

glfw.terminate()

Output

It is expected that all faces of the above cube are lime.

Right now, it shows no errors, but it does not render the cube properly. The attached GIF explains what I mean. Any help will be highly appreciated.

Source Link
Loading