class CommonBuffer(): def __init__(self): self.data = C_CommonBuffer() self.UBO = UBO() def load(self, scene, resolution, sample_offset=(0, 0), sample_count=0, camera=None, projection=None): self.data.CAMERA = tuple( camera if camera else scene.camera.camera_matrix) self.data.PROJECTION = tuple( projection if projection else scene.camera.projection_matrix) self.data.RESOLUTION = resolution self.data.SAMPLE_OFFSET = sample_offset self.data.SAMPLE_COUNT = sample_count self.data.FRAME = scene.frame self.data.TIME = scene.time self.UBO.load_data(self.data) def bind(self, block): self.UBO.bind(block) def shader_callback(self, shader): if 'COMMON_UNIFORMS' in shader.uniform_blocks: self.bind(shader.uniform_blocks['COMMON_UNIFORMS'])
def __init__(self): self.data = C_NPR_LightShadersBuffer() self.custom_shading_count = 0 self.UBO = UBO() self.texture = None self.fbos = None
def __init__(self): class C_NPR_LightGroupsBuffer(ctypes.Structure): _fields_ = [ ('light_group_index', ctypes.c_int*Lighting.MAX_LIGHTS), ] self.data = C_NPR_LightGroupsBuffer() self.UBO = UBO()
class NPR_LightShaders(): def __init__(self): class C_NPR_LightShadersBuffer(ctypes.Structure): _fields_ = [ ('custom_shading_index', ctypes.c_int * Lighting.MAX_LIGHTS), ] self.data = C_NPR_LightShadersBuffer() self.custom_shading_count = 0 self.UBO = UBO() self.texture = None self.fbos = None def load(self, pipeline, depth_texture, scene): self.custom_shading_count = 0 for i, light in enumerate(scene.lights): custom_shading_index = -1 if light.parameters['Shader'] is not None: custom_shading_index = self.custom_shading_count self.custom_shading_count += 1 self.data.custom_shading_index[i] = custom_shading_index self.UBO.load_data(self.data) if self.custom_shading_count == 0: return lights = [ l for l in scene.lights if l.parameters['Shader'] is not None ] tex = self.texture if tex is None or tex.resolution != depth_texture.resolution or tex.length < len( lights): self.texture = TextureArray(depth_texture.resolution, len(lights), GL_RGB32F) self.fbos = [] for i in range(len(lights)): self.fbos.append( RenderTarget([ArrayLayerTarget(self.texture, i)])) for i, light in enumerate(lights): material = light.parameters['Shader'] if material.shader and 'SHADER' in material.shader.keys(): shader = material.shader['SHADER'] for resource in scene.shader_resources: resource.shader_callback(shader) shader.textures['IN_DEPTH'] = depth_texture if 'LIGHT_INDEX' in shader.uniforms: light_index = scene.lights.index(light) shader.uniforms['LIGHT_INDEX'].set_value(light_index) pipeline.draw_screen_pass(shader, self.fbos[i]) def shader_callback(self, shader): if 'LIGHTS_CUSTOM_SHADING' in shader.uniform_blocks: self.UBO.bind(shader.uniform_blocks['LIGHTS_CUSTOM_SHADING']) shader.textures['IN_LIGHT_CUSTOM_SHADING'] = self.texture
def __init__(self): class C_NPR_LightShadersBuffer(ctypes.Structure): _fields_ = [ ('custom_shading_index', ctypes.c_int * Lighting.MAX_LIGHTS), ] self.data = C_NPR_LightShadersBuffer() self.custom_shading_count = 0 self.UBO = UBO() self.texture = None self.fbos = None
def build_scene_batches(self, objects): result = {} for obj in objects: if obj.material not in result: result[obj.material] = {} if obj.mesh not in result[obj.material]: result[obj.material][obj.mesh] = {} mesh_dict = result[obj.material][obj.mesh] if obj.mirror_scale: if 'mirror_scale' not in mesh_dict: mesh_dict['mirror_scale'] = [] mesh_dict['mirror_scale'].append(obj) else: if 'normal_scale' not in mesh_dict: mesh_dict['normal_scale'] = [] mesh_dict['normal_scale'].append(obj) # Assume at least 64kb of UBO storage (d3d11 requirement) and max element size of mat4 max_instances = 1000 models = (max_instances * (ctypes.c_float * 16))() ids = (max_instances * ctypes.c_uint)() for material, meshes in result.items(): for mesh, scale_groups in meshes.items(): for scale_group, objs in scale_groups.items(): batches = [] scale_groups[scale_group] = batches i = 0 batch_length = len(objs) while i < batch_length: instance_i = i % max_instances models[instance_i] = objs[i].matrix ids[instance_i] = objs[i].parameters['ID'] i += 1 instances_count = instance_i + 1 if i == batch_length or instances_count == max_instances: local_models = ((ctypes.c_float * 16) * instances_count).from_address( ctypes.addressof(models)) local_ids = (ctypes.c_uint * instances_count).from_address( ctypes.addressof(ids)) models_UBO = UBO() ids_UBO = UBO() models_UBO.load_data(local_models) ids_UBO.load_data(local_ids) batches.append({ 'instances_count': instances_count, 'BATCH_MODELS': models_UBO, 'BATCH_IDS': ids_UBO, }) return result
class NPR_LightShaders(object): def __init__(self): self.data = C_NPR_LightShadersBuffer() self.custom_shading_count = 0 self.UBO = UBO() self.texture = None self.fbos = None def load(self, pipeline, depth_texture, scene): self.custom_shading_count = 0 for i, light in enumerate(scene.lights): custom_shading_index = -1 if light.parameters['Shader'] is not None: custom_shading_index = self.custom_shading_count self.custom_shading_count += 1 self.data.custom_shading_index[i] = custom_shading_index self.UBO.load_data(self.data) if self.custom_shading_count == 0: return lights = [ l for l in scene.lights if l.parameters['Shader'] is not None ] tex = self.texture if tex is None or tex.resolution != depth_texture.resolution or tex.length < len( lights): self.texture = TextureArray(depth_texture.resolution, len(lights), GL_RGB32F) self.fbos = [] for i in range(len(lights)): self.fbos.append( RenderTarget([ArrayLayerTarget(self.texture, i)])) for i, light in enumerate(lights): shader = light.parameters['Shader']['SHADER'] pipeline.common_buffer.bind( shader.uniform_blocks['COMMON_UNIFORMS']) pipeline.lights_buffer.bind(shader.uniform_blocks['SCENE_LIGHTS']) shader.textures['IN_DEPTH'] = depth_texture if 'LIGHT_INDEX' in shader.uniforms: shader.uniforms['LIGHT_INDEX'].set_value(i) pipeline.draw_screen_pass(shader, self.fbos[i]) def shader_callback(self, shader): if 'LIGHTS_CUSTOM_SHADING' in shader.uniform_blocks: self.UBO.bind(shader.uniform_blocks['LIGHTS_CUSTOM_SHADING']) shader.textures['IN_LIGHT_CUSTOM_SHADING'] = self.texture
class CommonBuffer(object): def __init__(self): self.data = C_CommonBuffer() self.UBO = UBO() def load(self, scene, resolution, sample_offset=(0,0), sample_count=0, camera=None, projection = None): self.data.CAMERA = tuple(camera if camera else scene.camera.camera_matrix) self.data.PROJECTION = tuple(projection if projection else scene.camera.projection_matrix) self.data.RESOLUTION = resolution self.data.SAMPLE_OFFSET = sample_offset self.data.SAMPLE_COUNT = sample_count self.data.FRAME = scene.frame self.data.TIME = scene.time self.UBO.load_data(self.data) def bind(self, location): self.UBO.bind(location)
class NPR_LightsGroupsBuffer(object): def __init__(self): self.data = C_NPR_LightGroupsBuffer() self.UBO = UBO() def load(self, scene): for i, light in enumerate(scene.lights): self.data.light_group_index[i] = light.parameters['Light Group'] self.UBO.load_data(self.data) for material in scene.materials: for shader in material.shader.values(): if 'MATERIAL_LIGHT_GROUPS' in shader.uniforms.keys(): shader.uniforms['MATERIAL_LIGHT_GROUPS'].set_value( material.parameters['Light Groups.Light']) def shader_callback(self, shader): if 'LIGHT_GROUPS' in shader.uniform_blocks: self.UBO.bind(shader.uniform_blocks['LIGHT_GROUPS'])
class NPR_LightsGroupsBuffer(): def __init__(self): class C_NPR_LightGroupsBuffer(ctypes.Structure): _fields_ = [ ('light_group_index', ctypes.c_int*Lighting.MAX_LIGHTS), ] self.data = C_NPR_LightGroupsBuffer() self.UBO = UBO() def load(self, scene): for i, light in enumerate(scene.lights): self.data.light_group_index[i] = light.parameters['Light Group'] self.UBO.load_data(self.data) for material in scene.batches.keys(): for shader in material.shader.values(): if 'MATERIAL_LIGHT_GROUPS' in shader.uniforms.keys(): shader.uniforms['MATERIAL_LIGHT_GROUPS'].set_value(material.parameters['Light Groups.Light']) def shader_callback(self, shader): if 'LIGHT_GROUPS' in shader.uniform_blocks: self.UBO.bind(shader.uniform_blocks['LIGHT_GROUPS'])
def __init__(self): self.data = C_NPR_LightGroupsBuffer() self.UBO = UBO()
def __init__(self): self.data = C_LightsBuffer() self.UBO = UBO() self.spots = None self.suns = None self.points = None
class LightsBuffer(object): def __init__(self): self.data = C_LightsBuffer() self.UBO = UBO() self.spots = None self.suns = None self.points = None def load(self, scene, cascades_count, cascades_distribution_scalar, cascades_max_distance=1.0): #TODO: Automatic distribution exponent basedd on FOV spot_count = 0 sun_count = 0 point_count = 0 from collections import OrderedDict self.spots = OrderedDict() self.suns = OrderedDict() self.points = OrderedDict() for i, light in enumerate(scene.lights): self.data.lights[i].color = light.color self.data.lights[i].type = light.type self.data.lights[i].position = light.position self.data.lights[i].radius = light.radius self.data.lights[i].direction = light.direction self.data.lights[i].spot_angle = light.spot_angle self.data.lights[i].spot_blend = light.spot_blend if light.type == LIGHT_SPOT: self.data.lights[i].type_index = spot_count projection_matrix = make_projection_matrix( light.spot_angle, 1, 0.01, light.radius) spot_matrix = projection_matrix * pyrr.Matrix44(light.matrix) self.data.spot_matrices[spot_count] = flatten_matrix( spot_matrix) self.spots[light] = [(light.matrix, flatten_matrix(projection_matrix))] spot_count += 1 if light.type == LIGHT_SUN: self.data.lights[i].type_index = sun_count sun_matrix = pyrr.Matrix44(light.matrix) projection_matrix = pyrr.Matrix44( scene.camera.projection_matrix) view_matrix = projection_matrix * pyrr.Matrix44( scene.camera.camera_matrix) cascades_matrices = get_sun_cascades( sun_matrix, projection_matrix, view_matrix, cascades_count, cascades_distribution_scalar, cascades_max_distance) self.suns[light] = [] for i, cascade in enumerate(cascades_matrices): cascade = flatten_matrix(cascade) self.data.sun_matrices[sun_count * cascades_count + i] = cascade self.suns[light].append( (cascade, flatten_matrix(pyrr.Matrix44.identity()))) sun_count += 1 if light.type == LIGHT_POINT: self.data.lights[i].type_index = point_count cube_map_axes = [((1, 0, 0), (0, -1, 0)), ((-1, 0, 0), (0, -1, 0)), ((0, 1, 0), (0, 0, 1)), ((0, -1, 0), (0, 0, -1)), ((0, 0, 1), (0, -1, 0)), ((0, 0, -1), (0, -1, 0))] matrices = [] for axes in cube_map_axes: position = pyrr.Vector3(light.position) front = pyrr.Vector3(axes[0]) up = pyrr.Vector3(axes[1]) matrices.append( pyrr.Matrix44.look_at(position, position + front, up)) projection_matrix = make_projection_matrix( math.pi / 2.0, 1.0, 0.01, light.radius) self.points[light] = [] for i in range(6): self.points[light].append( (flatten_matrix(matrices[i]), flatten_matrix(projection_matrix))) point_count += 1 self.data.lights_count = len(scene.lights) self.data.cascades_count = cascades_count self.UBO.load_data(self.data) def bind(self, location): self.UBO.bind(location)
def __init__(self): self.data = C_LightsBuffer() self.UBO = UBO() self.spot_matrices = [] self.sun_matrices = [] self.point_matrices = []
def __init__(self): self.data = C_CommonBuffer() self.UBO = UBO()