Почему в моем скайбоксе края кажутся видимыми и смещенными, несмотря на правильное назначение граней?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Почему в моем скайбоксе края кажутся видимыми и смещенными, несмотря на правильное назначение граней?

Сообщение Anonymous »

Я реализую скайбокс в своем 3D-проекте на Python, используя шесть отдельных файлов текстур для каждой грани куба. Файлы текстур названы в соответствии с их ориентацией:
nx: Negative X (левая грань)
пикселей: положительный X (правая сторона)
ny: отрицательный Y (нижняя сторона)
< strong>py: положительная Y (верхняя грань)
nz: отрицательная Z (задняя сторона)
pz: положительная Z (лицевая сторона)
Я применил текстуры к соответствующим граням куба, но края между гранями четко видны, а общее выравнивание выглядит неправильным.
Изображение

Изображение
< /p>
Я подозреваю следующее:
Некоторые текстуры могут быть перевернуты, повернуты или перевернуты.
УФ-преобразование или ориентация моего лица куб может быть неверным.
Настройки фильтрации текстур или упаковки могут вызывать проблемы.
Что я пробовал:
Проверено, что каждая текстура сопоставлена ​​с правильным лицом в соответствии с соглашением об именовании.
Вручную проверил текстуры на предмет выравнивания, но не смог определить, правильно ли они ориентированы.
Наблюдения:
Швы видны и плохо сочетаются между гранями.
Текстуры не перетекают плавно по соседним краям.
Мои вопросы:
Как определить, связана ли проблема с неправильной ориентацией текстуры (например, переворотом или вращением)?
Существуют ли методы отладки и проверки правильного выравнивания текстуры скайбокса?
Любые советы или советы по устранению неполадок будут полезны. будем очень признательны!
Мой файл кода:

Код: Выделить всё

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from math import pi, sin, cos, sqrt

# Load textures
def load_texture(file_path, use_alpha=False):
try:
# Use convert_alpha() for images with transparency
if use_alpha:
texture_surface = pygame.image.load(file_path).convert_alpha()
texture_data = pygame.image.tostring(texture_surface, "RGBA", True)
else:
texture_surface = pygame.image.load(file_path).convert()
texture_data = pygame.image.tostring(texture_surface, "RGB", True)
width, height = texture_surface.get_size()

texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

# Use GL_RGBA for textures with alpha
if use_alpha:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data)
else:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data)

print(f"Texture loaded: {file_path}, ID: {texture_id}")
return texture_id
except Exception as e:
print(f"Error loading texture {file_path}: {e}")
return None

# File paths for textures
earth_day_map = "textures/8k_earth_daymap.jpg"
earth_night_map = "textures/8k_earth_nightmap.jpg"
clouds_map = "textures/output.png"

# Skybox texture file paths
skybox_faces = {
'right':  'textures/px.png',  # Positive X
'left':   'textures/nx.png',  # Negative X
'top':    'textures/py.png',  # Positive Y
'bottom': 'textures/ny.png',  # Negative Y
'front':  'textures/pz.png',  # Positive Z
'back':    'textures/nz.png',  # Negative Z
}

# Create sphere vertices, normals, texture coordinates, and indices
def create_sphere(radius, slices, stacks):
vertices = []
normals = []
tex_coords = []
indices = []

for stack in range(stacks + 1):
phi = pi / 2 - stack * pi / stacks
y = radius * sin(phi)
scale = radius * cos(phi)

for slice_ in range(slices + 1):
theta = slice_ * 2 * pi / slices
x = scale * cos(theta)
z = scale * sin(theta)

# Vertex positions
vertices.extend([x, y, z])

# Normals (normalized vertex positions)
length = sqrt(x * x + y * y + z * z)
normals.extend([x / length, y / length, z / length])

# Texture coordinates
tex_coords.extend([slice_ / slices, 1 - stack / stacks])

for stack in range(stacks):
for slice_ in range(slices):
first = stack * (slices + 1) + slice_
second = first + slices + 1
indices.extend([first, second, first + 1, second, second + 1, first + 1])

return vertices, normals, tex_coords, indices

# Setup lighting
def setup_lighting():
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)

light_position = [1, 1, 1, 0]
light_color = [1.5, 1.5, 1.5, 1]
ambient_light = [0.8, 0.8, 0.8, 1]

glLightfv(GL_LIGHT0, GL_POSITION, light_position)
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color)
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light)

glMaterialfv(GL_FRONT, GL_AMBIENT, [0.8, 0.8, 0.8, 1.0])
glMaterialfv(GL_FRONT, GL_DIFFUSE, [1.2, 1.2, 1.2, 1.0])
glMaterialfv(GL_FRONT, GL_SPECULAR, [0.5, 0.5, 0.5, 1.0])
glMaterialf(GL_FRONT, GL_SHININESS, 50.0)

# Main application
def main():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)

glEnable(GL_DEPTH_TEST)
glEnable(GL_TEXTURE_2D)

setup_lighting()

# Load textures
day_texture = load_texture(earth_day_map)
night_texture = load_texture(earth_night_map)
clouds_texture = load_texture(clouds_map, use_alpha=True)

skybox_textures = {}
for face, file in skybox_faces.items():
skybox_textures[face] = load_texture(file)

if day_texture is None or night_texture is None or clouds_texture is None:
print("Failed to load textures.")
return

# Sphere data for Earth
radius = 1.0
slices = 64
stacks = 64
vertices, normals, tex_coords, indices = create_sphere(radius, slices, stacks)

