feat(render): SAGE water/ocean shaders, per-user logs, camera & culling
Terrain pass now ports the SAGE water model (Ocean.fx / OpenSAGE Water.frag): a de-gridded procedural wave normal combined with the retail ra3_deepocean flow and ra3_deepocean_nrm bump maps (appended as the last two terrain-atlas layers, no new backend binding), Schlick fresnel, sky reflection + depth-graded refraction, SAGE diffuse/specular lighting, depth-based transparency, and an underwater tint (UnderwaterDeferred.fx). Mirrored across terrain.frag / dx_terrain.hlsl / webgl_terrain_frag.glsl / webgpu_terrain.wgsl. Also: logs move to the per-user state dir (%LOCALAPPDATA%\\OpenRA3\\logs, else XDG) and archive as openra3.<stamp>.log; the FPS label shows the active backend; middle-drag camera reset; objects and roads below the water plane are culled.
This commit is contained in:
@@ -765,6 +765,7 @@ export namespace ra3::models {
|
||||
usize placed = 0;
|
||||
usize missing = 0;
|
||||
usize roads = 0;
|
||||
usize hidden = 0; ///< Objects/roads below the water plane, not drawn.
|
||||
|
||||
[[nodiscard]] auto empty() const -> bool { return indices.empty(); }
|
||||
[[nodiscard]] auto triangle_count() const -> usize { return indices.size() / 3U; }
|
||||
@@ -823,9 +824,14 @@ export namespace ra3::models {
|
||||
* @param ground_height Terrain height (world Z) at a world `(x, y)`, so
|
||||
* objects sit on the relief instead of a flat plane.
|
||||
* @param texture_size Edge length of the shared texture array (0 = auto).
|
||||
* @param cull_below_z Skip placements whose base sits below this world Z
|
||||
* (the water plane): an opaque water surface hides
|
||||
* submerged objects, so drawing them would float them
|
||||
* on top of the sea.
|
||||
*/
|
||||
[[nodiscard]] inline auto build_scene(const asset_stream &stream, std::span<const placement> placements,
|
||||
const std::function<float(float, float)> &ground_height = {}, uint32 texture_size = 128U) -> scene {
|
||||
const std::function<float(float, float)> &ground_height = {}, uint32 texture_size = 128U,
|
||||
float cull_below_z = -3.4e38F) -> scene {
|
||||
scene out;
|
||||
out.texture_size = texture_size == 0U ? 128U : texture_size;
|
||||
std::unordered_map<std::string, uint32> texture_layers;
|
||||
@@ -972,6 +978,12 @@ export namespace ra3::models {
|
||||
if ((a.road_type & 2U) == 0U) continue; // RoadType::Start
|
||||
const auto &b = placements[i + 1U];
|
||||
if ((b.road_type & 4U) == 0U || b.type != a.type) continue; // RoadType::End
|
||||
const auto road_base = (ground_height ? ground_height(a.x, a.y) : 0.0F) + a.z;
|
||||
if (road_base < cull_below_z) {
|
||||
++out.hidden;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
emit_road(a, b);
|
||||
++i;
|
||||
}
|
||||
@@ -986,6 +998,10 @@ export namespace ra3::models {
|
||||
const auto cos_a = std::cos(item.angle);
|
||||
const auto sin_a = std::sin(item.angle);
|
||||
const auto base_z = (ground_height ? ground_height(item.x, item.y) : 0.0F) + item.z;
|
||||
if (base_z < cull_below_z) {
|
||||
++out.hidden;
|
||||
continue;
|
||||
}
|
||||
bool drawn = false;
|
||||
for (const auto *mesh_asset: meshes) {
|
||||
// Only opaque material parts are drawn; meshes with no diffuse
|
||||
|
||||
Reference in New Issue
Block a user