pythonopenglvbo

Unexpected lines between textured cubes in pyopengl


I am making a little game in python, which renders cubes. There are unexpected lines between cubes, and they disappear when we get closer.

My code:

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

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

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

if __name__ == "__main__":
    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)
    if not DEV_MODE and not USING_RENDERDOC:
        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()
        try:
            gluPerspective(70, w / h, 0.1, 1000)
        except ZeroDivisionError:
            pass
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

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

    storage = TerrainMeshStorage(renderer)

    def add_cube(renderer, 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("dirt"))
        renderer.add((x, y, z,  x, y, Z,  x, Y, Z,  x, Y, z), renderer.texture_manager.get_texture("grass_side"))
        renderer.add((X, y, Z,  X, y, z,  X, Y, z,  X, Y, Z), renderer.texture_manager.get_texture("grass_side"))
        renderer.add((x, y, Z,  X, y, Z,  X, Y, Z,  x, Y, Z), renderer.texture_manager.get_texture("grass_side"))
        renderer.add((X, y, z,  x, y, z,  x, Y, z,  X, Y, z), renderer.texture_manager.get_texture("grass_side"))

    for x in range(-10, 10):
        for z in range(-10, 10):
            add_cube(storage, x, -1, z)

    renderer.add_mesh(storage)

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

        if not USING_RENDERDOC:
            player.update()
            
        renderer.render()

        glfw.poll_events()
        glfw.swap_buffers(window)

    glfw.terminate()

I expect the output to be a fully solid lime surface but I get these lines as you can see in the screenshot. I have tried using GL_LINE_SMOOTH among other things, but they don;t work.

output


Solution

  • The solution

    As mentioned in an answer here, I found out the solution.

    My code for binding the image in the TextureManager class:

    def bind(self):
        import pygame
        texSurface = pygame.image.load(self.save_path)
        texData = pygame.image.tostring(texSurface, "RGBA", 1)
        width = texSurface.get_width()
        height = texSurface.get_height()
        texid = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, texid)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 
                0, GL_RGBA, GL_UNSIGNED_BYTE, texData)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        return texid
    

    I used option 1 in the answer of the linked question, and changed the min filter to GL_NEAREST instead of GL_LINEAR.

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) -> glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)