Offline::OfflineRenderDeviceCaps LoadPlatformConfig(std::string const & platform) { ResIdentifierPtr plat = ResLoader::Instance().Open("PlatConf/" + platform + ".plat"); KlayGE::XMLDocument doc; XMLNodePtr root = doc.Parse(plat); Offline::OfflineRenderDeviceCaps caps; caps.platform = RetrieveAttrValue(root, "name", ""); caps.major_version = static_cast<uint8_t>(RetrieveAttrValue(root, "major_version", 0)); caps.minor_version = static_cast<uint8_t>(RetrieveAttrValue(root, "minor_version", 0)); caps.requires_flipping = RetrieveNodeValue(root, "requires_flipping", 0) ? true : false; std::string const fourcc_str = RetrieveNodeValue(root, "native_shader_fourcc", ""); caps.native_shader_fourcc = (fourcc_str[0] << 0) + (fourcc_str[1] << 8) + (fourcc_str[2] << 16) + (fourcc_str[3] << 24); caps.native_shader_version = RetrieveNodeValue(root, "native_shader_version", 0); XMLNodePtr max_shader_model_node = root->FirstNode("max_shader_model"); caps.max_shader_model = ShaderModel(static_cast<uint8_t>(RetrieveAttrValue(max_shader_model_node, "major", 0)), static_cast<uint8_t>(RetrieveAttrValue(max_shader_model_node, "minor", 0))); caps.max_texture_depth = RetrieveNodeValue(root, "max_texture_depth", 0); caps.max_texture_array_length = RetrieveNodeValue(root, "max_texture_array_length", 0); caps.max_pixel_texture_units = static_cast<uint8_t>(RetrieveNodeValue(root, "max_pixel_texture_units", 0)); caps.max_simultaneous_rts = static_cast<uint8_t>(RetrieveNodeValue(root, "max_simultaneous_rts", 0)); caps.standard_derivatives_support = RetrieveNodeValue(root, "standard_derivatives_support", 0) ? true : false; caps.shader_texture_lod_support = RetrieveNodeValue(root, "shader_texture_lod_support", 0) ? true : false; caps.fp_color_support = RetrieveNodeValue(root, "fp_color_support", 0) ? true : false; caps.pack_to_rgba_required = RetrieveNodeValue(root, "pack_to_rgba_required", 0) ? true : false; caps.gs_support = RetrieveNodeValue(root, "gs_support", 0) ? true : false; caps.cs_support = RetrieveNodeValue(root, "cs_support", 0) ? true : false; caps.hs_support = RetrieveNodeValue(root, "hs_support", 0) ? true : false; caps.ds_support = RetrieveNodeValue(root, "ds_support", 0) ? true : false; caps.bc4_support = RetrieveNodeValue(root, "bc4_support", 0) ? true : false; caps.bc5_support = RetrieveNodeValue(root, "bc5_support", 0) ? true : false; caps.frag_depth_support = RetrieveNodeValue(root, "frag_depth_support", 0) ? true : false; caps.ubo_support = RetrieveNodeValue(root, "ubo_support", 0) ? true : false; return caps; }
void PackJTML(std::string const & jtml_name) { Timer timer; ResIdentifierPtr jtml = ResLoader::Instance().Open(jtml_name); KlayGE::XMLDocument doc; XMLNodePtr root = doc.Parse(jtml); uint32_t n = root->AttribInt("num_tiles", 2048); uint32_t num_tiles = 1; while (num_tiles * 2 <= n) { num_tiles *= 2; } uint32_t tile_size = root->AttribInt("tile_size", 128); std::string fmt_str = root->AttribString("format", ""); ElementFormat format = EF_ARGB8; if ("ARGB8" == fmt_str) { format = EF_ARGB8; } else if ("ABGR8" == fmt_str) { format = EF_ABGR8; } uint32_t pixel_size = NumFormatBytes(format); JudaTexturePtr juda_tex = MakeSharedPtr<JudaTexture>(num_tiles, tile_size, format); uint32_t level = juda_tex->TreeLevels() - 1; RenderFactory& rf = Context::Instance().RenderFactoryInstance(); uint32_t attr = 0; for (XMLNodePtr node = root->FirstNode("image"); node; node = node->NextSibling("image"), ++ attr) { timer.restart(); std::string name = node->AttribString("name", ""); int32_t x = node->AttribInt("x", 0); int32_t y = node->AttribInt("y", 0); std::string address_u_str = node->AttribString("address_u", "wrap"); std::string address_v_str = node->AttribString("address_v", "wrap"); Color border_clr; border_clr.r() = node->AttribFloat("border_r", 0.0f); border_clr.g() = node->AttribFloat("border_g", 0.0f); border_clr.b() = node->AttribFloat("border_b", 0.0f); border_clr.a() = node->AttribFloat("border_a", 0.0f); uint32_t border_clr_u8; switch (format) { case EF_ARGB8: border_clr_u8 = border_clr.ARGB(); break; case EF_ABGR8: border_clr_u8 = border_clr.ABGR(); break; default: border_clr_u8 = 0; break; } TexAddressingMode addr_u, addr_v; std::shared_ptr<address_calculator> calc_u, calc_v; if ("mirror" == address_u_str) { addr_u = TAM_Mirror; calc_u = address_calculators[TAM_Mirror]; } else if ("clamp" == address_u_str) { addr_u = TAM_Clamp; calc_u = address_calculators[TAM_Clamp]; } else if ("border" == address_u_str) { addr_u = TAM_Border; calc_u = address_calculators[TAM_Border]; } else { addr_u = TAM_Wrap; calc_u = address_calculators[TAM_Wrap]; } if ("mirror" == address_v_str) { addr_v = TAM_Mirror; calc_v = address_calculators[TAM_Mirror]; } else if ("clamp" == address_v_str) { addr_v = TAM_Clamp; calc_v = address_calculators[TAM_Clamp]; } else if ("border" == address_v_str) { addr_v = TAM_Border; calc_v = address_calculators[TAM_Border]; } else { addr_v = TAM_Wrap; calc_v = address_calculators[TAM_Wrap]; } cout << "Processing " << name << "... "; TexturePtr src_texture = SyncLoadTexture(name, EAH_CPU_Read | EAH_CPU_Write); if (src_texture->Type() != Texture::TT_2D) { cout << "Texture " << name << "is not 2D texture. Skipped." << endl; continue; } uint32_t in_width = src_texture->Width(0); uint32_t in_height = src_texture->Height(0); TexturePtr texture = rf.MakeTexture2D(in_width, in_height, 1, 1, format, 1, 0, EAH_CPU_Read | EAH_CPU_Write); src_texture->CopyToTexture(*texture); Texture::Mapper mapper(*texture, 0, 0, TMA_Read_Only, 0, 0, in_width, in_height); uint8_t const * in_data_p = mapper.Pointer<uint8_t>(); int32_t in_num_tiles_x = std::min((in_width + tile_size - 1) / tile_size, num_tiles); int32_t in_num_tiles_y = std::min((in_height + tile_size - 1) / tile_size, num_tiles); int32_t beg_tile_x = 0; int32_t end_tile_x = std::min(static_cast<int32_t>(x + in_num_tiles_x), static_cast<int32_t>(num_tiles)) - x; int32_t beg_tile_y = 0; int32_t end_tile_y = std::min(static_cast<int32_t>(y + in_num_tiles_y), static_cast<int32_t>(num_tiles)) - y; juda_tex->AddImageEntry(name, x, y, in_num_tiles_x, in_num_tiles_y, addr_u, addr_v, border_clr); std::vector<std::vector<uint8_t>> tiles; std::vector<uint32_t> tile_ids; std::vector<uint32_t> tile_attrs; for (int32_t by = beg_tile_y; by < end_tile_y; ++ by) { tiles.clear(); tile_ids.clear(); tile_attrs.clear(); for (int32_t bx = beg_tile_x; bx < end_tile_x; ++ bx) { uint32_t xindex = bx - beg_tile_x; tiles.push_back(std::vector<uint8_t>(tile_size * tile_size * pixel_size, 0)); tile_ids.push_back(juda_tex->EncodeTileID(level, bx + x, by + y)); tile_attrs.push_back(attr); for (size_t dy = 0; dy < tile_size; ++ dy) { int32_t tex_y = (*calc_v)(static_cast<int32_t>(by * tile_size + dy), in_height); if (tex_y >= 0) { for (size_t dx = 0; dx < tile_size; ++ dx) { int32_t tex_x = (*calc_u)(static_cast<int32_t>(bx * tile_size + dx), in_width); if (tex_x >= 0) { std::memcpy(&tiles[xindex][(dy * tile_size + dx) * pixel_size], &in_data_p[tex_y * mapper.RowPitch() + tex_x * pixel_size], pixel_size); } else { std::memcpy(&tiles[xindex][(dy * tile_size + dx) * pixel_size], &border_clr_u8, pixel_size); } } } else { for (size_t dx = 0; dx < tile_size; ++ dx) { std::memcpy(&tiles[xindex][(dy * tile_size + dx) * pixel_size], &border_clr_u8, pixel_size); } } } } juda_tex->CommitTiles(tiles, tile_ids, tile_attrs); } cout << "Takes " << timer.elapsed() << "s" << endl; } cout << "Total tiles: " << ((1UL << (juda_tex->TreeLevels() * 2)) - 1) / (4 - 1) << endl; cout << "Non empty tiles: " << juda_tex->NumNonEmptyNodes() << endl; cout << "Tree depth: " << juda_tex->TreeLevels() << endl; std::string base_name = jtml_name.substr(0, jtml_name.find_last_of('.')); cout << "Saving... "; timer.restart(); SaveJudaTexture(juda_tex, base_name + ".jdt"); cout << "Takes " << timer.elapsed() << "s" << endl << endl; }
void SaveRenderMaterial(RenderMaterialPtr const & mtl, std::string const & mtlml_name) { KlayGE::XMLDocument doc; XMLNodePtr root = doc.AllocNode(XNT_Element, "material"); doc.RootNode(root); { XMLNodePtr albedo_node = doc.AllocNode(XNT_Element, "albedo"); std::string color_str = boost::lexical_cast<std::string>(mtl->albedo.x()) + ' ' + boost::lexical_cast<std::string>(mtl->albedo.y()) + ' ' + boost::lexical_cast<std::string>(mtl->albedo.z()) + ' ' + boost::lexical_cast<std::string>(mtl->albedo.w()); albedo_node->AppendAttrib(doc.AllocAttribString("color", color_str)); if (!mtl->tex_names[RenderMaterial::TS_Albedo].empty()) { albedo_node->AppendAttrib(doc.AllocAttribString("texture", mtl->tex_names[RenderMaterial::TS_Albedo])); } root->AppendNode(albedo_node); } if ((mtl->metalness > 0) || !mtl->tex_names[RenderMaterial::TS_Metalness].empty()) { XMLNodePtr metalness_node = doc.AllocNode(XNT_Element, "metalness"); if (mtl->metalness > 0) { metalness_node->AppendAttrib(doc.AllocAttribFloat("value", mtl->metalness)); } if (!mtl->tex_names[RenderMaterial::TS_Metalness].empty()) { metalness_node->AppendAttrib(doc.AllocAttribString("texture", mtl->tex_names[RenderMaterial::TS_Metalness])); } root->AppendNode(metalness_node); } if ((mtl->glossiness > 0) || !mtl->tex_names[RenderMaterial::TS_Glossiness].empty()) { XMLNodePtr glossiness_node = doc.AllocNode(XNT_Element, "glossiness"); if (mtl->glossiness > 0) { glossiness_node->AppendAttrib(doc.AllocAttribFloat("value", mtl->glossiness)); } if (!mtl->tex_names[RenderMaterial::TS_Glossiness].empty()) { glossiness_node->AppendAttrib(doc.AllocAttribString("texture", mtl->tex_names[RenderMaterial::TS_Glossiness])); } root->AppendNode(glossiness_node); } if ((mtl->emissive.x() > 0) || (mtl->emissive.y() > 0) || (mtl->emissive.z() > 0) || (!mtl->tex_names[RenderMaterial::TS_Emissive].empty())) { XMLNodePtr emissive_node = doc.AllocNode(XNT_Element, "emissive"); if ((mtl->emissive.x() > 0) || (mtl->emissive.y() > 0) || (mtl->emissive.z() > 0)) { std::string color_str = boost::lexical_cast<std::string>(mtl->emissive.x()) + ' ' + boost::lexical_cast<std::string>(mtl->emissive.y()) + ' ' + boost::lexical_cast<std::string>(mtl->emissive.z()); emissive_node->AppendAttrib(doc.AllocAttribString("color", color_str)); } if (!mtl->tex_names[RenderMaterial::TS_Emissive].empty()) { emissive_node->AppendAttrib(doc.AllocAttribString("texture", mtl->tex_names[RenderMaterial::TS_Emissive])); } root->AppendNode(emissive_node); } if (!mtl->tex_names[RenderMaterial::TS_Normal].empty()) { XMLNodePtr normal_node = doc.AllocNode(XNT_Element, "normal"); normal_node->AppendAttrib(doc.AllocAttribString("texture", mtl->tex_names[RenderMaterial::TS_Normal])); root->AppendNode(normal_node); } if (!mtl->tex_names[RenderMaterial::TS_Height].empty()) { XMLNodePtr height_node = doc.AllocNode(XNT_Element, "height"); height_node->AppendAttrib(doc.AllocAttribString("texture", mtl->tex_names[RenderMaterial::TS_Height])); height_node->AppendAttrib(doc.AllocAttribFloat("offset", mtl->height_offset_scale.x())); height_node->AppendAttrib(doc.AllocAttribFloat("scale", mtl->height_offset_scale.y())); root->AppendNode(height_node); } if (mtl->detail_mode != RenderMaterial::SDM_Parallax) { XMLNodePtr detail_node = doc.AllocNode(XNT_Element, "detail"); std::string detail_mode_str; switch (mtl->detail_mode) { case RenderMaterial::SDM_FlatTessellation: detail_mode_str = "Flat Tessellation"; break; case RenderMaterial::SDM_SmoothTessellation: detail_mode_str = "Smooth Tessellation"; break; default: KFL_UNREACHABLE("Invalid surface detail mode"); } detail_node->AppendAttrib(doc.AllocAttribString("mode", detail_mode_str)); { XMLNodePtr tess_node = doc.AllocNode(XNT_Element, "tess"); tess_node->AppendAttrib(doc.AllocAttribFloat("edge_hint", mtl->tess_factors.x())); tess_node->AppendAttrib(doc.AllocAttribFloat("inside_hint", mtl->tess_factors.y())); tess_node->AppendAttrib(doc.AllocAttribFloat("min", mtl->tess_factors.z())); tess_node->AppendAttrib(doc.AllocAttribFloat("max", mtl->tess_factors.w())); detail_node->AppendNode(tess_node); } root->AppendNode(detail_node); } if (mtl->transparent) { XMLNodePtr transparent_node = doc.AllocNode(XNT_Element, "transparent"); transparent_node->AppendAttrib(doc.AllocAttribString("value", "1")); root->AppendNode(transparent_node); } if (mtl->alpha_test > 0) { XMLNodePtr alpha_test_node = doc.AllocNode(XNT_Element, "alpha_test"); alpha_test_node->AppendAttrib(doc.AllocAttribFloat("value", mtl->alpha_test)); root->AppendNode(alpha_test_node); } if (mtl->sss) { XMLNodePtr sss_node = doc.AllocNode(XNT_Element, "sss"); sss_node->AppendAttrib(doc.AllocAttribString("value", "1")); root->AppendNode(sss_node); } if (mtl->two_sided) { XMLNodePtr two_sided_node = doc.AllocNode(XNT_Element, "two_sided"); two_sided_node->AppendAttrib(doc.AllocAttribString("value", "1")); root->AppendNode(two_sided_node); } std::ofstream ofs(mtlml_name.c_str()); if (!ofs) { ofs.open((ResLoader::Instance().LocalFolder() + mtlml_name).c_str()); } doc.Print(ofs); }
void SubThreadStage() { ResIdentifierPtr psmm_input = ResLoader::Instance().Open(ps_desc_.res_name); KlayGE::XMLDocument doc; XMLNodePtr root = doc.Parse(psmm_input); { XMLNodePtr particle_node = root->FirstNode("particle"); { XMLNodePtr alpha_node = particle_node->FirstNode("alpha"); ps_desc_.ps_data->particle_alpha_from_tex = alpha_node->Attrib("from")->ValueString(); ps_desc_.ps_data->particle_alpha_to_tex = alpha_node->Attrib("to")->ValueString(); } { XMLNodePtr color_node = particle_node->FirstNode("color"); { Color from; XMLAttributePtr attr = color_node->Attrib("from"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); from[i] = static_cast<float>(atof(strs[i].c_str())); } else { from[i] = 0; } } } from.a() = 1; ps_desc_.ps_data->particle_color_from = from; Color to; attr = color_node->Attrib("to"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); to[i] = static_cast<float>(atof(strs[i].c_str())); } else { to[i] = 0; } } } to.a() = 1; ps_desc_.ps_data->particle_color_to = to; } } } { XMLNodePtr emitter_node = root->FirstNode("emitter"); XMLAttributePtr type_attr = emitter_node->Attrib("type"); if (type_attr) { ps_desc_.ps_data->emitter_type = type_attr->ValueString(); } else { ps_desc_.ps_data->emitter_type = "point"; } XMLNodePtr freq_node = emitter_node->FirstNode("frequency"); if (freq_node) { XMLAttributePtr attr = freq_node->Attrib("value"); ps_desc_.ps_data->frequency = attr->ValueFloat(); } XMLNodePtr angle_node = emitter_node->FirstNode("angle"); if (angle_node) { XMLAttributePtr attr = angle_node->Attrib("value"); ps_desc_.ps_data->angle = attr->ValueInt() * DEG2RAD; } XMLNodePtr pos_node = emitter_node->FirstNode("pos"); if (pos_node) { float3 min_pos(0, 0, 0); XMLAttributePtr attr = pos_node->Attrib("min"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); min_pos[i] = static_cast<float>(atof(strs[i].c_str())); } else { min_pos[i] = 0; } } } ps_desc_.ps_data->min_pos = min_pos; float3 max_pos(0, 0, 0); attr = pos_node->Attrib("max"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); max_pos[i] = static_cast<float>(atof(strs[i].c_str())); } else { max_pos[i] = 0; } } } ps_desc_.ps_data->max_pos = max_pos; } XMLNodePtr vel_node = emitter_node->FirstNode("vel"); if (vel_node) { XMLAttributePtr attr = vel_node->Attrib("min"); ps_desc_.ps_data->min_vel = attr->ValueFloat(); attr = vel_node->Attrib("max"); ps_desc_.ps_data->max_vel = attr->ValueFloat(); } XMLNodePtr life_node = emitter_node->FirstNode("life"); if (life_node) { XMLAttributePtr attr = life_node->Attrib("min"); ps_desc_.ps_data->min_life = attr->ValueFloat(); attr = life_node->Attrib("max"); ps_desc_.ps_data->max_life = attr->ValueFloat(); } } { XMLNodePtr updater_node = root->FirstNode("updater"); XMLAttributePtr type_attr = updater_node->Attrib("type"); if (type_attr) { ps_desc_.ps_data->updater_type = type_attr->ValueString(); } else { ps_desc_.ps_data->updater_type = "polyline"; } if ("polyline" == ps_desc_.ps_data->updater_type) { for (XMLNodePtr node = updater_node->FirstNode("curve"); node; node = node->NextSibling("curve")) { std::vector<float2> xys; for (XMLNodePtr ctrl_point_node = node->FirstNode("ctrl_point"); ctrl_point_node; ctrl_point_node = ctrl_point_node->NextSibling("ctrl_point")) { XMLAttributePtr attr_x = ctrl_point_node->Attrib("x"); XMLAttributePtr attr_y = ctrl_point_node->Attrib("y"); xys.push_back(float2(attr_x->ValueFloat(), attr_y->ValueFloat())); } XMLAttributePtr attr = node->Attrib("name"); size_t const name_hash = RT_HASH(attr->ValueString().c_str()); if (CT_HASH("size_over_life") == name_hash) { ps_desc_.ps_data->size_over_life_ctrl_pts = xys; } else if (CT_HASH("mass_over_life") == name_hash) { ps_desc_.ps_data->mass_over_life_ctrl_pts = xys; } else if (CT_HASH("opacity_over_life") == name_hash) { ps_desc_.ps_data->opacity_over_life_ctrl_pts = xys; } } } } RenderFactory& rf = Context::Instance().RenderFactoryInstance(); RenderDeviceCaps const & caps = rf.RenderEngineInstance().DeviceCaps(); if (caps.multithread_res_creating_support) { this->MainThreadStage(); } }