Anonymous
Почему карта теней не работает в моей программе pyopengl? [закрыто]
Сообщение
Anonymous » 28 сен 2024, 17:18
main.py:
Код: Выделить всё
from camera import Camera
from config import *
from model import *
class App:
def __init__(self):
pygame.init()
self.screen_width = 900
self.screen_height = 500
self.create_window()
self.shader = load_shader('default')
self.depth_shader = load_shader('depth')
self.camera = Camera(position = (0, 10, 0), fov = 90, aspect_ratio = pygame.display.get_surface().get_size()[0] / pygame.display.get_surface().get_size()[1], near = 0.1, far = 50)
self.vao = get_vao()
self.vbo = get_vbo()
self.instance_vbo = get_vbo()
self.basic_transformations = {'position': (0, 0, 0), 'rotation': (0, 0, 0), 'scale': (1, 1, 1)}
self.old_tick = 0
self.current_tick = 0
self.delta_time = 0
self.clock = pygame.time.Clock()
self.set_attribs()
self.init_objects()
self.set_instance_data()
def create_window(self):
pygame.display.set_mode((self.screen_width, self.screen_height), pygame.OPENGL | pygame.DOUBLEBUF | pygame.RESIZABLE)
pygame.display.set_caption('PyOpenGL 3D Engine')
glClearColor(0.15, 0.15, 0.15, 1)
def set_attribs(self):
glEnable(GL_DEPTH_TEST)
def init_objects(self):
self.cube = Cube('textures/cubes/white_cube.png', self.shader, self.vao, self.vbo, self.instance_vbo, self.camera)
random_color = random.choice(('red', 'blue', 'green', 'yellow'))
self.cube_2 = Cube(f'textures/cubes/{random_color}_cube.png', self.shader, self.vao, self.vbo, self.instance_vbo, self.camera)
self.lights = []
self.sun = Sun()
self.shadow_map = ShadowMap(1, self.sun, self.depth_shader)
glUniform1i(glGetUniformLocation(self.shader, 'ShadowMap'), self.shadow_map.unit)
def set_instance_data(self):
platform_size = (32, 32)
for x in range(-platform_size[0] // 2, platform_size[0] // 2):
for z in range(-platform_size[1] // 2, platform_size[1] // 2):
self.cube.instance_positions.append((x, 0, z))
self.cube_2.instance_positions.append((0, 2, 0))
def draw(self):
self.shadow_map.draw()
glUseProgram(self.shader)
self.shadow_map.use()
glUniformMatrix4fv(glGetUniformLocation(self.shader, 'lightSpaceMatrix'), 1, GL_FALSE, glm.value_ptr(self.shadow_map.lightSpaceMatrix))
glViewport(0, 0, self.screen_width, self.screen_height)
self.camera.aspect_ratio = self.screen_width / self.screen_height
self.camera.projection_matrix = self.camera.calculate_projection_matrix()
self.cube.draw(ShinyLevel = 0.0, transformations = self.basic_transformations, lights = self.lights, sun = self.sun)
self.cube_2.draw(ShinyLevel = 0.5, transformations = self.basic_transformations, lights = self.lights, sun = self.sun)
def game_loop(self):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
self.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_F11:
pygame.display.toggle_fullscreen()
if event.type == pygame.VIDEORESIZE:
self.screen_width, self.screen_height = event.size
glViewport(0, 0, self.screen_width, self.screen_height)
self.camera.aspect_ratio = self.screen_width / self.screen_height
self.camera.projection_matrix = self.camera.calculate_projection_matrix()
pygame.event.set_grab(True)
pygame.mouse.set_visible(False)
self.camera.update()
glUseProgram(self.shader)
self.view = self.camera.get_view_matrix()
glUniformMatrix4fv(glGetUniformLocation(self.shader, 'view'), 1, GL_FALSE, glm.value_ptr(self.view))
self.projection = self.camera.get_projection_matrix()
glUniformMatrix4fv(glGetUniformLocation(self.shader, 'projection'), 1, GL_FALSE, glm.value_ptr(self.projection))
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
self.draw()
pygame.display.flip()
def run(self):
self.game_loop()
def quit(self):
self.shadow_map.destroy()
self.cube.destroy()
self.cube_2.destroy()
glDeleteProgram(self.shader)
pygame.quit()
exit()
if __name__ == '__main__':
app = App()
app.run()
model.py:
Код: Выделить всё
from config import *
class Base:
def __init__(self, texture_path, shader, vao, vbo, instance_vbo, camera):
self.shader = shader
self.vao = vao
self.vbo = vbo
self.instance_vbo = instance_vbo
self.camera = camera
if texture_path is not None:
self.texture = Texture(texture_path, 0)
else:
self.texture = None
self.render_mode = GL_TRIANGLES
glUseProgram(self.shader)
self.set_vertices()
self.set_data()
self.set_attribs()
def set_vertices(self):
self.vertices = ()
def set_data(self):
self.vertices = np.array(self.vertices, dtype=np.float32)
self.instance_positions = []
self.attribs_count = 8
try:
self.vertex_count = int(len(self.vertices) / self.attribs_count)
except ZeroDivisionError:
self.vertex_count = 0
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
glUniform1i(glGetUniformLocation(self.shader, 'Image'), self.texture.unit)
def set_instance_data(self):
self.instance_positions = np.array(self.instance_positions, dtype=np.float32)
glBindBuffer(GL_ARRAY_BUFFER, self.instance_vbo)
glBufferData(GL_ARRAY_BUFFER, self.instance_positions.nbytes, self.instance_positions, GL_STATIC_DRAW)
glEnableVertexAttribArray(3)
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glVertexAttribDivisor(3, 1)
def set_attribs(self):
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.attribs_count * 4, ctypes.c_void_p(0))
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, self.attribs_count * 4, ctypes.c_void_p(12))
glEnableVertexAttribArray(2)
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, self.attribs_count * 4, ctypes.c_void_p(20))
def get_model_matrix(self, position, rotation, scale):
model = glm.mat4(1.0)
model = glm.translate(model, glm.vec3(position))
model = glm.rotate(model, glm.radians(rotation[0]), glm.vec3(1, 0, 0))
model = glm.rotate(model, glm.radians(rotation[1]), glm.vec3(0, 1, 0))
model = glm.rotate(model, glm.radians(rotation[2]), glm.vec3(0, 0, 1))
model = glm.scale(model, glm.vec3(scale))
return model
def update(self):
pass
def draw(self, ShinyLevel, transformations, lights, sun):
glUseProgram(self.shader)
glBindVertexArray(self.vao)
self.set_instance_data()
self.update()
glUniform1f(glGetUniformLocation(self.shader, 'ShinyLevel'), ShinyLevel)
glUniform1i(glGetUniformLocation(self.shader, 'IsF1Clicked'), pygame.key.get_pressed()[pygame.K_F1])
lights_num = len(lights)
if self.texture is not None:
self.texture.use()
self.model = self.get_model_matrix(transformations['position'], transformations['rotation'], transformations['scale'])
glUniformMatrix4fv(glGetUniformLocation(self.shader, 'model'), 1, GL_FALSE, glm.value_ptr(self.model))
for i, light in enumerate(lights):
glUniform3fv(glGetUniformLocation(self.shader, f'lights[{i}].position'), 1, glm.value_ptr(light.position))
glUniform3fv(glGetUniformLocation(self.shader, f'lights[{i}].color'), 1, glm.value_ptr(light.color))
glUniform1f(glGetUniformLocation(self.shader, f'lights[{i}].strength'), light.strength)
glUniform3fv(glGetUniformLocation(self.shader, 'sun.position'), 1, glm.value_ptr(sun.position))
glUniform3fv(glGetUniformLocation(self.shader, 'sun.color'), 1, glm.value_ptr(sun.color))
glUniform3fv(glGetUniformLocation(self.shader, 'sun.direction'), 1, glm.value_ptr(sun.direction))
glUniform3fv(glGetUniformLocation(self.shader, 'viewPos'), 1, glm.value_ptr(self.camera.position))
glUniform1i(glGetUniformLocation(self.shader, 'numLights'), lights_num)
glDrawArraysInstanced(self.render_mode, 0, self.vertex_count, len(self.instance_positions))
def destroy(self):
self.texture.destroy()
glDeleteVertexArrays(1, [self.vao])
glDeleteBuffers(1, [self.vbo])
glDeleteBuffers(1, [self.instance_vbo])
class Cube(Base):
def __init__(self, texture_path, shader, vao, vbo, instance_vbo, camera):
super().__init__(texture_path, shader, vao, vbo, instance_vbo, camera)
def set_vertices(self):
self.vertices = (
# Front face
-0.5, -0.5, -0.5, 0, 0, 0, 0, -1,
0.5, -0.5, -0.5, 1, 0, 0, 0, -1,
0.5, 0.5, -0.5, 1, 1, 0, 0, -1,
-0.5, -0.5, -0.5, 0, 0, 0, 0, -1,
0.5, 0.5, -0.5, 1, 1, 0, 0, -1,
-0.5, 0.5, -0.5, 0, 1, 0, 0, -1,
# Back face
-0.5, -0.5, 0.5, 0, 0, 0, 0, 1,
0.5, -0.5, 0.5, 1, 0, 0, 0, 1,
0.5, 0.5, 0.5, 1, 1, 0, 0, 1,
-0.5, -0.5, 0.5, 0, 0, 0, 0, 1,
0.5, 0.5, 0.5, 1, 1, 0, 0, 1,
-0.5, 0.5, 0.5, 0, 1, 0, 0, 1,
# Left face
-0.5, -0.5, -0.5, 0, 0, -1, 0, 0,
-0.5, 0.5, -0.5, 1, 0, -1, 0, 0,
-0.5, 0.5, 0.5, 1, 1, -1, 0, 0,
-0.5, -0.5, -0.5, 0, 0, -1, 0, 0,
-0.5, 0.5, 0.5, 1, 1, -1, 0, 0,
-0.5, -0.5, 0.5, 0, 1, -1, 0, 0,
# Right face
0.5, -0.5, -0.5, 0, 0, 1, 0, 0,
0.5, 0.5, -0.5, 1, 0, 1, 0, 0,
0.5, 0.5, 0.5, 1, 1, 1, 0, 0,
0.5, -0.5, -0.5, 0, 0, 1, 0, 0,
0.5, 0.5, 0.5, 1, 1, 1, 0, 0,
0.5, -0.5, 0.5, 0, 1, 1, 0, 0,
# Top face
-0.5, 0.5, -0.5, 0, 0, 0, 1, 0,
0.5, 0.5, -0.5, 1, 0, 0, 1, 0,
0.5, 0.5, 0.5, 1, 1, 0, 1, 0,
-0.5, 0.5, -0.5, 0, 0, 0, 1, 0,
0.5, 0.5, 0.5, 1, 1, 0, 1, 0,
-0.5, 0.5, 0.5, 0, 1, 0, 1, 0,
# Bottom face
-0.5, -0.5, -0.5, 0, 0, 0, -1, 0,
0.5, -0.5, -0.5, 1, 0, 0, -1, 0,
0.5, -0.5, 0.5, 1, 1, 0, -1, 0,
-0.5, -0.5, -0.5, 0, 0, 0, -1, 0,
0.5, -0.5, 0.5, 1, 1, 0, -1, 0,
-0.5, -0.5, 0.5, 0, 1, 0, -1, 0,
)
class Light:
def __init__(self, position = (0, 5, 0), color = (1, 1, 1), strength = 1):
self.position = glm.vec3(position)
self.color = glm.vec3(color)
self.strength = strength
def update_position(self, position):
self.position = glm.vec3(position)
def update_color(self, color):
self.color = glm.vec3(color)
def update_strength(self, strength):
self.strength = strength
class Sun:
def __init__(self, color = (1, 1, 1), direction = (-1, -1.5, -1)):
self.position = glm.vec3((0, 0, 0))
self.color = glm.vec3(color)
self.direction = glm.vec3(direction)
def update_position(self, position):
self.position = glm.vec3(position)
def update_color(self, color):
self.color = glm.vec3(color)
def update_direction(self, direction):
self.direction = direction
camera.py:
Код: Выделить всё
from config import *
class Camera:
def __init__(self, position, fov, aspect_ratio, near, far):
self.position = glm.vec3(position)
self.up = glm.vec3(0, 1, 0)
self.forward = glm.vec3(0, 0, 1)
self.right = glm.vec3(1, 0, 0)
self.fov = glm.radians(fov / 2)
self.aspect_ratio = aspect_ratio
self.near = near
self.far = far
self.view_matrix = self.calculate_view_matrix()
self.projection_matrix = self.calculate_projection_matrix()
self.yaw = 90
self.pitch = 0
self.speed = 0.0025
self.sens = 2
def update_vectors(self):
self.forward.x = glm.cos(self.yaw) * glm.cos(self.pitch)
self.forward.y = glm.sin(self.pitch)
self.forward.z = glm.sin(self.yaw) * glm.cos(self.pitch)
self.forward = glm.normalize(self.forward)
self.right = glm.normalize(glm.cross(self.forward, self.up))
def update(self):
self.update_vectors()
self.player_movement()
self.mouse_movement()
self.view_matrix = self.calculate_view_matrix()
def calculate_view_matrix(self):
return glm.lookAt(self.position, self.position + self.forward, self.up)
def calculate_projection_matrix(self):
return glm.perspective(self.fov, self.aspect_ratio, self.near, self.far)
def get_view_matrix(self):
return self.view_matrix
def get_projection_matrix(self):
return self.projection_matrix
def player_movement(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LSHIFT]:
speed = self.speed * 1.5
else:
speed = self.speed
if keys[pygame.K_w]:
self.position += self.forward * speed
if keys[pygame.K_s]:
self.position -= self.forward * speed
if keys[pygame.K_a]:
self.position -= self.right * speed
if keys[pygame.K_d]:
self.position += self.right * speed
if keys[pygame.K_q]:
self.position += self.up * speed
if keys[pygame.K_e]:
self.position -= self.up * speed
def mouse_movement(self):
x, y = pygame.mouse.get_rel()
self.yaw += (x / 1000) * self.sens
self.pitch -= (y / 1000) * self.sens
config.py:
Код: Выделить всё
import pygame
import glm
import numpy as np
import ctypes
import glm
import random
from OpenGL.GL import *
from OpenGL.GL.shaders import compileShader, compileProgram
from sys import exit
def load_shader(shader_name):
with open(f'shaders/{shader_name}.vert') as f:
vertex_src = f.readlines()
with open(f'shaders/{shader_name}.frag') as f:
fragment_src = f.readlines()
shader = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER),
compileShader(fragment_src, GL_FRAGMENT_SHADER))
glUseProgram(shader)
return shader
def get_vao():
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
return vao
def get_vbo():
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
return vbo
def get_fbo():
fbo = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, fbo)
return fbo
class Texture:
def __init__(self, path, unit):
self.unit = unit
texture = pygame.image.load(path).convert_alpha()
width, height = texture.get_rect().size
texture_data = pygame.image.tostring(texture, 'RGBA', True)
self.texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.texture_id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data)
glGenerateMipmap(GL_TEXTURE_2D)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
def use(self):
exec(f'glActiveTexture(GL_TEXTURE{self.unit})')
glBindTexture(GL_TEXTURE_2D, self.texture_id)
def destroy(self):
glDeleteTextures(1, [self.texture_id,])
class ShadowMap:
def __init__(self, unit, light, depth_shader):
self.fbo = get_fbo()
self.unit = unit
self.resolution = (1024, 1024)
self.BaseLight = light
self.depth_shader = depth_shader
self.lightSpaceMatrix = glm.mat4(1.0)
self.border_color = glm.vec4(1.0)
self.depth_map = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.depth_map)
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, *self.resolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, glm.value_ptr(self.border_color))
glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, self.depth_map, 0)
glDrawBuffer(GL_NONE)
glReadBuffer(GL_NONE)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
def draw(self):
glUseProgram(self.depth_shader)
glViewport(0, 0, *self.resolution)
glBindFramebuffer(GL_FRAMEBUFFER, self.fbo)
glClear(GL_DEPTH_BUFFER_BIT)
self.position = 10 * self.BaseLight.direction
self.center = glm.vec3(0.0, 0.0, 0.0)
self.up = glm.vec3(0.0, 0.0, 1.0)
self.projection = glm.ortho(-10, 10, -10, 10, 1.0, 20.0)
self.view = glm.lookAt(self.position, self.center, self.up)
self.lightSpaceMatrix = self.projection * self.view
glUniformMatrix4fv(glGetUniformLocation(self.depth_shader, 'lightSpaceMatrix'), 1, GL_FALSE, glm.value_ptr(self.lightSpaceMatrix))
glBindFramebuffer(GL_FRAMEBUFFER, 0)
def use(self):
exec(f'glActiveTexture(GL_TEXTURE{self.unit})')
glBindTexture(GL_TEXTURE_2D, self.depth_map)
def destroy(self):
glDeleteTextures(1, [self.depth_map,])
glDeleteFramebuffers(1, [self.fbo,])
default.vert:
Код: Выделить всё
#version 330 core
layout(location = 0) in vec3 vertexPos;
layout(location = 1) in vec2 vertexTexCoord;
layout(location = 2) in vec3 vertexNormal;
layout(location = 3) in vec3 instancePos;
out vec3 position;
out vec2 texcoord;
out vec3 normal;
out vec4 PositionLightSpace;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
void main()
{
vec4 worldPosition = model * vec4(vertexPos, 1.0) + vec4(instancePos, 0.0);
gl_Position = projection * view * worldPosition;
position = worldPosition.xyz;
texcoord = vertexTexCoord;
normal = normalize(mat3(model) * vertexNormal);
PositionLightSpace = lightSpaceMatrix * vec4(position, 1.0);
int renderMode = 0;
}
default.frag:
Код: Выделить всё
#version 330 core
in vec3 position;
in vec2 texcoord;
in vec3 normal;
in vec4 PositionLightSpace;
struct Light
{
vec3 position;
vec3 color;
vec3 strength;
};
struct DirectionalLight
{
vec3 color;
vec3 direction;
};
out vec4 FragColor;
vec3 calculatePointLight(Light light, vec3 Position, vec3 Normal);
vec3 calculateDirectionalLight(DirectionalLight Sun, vec3 Position, vec3 Normal);
float calculateShadow(vec4 PositionLightSpace);
#define MAX_LIGHTS 100
uniform Light lights[MAX_LIGHTS];
uniform DirectionalLight sun;
uniform int numLights;
uniform vec3 viewPos;
uniform sampler2D Image;
uniform sampler2D shadowMap;
uniform float ShinyLevel;
uniform bool IsF1Clicked;
void main()
{
vec3 temp = vec3(0.0);
vec3 lightDir = -sun.direction;
float shadow = calculateShadow(PositionLightSpace);
temp += (1.0 - shadow) * calculateDirectionalLight(sun, position, normal);
for(int i = 0; i < numLights; i++)
{
temp += calculatePointLight(lights[i], position, normal);
}
int renderMode = 0;
if (IsF1Clicked)
{
renderMode = 1;
}
if (renderMode == 0)
{
FragColor = vec4(temp, 1.0);
}
if (renderMode == 1)
{
FragColor = vec4(vec3(shadow), 1.0);
}
}
vec3 calculatePointLight(Light light, vec3 Position, vec3 Normal)
{
vec3 result = vec3(0.0);
vec3 baseTexture = texture(Image, texcoord).rgb;
vec3 lightDir = light.position - Position;
float distance = length(lightDir);
lightDir = normalize(lightDir);
vec3 viewDir = normalize(viewPos - Position);
vec3 reflectDir = reflect(-lightDir, Normal);
// ambient
result += 0.1 * baseTexture;
// diffuse
float diff = max(0.0, dot(Normal, lightDir));
result += light.color * light.strength * diff * baseTexture;
// specular
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
result += light.color * light.strength * spec;
return result;
}
vec3 calculateDirectionalLight(DirectionalLight Sun, vec3 Position, vec3 Normal)
{
vec3 result = vec3(0.0);
vec3 baseTexture = texture(Image, texcoord).rgb;
vec3 normal = normalize(Normal);
vec3 lightDir = normalize(-Sun.direction);
lightDir = normalize(lightDir);
vec3 viewDir = normalize(viewPos - Position);
vec3 reflectDir = reflect(-lightDir, normal);
// ambient
result += 0.2 * baseTexture;
// diffuse
float diffuse = max(0.0, dot(normal, lightDir));
result += Sun.color * diffuse * baseTexture;
// specular
float specular = pow(max(dot(viewDir, reflectDir), 0.0), 32);
result += ShinyLevel * Sun.color * specular * baseTexture;
return result;
}
float calculateShadow(vec4 fragPosLightSpace)
{
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5;
float d1 = texture(shadowMap, projCoords.xy).r;
float d2 = projCoords.z;
vec3 normal = normal;
vec3 lightDir = normalize(-10 * sun.direction - position);
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
float shadow = 0.0;
vec2 texelsize = 1.0 / textureSize(shadowMap, 0);
for (int x = -1; x 1.0)
{
shadow = 0.0;
}
return shadow;
}
глубина.верт:
Код: Выделить всё
#version 330 core
layout(location = 0) in vec3 vertexPos;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;
void main()
{
gl_Position = lightSpaceMatrix * model * vec4(vertexPos, 1.0);
}
глубина.фраг:
Код: Выделить всё
#version 330 core
void main()
{
gl_FragDepth = gl_FragCoord.z;
}
Это моя программа. несуществующие фигуры, созданные картой теней, снимок экрана и мой снимок экрана с этой ошибкой. Я пытался создавать тени в pyopengl, но карта теней отображает несуществующие фигуры. Программа не возвращает никаких ошибок.
Что я делаю не так? Может ли кто-нибудь мне помочь?
Подробнее здесь:
https://stackoverflow.com/questions/790 ... gl-program
1727533097
Anonymous
main.py: [code]from camera import Camera from config import * from model import * class App: def __init__(self): pygame.init() self.screen_width = 900 self.screen_height = 500 self.create_window() self.shader = load_shader('default') self.depth_shader = load_shader('depth') self.camera = Camera(position = (0, 10, 0), fov = 90, aspect_ratio = pygame.display.get_surface().get_size()[0] / pygame.display.get_surface().get_size()[1], near = 0.1, far = 50) self.vao = get_vao() self.vbo = get_vbo() self.instance_vbo = get_vbo() self.basic_transformations = {'position': (0, 0, 0), 'rotation': (0, 0, 0), 'scale': (1, 1, 1)} self.old_tick = 0 self.current_tick = 0 self.delta_time = 0 self.clock = pygame.time.Clock() self.set_attribs() self.init_objects() self.set_instance_data() def create_window(self): pygame.display.set_mode((self.screen_width, self.screen_height), pygame.OPENGL | pygame.DOUBLEBUF | pygame.RESIZABLE) pygame.display.set_caption('PyOpenGL 3D Engine') glClearColor(0.15, 0.15, 0.15, 1) def set_attribs(self): glEnable(GL_DEPTH_TEST) def init_objects(self): self.cube = Cube('textures/cubes/white_cube.png', self.shader, self.vao, self.vbo, self.instance_vbo, self.camera) random_color = random.choice(('red', 'blue', 'green', 'yellow')) self.cube_2 = Cube(f'textures/cubes/{random_color}_cube.png', self.shader, self.vao, self.vbo, self.instance_vbo, self.camera) self.lights = [] self.sun = Sun() self.shadow_map = ShadowMap(1, self.sun, self.depth_shader) glUniform1i(glGetUniformLocation(self.shader, 'ShadowMap'), self.shadow_map.unit) def set_instance_data(self): platform_size = (32, 32) for x in range(-platform_size[0] // 2, platform_size[0] // 2): for z in range(-platform_size[1] // 2, platform_size[1] // 2): self.cube.instance_positions.append((x, 0, z)) self.cube_2.instance_positions.append((0, 2, 0)) def draw(self): self.shadow_map.draw() glUseProgram(self.shader) self.shadow_map.use() glUniformMatrix4fv(glGetUniformLocation(self.shader, 'lightSpaceMatrix'), 1, GL_FALSE, glm.value_ptr(self.shadow_map.lightSpaceMatrix)) glViewport(0, 0, self.screen_width, self.screen_height) self.camera.aspect_ratio = self.screen_width / self.screen_height self.camera.projection_matrix = self.camera.calculate_projection_matrix() self.cube.draw(ShinyLevel = 0.0, transformations = self.basic_transformations, lights = self.lights, sun = self.sun) self.cube_2.draw(ShinyLevel = 0.5, transformations = self.basic_transformations, lights = self.lights, sun = self.sun) def game_loop(self): while True: for event in pygame.event.get(): if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE): self.quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_F11: pygame.display.toggle_fullscreen() if event.type == pygame.VIDEORESIZE: self.screen_width, self.screen_height = event.size glViewport(0, 0, self.screen_width, self.screen_height) self.camera.aspect_ratio = self.screen_width / self.screen_height self.camera.projection_matrix = self.camera.calculate_projection_matrix() pygame.event.set_grab(True) pygame.mouse.set_visible(False) self.camera.update() glUseProgram(self.shader) self.view = self.camera.get_view_matrix() glUniformMatrix4fv(glGetUniformLocation(self.shader, 'view'), 1, GL_FALSE, glm.value_ptr(self.view)) self.projection = self.camera.get_projection_matrix() glUniformMatrix4fv(glGetUniformLocation(self.shader, 'projection'), 1, GL_FALSE, glm.value_ptr(self.projection)) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.draw() pygame.display.flip() def run(self): self.game_loop() def quit(self): self.shadow_map.destroy() self.cube.destroy() self.cube_2.destroy() glDeleteProgram(self.shader) pygame.quit() exit() if __name__ == '__main__': app = App() app.run() [/code] model.py: [code]from config import * class Base: def __init__(self, texture_path, shader, vao, vbo, instance_vbo, camera): self.shader = shader self.vao = vao self.vbo = vbo self.instance_vbo = instance_vbo self.camera = camera if texture_path is not None: self.texture = Texture(texture_path, 0) else: self.texture = None self.render_mode = GL_TRIANGLES glUseProgram(self.shader) self.set_vertices() self.set_data() self.set_attribs() def set_vertices(self): self.vertices = () def set_data(self): self.vertices = np.array(self.vertices, dtype=np.float32) self.instance_positions = [] self.attribs_count = 8 try: self.vertex_count = int(len(self.vertices) / self.attribs_count) except ZeroDivisionError: self.vertex_count = 0 glBindBuffer(GL_ARRAY_BUFFER, self.vbo) glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW) glUniform1i(glGetUniformLocation(self.shader, 'Image'), self.texture.unit) def set_instance_data(self): self.instance_positions = np.array(self.instance_positions, dtype=np.float32) glBindBuffer(GL_ARRAY_BUFFER, self.instance_vbo) glBufferData(GL_ARRAY_BUFFER, self.instance_positions.nbytes, self.instance_positions, GL_STATIC_DRAW) glEnableVertexAttribArray(3) glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0)) glVertexAttribDivisor(3, 1) def set_attribs(self): glEnableVertexAttribArray(0) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.attribs_count * 4, ctypes.c_void_p(0)) glEnableVertexAttribArray(1) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, self.attribs_count * 4, ctypes.c_void_p(12)) glEnableVertexAttribArray(2) glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, self.attribs_count * 4, ctypes.c_void_p(20)) def get_model_matrix(self, position, rotation, scale): model = glm.mat4(1.0) model = glm.translate(model, glm.vec3(position)) model = glm.rotate(model, glm.radians(rotation[0]), glm.vec3(1, 0, 0)) model = glm.rotate(model, glm.radians(rotation[1]), glm.vec3(0, 1, 0)) model = glm.rotate(model, glm.radians(rotation[2]), glm.vec3(0, 0, 1)) model = glm.scale(model, glm.vec3(scale)) return model def update(self): pass def draw(self, ShinyLevel, transformations, lights, sun): glUseProgram(self.shader) glBindVertexArray(self.vao) self.set_instance_data() self.update() glUniform1f(glGetUniformLocation(self.shader, 'ShinyLevel'), ShinyLevel) glUniform1i(glGetUniformLocation(self.shader, 'IsF1Clicked'), pygame.key.get_pressed()[pygame.K_F1]) lights_num = len(lights) if self.texture is not None: self.texture.use() self.model = self.get_model_matrix(transformations['position'], transformations['rotation'], transformations['scale']) glUniformMatrix4fv(glGetUniformLocation(self.shader, 'model'), 1, GL_FALSE, glm.value_ptr(self.model)) for i, light in enumerate(lights): glUniform3fv(glGetUniformLocation(self.shader, f'lights[{i}].position'), 1, glm.value_ptr(light.position)) glUniform3fv(glGetUniformLocation(self.shader, f'lights[{i}].color'), 1, glm.value_ptr(light.color)) glUniform1f(glGetUniformLocation(self.shader, f'lights[{i}].strength'), light.strength) glUniform3fv(glGetUniformLocation(self.shader, 'sun.position'), 1, glm.value_ptr(sun.position)) glUniform3fv(glGetUniformLocation(self.shader, 'sun.color'), 1, glm.value_ptr(sun.color)) glUniform3fv(glGetUniformLocation(self.shader, 'sun.direction'), 1, glm.value_ptr(sun.direction)) glUniform3fv(glGetUniformLocation(self.shader, 'viewPos'), 1, glm.value_ptr(self.camera.position)) glUniform1i(glGetUniformLocation(self.shader, 'numLights'), lights_num) glDrawArraysInstanced(self.render_mode, 0, self.vertex_count, len(self.instance_positions)) def destroy(self): self.texture.destroy() glDeleteVertexArrays(1, [self.vao]) glDeleteBuffers(1, [self.vbo]) glDeleteBuffers(1, [self.instance_vbo]) class Cube(Base): def __init__(self, texture_path, shader, vao, vbo, instance_vbo, camera): super().__init__(texture_path, shader, vao, vbo, instance_vbo, camera) def set_vertices(self): self.vertices = ( # Front face -0.5, -0.5, -0.5, 0, 0, 0, 0, -1, 0.5, -0.5, -0.5, 1, 0, 0, 0, -1, 0.5, 0.5, -0.5, 1, 1, 0, 0, -1, -0.5, -0.5, -0.5, 0, 0, 0, 0, -1, 0.5, 0.5, -0.5, 1, 1, 0, 0, -1, -0.5, 0.5, -0.5, 0, 1, 0, 0, -1, # Back face -0.5, -0.5, 0.5, 0, 0, 0, 0, 1, 0.5, -0.5, 0.5, 1, 0, 0, 0, 1, 0.5, 0.5, 0.5, 1, 1, 0, 0, 1, -0.5, -0.5, 0.5, 0, 0, 0, 0, 1, 0.5, 0.5, 0.5, 1, 1, 0, 0, 1, -0.5, 0.5, 0.5, 0, 1, 0, 0, 1, # Left face -0.5, -0.5, -0.5, 0, 0, -1, 0, 0, -0.5, 0.5, -0.5, 1, 0, -1, 0, 0, -0.5, 0.5, 0.5, 1, 1, -1, 0, 0, -0.5, -0.5, -0.5, 0, 0, -1, 0, 0, -0.5, 0.5, 0.5, 1, 1, -1, 0, 0, -0.5, -0.5, 0.5, 0, 1, -1, 0, 0, # Right face 0.5, -0.5, -0.5, 0, 0, 1, 0, 0, 0.5, 0.5, -0.5, 1, 0, 1, 0, 0, 0.5, 0.5, 0.5, 1, 1, 1, 0, 0, 0.5, -0.5, -0.5, 0, 0, 1, 0, 0, 0.5, 0.5, 0.5, 1, 1, 1, 0, 0, 0.5, -0.5, 0.5, 0, 1, 1, 0, 0, # Top face -0.5, 0.5, -0.5, 0, 0, 0, 1, 0, 0.5, 0.5, -0.5, 1, 0, 0, 1, 0, 0.5, 0.5, 0.5, 1, 1, 0, 1, 0, -0.5, 0.5, -0.5, 0, 0, 0, 1, 0, 0.5, 0.5, 0.5, 1, 1, 0, 1, 0, -0.5, 0.5, 0.5, 0, 1, 0, 1, 0, # Bottom face -0.5, -0.5, -0.5, 0, 0, 0, -1, 0, 0.5, -0.5, -0.5, 1, 0, 0, -1, 0, 0.5, -0.5, 0.5, 1, 1, 0, -1, 0, -0.5, -0.5, -0.5, 0, 0, 0, -1, 0, 0.5, -0.5, 0.5, 1, 1, 0, -1, 0, -0.5, -0.5, 0.5, 0, 1, 0, -1, 0, ) class Light: def __init__(self, position = (0, 5, 0), color = (1, 1, 1), strength = 1): self.position = glm.vec3(position) self.color = glm.vec3(color) self.strength = strength def update_position(self, position): self.position = glm.vec3(position) def update_color(self, color): self.color = glm.vec3(color) def update_strength(self, strength): self.strength = strength class Sun: def __init__(self, color = (1, 1, 1), direction = (-1, -1.5, -1)): self.position = glm.vec3((0, 0, 0)) self.color = glm.vec3(color) self.direction = glm.vec3(direction) def update_position(self, position): self.position = glm.vec3(position) def update_color(self, color): self.color = glm.vec3(color) def update_direction(self, direction): self.direction = direction [/code] camera.py: [code]from config import * class Camera: def __init__(self, position, fov, aspect_ratio, near, far): self.position = glm.vec3(position) self.up = glm.vec3(0, 1, 0) self.forward = glm.vec3(0, 0, 1) self.right = glm.vec3(1, 0, 0) self.fov = glm.radians(fov / 2) self.aspect_ratio = aspect_ratio self.near = near self.far = far self.view_matrix = self.calculate_view_matrix() self.projection_matrix = self.calculate_projection_matrix() self.yaw = 90 self.pitch = 0 self.speed = 0.0025 self.sens = 2 def update_vectors(self): self.forward.x = glm.cos(self.yaw) * glm.cos(self.pitch) self.forward.y = glm.sin(self.pitch) self.forward.z = glm.sin(self.yaw) * glm.cos(self.pitch) self.forward = glm.normalize(self.forward) self.right = glm.normalize(glm.cross(self.forward, self.up)) def update(self): self.update_vectors() self.player_movement() self.mouse_movement() self.view_matrix = self.calculate_view_matrix() def calculate_view_matrix(self): return glm.lookAt(self.position, self.position + self.forward, self.up) def calculate_projection_matrix(self): return glm.perspective(self.fov, self.aspect_ratio, self.near, self.far) def get_view_matrix(self): return self.view_matrix def get_projection_matrix(self): return self.projection_matrix def player_movement(self): keys = pygame.key.get_pressed() if keys[pygame.K_LSHIFT]: speed = self.speed * 1.5 else: speed = self.speed if keys[pygame.K_w]: self.position += self.forward * speed if keys[pygame.K_s]: self.position -= self.forward * speed if keys[pygame.K_a]: self.position -= self.right * speed if keys[pygame.K_d]: self.position += self.right * speed if keys[pygame.K_q]: self.position += self.up * speed if keys[pygame.K_e]: self.position -= self.up * speed def mouse_movement(self): x, y = pygame.mouse.get_rel() self.yaw += (x / 1000) * self.sens self.pitch -= (y / 1000) * self.sens [/code] config.py: [code]import pygame import glm import numpy as np import ctypes import glm import random from OpenGL.GL import * from OpenGL.GL.shaders import compileShader, compileProgram from sys import exit def load_shader(shader_name): with open(f'shaders/{shader_name}.vert') as f: vertex_src = f.readlines() with open(f'shaders/{shader_name}.frag') as f: fragment_src = f.readlines() shader = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER)) glUseProgram(shader) return shader def get_vao(): vao = glGenVertexArrays(1) glBindVertexArray(vao) return vao def get_vbo(): vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vbo) return vbo def get_fbo(): fbo = glGenFramebuffers(1) glBindFramebuffer(GL_FRAMEBUFFER, fbo) return fbo class Texture: def __init__(self, path, unit): self.unit = unit texture = pygame.image.load(path).convert_alpha() width, height = texture.get_rect().size texture_data = pygame.image.tostring(texture, 'RGBA', True) self.texture_id = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.texture_id) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data) glGenerateMipmap(GL_TEXTURE_2D) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) def use(self): exec(f'glActiveTexture(GL_TEXTURE{self.unit})') glBindTexture(GL_TEXTURE_2D, self.texture_id) def destroy(self): glDeleteTextures(1, [self.texture_id,]) class ShadowMap: def __init__(self, unit, light, depth_shader): self.fbo = get_fbo() self.unit = unit self.resolution = (1024, 1024) self.BaseLight = light self.depth_shader = depth_shader self.lightSpaceMatrix = glm.mat4(1.0) self.border_color = glm.vec4(1.0) self.depth_map = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.depth_map) glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, *self.resolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, glm.value_ptr(self.border_color)) glBindFramebuffer(GL_FRAMEBUFFER, self.fbo) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, self.depth_map, 0) glDrawBuffer(GL_NONE) glReadBuffer(GL_NONE) glBindFramebuffer(GL_FRAMEBUFFER, 0) def draw(self): glUseProgram(self.depth_shader) glViewport(0, 0, *self.resolution) glBindFramebuffer(GL_FRAMEBUFFER, self.fbo) glClear(GL_DEPTH_BUFFER_BIT) self.position = 10 * self.BaseLight.direction self.center = glm.vec3(0.0, 0.0, 0.0) self.up = glm.vec3(0.0, 0.0, 1.0) self.projection = glm.ortho(-10, 10, -10, 10, 1.0, 20.0) self.view = glm.lookAt(self.position, self.center, self.up) self.lightSpaceMatrix = self.projection * self.view glUniformMatrix4fv(glGetUniformLocation(self.depth_shader, 'lightSpaceMatrix'), 1, GL_FALSE, glm.value_ptr(self.lightSpaceMatrix)) glBindFramebuffer(GL_FRAMEBUFFER, 0) def use(self): exec(f'glActiveTexture(GL_TEXTURE{self.unit})') glBindTexture(GL_TEXTURE_2D, self.depth_map) def destroy(self): glDeleteTextures(1, [self.depth_map,]) glDeleteFramebuffers(1, [self.fbo,]) [/code] default.vert: [code]#version 330 core layout(location = 0) in vec3 vertexPos; layout(location = 1) in vec2 vertexTexCoord; layout(location = 2) in vec3 vertexNormal; layout(location = 3) in vec3 instancePos; out vec3 position; out vec2 texcoord; out vec3 normal; out vec4 PositionLightSpace; uniform mat4 projection; uniform mat4 view; uniform mat4 model; uniform mat4 lightSpaceMatrix; void main() { vec4 worldPosition = model * vec4(vertexPos, 1.0) + vec4(instancePos, 0.0); gl_Position = projection * view * worldPosition; position = worldPosition.xyz; texcoord = vertexTexCoord; normal = normalize(mat3(model) * vertexNormal); PositionLightSpace = lightSpaceMatrix * vec4(position, 1.0); int renderMode = 0; } [/code] default.frag: [code]#version 330 core in vec3 position; in vec2 texcoord; in vec3 normal; in vec4 PositionLightSpace; struct Light { vec3 position; vec3 color; vec3 strength; }; struct DirectionalLight { vec3 color; vec3 direction; }; out vec4 FragColor; vec3 calculatePointLight(Light light, vec3 Position, vec3 Normal); vec3 calculateDirectionalLight(DirectionalLight Sun, vec3 Position, vec3 Normal); float calculateShadow(vec4 PositionLightSpace); #define MAX_LIGHTS 100 uniform Light lights[MAX_LIGHTS]; uniform DirectionalLight sun; uniform int numLights; uniform vec3 viewPos; uniform sampler2D Image; uniform sampler2D shadowMap; uniform float ShinyLevel; uniform bool IsF1Clicked; void main() { vec3 temp = vec3(0.0); vec3 lightDir = -sun.direction; float shadow = calculateShadow(PositionLightSpace); temp += (1.0 - shadow) * calculateDirectionalLight(sun, position, normal); for(int i = 0; i < numLights; i++) { temp += calculatePointLight(lights[i], position, normal); } int renderMode = 0; if (IsF1Clicked) { renderMode = 1; } if (renderMode == 0) { FragColor = vec4(temp, 1.0); } if (renderMode == 1) { FragColor = vec4(vec3(shadow), 1.0); } } vec3 calculatePointLight(Light light, vec3 Position, vec3 Normal) { vec3 result = vec3(0.0); vec3 baseTexture = texture(Image, texcoord).rgb; vec3 lightDir = light.position - Position; float distance = length(lightDir); lightDir = normalize(lightDir); vec3 viewDir = normalize(viewPos - Position); vec3 reflectDir = reflect(-lightDir, Normal); // ambient result += 0.1 * baseTexture; // diffuse float diff = max(0.0, dot(Normal, lightDir)); result += light.color * light.strength * diff * baseTexture; // specular float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); result += light.color * light.strength * spec; return result; } vec3 calculateDirectionalLight(DirectionalLight Sun, vec3 Position, vec3 Normal) { vec3 result = vec3(0.0); vec3 baseTexture = texture(Image, texcoord).rgb; vec3 normal = normalize(Normal); vec3 lightDir = normalize(-Sun.direction); lightDir = normalize(lightDir); vec3 viewDir = normalize(viewPos - Position); vec3 reflectDir = reflect(-lightDir, normal); // ambient result += 0.2 * baseTexture; // diffuse float diffuse = max(0.0, dot(normal, lightDir)); result += Sun.color * diffuse * baseTexture; // specular float specular = pow(max(dot(viewDir, reflectDir), 0.0), 32); result += ShinyLevel * Sun.color * specular * baseTexture; return result; } float calculateShadow(vec4 fragPosLightSpace) { vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; projCoords = projCoords * 0.5 + 0.5; float d1 = texture(shadowMap, projCoords.xy).r; float d2 = projCoords.z; vec3 normal = normal; vec3 lightDir = normalize(-10 * sun.direction - position); float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005); float shadow = 0.0; vec2 texelsize = 1.0 / textureSize(shadowMap, 0); for (int x = -1; x 1.0) { shadow = 0.0; } return shadow; } [/code] глубина.верт: [code]#version 330 core layout(location = 0) in vec3 vertexPos; uniform mat4 lightSpaceMatrix; uniform mat4 model; void main() { gl_Position = lightSpaceMatrix * model * vec4(vertexPos, 1.0); } [/code] глубина.фраг: [code]#version 330 core void main() { gl_FragDepth = gl_FragCoord.z; } [/code] Это моя программа. несуществующие фигуры, созданные картой теней, снимок экрана и мой снимок экрана с этой ошибкой. Я пытался создавать тени в pyopengl, но карта теней отображает несуществующие фигуры. Программа не возвращает никаких ошибок. [b]Что я делаю не так?[/b] [b]Может ли кто-нибудь мне помочь?[/b] Подробнее здесь: [url]https://stackoverflow.com/questions/79026014/why-are-shadow-map-not-working-in-my-pyopengl-program[/url]