EG/plugins/user/fluid_simulation/rendering/water_renderer.py
2025-12-12 16:16:15 +08:00

978 lines
32 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
水体渲染器模块
负责水体的高质量渲染和视觉效果
"""
import time
from typing import Dict, Any, List, Optional, Tuple
import math
import numpy as np
class WaterRenderer:
"""
水体渲染器
负责水体的高质量渲染和视觉效果,包括反射、折射、泡沫等
"""
def __init__(self, plugin):
"""
初始化水体渲染器
Args:
plugin: 水体和流体模拟插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 渲染配置
self.render_config = {
'quality_level': 'medium', # 'low', 'medium', 'high', 'ultra'
'tessellation_factor': 4.0,
'lod_enabled': True,
'lod_distance': 100.0,
'max_patch_size': 50.0,
'render_distance': 500.0
}
# 着色器配置
self.shader_config = {
'water_shader': 'pbr', # 'standard', 'pbr', 'advanced'
'lighting_model': 'cook_torrance', # 'blinn_phong', 'cook_torrance', 'ward'
'normal_mapping': True,
'detail_mapping': True,
'reflection_enabled': True,
'refraction_enabled': True,
'caustics_enabled': True,
'foam_enabled': True,
'underwater_effects': True
}
# 材质属性
self.material_properties = {
'base_color': (0.0, 0.2, 0.5, 0.9), # RGBA
'specular_color': (0.8, 0.8, 0.9),
'roughness': 0.05,
'metallic': 0.0,
'reflectance': 0.95,
'refractive_index': 1.333,
'absorption_color': (0.0, 0.05, 0.15),
'absorption_coefficient': 0.1
}
# 光照配置
self.lighting_config = {
'ambient_light': (0.1, 0.1, 0.15),
'diffuse_light': (0.9, 0.9, 0.95),
'specular_light': (1.0, 1.0, 1.0),
'light_direction': (0.5, 1.0, 0.3),
'shadow_enabled': True,
'shadow_quality': 'medium'
}
# 波浪渲染配置
self.wave_render_config = {
'normal_strength': 1.0,
'fresnel_power': 5.0,
'fresnel_bias': 0.2,
'wave_scale': 1.0,
'wave_speed': 1.0,
'wave_detail': 0.5
}
# 反射配置
self.reflection_config = {
'reflection_quality': 'medium', # 'low', 'medium', 'high', 'screen'
'planar_reflections': True,
'sky_reflections': True,
'reflection_distance': 200.0,
'update_frequency': 30.0 # Hz
}
# 折射配置
self.refraction_config = {
'refraction_quality': 'medium', # 'low', 'medium', 'high'
'chromatic_aberration': True,
'chromatic_intensity': 0.02
}
# 泡沫配置
self.foam_config = {
'foam_enabled': True,
'foam_threshold': 0.7,
'foam_smoothness': 0.3,
'foam_speed': 0.5,
'foam_color': (0.95, 0.95, 0.95, 0.8)
}
# 焦散配置
self.caustics_config = {
'caustics_enabled': True,
'caustics_intensity': 1.0,
'caustics_scale': 5.0,
'caustics_speed': 0.2,
'caustics_color': (0.9, 0.8, 0.6)
}
# 水下效果配置
self.underwater_config = {
'underwater_fog': True,
'fog_density': 0.05,
'fog_color': (0.0, 0.1, 0.2),
'god_rays_enabled': True,
'god_rays_intensity': 0.5
}
# 渲染状态
self.render_state = {
'last_render_time': 0.0,
'frames_rendered': 0,
'patches_rendered': 0,
'triangles_rendered': 0
}
# 性能统计
self.performance_stats = {
'render_calls': 0,
'render_time_total': 0.0,
'average_render_time': 0.0,
'patches_drawn': 0,
'vertices_processed': 0
}
# 特效配置
self.effect_config = {
'motion_blur': False,
'anti_aliasing': 'fxaa', # 'none', 'fxaa', 'ssaa', 'msaa'
'bloom_enabled': True,
'bloom_intensity': 0.3,
'depth_of_field': False,
'dof_focus_distance': 50.0
}
# 相机和视图
self.camera_state = {
'position': (0.0, 0.0, 0.0),
'view_matrix': None,
'projection_matrix': None,
'fov': 60.0
}
# 环境映射
self.environment_mapping = {
'skybox_enabled': True,
'skybox_texture': None,
'irradiance_map': None,
'prefiltered_map': None
}
print("✓ 水体渲染器已创建")
def initialize(self) -> bool:
"""
初始化水体渲染器
Returns:
是否初始化成功
"""
try:
# 初始化渲染资源
self._initialize_render_resources()
self.initialized = True
print("✓ 水体渲染器初始化完成")
return True
except Exception as e:
print(f"✗ 水体渲染器初始化失败: {e}")
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用水体渲染器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 水体渲染器未初始化")
return False
self.enabled = True
print("✓ 水体渲染器已启用")
return True
except Exception as e:
print(f"✗ 水体渲染器启用失败: {e}")
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用水体渲染器"""
try:
self.enabled = False
print("✓ 水体渲染器已禁用")
except Exception as e:
print(f"✗ 水体渲染器禁用失败: {e}")
import traceback
traceback.print_exc()
def finalize(self):
"""清理水体渲染器资源"""
try:
self.disable()
self._cleanup_render_resources()
self.initialized = False
print("✓ 水体渲染器资源已清理")
except Exception as e:
print(f"✗ 水体渲染器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新水体渲染器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 更新渲染状态
self.render_state['last_render_time'] += dt
self.render_state['frames_rendered'] += 1
# 更新波浪动画
self._update_wave_animation(dt)
except Exception as e:
print(f"✗ 水体渲染器更新失败: {e}")
import traceback
traceback.print_exc()
def _initialize_render_resources(self):
"""初始化渲染资源"""
try:
# 在实际实现中,这里会初始化着色器、纹理、缓冲区等
print("✓ 水体渲染资源初始化完成")
except Exception as e:
print(f"✗ 水体渲染资源初始化失败: {e}")
raise
def _cleanup_render_resources(self):
"""清理渲染资源"""
try:
# 在实际实现中,这里会释放着色器、纹理、缓冲区等资源
print("✓ 水体渲染资源清理完成")
except Exception as e:
print(f"✗ 水体渲染资源清理失败: {e}")
def _update_wave_animation(self, dt: float):
"""
更新波浪动画
Args:
dt: 时间增量
"""
try:
# 在实际实现中,这里会更新波浪动画参数
# 用于纹理坐标滚动、法线贴图动画等
pass
except Exception as e:
print(f"✗ 波浪动画更新失败: {e}")
def render_water(self, water_data: Dict[str, Any], camera_position: tuple):
"""
渲染水体
Args:
water_data: 水体数据字典
camera_position: 相机位置
"""
try:
start_time = time.time()
# 更新相机状态
self.camera_state['position'] = camera_position
# 获取水体网格数据
vertices = water_data.get('vertices', [])
normals = water_data.get('normals', [])
uvs = water_data.get('uvs', [])
indices = water_data.get('indices', [])
if not vertices or not indices:
return
# 应用LOD如果启用
if self.render_config['lod_enabled']:
vertices, normals, uvs, indices = self._apply_lod(
vertices, normals, uvs, indices, camera_position
)
# 在实际实现中,这里会:
# 1. 设置水体着色器参数
# 2. 上传网格数据到GPU
# 3. 应用材质和光照
# 4. 处理反射/折射效果
# 5. 执行网格渲染
# 更新统计信息
triangle_count = len(indices) // 3
self.performance_stats['render_calls'] += 1
self.performance_stats['patches_drawn'] += 1
self.performance_stats['vertices_processed'] += len(vertices)
self.render_state['patches_rendered'] += 1
self.render_state['triangles_rendered'] += triangle_count
render_time = time.time() - start_time
self.performance_stats['render_time_total'] += render_time
if self.performance_stats['render_calls'] > 0:
self.performance_stats['average_render_time'] = (
self.performance_stats['render_time_total'] /
self.performance_stats['render_calls']
)
print(f"✓ 水体渲染完成 ({triangle_count} 三角形)")
except Exception as e:
print(f"✗ 水体渲染失败: {e}")
import traceback
traceback.print_exc()
def _apply_lod(self, vertices: List[Tuple[float, float, float]],
normals: List[Tuple[float, float, float]],
uvs: List[Tuple[float, float]],
indices: List[int],
camera_position: Tuple[float, float, float]) -> Tuple[List, List, List, List]:
"""
应用LOD细节层次
Args:
vertices: 顶点列表
normals: 法线列表
uvs: UV坐标列表
indices: 索引列表
camera_position: 相机位置
Returns:
简化后的网格数据
"""
try:
# 计算到相机的距离
# 在实际实现中,这里会根据距离简化网格
lod_distance = self.render_config['lod_distance']
# 简化处理(示例)
return vertices, normals, uvs, indices
except Exception as e:
print(f"✗ LOD应用失败: {e}")
return vertices, normals, uvs, indices
def set_render_config(self, config: Dict[str, Any]):
"""
设置渲染配置
Args:
config: 渲染配置字典
"""
try:
self.render_config.update(config)
print(f"✓ 渲染配置已更新: {self.render_config}")
except Exception as e:
print(f"✗ 渲染配置设置失败: {e}")
def get_render_config(self) -> Dict[str, Any]:
"""
获取渲染配置
Returns:
渲染配置字典
"""
return self.render_config.copy()
def set_shader_config(self, config: Dict[str, Any]):
"""
设置着色器配置
Args:
config: 着色器配置字典
"""
try:
self.shader_config.update(config)
print(f"✓ 着色器配置已更新: {self.shader_config}")
except Exception as e:
print(f"✗ 着色器配置设置失败: {e}")
def get_shader_config(self) -> Dict[str, Any]:
"""
获取着色器配置
Returns:
着色器配置字典
"""
return self.shader_config.copy()
def set_material_properties(self, properties: Dict[str, Any]):
"""
设置材质属性
Args:
properties: 材质属性字典
"""
try:
self.material_properties.update(properties)
print(f"✓ 材质属性已更新: {self.material_properties}")
except Exception as e:
print(f"✗ 材质属性设置失败: {e}")
def get_material_properties(self) -> Dict[str, Any]:
"""
获取材质属性
Returns:
材质属性字典
"""
return self.material_properties.copy()
def set_lighting_config(self, config: Dict[str, Any]):
"""
设置光照配置
Args:
config: 光照配置字典
"""
try:
self.lighting_config.update(config)
print(f"✓ 光照配置已更新: {self.lighting_config}")
except Exception as e:
print(f"✗ 光照配置设置失败: {e}")
def get_lighting_config(self) -> Dict[str, Any]:
"""
获取光照配置
Returns:
光照配置字典
"""
return self.lighting_config.copy()
def set_wave_render_config(self, config: Dict[str, Any]):
"""
设置波浪渲染配置
Args:
config: 波浪渲染配置字典
"""
try:
self.wave_render_config.update(config)
print(f"✓ 波浪渲染配置已更新: {self.wave_render_config}")
except Exception as e:
print(f"✗ 波浪渲染配置设置失败: {e}")
def get_wave_render_config(self) -> Dict[str, Any]:
"""
获取波浪渲染配置
Returns:
波浪渲染配置字典
"""
return self.wave_render_config.copy()
def set_reflection_config(self, config: Dict[str, Any]):
"""
设置反射配置
Args:
config: 反射配置字典
"""
try:
self.reflection_config.update(config)
print(f"✓ 反射配置已更新: {self.reflection_config}")
except Exception as e:
print(f"✗ 反射配置设置失败: {e}")
def get_reflection_config(self) -> Dict[str, Any]:
"""
获取反射配置
Returns:
反射配置字典
"""
return self.reflection_config.copy()
def set_refraction_config(self, config: Dict[str, Any]):
"""
设置折射配置
Args:
config: 折射配置字典
"""
try:
self.refraction_config.update(config)
print(f"✓ 折射配置已更新: {self.refraction_config}")
except Exception as e:
print(f"✗ 折射配置设置失败: {e}")
def get_refraction_config(self) -> Dict[str, Any]:
"""
获取折射配置
Returns:
折射配置字典
"""
return self.refraction_config.copy()
def set_foam_config(self, config: Dict[str, Any]):
"""
设置泡沫配置
Args:
config: 泡沫配置字典
"""
try:
self.foam_config.update(config)
print(f"✓ 泡沫配置已更新: {self.foam_config}")
except Exception as e:
print(f"✗ 泡沫配置设置失败: {e}")
def get_foam_config(self) -> Dict[str, Any]:
"""
获取泡沫配置
Returns:
泡沫配置字典
"""
return self.foam_config.copy()
def set_caustics_config(self, config: Dict[str, Any]):
"""
设置焦散配置
Args:
config: 焦散配置字典
"""
try:
self.caustics_config.update(config)
print(f"✓ 焦散配置已更新: {self.caustics_config}")
except Exception as e:
print(f"✗ 焦散配置设置失败: {e}")
def get_caustics_config(self) -> Dict[str, Any]:
"""
获取焦散配置
Returns:
焦散配置字典
"""
return self.caustics_config.copy()
def set_underwater_config(self, config: Dict[str, Any]):
"""
设置水下效果配置
Args:
config: 水下效果配置字典
"""
try:
self.underwater_config.update(config)
print(f"✓ 水下效果配置已更新: {self.underwater_config}")
except Exception as e:
print(f"✗ 水下效果配置设置失败: {e}")
def get_underwater_config(self) -> Dict[str, Any]:
"""
获取水下效果配置
Returns:
水下效果配置字典
"""
return self.underwater_config.copy()
def set_effect_config(self, config: Dict[str, Any]):
"""
设置特效配置
Args:
config: 特效配置字典
"""
try:
self.effect_config.update(config)
print(f"✓ 特效配置已更新: {self.effect_config}")
except Exception as e:
print(f"✗ 特效配置设置失败: {e}")
def get_effect_config(self) -> Dict[str, Any]:
"""
获取特效配置
Returns:
特效配置字典
"""
return self.effect_config.copy()
def get_render_state(self) -> Dict[str, Any]:
"""
获取渲染状态
Returns:
渲染状态字典
"""
return self.render_state.copy()
def get_performance_stats(self) -> Dict[str, Any]:
"""
获取性能统计信息
Returns:
性能统计字典
"""
return self.performance_stats.copy()
def reset_performance_stats(self):
"""重置性能统计信息"""
try:
self.performance_stats = {
'render_calls': 0,
'render_time_total': 0.0,
'average_render_time': 0.0,
'patches_drawn': 0,
'vertices_processed': 0
}
print("✓ 性能统计信息已重置")
except Exception as e:
print(f"✗ 性能统计信息重置失败: {e}")
def update_camera_state(self, position: tuple, view_matrix: Any = None,
projection_matrix: Any = None, fov: float = 60.0):
"""
更新相机状态
Args:
position: 相机位置
view_matrix: 视图矩阵
projection_matrix: 投影矩阵
fov: 视野角度
"""
try:
self.camera_state['position'] = position
self.camera_state['view_matrix'] = view_matrix
self.camera_state['projection_matrix'] = projection_matrix
self.camera_state['fov'] = fov
except Exception as e:
print(f"✗ 相机状态更新失败: {e}")
def calculate_water_lighting(self, position: tuple, normal: tuple,
view_direction: tuple) -> tuple:
"""
计算水体光照(基于物理的渲染)
Args:
position: 位置
normal: 波浪法线
view_direction: 视线方向
Returns:
光照颜色 (r, g, b)
"""
try:
# 获取光照配置
ambient = self.lighting_config['ambient_light']
diffuse = self.lighting_config['diffuse_light']
light_dir = self.lighting_config['light_direction']
# 获取材质属性
base_color = self.material_properties['base_color'][:3]
specular_color = self.material_properties['specular_color']
roughness = self.material_properties['roughness']
metallic = self.material_properties['metallic']
# 归一化向量
norm_normal = np.array(normal) / np.linalg.norm(normal)
norm_light_dir = np.array(light_dir) / np.linalg.norm(light_dir)
norm_view_dir = np.array(view_direction) / np.linalg.norm(view_direction)
# 计算半角向量
half_vector = norm_light_dir + norm_view_dir
norm_half_vector = half_vector / np.linalg.norm(half_vector)
# 计算Fresnel效应
fresnel = self._calculate_fresnel(norm_normal, norm_view_dir)
# 漫反射项 (Lambertian)
ndotl = max(0.0, np.dot(norm_normal, norm_light_dir))
diffuse_contrib = (
ndotl * diffuse[0] * base_color[0],
ndotl * diffuse[1] * base_color[1],
ndotl * diffuse[2] * base_color[2]
)
# 镜面反射项 (Cook-Torrance)
specular_contrib = (0.0, 0.0, 0.0)
if ndotl > 0:
# 法线分布函数 (Trowbridge-Reitz GGX)
ndoth = max(0.0, np.dot(norm_normal, norm_half_vector))
alpha = roughness * roughness
alpha2 = alpha * alpha
denom = ndoth * ndoth * (alpha2 - 1.0) + 1.0
d = alpha2 / (math.pi * denom * denom)
# 几何函数
ndotv = max(0.0, np.dot(norm_normal, norm_view_dir))
k = (roughness + 1.0) * (roughness + 1.0) / 8.0
g1l = ndotl / (ndotl * (1.0 - k) + k)
g1v = ndotv / (ndotv * (1.0 - k) + k)
g = g1l * g1v
# Fresnel项 (Schlick近似)
f0 = np.array(specular_color) if metallic > 0.5 else np.array([0.04, 0.04, 0.04])
f = f0 + (1.0 - f0) * pow(1.0 - np.dot(norm_half_vector, norm_view_dir), 5.0)
# 完整的镜面反射贡献
if (ndotl * ndotv) > 0:
specular = (d * g * f) / (4.0 * ndotl * ndotv)
specular_contrib = (
specular[0] * diffuse[0],
specular[1] * diffuse[1],
specular[2] * diffuse[2]
)
# 环境光项
ambient_contrib = (
ambient[0] * base_color[0],
ambient[1] * base_color[1],
ambient[2] * base_color[2]
)
# 合成最终颜色
final_color = (
ambient_contrib[0] + diffuse_contrib[0] + specular_contrib[0],
ambient_contrib[1] + diffuse_contrib[1] + specular_contrib[1],
ambient_contrib[2] + diffuse_contrib[2] + specular_contrib[2]
)
# 应用Fresnel效应
final_color = (
final_color[0] * (1.0 - fresnel) + fresnel,
final_color[1] * (1.0 - fresnel) + fresnel,
final_color[2] * (1.0 - fresnel) + fresnel
)
# 确保颜色值在有效范围内
final_color = (
max(0.0, min(1.0, final_color[0])),
max(0.0, min(1.0, final_color[1])),
max(0.0, min(1.0, final_color[2]))
)
return final_color
except Exception as e:
print(f"✗ 水体光照计算失败: {e}")
return (0.1, 0.2, 0.5)
def _calculate_fresnel(self, normal: np.ndarray, view_dir: np.ndarray) -> float:
"""
计算Fresnel反射系数
Args:
normal: 表面法线
view_dir: 视线方向
Returns:
Fresnel系数
"""
try:
# 简化的Fresnel计算
ndotv = max(0.0, np.dot(normal, view_dir))
fresnel = pow(1.0 - ndotv, self.wave_render_config['fresnel_power'])
fresnel = max(0.0, min(1.0, fresnel + self.wave_render_config['fresnel_bias']))
return fresnel
except Exception as e:
return 0.5
def calculate_wave_normal(self, position: tuple, time_value: float) -> tuple:
"""
计算波浪法线
Args:
position: 位置 (x, z)
time_value: 时间值
Returns:
波浪法线 (nx, ny, nz)
"""
try:
# 在实际实现中,这里会根据波浪系统计算精确的法线
# 简化处理,返回一个基于位置的法线
x, z = position
# 简单的波浪法线计算(示例)
wave_height_x = 0.1 * math.sin(x * 0.1 + time_value)
wave_height_z = 0.1 * math.sin(z * 0.1 + time_value)
# 计算法线
normal = np.array([-wave_height_x, 1.0, -wave_height_z])
normal = normal / np.linalg.norm(normal)
return tuple(normal)
except Exception as e:
print(f"✗ 波浪法线计算失败: {e}")
return (0.0, 1.0, 0.0)
def generate_water_foam(self, wave_height: float, velocity: float) -> float:
"""
生成泡沫效果
Args:
wave_height: 波浪高度
velocity: 水流速度
Returns:
泡沫强度 (0.0-1.0)
"""
try:
# 获取泡沫配置
foam_threshold = self.foam_config['foam_threshold']
foam_smoothness = self.foam_config['foam_smoothness']
# 基于波浪高度和速度计算泡沫
foam_factor = max(0.0, wave_height - foam_threshold) / (1.0 - foam_threshold)
velocity_factor = min(1.0, velocity / 5.0)
# 合成泡沫强度
foam_intensity = foam_factor * (1.0 - velocity_factor * 0.5)
# 应用平滑处理
foam_intensity = pow(foam_intensity, foam_smoothness)
return max(0.0, min(1.0, foam_intensity))
except Exception as e:
print(f"✗ 泡沫效果计算失败: {e}")
return 0.0
def apply_post_processing(self, render_target: Any) -> Any:
"""
应用后处理效果
Args:
render_target: 渲染目标
Returns:
处理后的渲染目标
"""
try:
# 在实际实现中,这里会应用各种后处理效果
# 如抗锯齿、泛光、景深、运动模糊等
if self.effect_config['anti_aliasing'] != 'none':
render_target = self._apply_anti_aliasing(render_target)
if self.effect_config['bloom_enabled']:
render_target = self._apply_bloom(render_target)
if self.effect_config['motion_blur']:
render_target = self._apply_motion_blur(render_target)
if self.effect_config['depth_of_field']:
render_target = self._apply_depth_of_field(render_target)
return render_target
except Exception as e:
print(f"✗ 后处理应用失败: {e}")
return render_target
def _apply_anti_aliasing(self, render_target: Any) -> Any:
"""
应用抗锯齿
Args:
render_target: 渲染目标
Returns:
处理后的渲染目标
"""
try:
# 在实际实现中这里会应用FXAA、SSAA或MSAA等抗锯齿技术
aa_type = self.effect_config['anti_aliasing']
print(f"✓ 应用抗锯齿: {aa_type}")
return render_target
except Exception as e:
print(f"✗ 抗锯齿应用失败: {e}")
return render_target
def _apply_bloom(self, render_target: Any) -> Any:
"""
应用泛光效果
Args:
render_target: 渲染目标
Returns:
处理后的渲染目标
"""
try:
# 在实际实现中,这里会应用泛光效果
intensity = self.effect_config['bloom_intensity']
print(f"✓ 应用泛光效果 (强度: {intensity})")
return render_target
except Exception as e:
print(f"✗ 泛光效果应用失败: {e}")
return render_target
def _apply_motion_blur(self, render_target: Any) -> Any:
"""
应用运动模糊
Args:
render_target: 渲染目标
Returns:
处理后的渲染目标
"""
try:
# 在实际实现中,这里会应用运动模糊效果
samples = 8 if self.effect_config['motion_blur'] else 0
print(f"✓ 应用运动模糊 ({samples} 采样)")
return render_target
except Exception as e:
print(f"✗ 运动模糊应用失败: {e}")
return render_target
def _apply_depth_of_field(self, render_target: Any) -> Any:
"""
应用景深效果
Args:
render_target: 渲染目标
Returns:
处理后的渲染目标
"""
try:
# 在实际实现中,这里会应用景深效果
focus_distance = self.effect_config['dof_focus_distance']
print(f"✓ 应用景深效果 (焦点距离: {focus_distance})")
return render_target
except Exception as e:
print(f"✗ 景深效果应用失败: {e}")
return render_target