# Sphere data for clouds
clouds_radius = 1.02  # Slightly larger than Earth's radius
clouds_vertices, clouds_normals, clouds_tex_coords, _ = create_sphere(clouds_radius, slices, stacks)

# Set up perspective and view matrix
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, (display[0] / display[1]), 0.1, 100)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

zoom = -5
rotation_x, rotation_y = 0, 0
current_texture = day_texture

def render_skybox(size):
glDisable(GL_DEPTH_TEST)
glDisable(GL_LIGHTING)
glDepthMask(GL_FALSE)

glPushMatrix()
glTranslatef(0, 0, 0)
glScalef(size, size, size)

faces = [
('right',  [(1, -1, -1), (1, -1, 1), (1, 1, 1), (1, 1, -1)]),
('left',   [(-1, -1, 1), (-1, -1, -1), (-1, 1, -1), (-1, 1, 1)]),
('top',    [(-1, 1, -1), (1, 1, -1), (1, 1, 1), (-1, 1, 1)]),
('bottom', [(-1, -1, 1), (1, -1, 1), (1, -1, -1), (-1, -1, -1)]),
('front',  [(-1, -1, -1), (1, -1, -1), (1, 1, -1), (-1, 1, -1)]),
('back',   [(1, -1, 1), (-1, -1, 1), (-1, 1, 1), (1, 1, 1)]),
]

glEnable(GL_TEXTURE_2D)
glColor4f(1.0, 1.0, 1.0, 1.0)

for face_name, vertices in faces:
glBindTexture(GL_TEXTURE_2D, skybox_textures[face_name])
glBegin(GL_QUADS)
for i, (x, y, z) in enumerate(vertices):
s = i % 2
t = (i // 2) % 2
glTexCoord2f(s, t)
glVertex3f(x, y,  z)
glEnd()

glPopMatrix()

glDepthMask(GL_TRUE)
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)

def compute_zoom_step(zoom, min_zoom, max_zoom):
zoom_range = max_zoom - min_zoom
distance_to_limit = min(zoom - min_zoom, max_zoom - zoom)
return (distance_to_limit / zoom_range) * 0.5

min_zoom, max_zoom = -10, -1.2

clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
return
if event.type == MOUSEBUTTONDOWN:
step = compute_zoom_step(zoom, min_zoom, max_zoom)
if event.button == 4:  # Scroll up
zoom = min(max_zoom, zoom + step)
if event.button == 5:  # Scroll down
zoom = max(min_zoom, zoom - step)
if event.type == MOUSEMOTION:
if pygame.mouse.get_pressed()[0]:  # Left button pressed
dx, dy = event.rel
rotation_x += dy * 0.5
rotation_y += dx * 0.5
if event.type == KEYDOWN:
if event.key == K_n:   # Press 'n' to toggle night texture
current_texture = night_texture if current_texture == day_texture else day_texture

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glTranslatef(0, 0, zoom)
glRotatef(rotation_x, 1, 0, 0)
glRotatef(rotation_y, 0, 1, 0)

# Render the skybox before other objects
render_skybox(size=50)

# --- Render Earth ---
glPushMatrix()
glBindTexture(GL_TEXTURE_2D, current_texture)

glDisable(GL_BLEND)         # Ensure blending is disabled
glDepthMask(GL_TRUE)        # Enable depth writing

# Enable and set pointers
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)

# Convert lists to GLfloat arrays
vertex_data = (GLfloat * len(vertices))(*vertices)
normal_data = (GLfloat * len(normals))(*normals)
texcoord_data = (GLfloat * len(tex_coords))(*tex_coords)
index_data = (GLuint * len(indices))(*indices)

glVertexPointer(3, GL_FLOAT, 0, vertex_data)
glNormalPointer(GL_FLOAT, 0, normal_data)
glTexCoordPointer(2, GL_FLOAT, 0, texcoord_data)

glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, index_data)

glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_NORMAL_ARRAY)
glDisableClientState(GL_TEXTURE_COORD_ARRAY)

glPopMatrix()

# --- Render Clouds ---
glPushMatrix()
glBindTexture(GL_TEXTURE_2D, clouds_texture)

glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glDepthMask(GL_FALSE)       # Disable depth writing

if current_texture == day_texture:
glColor4f(1.0, 1.0, 1.0, 0.9)
else:
glColor4f(1.0, 1.0, 1.0, 0.2)  # Set transparency

# Enable and set pointers for clouds
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)

clouds_vertex_data = (GLfloat * len(clouds_vertices))(*clouds_vertices)
clouds_normal_data = (GLfloat * len(clouds_normals))(*clouds_normals)
clouds_texcoord_data = (GLfloat * len(clouds_tex_coords))(*clouds_tex_coords)
clouds_index_data = (GLuint * len(indices))(*indices)  # Use the same indices

glVertexPointer(3, GL_FLOAT, 0, clouds_vertex_data)
glNormalPointer(GL_FLOAT, 0, clouds_normal_data)
glTexCoordPointer(2, GL_FLOAT, 0, clouds_texcoord_data)

glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, clouds_index_data)

glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_NORMAL_ARRAY)
glDisableClientState(GL_TEXTURE_COORD_ARRAY)

glDepthMask(GL_TRUE)        # Re-enable depth writing
glDisable(GL_BLEND)

glPopMatrix()

pygame.display.flip()
clock.tick(60)

if __name__ == "__main__":
main()
Ps: При необходимости могу предоставить изображения скайбокса.

Подробнее здесь: https://stackoverflow.com/questions/792 ... t-face-ass
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»