Почему я получаю черную сцену в OpenGL на Python?
Я строю сцену: цилиндр, а вокруг него крутятся тор и икосаэдр, которые входят в туман и выходят из тумана. Использую файл с текстурой тумана (любой). Однако на выходе получаю черную сцену - почему так?
Код:
from pygame.locals import *
import pygame
import math
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GL.shaders import compileProgram, compileShader
# создаем окно
pygame.init()
display_size = (800, 600)
pygame.display.set_mode(display_size, DOUBLEBUF | OPENGL)
# БЛОК 2: Загрузка и настройка шейдеров
# устанавливаем шейдеры
vertex_shader = """
#version 330
in vec3 position;
in vec2 texture_coords;
out vec2 new_texture_coords;
uniform mat4 model;
uniform mat4 view_matrix;
uniform mat4 projection;
void main()
{
gl_Position = projection * view_matrix * model * vec4(position, 1.0);
new_texture_coords = texture_coords;
}
"""
fragment_shader = """
#version 330
in vec2 new_texture_coords;
out vec4 outcolor;
uniform sampler2D cloud_texture;
uniform vec4 fog_color;
void main()
{
vec4 texcolor = texture(cloud_texture, new_texture_coords);
outcolor = mix(fog_color, texcolor, texcolor.a);
}
"""
scale = 1
def vertex(x, y, z):
""" Возвращаем координаты вершин икосаэндра """
length = math.sqrt(x**2 + y**2 + z**2)
return [(i * scale) / length for i in (x,y,z)]
# Создаём икосаэдр
# Золотое сечение
PHI = (1 + math.sqrt(5)) / 2
vertices = [
vertex(-1, PHI, 0),
vertex( 1, PHI, 0),
vertex(-1, -PHI, 0),
vertex( 1, -PHI, 0),
vertex(0, -1, PHI),
vertex(0, 1, PHI),
vertex(0, -1, -PHI),
vertex(0, 1, -PHI),
vertex( PHI, 0, -1),
vertex( PHI, 0, 1),
vertex(-PHI, 0, -1),
vertex(-PHI, 0, 1),
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
]
indices = [
# 5 полигонов вокруг нулевой точки
0, 11, 5,
0, 5, 1,
0, 1, 7,
0, 7, 10,
0, 10, 11,
# Полигоны вокруг
1, 5, 9,
5, 11, 4,
11, 10, 2,
10, 7, 6,
7, 1, 8,
# 5 полигонов вокруг третьей точки
3, 9, 4,
3, 4, 2,
3, 2, 6,
3, 6, 8,
3, 8, 9,
# Полигоны вокруг
4, 9, 5,
2, 4, 11,
6, 2, 10,
8, 6, 7,
9, 8, 1
]
shader_program = compileProgram(
compileShader(vertex_shader, GL_VERTEX_SHADER),
compileShader(fragment_shader, GL_FRAGMENT_SHADER)
)
# получаем локации uniform-переменных в шейдерах
model_loc = glGetUniformLocation(shader_program, "model")
view_loc = glGetUniformLocation(shader_program, "view")
projection_loc = glGetUniformLocation(shader_program, "projection")
cloud_texture_loc = glGetUniformLocation(shader_program, "cloud_texture")
fog_color_loc = glGetUniformLocation(shader_program, "fog_color")
# БЛОК 3: Загрузка текстуры и установка параметров облака
# загружаем текстуру с облаком
cloud_texture = pygame.image.load('fog.png')
cloud_texture_data = pygame.image.tostring(cloud_texture, 'RGB', True)
# создаем текстуру
cloud_texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, cloud_texture_id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, cloud_texture.get_width(), cloud_texture.get_height(),
0, GL_RGB, GL_UNSIGNED_BYTE, cloud_texture_data)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
# задаем цвет тумана
fog_color = [0.4, 0.4, 0.3, 0.5]
# fog_color = [1, 1, 1, 0.5]
# задаем свойства облака
cloud_thickness = 0.1
cloud_width = 4
# БЛОК 4: Анимация и установка свойств отображения
# анимация
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
gluLookAt(0, -10, 10, 0, 0, 0, 0, 1, 0)
# БЛОК 5: Отрисовка облака и цилиндра
def draw_cloud():
glUseProgram(shader_program) # используем шейдерную программу
# передаем значения uniform-переменных (матрицы) в шейдеры
# устанавливает значение матрицы моделирования в шейдерную программу
glUniformMatrix4fv(model_loc, 1, GL_FALSE, glGetFloatv(GL_MODELVIEW_MATRIX))
# устанавливает значение матрицы вида в шейдерную программу
glUniformMatrix4fv(view_loc, 1, GL_FALSE, glGetFloatv(GL_PROJECTION_MATRIX))
# устанавливает значение матрицы проекции в шейдерную программу
glUniformMatrix4fv(projection_loc, 1, GL_FALSE, glGetFloatv(GL_PROJECTION_MATRIX))
# устанавливает значение цвета тумана в шейдерную программу
glUniform4fv(fog_color_loc, 1, fog_color)
# устанавливает текстуру облаков в шейдерную программу
glUniform1i(cloud_texture_loc, 0)
# включаем туман
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, fog_color)
glFogi(GL_FOG_MODE, GL_EXP2)
glFogf(GL_FOG_DENSITY, 0.05)
# Отрисовка икосаэдра
glColor3f(1.0, 0.0, 0.0)
glBegin(GL_TRIANGLES)
for i in indices:
glVertex3fv(vertices[i])
glEnd()
# Отрисовка цилиндра
glColor3f(1.0, 1.0, 1.0)
glPushMatrix()
glTranslatef(5, 0, 0)
quad = gluNewQuadric()
glRotatef(90, 1, 0, 0)
gluDisk(quad, 0.0, 0.5, 32, 32)
gluCylinder(quad, 0.5, 0.5, 2, 32, 32)
gluDisk(quad, 0.0, 0.5, 32, 32)
gluDeleteQuadric(quad)
glPopMatrix()
def end_draw_cloud():
"""
Функция для избавления от переполнения стека матриц
"""
glDisable(GL_FOG) # выключаем туман
# БЛОК 6: Отрисовка сцены
def draw_scene():
# очищаем экран
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
draw_cloud()
pygame.display.flip()
# БЛОК 7: Основной цикл рендеринга
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
draw_scene()
end_draw_cloud()
pygame.time.wait(10)