diff --git a/WickedEngine/wiColor.h b/WickedEngine/wiColor.h index da04cef59..b4f53950c 100644 --- a/WickedEngine/wiColor.h +++ b/WickedEngine/wiColor.h @@ -41,6 +41,15 @@ namespace wi rgba |= (c - 'A' + 10) << shift; shift += 4u; break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + rgba |= (c - 'a' + 10) << shift; + shift += 4u; + break; case '#': break; default: diff --git a/WickedEngine/wiPrimitive.cpp b/WickedEngine/wiPrimitive.cpp index d873a2864..51281bf7d 100644 --- a/WickedEngine/wiPrimitive.cpp +++ b/WickedEngine/wiPrimitive.cpp @@ -412,11 +412,15 @@ namespace wi::primitive } XMFLOAT4X4 Sphere::GetPlacementOrientation(const XMFLOAT3& position, const XMFLOAT3& normal) const { - XMVECTOR N = XMLoadFloat3(&normal); + XMVECTOR N = XMVector3Normalize(XMLoadFloat3(&normal)); XMVECTOR P = XMLoadFloat3(&position); XMVECTOR E = XMLoadFloat3(¢er) - P; XMVECTOR T = XMVector3Normalize(XMVector3Cross(N, P - E)); XMVECTOR B = XMVector3Normalize(XMVector3Cross(T, N)); + N = XMVectorSetW(N, 0); + T = XMVectorSetW(T, 0); + B = XMVectorSetW(B, 0); + P = XMVectorSetW(P, 1); XMMATRIX M = { T, N, B, P }; XMFLOAT4X4 orientation; XMStoreFloat4x4(&orientation, M); @@ -574,12 +578,16 @@ namespace wi::primitive const XMVECTOR Base = XMLoadFloat3(&base); const XMVECTOR Tip = XMLoadFloat3(&tip); const XMVECTOR Axis = XMVector3Normalize(Tip - Base); - XMVECTOR N = XMLoadFloat3(&normal); + XMVECTOR N = XMVector3Normalize(XMLoadFloat3(&normal)); XMVECTOR P = XMLoadFloat3(&position); XMVECTOR E = Axis; XMVECTOR T = XMVector3Normalize(XMVector3Cross(N, P - E)); - XMVECTOR Binorm = XMVector3Normalize(XMVector3Cross(T, N)); - XMMATRIX M = { T, N, Binorm, P }; + XMVECTOR B = XMVector3Normalize(XMVector3Cross(T, N)); + N = XMVectorSetW(N, 0); + T = XMVectorSetW(T, 0); + B = XMVectorSetW(B, 0); + P = XMVectorSetW(P, 1); + XMMATRIX M = { T, N, B, P }; XMFLOAT4X4 orientation; XMStoreFloat4x4(&orientation, M); return orientation; @@ -800,11 +808,15 @@ namespace wi::primitive } XMFLOAT4X4 Ray::GetPlacementOrientation(const XMFLOAT3& position, const XMFLOAT3& normal) const { - XMVECTOR N = XMLoadFloat3(&normal); + XMVECTOR N = XMVector3Normalize(XMLoadFloat3(&normal)); XMVECTOR P = XMLoadFloat3(&position); XMVECTOR E = XMLoadFloat3(&origin); XMVECTOR T = XMVector3Normalize(XMVector3Cross(N, P - E)); XMVECTOR B = XMVector3Normalize(XMVector3Cross(T, N)); + N = XMVectorSetW(N, 0); + T = XMVectorSetW(T, 0); + B = XMVectorSetW(B, 0); + P = XMVectorSetW(P, 1); XMMATRIX M = { T, N, B, P }; XMFLOAT4X4 orientation; XMStoreFloat4x4(&orientation, M); diff --git a/WickedEngine/wiRandom.h b/WickedEngine/wiRandom.h index fc82e3130..bc9f67e45 100644 --- a/WickedEngine/wiRandom.h +++ b/WickedEngine/wiRandom.h @@ -11,16 +11,16 @@ namespace wi::random { uint64_t state = 0; - inline RNG(uint64_t seed = 0) : state(seed) {} + constexpr RNG(uint64_t seed = 0) : state(seed) {} // seeds the random number generator, seed should be non-zero number - inline void seed(uint64_t seed) + constexpr void seed(uint64_t seed) { state = seed; } // gives an uint in range [0, UINT64_MAX] - inline uint64_t next_uint() + constexpr uint64_t next_uint() { state ^= state >> 12; state ^= state << 25; @@ -28,14 +28,14 @@ namespace wi::random return state * 0x2545F4914F6CDD1DULL; } // gives an uint64 in range [min, max] - inline uint64_t next_uint(uint64_t min, uint64_t max) + constexpr uint64_t next_uint(uint64_t min, uint64_t max) { if (min == max) return min; return min + (next_uint() % (std::min(std::numeric_limits::max() - uint64_t(1), std::max(uint64_t(1), max - min)) + uint64_t(1))); } // gives an uint32 in range [min, max] - inline uint32_t next_uint(uint32_t min, uint32_t max) + constexpr uint32_t next_uint(uint32_t min, uint32_t max) { if (min == max) return min; @@ -43,20 +43,25 @@ namespace wi::random } // gives an int64 in range [-INT64_MAX, INT64_MAX] - inline int64_t next_int() + constexpr int64_t next_int() { - uint64_t u = next_uint(); - return *(int64_t*)&u; + union + { + uint64_t u; + int64_t i; + } value = {}; + value.u = next_uint(); + return value.i; } // gives an int64 in range [min, max] - inline int64_t next_int(int64_t min, int64_t max) + constexpr int64_t next_int(int64_t min, int64_t max) { if (min == max) return min; return min + int64_t(next_uint() % (std::min(std::numeric_limits::max() - int64_t(1), std::max(int64_t(1), max - min)) + int64_t(1))); // we roll next_uint here to avoid negative value messing with range mapping } // gives an int32 in range [min, max] - inline int32_t next_int(int32_t min, int32_t max) + constexpr int32_t next_int(int32_t min, int32_t max) { if (min == max) return min; @@ -64,13 +69,18 @@ namespace wi::random } // gives a float in range [0, 1] - inline float next_float() + constexpr float next_float() { - uint32_t u = 0x3f800000 | (uint32_t(next_uint()) >> 9); - return *((float*)&u) - 1.0f; + union + { + uint32_t u; + float f; + } value = {}; + value.u = 0x3f800000 | (uint32_t(next_uint()) >> 9); + return value.f - 1.0f; } // gives a float in range [min, max] - inline float next_float(float min, float max) + constexpr float next_float(float min, float max) { return min + (max - min) * next_float(); } diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 51c2d4f57..e68fef363 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -1164,6 +1164,16 @@ namespace wi ); } + if (scene->weather.IsRealisticSky()) + { + wi::renderer::ComputeSkyAtmosphereSkyViewLut(cmd); + + if (scene->weather.IsRealisticSkyAerialPerspective()) + { + wi::renderer::ComputeSkyAtmosphereCameraVolumeLut(cmd); + } + } + if (scene->weather.IsVolumetricClouds() && !scene->weather.IsVolumetricCloudsReceiveShadow()) { // When volumetric cloud DOESN'T receive shadow it can be done async to shadow maps! @@ -1470,52 +1480,6 @@ namespace wi }); } - // Main camera weather compute effects depending on shadow maps, envmaps, etc, but don't depend on async surface pass: - if (scene->weather.IsRealisticSky() || scene->weather.IsVolumetricClouds()) - { - cmd = device->BeginCommandList(); - wi::jobsystem::Execute(ctx, [this, cmd](wi::jobsystem::JobArgs args) { - - wi::renderer::BindCameraCB( - *camera, - camera_previous, - camera_reflection, - cmd - ); - - if (scene->weather.IsRealisticSky()) - { - wi::renderer::ComputeSkyAtmosphereSkyViewLut(cmd); - - if (scene->weather.IsRealisticSkyAerialPerspective()) - { - wi::renderer::ComputeSkyAtmosphereCameraVolumeLut(cmd); - } - } - if (scene->weather.IsRealisticSky() && scene->weather.IsRealisticSkyAerialPerspective()) - { - wi::renderer::Postprocess_AerialPerspective( - aerialperspectiveResources, - cmd - ); - } - if (scene->weather.IsVolumetricClouds() && scene->weather.IsVolumetricCloudsReceiveShadow()) - { - // When volumetric cloud receives shadow it must be done AFTER shadow maps! - wi::renderer::Postprocess_VolumetricClouds( - volumetriccloudResources, - cmd, - *camera, - camera_previous, - camera_reflection, - wi::renderer::GetTemporalAAEnabled() || getFSR2Enabled(), - scene->weather.volumetricCloudsWeatherMapFirst.IsValid() ? &scene->weather.volumetricCloudsWeatherMapFirst.GetTexture() : nullptr, - scene->weather.volumetricCloudsWeatherMapSecond.IsValid() ? &scene->weather.volumetricCloudsWeatherMapSecond.GetTexture() : nullptr - ); - } - }); - } - // Main camera opaque color pass: cmd = device->BeginCommandList(); device->WaitCommandList(cmd, cmd_maincamera_compute_effects); @@ -1531,6 +1495,28 @@ namespace wi cmd ); + if (scene->weather.IsRealisticSky() && scene->weather.IsRealisticSkyAerialPerspective()) + { + wi::renderer::Postprocess_AerialPerspective( + aerialperspectiveResources, + cmd + ); + } + if (scene->weather.IsVolumetricClouds() && scene->weather.IsVolumetricCloudsReceiveShadow()) + { + // When volumetric cloud receives shadow it must be done AFTER shadow maps! + wi::renderer::Postprocess_VolumetricClouds( + volumetriccloudResources, + cmd, + *camera, + camera_previous, + camera_reflection, + wi::renderer::GetTemporalAAEnabled() || getFSR2Enabled(), + scene->weather.volumetricCloudsWeatherMapFirst.IsValid() ? &scene->weather.volumetricCloudsWeatherMapFirst.GetTexture() : nullptr, + scene->weather.volumetricCloudsWeatherMapSecond.IsValid() ? &scene->weather.volumetricCloudsWeatherMapSecond.GetTexture() : nullptr + ); + } + if (getRaytracedReflectionEnabled()) { wi::renderer::Postprocess_RTReflection( diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 636f93a4c..55f07237f 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -5795,6 +5795,7 @@ namespace wi::scene spline.spline_node_transforms.resize(spline.spline_node_entities.size()); // BEFORE mesh update: LOCAL space transform (because mesh will be also transformed by ObjectComponent instance) + spline.precomputed_total_distance = 0; for (size_t i = 0; i < spline.spline_node_entities.size(); ++i) { Entity node_entity = spline.spline_node_entities[i]; @@ -5808,6 +5809,7 @@ namespace wi::scene // Force update in local space: spline.spline_node_transforms[i].SetDirty(); spline.spline_node_transforms[i].UpdateTransform(); + spline.spline_node_transforms[i].ApplyTransform(); } } @@ -5822,6 +5824,7 @@ namespace wi::scene MeshComponent* mesh = meshes.GetComponent(entity); if (mesh != nullptr) { + spline.PrecomputeSplineNodeDistances(); // local space spline.prev_mesh_generation_subdivision = spline.mesh_generation_subdivision; spline.prev_mesh_generation_vertical_subdivision = spline.mesh_generation_vertical_subdivision; spline.prev_mesh_generation_nodes = (int)spline.spline_node_entities.size(); @@ -6007,6 +6010,7 @@ namespace wi::scene } // AFTER mesh generation, parented update: + spline.precomputed_total_distance = 0; for (size_t i = 0; i < spline.spline_node_entities.size(); ++i) { Entity node_entity = spline.spline_node_entities[i]; @@ -6014,9 +6018,12 @@ namespace wi::scene if (node_transform != nullptr) { XMStoreFloat4x4(&spline.spline_node_transforms[i].world, ComputeEntityMatrixRecursive(node_entity)); + spline.spline_node_transforms[i].ApplyTransform(); } } + spline.PrecomputeSplineNodeDistances(); // world space + // Compute AABB: if (dirty || (spline.dirty_terrain && spline.terrain_modifier_amount > 0)) { diff --git a/WickedEngine/wiScene_Components.cpp b/WickedEngine/wiScene_Components.cpp index dcd2c53b6..2291d6ef4 100644 --- a/WickedEngine/wiScene_Components.cpp +++ b/WickedEngine/wiScene_Components.cpp @@ -102,6 +102,14 @@ namespace wi::scene XMFLOAT3 v = wi::math::GetRight(world); return XMLoadFloat3(&v); } + void TransformComponent::GetPositionRotationScale(XMFLOAT3& position, XMFLOAT4& rotation, XMFLOAT3& scale) const + { + XMVECTOR S, R, T; + XMMatrixDecompose(&S, &R, &T, XMLoadFloat4x4(&world)); + XMStoreFloat3(&position, T); + XMStoreFloat4(&rotation, R); + XMStoreFloat3(&scale, S); + } void TransformComponent::UpdateTransform() { if (IsDirty()) @@ -2861,6 +2869,13 @@ namespace wi::scene XMMATRIX SplineComponent::EvaluateSplineAt(float t) const { + // Notes: + // - This function uses the spline_node_transforms which are precomputed before using this by the scene's RunSplineUpdateSystem() + // - it uses _local members of the transforms, but they can be either wlocal or world space, depending on when we use it and what was stored in them at that point + // for example mesh updates will use local spaces, but terrain updates will use world spaces + // - precomputed_node_distances must be updated before this, it is done by RunSplineUpdateSystem() + // this is made to avoid computing distances every time we call this which might be a lot + if (spline_node_transforms.empty()) return {}; if (spline_node_transforms.size() == 1) @@ -2868,14 +2883,14 @@ namespace wi::scene if (spline_node_transforms.size() == 2) { - XMVECTOR P0 = spline_node_transforms[0].GetPositionV(); - XMVECTOR P1 = spline_node_transforms[1].GetPositionV(); + XMVECTOR P0 = XMLoadFloat3(&spline_node_transforms[0].translation_local); + XMVECTOR P1 = XMLoadFloat3(&spline_node_transforms[1].translation_local); - XMVECTOR W0 = XMVectorReplicate(spline_node_transforms[0].GetScale().x); - XMVECTOR W1 = XMVectorReplicate(spline_node_transforms[1].GetScale().x); + XMVECTOR W0 = XMVectorReplicate(spline_node_transforms[0].scale_local.x); + XMVECTOR W1 = XMVectorReplicate(spline_node_transforms[1].scale_local.x); - XMVECTOR Q0 = XMQuaternionNormalize(spline_node_transforms[0].GetRotationV()); - XMVECTOR Q1 = XMQuaternionNormalize(spline_node_transforms[1].GetRotationV()); + XMVECTOR Q0 = XMQuaternionNormalize(XMLoadFloat4(&spline_node_transforms[0].rotation_local)); + XMVECTOR Q1 = XMQuaternionNormalize(XMLoadFloat4(&spline_node_transforms[1].rotation_local)); XMVECTOR P = XMVectorLerp(P0, P1, t); XMVECTOR Q = XMQuaternionNormalize(XMQuaternionSlerp(Q0, Q1, t)); @@ -2905,26 +2920,19 @@ namespace wi::scene beforelast++; } - float total_distance = 0; - for (int i = 0; i < beforelast; ++i) - { - const TransformComponent& transform0 = spline_node_transforms[(i + first) % cnt]; - const TransformComponent& transform1 = spline_node_transforms[(i + second) % cnt]; - total_distance += wi::math::Distance(transform0.GetPosition(), transform1.GetPosition()); - } - float tdist = t * total_distance; + float tdist = t * precomputed_total_distance; int t0 = 0; // prev int t1 = 0; // current int t2 = 1; // next int t3 = 1; // after next float tmid = 0; - total_distance = 0; + + // This is similar to a keyframe search: + float total_distance = 0; for (int i = 0; i < beforelast; ++i) { - const TransformComponent& transform0 = spline_node_transforms[(i + first) % cnt]; - const TransformComponent& transform1 = spline_node_transforms[(i + second) % cnt]; float dist_prev = total_distance; - total_distance += wi::math::Distance(transform0.GetPosition(), transform1.GetPosition()); + total_distance += precomputed_node_distances[i]; if (total_distance >= tdist) { if (IsLooped()) @@ -2946,10 +2954,10 @@ namespace wi::scene } } - XMVECTOR P0 = spline_node_transforms[t0].GetPositionV(); - XMVECTOR P1 = spline_node_transforms[t1].GetPositionV(); - XMVECTOR P2 = spline_node_transforms[t2].GetPositionV(); - XMVECTOR P3 = spline_node_transforms[t3].GetPositionV(); + XMVECTOR P0 = XMLoadFloat3(&spline_node_transforms[t0].translation_local); + XMVECTOR P1 = XMLoadFloat3(&spline_node_transforms[t1].translation_local); + XMVECTOR P2 = XMLoadFloat3(&spline_node_transforms[t2].translation_local); + XMVECTOR P3 = XMLoadFloat3(&spline_node_transforms[t3].translation_local); if (t1 == t0) { @@ -2962,15 +2970,15 @@ namespace wi::scene P3 += P2 - P1; } - XMVECTOR W0 = XMVectorReplicate(spline_node_transforms[t0].GetScale().x); - XMVECTOR W1 = XMVectorReplicate(spline_node_transforms[t1].GetScale().x); - XMVECTOR W2 = XMVectorReplicate(spline_node_transforms[t2].GetScale().x); - XMVECTOR W3 = XMVectorReplicate(spline_node_transforms[t3].GetScale().x); + XMVECTOR W0 = XMVectorReplicate(spline_node_transforms[t0].scale_local.x); + XMVECTOR W1 = XMVectorReplicate(spline_node_transforms[t1].scale_local.x); + XMVECTOR W2 = XMVectorReplicate(spline_node_transforms[t2].scale_local.x); + XMVECTOR W3 = XMVectorReplicate(spline_node_transforms[t3].scale_local.x); - XMVECTOR Q0 = XMQuaternionNormalize(spline_node_transforms[t0].GetRotationV()); - XMVECTOR Q1 = XMQuaternionNormalize(spline_node_transforms[t1].GetRotationV()); - XMVECTOR Q2 = XMQuaternionNormalize(spline_node_transforms[t2].GetRotationV()); - XMVECTOR Q3 = XMQuaternionNormalize(spline_node_transforms[t3].GetRotationV()); + XMVECTOR Q0 = XMQuaternionNormalize(XMLoadFloat4(&spline_node_transforms[t0].rotation_local)); + XMVECTOR Q1 = XMQuaternionNormalize(XMLoadFloat4(&spline_node_transforms[t1].rotation_local)); + XMVECTOR Q2 = XMQuaternionNormalize(XMLoadFloat4(&spline_node_transforms[t2].rotation_local)); + XMVECTOR Q3 = XMQuaternionNormalize(XMLoadFloat4(&spline_node_transforms[t3].rotation_local)); XMVECTOR P = wi::math::CatmullRomCentripetal(P0, P1, P2, P3, tmid); XMVECTOR P_prev = wi::math::CatmullRomCentripetal(P0, P1, P2, P3, saturate(tmid - 0.01f)); @@ -2997,7 +3005,7 @@ namespace wi::scene if (spline_node_transforms.empty()) return XMVectorZero(); if (spline_node_transforms.size() == 1) - return spline_node_transforms[0].GetPositionV(); + return XMLoadFloat3(&spline_node_transforms[0].translation_local); steps *= (int)spline_node_transforms.size(); float mindist = FLT_MAX; @@ -3081,4 +3089,30 @@ namespace wi::scene } return ret; } + void SplineComponent::PrecomputeSplineNodeDistances() + { + if (spline_node_transforms.empty()) + return; + precomputed_node_distances.resize(spline_node_transforms.size()); + int cnt = (int)spline_node_transforms.size(); + int first = 0; + int second = 1; + int beforelast = cnt - 1; + if (IsLooped()) + { + first = cnt - 1; + second = first + 1; + beforelast++; + } + + precomputed_total_distance = 0; + for (int i = 0; i < beforelast; ++i) + { + const XMFLOAT3& pos0 = spline_node_transforms[(i + first) % cnt].translation_local; + const XMFLOAT3& pos1 = spline_node_transforms[(i + second) % cnt].translation_local; + const float distance = wi::math::Distance(pos0, pos1); + precomputed_total_distance += distance; + precomputed_node_distances[i] = distance; + } + } } diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 50f2062b1..5e74dcb94 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -78,6 +78,7 @@ namespace wi::scene XMVECTOR GetForwardV() const; XMVECTOR GetUpV() const; XMVECTOR GetRightV() const; + void GetPositionRotationScale(XMFLOAT3& position, XMFLOAT4& rotation, XMFLOAT3& scale) const; // Computes the local space matrix from scale, rotation, translation and returns it XMMATRIX GetLocalMatrix() const; // Returns the stored world matrix that was computed the last time UpdateTransform() was called @@ -2558,6 +2559,8 @@ namespace wi::scene // Non-serialized attributes: wi::vector spline_node_transforms; + wi::vector precomputed_node_distances; + float precomputed_total_distance = 0; float prev_width = 1; float prev_rotation = 0; int prev_mesh_generation_subdivision = 0; @@ -2579,8 +2582,12 @@ namespace wi::scene // Trace a point on the spline's plane: XMVECTOR TraceSplinePlane(const XMVECTOR& ORIGIN, const XMVECTOR& DIRECTION, int steps = 10) const; + // Compute the boounding box of the spline iteratively wi::primitive::AABB ComputeAABB(int steps = 10) const; + // Precompute the spline node distances that will be used at spline evaluation calls + void PrecomputeSplineNodeDistances(); + // By default the spline is drawn as camera facing, this can be used to set it to be drawn aligned to segment rotations: bool IsDrawAligned() const { return _flags & DRAW_ALIGNED; } void SetDrawAligned(bool value = true) { if (value) { _flags |= DRAW_ALIGNED; } else { _flags &= ~DRAW_ALIGNED; } } diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp index 9aa981390..86f14662c 100644 --- a/WickedEngine/wiTerrain.cpp +++ b/WickedEngine/wiTerrain.cpp @@ -963,8 +963,9 @@ namespace wi::terrain constexpr int chunk_width_padded = chunk_width + 1; constexpr uint32_t vertexCount_padded = chunk_width_padded * chunk_width_padded; float heights_padded[chunk_width_padded][chunk_width_padded]; + const XMVECTOR UP = XMVectorSet(0, 1, 0, 0); wi::jobsystem::Dispatch(ctx, vertexCount_padded, chunk_width_padded * 4, [&](wi::jobsystem::JobArgs args) { - uint32_t index = args.jobIndex; + const uint32_t index = args.jobIndex; const XMUINT2 coord = XMUINT2(index % chunk_width_padded, index / chunk_width_padded); const float x = (float(coord.x) - chunk_half_width) * chunk_scale; const float z = (float(coord.y) - chunk_half_width) * chunk_scale; @@ -976,22 +977,19 @@ namespace wi::terrain modifier->Apply(world_pos, height); } height = lerp(bottomLevel, topLevel, height); - XMVECTOR corner = XMVectorSet(world_pos.x, height, world_pos.y, 0); - // Apply splines: + // Apply splines to height only: + const XMVECTOR P = XMVectorSet(world_pos.x, -100000, world_pos.y, 0); for (size_t j = 0; j < generator->splines.size(); ++j) { const SplineComponent& spline = generator->splines[j]; - if (spline.terrain_modifier_amount <= 0 || !spline.aabb.intersects(corner)) + if (!spline.aabb.intersects(P)) continue; - XMVECTOR P = XMVectorSetY(corner, -1000); - XMVECTOR S = spline.TraceSplinePlane(P, XMVectorSet(0, 1, 0, 0), 4); + XMVECTOR S = spline.TraceSplinePlane(P, UP, 4); S = spline.ClosestPointOnSpline(S, 4); - float splineheight = XMVectorGetY(S); - P = XMVectorSetY(P, splineheight); - float splinedist = wi::math::Distance(P, S); + const float splineheight = XMVectorGetY(S); + const float splinedist = wi::math::Distance(XMVectorSetY(P, splineheight), S); height = lerp(splineheight, height, smoothstep(0.0f, 1.0f, saturate(splinedist * sqr(spline.terrain_modifier_amount)))); - corner = XMVectorSetY(corner, height); } heights_padded[coord.x][coord.y] = height; @@ -1084,8 +1082,6 @@ namespace wi::terrain chunk_data.grass.CreateFromMesh(mesh); } - wi::jobsystem::Wait(ctx); // wait until mesh.CreateRenderData() async task finishes - // Create the textures for virtual texture update: CreateChunkRegionTexture(chunk_data); @@ -1101,6 +1097,8 @@ namespace wi::terrain wi::physics::CreateRigidBodyShape(newrigidbody, transform.scale_local, &mesh); } + wi::jobsystem::Wait(ctx); // wait until mesh.CreateRenderData() async task finishes + generated_something = true; } @@ -1147,22 +1145,22 @@ namespace wi::terrain generator->scene.Component_Attach(chunk_data.props_entity, chunk_data.entity, true); chunk_data.prop_density_current = prop_density; - wi::random::RNG rng((uint32_t)chunk.compute_hash() ^ seed); + wi::random::RNG rng(chunk.compute_hash()); for (const auto& prop : props) { if (prop.data.empty()) continue; - int gen_count = (int)rng.next_uint( + const int gen_count = (int)rng.next_uint( uint32_t(prop.min_count_per_chunk * chunk_data.prop_density_current), std::max(1u, uint32_t(prop.max_count_per_chunk * chunk_data.prop_density_current)) ); for (int i = 0; i < gen_count; ++i) { - uint32_t tri = rng.next_uint(0, chunk_indices().lods[0].indexCount / 3); // random triangle on the chunk mesh - uint32_t ind0 = chunk_indices().indices[tri * 3 + 0]; - uint32_t ind1 = chunk_indices().indices[tri * 3 + 1]; - uint32_t ind2 = chunk_indices().indices[tri * 3 + 2]; + const uint32_t tri = rng.next_uint(0, chunk_indices().lods[0].indexCount / 3); // random triangle on the chunk mesh + const uint32_t ind0 = chunk_indices().indices[tri * 3 + 0]; + const uint32_t ind1 = chunk_indices().indices[tri * 3 + 1]; + const uint32_t ind2 = chunk_indices().indices[tri * 3 + 2]; const XMFLOAT3& pos0 = chunk_data.mesh_vertex_positions[ind0]; const XMFLOAT3& pos1 = chunk_data.mesh_vertex_positions[ind1]; const XMFLOAT3& pos2 = chunk_data.mesh_vertex_positions[ind2]; @@ -1180,15 +1178,17 @@ namespace wi::terrain f = 1 - f; g = 1 - g; } - XMFLOAT3 vertex_pos; - vertex_pos.x = pos0.x + f * (pos1.x - pos0.x) + g * (pos2.x - pos0.x); - vertex_pos.y = pos0.y + f * (pos1.y - pos0.y) + g * (pos2.y - pos0.y); - vertex_pos.z = pos0.z + f * (pos1.z - pos0.z) + g * (pos2.z - pos0.z); - XMFLOAT4 region; - region.x = region0.x + f * (region1.x - region0.x) + g * (region2.x - region0.x); - region.y = region0.y + f * (region1.y - region0.y) + g * (region2.y - region0.y); - region.z = region0.z + f * (region1.z - region0.z) + g * (region2.z - region0.z); - region.w = region0.w + f * (region1.w - region0.w) + g * (region2.w - region0.w); + const XMFLOAT3 vertex_pos = XMFLOAT3( + pos0.x + f * (pos1.x - pos0.x) + g * (pos2.x - pos0.x), + pos0.y + f * (pos1.y - pos0.y) + g * (pos2.y - pos0.y), + pos0.z + f * (pos1.z - pos0.z) + g * (pos2.z - pos0.z) + ); + const XMFLOAT4 region = XMFLOAT4( + region0.x + f * (region1.x - region0.x) + g * (region2.x - region0.x), + region0.y + f * (region1.y - region0.y) + g * (region2.y - region0.y), + region0.z + f * (region1.z - region0.z) + g * (region2.z - region0.z), + region0.w + f * (region1.w - region0.w) + g * (region2.w - region0.w) + ); const float noise = std::pow(perlin_noise.compute((vertex_pos.x + chunk_data.position.x) * prop.noise_frequency, vertex_pos.y * prop.noise_frequency, (vertex_pos.z + chunk_data.position.z) * prop.noise_frequency) * 0.5f + 0.5f, prop.noise_power); const float chance = std::pow(((float*)®ion)[prop.region], prop.region_power) * noise; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 9c7999ff8..67f0cd80d 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 741; + const int revision = 742; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);