def build_node_tree(world: bpy.types.World, frag: Shader): """Generates the shader code for the given world.""" world_name = arm.utils.safestr(world.name) world.world_defs = '' rpdat = arm.utils.get_rp() wrd = bpy.data.worlds['Arm'] if callback is not None: callback() # Traverse world node tree is_parsed = False if world.node_tree is not None: output_node = node_utils.get_node_by_type(world.node_tree, 'OUTPUT_WORLD') if output_node is not None: is_parsed = parse_world_output(world, output_node, frag) # No world nodes/no output node, use background color if not is_parsed: solid_mat = rpdat.arm_material_model == 'Solid' if rpdat.arm_irradiance and not solid_mat: world.world_defs += '_Irr' col = world.color world.arm_envtex_color = [col[0], col[1], col[2], 1.0] world.arm_envtex_strength = 1.0 # Clear to color if no texture or sky is provided if '_EnvSky' not in world.world_defs and '_EnvTex' not in world.world_defs: if '_EnvImg' not in world.world_defs: world.world_defs += '_EnvCol' frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') # Irradiance json file name world.arm_envtex_name = world_name world.arm_envtex_irr_name = world_name write_probes.write_color_irradiance(world_name, world.arm_envtex_color) # film_transparent if bpy.context.scene is not None and hasattr( bpy.context.scene.render, 'film_transparent') and bpy.context.scene.render.film_transparent: world.world_defs += '_EnvTransp' world.world_defs += '_EnvCol' frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') # Clouds enabled if rpdat.arm_clouds and world.arm_use_clouds: world.world_defs += '_EnvClouds' # Also set this flag globally so that the required textures are # included wrd.world_defs += '_EnvClouds' frag_write_clouds(world, frag) if '_EnvSky' in world.world_defs or '_EnvTex' in world.world_defs or '_EnvImg' in world.world_defs or '_EnvClouds' in world.world_defs: frag.add_uniform('float envmapStrength', link='_envmapStrength') frag_write_main(world, frag)
def build(): """Builds world shaders for all exported worlds.""" global shader_datas wrd = bpy.data.worlds['Arm'] rpdat = arm.utils.get_rp() mobile_mat = rpdat.arm_material_model == 'Mobile' or rpdat.arm_material_model == 'Solid' envpath = os.path.join(arm.utils.get_fp_build(), 'compiled', 'Assets', 'envmaps') wrd.world_defs = '' worlds = [] shader_datas = [] with write_probes.setup_envmap_render(): for scene in bpy.data.scenes: world = scene.world # Only export worlds from enabled scenes and only once per world if scene.arm_export and world is not None and world not in worlds: worlds.append(world) world.arm_envtex_name = '' create_world_shaders(world) if rpdat.arm_irradiance: # Plain background color if '_EnvCol' in world.world_defs: world_name = arm.utils.safestr(world.name) # Irradiance json file name world.arm_envtex_name = world_name world.arm_envtex_irr_name = world_name write_probes.write_color_irradiance( world_name, world.arm_envtex_color) # Render world to envmap for (ir)radiance, if no # other probes are exported elif world.arm_envtex_name == '': image_file = write_probes.render_envmap(envpath, world) image_filepath = os.path.join(envpath, image_file) world.arm_envtex_name = image_file world.arm_envtex_irr_name = os.path.basename( image_filepath).rsplit('.', 1)[0] write_radiance = rpdat.arm_radiance and not mobile_mat mip_count = write_probes.write_probes( image_filepath, write_probes.ENVMAP_FORMAT == 'JPEG', False, world.arm_envtex_num_mips, write_radiance) world.arm_envtex_num_mips = mip_count if write_radiance: # Set world def, everything else is handled by write_probes() wrd.world_defs += '_Rad'
def build_node_tree(world): wname = arm.utils.safestr(world.name) wrd = bpy.data.worlds['Arm'] wrd.world_defs = '' rpdat = arm.utils.get_rp() if callback != None: callback() # Traverse world node tree parsed = False if world.node_tree != None: output_node = node_utils.get_node_by_type(world.node_tree, 'OUTPUT_WORLD') if output_node != None: parse_world_output(world, output_node) parsed = True if parsed == False: solid_mat = rpdat.arm_material_model == 'Solid' if rpdat.arm_irradiance and not solid_mat: wrd.world_defs += '_Irr' c = world.color world.arm_envtex_color = [c[0], c[1], c[2], 1.0] world.arm_envtex_strength = 1.0 # Clear to color if no texture or sky is provided if '_EnvSky' not in wrd.world_defs and '_EnvTex' not in wrd.world_defs: if '_EnvImg' not in wrd.world_defs: wrd.world_defs += '_EnvCol' # Irradiance json file name world.arm_envtex_name = wname world.arm_envtex_irr_name = wname write_probes.write_color_irradiance(wname, world.arm_envtex_color) # film_transparent if bpy.context.scene != None and hasattr(bpy.context.scene.render, 'film_transparent') and bpy.context.scene.render.film_transparent: wrd.world_defs += '_EnvTransp' wrd.world_defs += '_EnvCol' # Clouds enabled if rpdat.arm_clouds: wrd.world_defs += '_EnvClouds' if '_EnvSky' in wrd.world_defs or '_EnvTex' in wrd.world_defs or '_EnvImg' in wrd.world_defs or '_EnvClouds' in wrd.world_defs: wrd.world_defs += '_EnvStr'
def build_node_tree(world): output = {} dat = {} output['material_datas'] = [dat] wname = arm.utils.safestr(world.name) dat['name'] = wname + '_material' context = {} dat['contexts'] = [context] context['name'] = 'world' context['bind_constants'] = [] context['bind_textures'] = [] bpy.data.worlds['Arm'].world_defs = '' # Traverse world node tree output_node = nodes.get_node_by_type(world.node_tree, 'OUTPUT_WORLD') if output_node != None: parse_world_output(world, output_node, context) # Clear to color if no texture or sky is provided wrd = bpy.data.worlds['Arm'] if '_EnvSky' not in wrd.world_defs and '_EnvTex' not in wrd.world_defs: if '_EnvImg' not in wrd.world_defs: wrd.world_defs += '_EnvCol' # Irradiance json file name world.world_envtex_name = wname world.world_envtex_irr_name = wname write_probes.write_color_irradiance(wname, world.world_envtex_color) # Clouds enabled if wrd.generate_clouds: wrd.world_defs += '_EnvClouds' # Percentage closer soft shadows if wrd.generate_pcss_state == 'On': wrd.world_defs += '_PCSS' sdk_path = arm.utils.get_sdk_path() assets.add(sdk_path + 'armory/Assets/noise64.png') assets.add_embedded_data('noise64.png') # Screen-space ray-traced shadows if wrd.generate_ssrs: wrd.world_defs += '_SSRS' if wrd.generate_two_sided_area_lamp: wrd.world_defs += '_TwoSidedAreaLamp' # Alternative models if wrd.lighting_model == 'Cycles': wrd.world_defs += '_Cycles' # TODO: Lamp texture test.. if wrd.generate_lamp_texture != '': bpy.data.worlds['Arm'].world_defs += '_LampColTex' if not wrd.generate_lamp_falloff: bpy.data.worlds['Arm'].world_defs += '_NoLampFalloff' voxelgi = False for cam in bpy.data.cameras: if cam.is_probe: wrd.world_defs += '_Probes' if cam.rp_shadowmap == 'None': wrd.world_defs += '_NoShadows' assets.add_khafile_def('arm_no_shadows') if cam.rp_voxelgi: voxelgi = True if cam.rp_dfrs: wrd.world_defs += '_DFRS' assets.add_khafile_def('arm_sdf') if cam.rp_dfao: wrd.world_defs += '_DFAO' assets.add_khafile_def('arm_sdf') if voxelgi: assets.add_khafile_def('arm_voxelgi') if wrd.voxelgi_revoxelize: assets.add_khafile_def('arm_voxelgi_revox') if wrd.voxelgi_multibounce: wrd.world_defs += '_VoxelGIMulti' wrd.world_defs += '_VoxelGI' wrd.world_defs += '_Rad' # Always do radiance for voxels wrd.world_defs += '_Irr' if arm.utils.get_gapi().startswith( 'direct3d'): # Flip Y axis in drawQuad command wrd.world_defs += '_InvY' # Area lamps for lamp in bpy.data.lamps: if lamp.type == 'AREA': wrd.world_defs += '_PolyLight' break # Data will be written after render path has been processed to gather all defines return output
def build_node_tree(world): output = {} dat = {} output['material_datas'] = [dat] wname = arm.utils.safestr(world.name) dat['name'] = wname + '_material' context = {} dat['contexts'] = [context] context['name'] = 'world' context['bind_constants'] = [] context['bind_textures'] = [] wrd = bpy.data.worlds['Arm'] wrd.world_defs = '' rpdat = arm.utils.get_rp() # Traverse world node tree parsed = False if world.node_tree != None: output_node = nodes.get_node_by_type(world.node_tree, 'OUTPUT_WORLD') if output_node != None: parse_world_output(world, output_node, context) parsed = True if parsed == False: if wrd.arm_irradiance and rpdat.arm_material_model != 'Restricted': wrd.world_defs += '_Irr' envmap_strength_const = {} envmap_strength_const['name'] = 'envmapStrength' envmap_strength_const['float'] = 1.0 context['bind_constants'].append(envmap_strength_const) world.arm_envtex_color = [0.051, 0.051, 0.051, 1.0] world.arm_envtex_strength = envmap_strength_const['float'] # Clear to color if no texture or sky is provided if '_EnvSky' not in wrd.world_defs and '_EnvTex' not in wrd.world_defs: if '_EnvImg' not in wrd.world_defs: wrd.world_defs += '_EnvCol' # Irradiance json file name world.arm_envtex_name = wname world.arm_envtex_irr_name = wname write_probes.write_color_irradiance(wname, world.arm_envtex_color) # Clouds enabled if rpdat.arm_clouds: wrd.world_defs += '_EnvClouds' # Percentage closer soft shadows if rpdat.arm_pcss_state == 'On': wrd.world_defs += '_PCSS' sdk_path = arm.utils.get_sdk_path() assets.add(sdk_path + 'armory/Assets/noise64.png') assets.add_embedded_data('noise64.png') # Screen-space ray-traced shadows if rpdat.arm_ssrs: wrd.world_defs += '_SSRS' if wrd.arm_two_sided_area_lamp: wrd.world_defs += '_TwoSidedAreaLamp' # Store contexts if rpdat.rp_hdr == False: wrd.world_defs += '_LDR' # Alternative models if rpdat.arm_material_model == 'Cycles': wrd.world_defs += '_Cycles' # TODO: Lamp texture test.. if wrd.arm_lamp_texture != '': wrd.world_defs += '_LampColTex' if wrd.arm_lamp_ies_texture != '': wrd.world_defs += '_LampIES' assets.add_embedded_data('iestexture.png') voxelgi = False voxelao = False if rpdat.rp_shadowmap == 'None': wrd.world_defs += '_NoShadows' assets.add_khafile_def('arm_no_shadows') if rpdat.rp_voxelgi: voxelgi = True elif rpdat.rp_voxelao: voxelao = True if rpdat.rp_dfrs: wrd.world_defs += '_DFRS' assets.add_khafile_def('arm_sdf') if rpdat.rp_dfao: wrd.world_defs += '_DFAO' assets.add_khafile_def('arm_sdf') if rpdat.rp_dfgi: wrd.world_defs += '_DFGI' assets.add_khafile_def('arm_sdf') wrd.world_defs += '_Rad' # Always do radiance for gi wrd.world_defs += '_Irr' if voxelgi: assets.add_khafile_def('arm_voxelgi') if rpdat.arm_voxelgi_revoxelize: assets.add_khafile_def('arm_voxelgi_revox') if rpdat.arm_voxelgi_camera: wrd.world_defs += '_VoxelGICam' if rpdat.arm_voxelgi_shadows: wrd.world_defs += '_VoxelGIDirect' wrd.world_defs += '_VoxelGIShadow' if rpdat.arm_voxelgi_refraction: wrd.world_defs += '_VoxelGIDirect' wrd.world_defs += '_VoxelGIRefract' wrd.world_defs += '_VoxelGI' wrd.world_defs += '_Rad' # Always do radiance for voxels wrd.world_defs += '_Irr' elif voxelao: assets.add_khafile_def('arm_voxelgi') if rpdat.arm_voxelgi_revoxelize: assets.add_khafile_def('arm_voxelgi_revox') wrd.world_defs += '_VoxelAO' wrd.world_defs += '_Rad' wrd.world_defs += '_Irr' if arm.utils.get_gapi().startswith( 'direct3d'): # Flip Y axis in drawQuad command wrd.world_defs += '_InvY' # Area lamps for lamp in bpy.data.lamps: if lamp.type == 'AREA': wrd.world_defs += '_PolyLight' break # Data will be written after render path has been processed to gather all defines return output
def build_node_tree(world: bpy.types.World, frag: Shader, vert: Shader, con: ShaderContext): """Generates the shader code for the given world.""" world_name = arm.utils.safestr(world.name) world.world_defs = '' rpdat = arm.utils.get_rp() wrd = bpy.data.worlds['Arm'] if callback is not None: callback() # film_transparent, do not render if bpy.context.scene is not None and bpy.context.scene.render.film_transparent: world.world_defs += '_EnvCol' frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') frag.write('fragColor.rgb = backgroundCol;') return parser_state = ParserState(ParserContext.WORLD, world) parser_state.con = con parser_state.curshader = frag parser_state.frag = frag parser_state.vert = vert cycles.state = parser_state # Traverse world node tree is_parsed = False if world.node_tree is not None: output_node = node_utils.get_node_by_type(world.node_tree, 'OUTPUT_WORLD') if output_node is not None: is_parsed = parse_world_output(world, output_node, frag) # No world nodes/no output node, use background color if not is_parsed: solid_mat = rpdat.arm_material_model == 'Solid' if rpdat.arm_irradiance and not solid_mat: world.world_defs += '_Irr' col = world.color world.arm_envtex_color = [col[0], col[1], col[2], 1.0] world.arm_envtex_strength = 1.0 # Irradiance/Radiance: clear to color if no texture or sky is provided if rpdat.arm_irradiance or rpdat.arm_irradiance: if '_EnvSky' not in world.world_defs and '_EnvTex' not in world.world_defs and '_EnvImg' not in world.world_defs: # Irradiance json file name world.arm_envtex_name = world_name world.arm_envtex_irr_name = world_name write_probes.write_color_irradiance(world_name, world.arm_envtex_color) # Clouds enabled if rpdat.arm_clouds and world.arm_use_clouds: world.world_defs += '_EnvClouds' # Also set this flag globally so that the required textures are # included wrd.world_defs += '_EnvClouds' frag_write_clouds(world, frag) if '_EnvSky' in world.world_defs or '_EnvTex' in world.world_defs or '_EnvImg' in world.world_defs or '_EnvClouds' in world.world_defs: frag.add_uniform('float envmapStrength', link='_envmapStrength') # Clear background color if '_EnvCol' in world.world_defs: frag.write('fragColor.rgb = backgroundCol;') elif '_EnvTex' in world.world_defs and '_EnvLDR' in world.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(2.2));') if '_EnvClouds' in world.world_defs: frag.write( 'if (n.z > 0.0) fragColor.rgb = mix(fragColor.rgb, traceClouds(fragColor.rgb, n), clamp(n.z * 5.0, 0, 1));' ) if '_EnvLDR' in world.world_defs: frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));') # Mark as non-opaque frag.write('fragColor.a = 0.0;') # Hack to make procedural textures work frag_bpos = ( frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') if frag_bpos: frag.add_in('vec3 bposition') vert.add_out('vec3 bposition') # Use normals for now vert.write('bposition = nor;') frag_mpos = ( frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') if frag_mpos: frag.add_in('vec3 mposition') vert.add_out('vec3 mposition') # Use normals for now vert.write('mposition = nor;') if frag.contains('texCoord') and not frag.contains('vec2 texCoord'): frag.add_in('vec2 texCoord') vert.add_out('vec2 texCoord') # World has no UV map vert.write('texCoord = vec2(1.0, 1.0);')
def build_node_tree(world): output = {} dat = {} output['material_datas'] = [dat] wname = arm.utils.safestr(world.name) dat['name'] = wname + '_material' context = {} dat['contexts'] = [context] context['name'] = 'world' context['bind_constants'] = [] context['bind_textures'] = [] wrd = bpy.data.worlds['Arm'] wrd.world_defs = '' rpdat = arm.utils.get_rp() # Traverse world node tree parsed = False if world.node_tree != None: output_node = node_utils.get_node_by_type(world.node_tree, 'OUTPUT_WORLD') if output_node != None: parse_world_output(world, output_node, context) parsed = True if parsed == False: solid_mat = rpdat.arm_material_model == 'Solid' if wrd.arm_irradiance and not solid_mat: wrd.world_defs += '_Irr' envmap_strength_const = {} envmap_strength_const['name'] = 'envmapStrength' envmap_strength_const['float'] = 1.0 context['bind_constants'].append(envmap_strength_const) c = world.horizon_color world.arm_envtex_color = [c[0], c[1], c[2], 1.0] world.arm_envtex_strength = envmap_strength_const['float'] # Clear to color if no texture or sky is provided if '_EnvSky' not in wrd.world_defs and '_EnvTex' not in wrd.world_defs: if '_EnvImg' not in wrd.world_defs: wrd.world_defs += '_EnvCol' # Irradiance json file name world.arm_envtex_name = wname world.arm_envtex_irr_name = wname write_probes.write_color_irradiance(wname, world.arm_envtex_color) # film_transparent if bpy.context.scene != None and bpy.context.scene.cycles != None and bpy.context.scene.cycles.film_transparent: wrd.world_defs += '_EnvTransp' wrd.world_defs += '_EnvCol' # Clouds enabled if rpdat.arm_clouds: wrd.world_defs += '_EnvClouds' # Screen-space ray-traced shadows if rpdat.arm_ssrs: wrd.world_defs += '_SSRS' if wrd.arm_two_sided_area_lamp: wrd.world_defs += '_TwoSidedAreaLamp' # Store contexts if rpdat.rp_hdr == False: wrd.world_defs += '_LDR' # Alternative models if rpdat.arm_diffuse_model == 'OrenNayar': wrd.world_defs += '_OrenNayar' # TODO: Lamp texture test.. if wrd.arm_lamp_texture != '': wrd.world_defs += '_LampColTex' if wrd.arm_lamp_ies_texture != '': wrd.world_defs += '_LampIES' assets.add_embedded_data('iestexture.png') if wrd.arm_lamp_clouds_texture != '': wrd.world_defs += '_LampClouds' assets.add_embedded_data('cloudstexture.png') voxelgi = False voxelao = False if rpdat.rp_renderer == 'Deferred': assets.add_khafile_def('arm_deferred') # Shadows if rpdat.rp_shadowmap_cascades != '1' and rpdat.rp_gi == 'Off': wrd.world_defs += '_CSM' assets.add_khafile_def('arm_csm') if rpdat.rp_shadowmap == 'Off': wrd.world_defs += '_NoShadows' assets.add_khafile_def('arm_no_shadows') # GI if rpdat.rp_gi == 'Voxel GI': voxelgi = True elif rpdat.rp_gi == 'Voxel AO': voxelao = True # SS # if rpdat.rp_dfrs: # wrd.world_defs += '_DFRS' # assets.add_khafile_def('arm_sdf') # if rpdat.rp_dfao: # wrd.world_defs += '_DFAO' # assets.add_khafile_def('arm_sdf') # if rpdat.rp_dfgi: # wrd.world_defs += '_DFGI' # assets.add_khafile_def('arm_sdf') # wrd.world_defs += '_Rad' # Always do radiance for gi # wrd.world_defs += '_Irr' if rpdat.rp_ssgi == 'RTGI' or rpdat.rp_ssgi == 'RTAO': if rpdat.rp_ssgi == 'RTGI': wrd.world_defs += '_RTGI' if wrd.arm_ssgi_rays == '9': wrd.world_defs += '_SSGICone9' if rpdat.rp_autoexposure: wrd.world_defs += '_AutoExposure' if voxelgi or voxelao: assets.add_khafile_def('arm_voxelgi') if rpdat.arm_voxelgi_revoxelize: assets.add_khafile_def('arm_voxelgi_revox') if rpdat.arm_voxelgi_camera: wrd.world_defs += '_VoxelGICam' if voxelgi and wrd.arm_voxelgi_diff_cones == '5': wrd.world_defs += '_VoxelGICone5' if voxelao and wrd.arm_voxelgi_ao_cones == '9': wrd.world_defs += '_VoxelAOCone9' wrd.world_defs += '_Rad' # Always do radiance for voxels wrd.world_defs += '_Irr' if voxelgi: assets.add_khafile_def('arm_voxelgi') if rpdat.arm_voxelgi_shadows: wrd.world_defs += '_VoxelGIDirect' wrd.world_defs += '_VoxelGIShadow' if rpdat.arm_voxelgi_refraction: wrd.world_defs += '_VoxelGIDirect' wrd.world_defs += '_VoxelGIRefract' if rpdat.arm_voxelgi_emission: wrd.world_defs += '_VoxelGIEmission' wrd.world_defs += '_VoxelGI' elif voxelao: wrd.world_defs += '_VoxelAO' if arm.utils.get_gapi().startswith( 'direct3d'): # Flip Y axis in drawQuad command wrd.world_defs += '_InvY' # Area lamps for lamp in bpy.data.lamps: if lamp.type == 'AREA': wrd.world_defs += '_LTC' assets.add_khafile_def('arm_ltc') break # Data will be written after render path has been processed to gather all defines return output