At first this seem to work but eventually I realized that at some point my up/down rotation are switched gradually overtime (almost like a slow sinus).
Any idea on how to rotate both x and y without distorting the image?
I have tried another approach where I try to simply use a mesh with a material based on objectOrientation (I use a sphere mesh to do a skysphere). This works well for the sky itself but now all my other actors flickers which was not the case with the dynamic texture (the niagara effects are the most afffected by the flickering).
In the end, the best option, is to make your own sky dome ( not sphere ), because it is possible to project the UVs down from a plane, and avoid almost all problems
Regarding
“The reason you’re getting distortion, is because the typical sphere has distorted UVs, especially pinched at the top”
I get what you mean but in my case the distortion was kind of dynamic (like a deflating or inflating balloon, but now with the screenshot from main post I don’t have any distortion, only up/down rotation degradation). I suspected my pivot point at first but it does not seem to be the issue.
The distortion from the sphere is really not that bad I can see it in the viewport with another non dynamic version of my texture.
PROS: Fluid rotation of the background at runtime
CONS: High flickering of actors (especially niagara systems)
Solution#2:
Code solution mixed to perform Angles to Quaternions transformation (to mix X axis and Y axis together, thx Bing Copilot) mixed with the solution presented in https://www.youtube.com/watch?v=IQ3wKSzAEG4. (This one use a /Engine/EngineSky/SM_SkySphere.SM_SkySphere instead of /Engine/BasicShapes/Sphere.Sphere)
f_YBasicRotation = 0 + 0.1 * f_Counter;
f_XBasicRotation = 0 + 0.1 * f_Counter;
f_Counter++;
// Define the rotations
FRotator RotationX(f_YBasicRotation, 0.0f, 0.0f);
FRotator RotationY(0.0f, 0.0f , f_XBasicRotation);
// Convert to quaternions
FQuat QuatX = FQuat(RotationX);
FQuat QuatY = FQuat(-1 * RotationY);
// Combine the quaternions
FQuat CombinedQuat = QuatY * QuatX;
// Ensure stability for small angles
if (CombinedQuat.IsIdentity())
{
CombinedQuat = FQuat::Identity;
}
// Get the axis and angle from the combined quaternion
FVector RotationAxis = CombinedQuat.GetRotationAxis();
float RotationAngle = CombinedQuat.GetAngle();
RotationAngle = FMath::RadiansToDegrees(RotationAngle); // Convert to degrees
// Output the axis and angle
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, FString::Printf(TEXT("N Rotation Axis: %s , Rotation Angle: %f degrees "), *RotationAxis.ToString(), RotationAngle));
// Create a vector with rotation angle
FVector MyVector(RotationAngle, 0.0f, 0.0f);
// Set the material parameters
UMID_DynamicSkyMaterial->SetVectorParameterValue(TEXT("AxisToSet"), RotationAxis);
UMID_DynamicSkyMaterial->SetVectorParameterValue(TEXT("XYZMapRotation"), MyVector * 0.001);
USMC_SkyDomeMesh->SetMaterial(0, UMID_DynamicSkyMaterial);
Because all the things in my view (within the sphere) (mainly niagara systems) flickers more with the mesh rotation approach than with the dynamic material approach
When I rotate the mesh (stuff in my game (within the sphere) flicker more)
When I rotate the material (stuff in my game (within the sphere) flicker less)
My hero! so finally Solution#1
(Mesh, material with object rotation) with your sky fix to the material does exactly what I am looking for and I have no more flickering! THX
EDITED (2024-12-30): I initially thought all text and screenshots above were enough to fix my issue.
However I realized that they were not (solution was good to fix flickering but over time I restarted getting unexpected rotation behavior (sphere would initially rotate in the right direction but would eventually starts acting weird (going up when I want to go down idem with left right and depending on my code version it could also slow to almost a stop).
To rotate my sky sphere a bit like a ball turret, I think I faced mainly the two following issues.
So finally what appears to be working is the following quaternions approach which are ideal to avoid gimbal lock and ease 3D rotation. This is not my official code but on what it was based on (thx bing, only really minor changes were required to work in my situation):
#include "YourActor.h"
#include "Components/StaticMeshComponent.h"
// Initialize current rotation as identity quaternion
FQuat CurrentRotation = FQuat::Identity;
// Apply incremental rotations
void AYourActor::ApplyRotation(const FQuat& DeltaRotation)
{
// Update current rotation
CurrentRotation = DeltaRotation * CurrentRotation;
// Convert quaternion to rotator
FRotator NewRotation = CurrentRotation.Rotator();
// Apply rotation to the sphere
YourMeshComponent->SetWorldRotation(NewRotation);
}
// Example of applying a delta yaw rotation
void AYourActor::RotateLeftRight(float DeltaYaw)
{
// Create a delta rotation quaternion for yaw
FQuat DeltaRotation = FQuat(FVector::UpVector, FMath::DegreesToRadians(DeltaYaw));
ApplyRotation(DeltaRotation);
}
// Example of applying a delta pitch rotation
void AYourActor::RotateUpDown(float DeltaPitch)
{
// Create a delta rotation quaternion for pitch
FQuat DeltaRotation = FQuat(FVector::RightVector, FMath::DegreesToRadians(DeltaPitch));
ApplyRotation(DeltaRotation);
}
// Tick function to reset delta values
void AYourActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Apply rotations based on input
// For example, call RotateLeftRight and RotateUpDown with input values
// Reset delta values for next frame
DeltaPitch = 0.0f;
DeltaYaw = 0.0f;
}
// YourActor.h file
class AYourActor : public AActor
{
GENERATED_BODY()
public:
// Constructor and other functions
AYourActor();
virtual void Tick(float DeltaTime) override;
protected:
virtual void BeginPlay() override;
private:
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* YourMeshComponent;
// Current rotation quaternion
FQuat CurrentRotation;
// Delta values for rotation
float DeltaPitch;
float DeltaYaw;
// Functions to apply rotations
void ApplyRotation(const FQuat& DeltaRotation);
void RotateLeftRight(float DeltaYaw);
void RotateUpDown(float DeltaPitch);
};
Please note @ClockworkOcean was ideal to fix flickering of various actors when rotating the sphere (thx again) but this solution also include the 3D rotations issues fixes for the difficulties of rotating a skysphere properly.