我对这个社区真的很陌生。我很抱歉之前的任何错误。我正在用GLFW和OpenGL制作一款像我的世界这样的游戏。问题是,它只正确地渲染了三个面,而其他面有一个奇怪的故障。以下是我的代码:
Main.py
# 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()
Renderer.py:
# imports
import glfw
from OpenGL.GL import *
from ctypes import *
from core.texture_manager import *
import threading
import numpy as np
from core.logger import *
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)
vertices = np.array(i[0], dtype=np.float32)
texture_coords = np.array(i[1], dtype=np.float32)
bytes_vertices = vertices.nbytes
bytes_texCoords = texture_coords.nbytes
verts = (GLfloat * len(vertices))(*vertices)
texCoords = (GLfloat * len(texture_coords))(*texture_coords)
log_vertex_addition((vertices, texture_coords), (bytes_vertices, bytes_texCoords), self._len*4, len(self.to_add))
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferSubData(GL_ARRAY_BUFFER, self._len, bytes_vertices, verts)
glVertexPointer (3, GL_FLOAT, 0, None)
glFlush()
glBindBuffer(GL_ARRAY_BUFFER, self.vbo_1)
glBufferSubData(GL_ARRAY_BUFFER, self._len, bytes_texCoords, texCoords)
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)
输出
预计上述立方体的所有面都是石灰。
现在,它没有显示任何错误,但它没有正确地呈现立方体。附件中的GIF解释了我的意思。
当我在renderer.py中使用这段代码时,它工作得很好!
# 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
为什么这段代码可以工作,而前一段代码不行?我错过了什么吗?
任何帮助我们都将不胜感激。
1条答案
按热度按时间noj0wjuj1#
解决方案
我注意到,文本坐标的每个顶点有两个元素,而顶点有三个。因此,我在
TerrainRenderer
类中创建了一个self._len_
变量来单独计算texCoord长度。以下是我的TerrainRenderer
代码: