diff --git a/panda/src/speedtree/config_speedtree.cxx b/panda/src/speedtree/config_speedtree.cxx index a5bb39bc37..68e0ff3823 100644 --- a/panda/src/speedtree/config_speedtree.cxx +++ b/panda/src/speedtree/config_speedtree.cxx @@ -37,23 +37,148 @@ ConfigVariableFilename speedtree_shaders_dir "shaders at runtime. If this is empty, the default is based on " "SPEEDTREE_BIN_DIR, as provided at compile time.")); -ConfigVariableBool speedtree_allow_horizontal_billboards -("speedtree-allow-horizontal-billboards", true, +ConfigVariableFilename speedtree_textures_dir +("speedtree-textures-dir", "", + PRC_DESC("Specifies the directory in which to locate textures referenced " + "by SRT files at runtime. The default is to search in the same " + "directory as the SRT file itself. Unfortunately, the model-path " + "cannot be searched, because SpeedTree only provides a single " + "directory option.")); + +ConfigVariableDouble speedtree_max_anisotropy +("speedtree-max-anisotropy", 0.0, + PRC_DESC("Specifies the maximum anisotropy for SpeedTree textures.")); + +ConfigVariableBool speedtree_horizontal_billboards +("speedtree-horizontal-billboards", true, PRC_DESC("Set this true to allow the use of horizontal billboards in " "SpeedTree, or false to disallow them. Documentation on this " "feature is sparse, but presumably enabling them increases " "visual quality and also causes a greater performance impact.")); -ConfigVariableInt speedtree_max_num_visible_cells -("speedtree-max-num-visible-cells", 75, - PRC_DESC("Specifies the maximum number of cells in a single SpeedTree forest " - "frustum. This is used internally by SpeedTree's billboard system.")); +ConfigVariableDouble speedtree_alpha_test_scalar +("speedtree-alpha-test-scalar", 0.57, + PRC_DESC("Undocumented speedtree config.")); + +ConfigVariableBool speedtree_z_pre_pass +("speedtree-z-pre-pass", false, + PRC_DESC("True if the SpeedTree renderer should perform a first pass " + "to fill the depth buffer before going back to draw pixels. " + "This can result in a cost savings if there is much overdraw and " + "if the pixel shader is particularly expensive, but in most cases " + "it will result in a cost penalty.")); ConfigVariableInt speedtree_max_billboard_images_by_base ("speedtree-max-billboard-images-by-base", 20, PRC_DESC("Specifies the maximum number of billboard images used by any single " "tree.")); +ConfigVariableDouble speedtree_visibility +("speedtree-visibility", 1000.0, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableDouble speedtree_global_light_scalar +("speedtree-global-light-scalar", 1.0, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableBool speedtree_specular_lighting +("speedtree-specular-lighting", false, + PRC_DESC("True to enable specular lighting effects in SpeedTree.")); + +ConfigVariableBool speedtree_transmission_lighting +("speedtree-transmission-lighting", false, + PRC_DESC("True to enable transmission lighting effects in SpeedTree.")); + +ConfigVariableBool speedtree_detail_layer +("speedtree-detail-layer", false, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableBool speedtree_detail_normal_mapping +("speedtree-detail-normal-mapping", false, + PRC_DESC("True to enable normal maps in SpeedTree.")); + +ConfigVariableBool speedtree_ambient_contrast +("speedtree-ambient-contrast", false, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableDouble speedtree_transmission_scalar +("speedtree-transmission-scalar", 1.0f, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableDouble speedtree_fog_start_distance +("speedtree-fog-start-distance", 2500.0, + PRC_DESC("Specifies the nearest distance at which fog begins to be visible.")); + +ConfigVariableDouble speedtree_fog_end_distance +("speedtree-fog-end-distance", 5000.0, + PRC_DESC("Specifies the distance at and beyond which fog is complete.")); + +ConfigVariableDouble speedtree_fog_color +("speedtree-fog-color", "1.0 1.0 1.0", + PRC_DESC("Specifies the r g b color of SpeedTree fog.")); + +ConfigVariableDouble speedtree_sky_color +("speedtree-sky-color", "0.2 0.3 0.5", + PRC_DESC("Specifies the r g b color of the SpeedTree sky, when the sky " + "is enabled. Currently unused.")); + +ConfigVariableDouble speedtree_sky_fog_min +("speedtree-sky-fog-min", -0.5, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableDouble speedtree_sky_fog_max +("speedtree-sky-fog-max", 1.0, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableDouble speedtree_sun_color +("speedtree-sun-color", "1.0 1.0 0.85", + PRC_DESC("Specifies the r g b color of the SpeedTree sun, when the sun " + "is enabled. Currently unused.")); + +ConfigVariableDouble speedtree_sun_size +("speedtree-sun-size", 0.001, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableDouble speedtree_sun_spread_exponent +("speedtree-sun-spread-exponent", 200.0, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableDouble speedtree_sun_fog_bloom +("speedtree-sun-fog-bloom", 0.0, + PRC_DESC("Undocumented SpeedTree parameter.")); + +ConfigVariableInt speedtree_num_shadow_maps +("speedtree-num-shadow-maps", 3, + PRC_DESC("Specifies the number of shadow maps to use to render SpeedTree " + "shadows.")); + +ConfigVariableInt speedtree_shadow_map_resolution +("speedtree-shadow-map-resolution", 0, //1024, + PRC_DESC("Specifies the resolution for rendering shadow maps. Should " + "be a power of 2. Specify 0 to disable shadowing in SpeedTree. " + "Currently unsupported.")); + +ConfigVariableBool speedtree_smooth_shadows +("speedtree-smooth-shadows", false, + PRC_DESC("True to enable a smoothing pass on the shadow maps.")); + +ConfigVariableBool speedtree_show_shadow_splits_on_terrain +("speedtree-show-shadow-splits-on-terrain", false, + PRC_DESC("Currently unsupported.")); + +ConfigVariableBool speedtree_wind_enabled +("speedtree-wind-enabled", true, + PRC_DESC("True to enable global wind in the SpeedTree world.")); + +ConfigVariableBool speedtree_frond_rippling +("speedtree-frond-rippling", true, + PRC_DESC("True to allow fronds to respond to the global wind.")); + +ConfigVariableInt speedtree_max_num_visible_cells +("speedtree-max-num-visible-cells", 75, + PRC_DESC("Specifies the maximum number of cells in a single SpeedTree forest " + "frustum. This is used internally by SpeedTree's billboard system.")); + ConfigVariableDouble speedtree_cull_cell_size ("speedtree-cull-cell-size", 1200, PRC_DESC("Specifies the size of a single SpeedTree cull cell, in Panda " diff --git a/panda/src/speedtree/config_speedtree.h b/panda/src/speedtree/config_speedtree.h index e802d2a5bb..c49e77083e 100644 --- a/panda/src/speedtree/config_speedtree.h +++ b/panda/src/speedtree/config_speedtree.h @@ -27,9 +27,39 @@ NotifyCategoryDecl(speedtree, EXPCL_PANDASPEEDTREE, EXPTP_PANDASPEEDTREE); extern ConfigVariableString speedtree_license; extern ConfigVariableFilename speedtree_shaders_dir; -extern ConfigVariableBool speedtree_allow_horizontal_billboards; -extern ConfigVariableInt speedtree_max_num_visible_cells; +extern ConfigVariableFilename speedtree_textures_dir; +extern ConfigVariableDouble speedtree_max_anisotropy; +extern ConfigVariableBool speedtree_horizontal_billboards; +extern ConfigVariableDouble speedtree_alpha_test_scalar; +extern ConfigVariableBool speedtree_z_pre_pass; extern ConfigVariableInt speedtree_max_billboard_images_by_base; + +extern ConfigVariableDouble speedtree_visibility; +extern ConfigVariableDouble speedtree_global_light_scalar; +extern ConfigVariableBool speedtree_specular_lighting; +extern ConfigVariableBool speedtree_transmission_lighting; +extern ConfigVariableBool speedtree_detail_layer; +extern ConfigVariableBool speedtree_detail_normal_mapping; +extern ConfigVariableBool speedtree_ambient_contrast; +extern ConfigVariableDouble speedtree_transmission_scalar; +extern ConfigVariableDouble speedtree_fog_start_distance; +extern ConfigVariableDouble speedtree_fog_end_distance; +extern ConfigVariableDouble speedtree_fog_color; +extern ConfigVariableDouble speedtree_sky_color; +extern ConfigVariableDouble speedtree_sky_fog_min; +extern ConfigVariableDouble speedtree_sky_fog_max; +extern ConfigVariableDouble speedtree_sun_color; +extern ConfigVariableDouble speedtree_sun_size; +extern ConfigVariableDouble speedtree_sun_spread_exponent; +extern ConfigVariableDouble speedtree_sun_fog_bloom; +extern ConfigVariableInt speedtree_num_shadow_maps; +extern ConfigVariableInt speedtree_shadow_map_resolution; +extern ConfigVariableBool speedtree_smooth_shadows; +extern ConfigVariableBool speedtree_show_shadow_splits_on_terrain; +extern ConfigVariableBool speedtree_wind_enabled; +extern ConfigVariableBool speedtree_frond_rippling; + +extern ConfigVariableInt speedtree_max_num_visible_cells; extern ConfigVariableDouble speedtree_cull_cell_size; extern ConfigVariableBool speedtree_5_2_stf; diff --git a/panda/src/speedtree/speedTreeNode.cxx b/panda/src/speedtree/speedTreeNode.cxx index 39067f3e15..f2907fc6f0 100644 --- a/panda/src/speedtree/speedTreeNode.cxx +++ b/panda/src/speedtree/speedTreeNode.cxx @@ -71,28 +71,73 @@ SpeedTreeNode(const string &name) : SpeedTree::SForestRenderInfo render_info; // First, get the shader directory. - if (!speedtree_shaders_dir.get_value().is_directory()) { - speedtree_cat.warning() - << "speedtree-shaders-dir is set to " << speedtree_shaders_dir - << ", which doesn't exist.\n"; + Filename shaders_dir = speedtree_shaders_dir; + + // We expect the shader directory to contain at least this one token + // filename (to prove it's the right directory). + Filename token_filename = "Branch.hlsl"; + if (!Filename(shaders_dir, token_filename).exists()) { + // If that shader directory doesn't work, look along the model-path. + if (token_filename.resolve_filename(get_model_path())) { + shaders_dir = token_filename.get_dirname(); + } else { + if (!shaders_dir.is_directory()) { + speedtree_cat.warning() + << "speedtree-shaders-dir is set to " << shaders_dir + << ", which doesn't exist.\n"; + } else { + speedtree_cat.warning() + << "speedtree-shaders-dir is set to " << shaders_dir + << ", which exists but doesn't contain " << token_filename + << ".\n"; + } + } } - string shaders_dir = speedtree_shaders_dir.get_value().to_os_specific(); + string os_shaders_dir = shaders_dir.to_os_specific(); // Ensure the path ends with a terminal slash; SpeedTree requires this. #ifdef WIN32 - if (!shaders_dir.empty() && shaders_dir[shaders_dir.length() - 1] != '\\') { - shaders_dir += "\\"; + if (!os_shaders_dir.empty() && os_shaders_dir[os_shaders_dir.length() - 1] != '\\') { + os_shaders_dir += "\\"; } #else - if (!shaders_dir.empty() && shaders_dir[shaders_dir.length() - 1] != '/') { - shaders_dir += "/"; + if (!os_shaders_dir.empty() && os_shaders_dir[os_shaders_dir.length() - 1] != '/') { + os_shaders_dir += "/"; } #endif - render_info.m_strShaderPath = shaders_dir.c_str(); + render_info.m_strShaderPath = os_shaders_dir.c_str(); + render_info.m_nMaxAnisotropy = speedtree_max_anisotropy; + render_info.m_bHorizontalBillboards = speedtree_horizontal_billboards; + render_info.m_fAlphaTestScalar = speedtree_alpha_test_scalar; + render_info.m_bZPrePass = speedtree_z_pre_pass; render_info.m_nMaxBillboardImagesByBase = speedtree_max_billboard_images_by_base; - render_info.m_nNumShadowMaps = 1; - render_info.m_nShadowMapResolution = 0; + render_info.m_fVisibility = speedtree_visibility; + render_info.m_fGlobalLightScalar = speedtree_global_light_scalar; + //render_info.m_sLightMaterial = ... + render_info.m_bSpecularLighting = speedtree_specular_lighting; + render_info.m_bTransmissionLighting = speedtree_transmission_lighting; + render_info.m_bDetailLayer = speedtree_detail_layer; + render_info.m_bDetailNormalMapping = speedtree_detail_normal_mapping; + render_info.m_bAmbientContrast = speedtree_ambient_contrast; + render_info.m_fTransmissionScalar = speedtree_transmission_scalar; + render_info.m_fFogStartDistance = speedtree_fog_start_distance; + render_info.m_fFogEndDistance = speedtree_fog_end_distance; + render_info.m_vFogColor = SpeedTree::Vec3(speedtree_fog_color[0], speedtree_fog_color[1], speedtree_fog_color[2]); + render_info.m_vSkyColor = SpeedTree::Vec3(speedtree_sky_color[0], speedtree_sky_color[1], speedtree_sky_color[2]); + render_info.m_fSkyFogMin = speedtree_sky_fog_min; + render_info.m_fSkyFogMax = speedtree_sky_fog_max; + render_info.m_vSunColor = SpeedTree::Vec3(speedtree_sun_color[0], speedtree_sun_color[1], speedtree_sun_color[2]); + render_info.m_fSunSize = speedtree_sun_size; + render_info.m_fSunSpreadExponent = speedtree_sun_spread_exponent; + render_info.m_fSunFogBloom = speedtree_sun_fog_bloom; + render_info.m_nNumShadowMaps = speedtree_num_shadow_maps; + render_info.m_nShadowMapResolution = speedtree_shadow_map_resolution; + render_info.m_bSmoothShadows = speedtree_smooth_shadows; + render_info.m_bShowShadowSplitsOnTerrain = speedtree_show_shadow_splits_on_terrain; + render_info.m_bWindEnabled = speedtree_wind_enabled; + render_info.m_bFrondRippling = speedtree_frond_rippling; + _forest.SetRenderInfo(render_info); } @@ -964,7 +1009,7 @@ repopulate() { _forest.GetBaseTrees().size(), speedtree_max_num_visible_cells, max_instances_by_cell, - speedtree_allow_horizontal_billboards); + speedtree_horizontal_billboards); } //////////////////////////////////////////////////////////////////// @@ -1105,9 +1150,26 @@ setup_for_render(GraphicsStateGuardian *gsg) { if (si != _population_stats.m_mMaxNumInstancesPerCellPerBase.end()) { max_instances = max(max_instances, (int)si->second); } - + + // Get the speedtree-textures-dir to pass for initialization. + string os_textures_dir; + if (!speedtree_textures_dir.empty()) { + os_textures_dir = speedtree_textures_dir.get_value().to_os_specific(); + // Ensure the path ends with a terminal slash; SpeedTree requires this. +#ifdef WIN32 + if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '\\') { + os_textures_dir += "\\"; + } +#else + if (!os_textures_dir.empty() && os_textures_dir[os_textures_dir.length() - 1] != '/') { + os_textures_dir += "/"; + } +#endif + } + if (!_forest.InitTreeGraphics((SpeedTree::CTreeRender *)tree->get_tree(), - max_instances, speedtree_allow_horizontal_billboards)) { + max_instances, speedtree_horizontal_billboards, + os_textures_dir.c_str())) { speedtree_cat.warning() << "Failed to init tree graphics for " << *tree << "\n"; speedtree_cat.warning()