浏览代码

Add time of day

Panagiotis Christopoulos Charitos 6 月之前
父节点
当前提交
1ad8a29632

+ 18 - 0
AnKi/Math/Functions.h

@@ -291,3 +291,21 @@ inline F32 computeTriangleArea(const TVec& a, const TVec& b, const TVec& c)
 /// @}
 
 } // end namespace anki
+
+// Now lay out functions that include other math headers
+
+#include <AnKi/Math/Vec.h>
+
+namespace anki {
+
+template<typename T>
+TVec<T, 3> sphericalToCartesian(T polar, T azimuth)
+{
+	TVec<T, 3> out;
+	out.x() = cos(polar) * sin(azimuth);
+	out.y() = cos(polar) * cos(azimuth);
+	out.z() = sin(polar);
+	return out;
+}
+
+} // end namespace anki

+ 15 - 17
AnKi/Renderer/IndirectDiffuseClipmaps.cpp

@@ -243,8 +243,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 			pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kSrvCompute);
 		}
 
-		pass.setWork([this, rtResultHandle, &ctx, sbtBuffer, irradianceVolumes, probeValidityVolumes,
-					  distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
+		pass.setWork([this, rtResultHandle, &ctx, sbtBuffer](RenderPassWorkContext& rgraphCtx) {
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 			cmdb.bindShaderProgram(m_rtLibraryGrProg.get());
@@ -417,7 +416,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 
 		pass.newTextureDependency(appliedGiRt, TextureUsageBit::kUavTraceRays);
 
-		pass.setWork([this, &ctx, sbtBuffer, irradianceVolumes, probeValidityVolumes, distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
+		pass.setWork([this, &ctx, sbtBuffer](RenderPassWorkContext& rgraphCtx) {
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 			cmdb.bindShaderProgram(m_rtLibraryGrProg.get());
@@ -497,24 +496,23 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 		}
 		pass.newTextureDependency(appliedGiRt, TextureUsageBit::kUavCompute);
 
-		pass.setWork(
-			[this, &ctx, irradianceVolumes, probeValidityVolumes, distanceMomentsVolumes, avgIrradianceVolumes](RenderPassWorkContext& rgraphCtx) {
-				CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+		pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
-				cmdb.bindShaderProgram(m_applyGiGrProg.get());
+			cmdb.bindShaderProgram(m_applyGiGrProg.get());
 
-				rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
-				rgraphCtx.bindSrv(1, 0, getGBuffer().getColorRt(2));
-				cmdb.bindSrv(2, 0, TextureView(&m_blueNoiseImg->getTexture(), TextureSubresourceDesc::firstSurface()));
+			rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(1, 0, getGBuffer().getColorRt(2));
+			cmdb.bindSrv(2, 0, TextureView(&m_blueNoiseImg->getTexture(), TextureSubresourceDesc::firstSurface()));
 
-				rgraphCtx.bindUav(0, 0, m_runCtx.m_handles.m_appliedIrradiance);
+			rgraphCtx.bindUav(0, 0, m_runCtx.m_handles.m_appliedIrradiance);
 
-				cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
+			cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 
-				cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
+			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
 
-				dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
-			});
+			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
+		});
 	}
 }
 
@@ -522,7 +520,7 @@ void IndirectDiffuseClipmaps::drawDebugProbes(const RenderingContext& ctx, Rende
 {
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
-	const U32 clipmap = 1;
+	const U32 clipmap = 0;
 
 	cmdb.bindShaderProgram(m_visProbesGrProg.get());
 
@@ -531,7 +529,7 @@ void IndirectDiffuseClipmaps::drawDebugProbes(const RenderingContext& ctx, Rende
 
 	cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 
-	const RenderTargetHandle visVolume = m_runCtx.m_handles.m_irradianceVolumes[clipmap];
+	const RenderTargetHandle visVolume = m_runCtx.m_handles.m_radianceVolumes[clipmap];
 	rgraphCtx.bindSrv(0, 0, visVolume);
 	rgraphCtx.bindSrv(1, 0, m_runCtx.m_handles.m_probeValidityVolumes[clipmap]);
 	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());

+ 96 - 0
AnKi/Scene/Components/LightComponent.cpp

@@ -15,6 +15,56 @@
 
 namespace anki {
 
+// Calculate day of the year
+static U32 dayOfYear(U32 year, U32 month, U32 day)
+{
+	struct tm date = {};
+	date.tm_year = year - 1900;
+	date.tm_mon = month - 1;
+	date.tm_mday = day;
+	mktime(&date);
+	return date.tm_yday + 1;
+}
+
+static void solarPosition(U32 year, U32 month, U32 day, F32 hourUtc, F32 latitude, F32 longitude, F32& elevation, F32& azimuth)
+{
+	const F32 N = F32(dayOfYear(year, month, day));
+
+	// Fractional year (in radians)
+	const F32 gamma = 2.0f * kPi / 365.0f * (N - 1.0f + (hourUtc - 12.0f) / 24.0f);
+
+	// Equation of time (minutes)
+	const F32 eqTime =
+		229.18f * (0.000075f + 0.001868f * cos(gamma) - 0.032077f * sin(gamma) - 0.014615f * cos(2.0f * gamma) - 0.040849f * sin(2.0f * gamma));
+
+	// Solar declination (radians)
+	const F32 decl = 0.006918f - 0.399912f * cos(gamma) + 0.070257f * sin(gamma) - 0.006758f * cos(2.0f * gamma) + 0.000907f * sin(2 * gamma)
+					 - 0.002697f * cos(3.0f * gamma) + 0.00148f * sin(3.0f * gamma);
+
+	// Time offset (minutes)
+	const F32 timeOffset = eqTime + 4.0f * longitude;
+
+	// True solar time (degrees)
+	const F32 tst = hourUtc * 60.0f + timeOffset;
+	const F32 ha = toRad((tst / 4.0f) - 180.0f); // Hour angle in radians
+
+	const F32 latRad = toRad(latitude);
+
+	// Solar zenith angle
+	const F32 cosZenith = sin(latRad) * sin(decl) + cos(latRad) * cos(decl) * cos(ha);
+	const F32 zenith = acos(cosZenith);
+	elevation = kPi / 2.0f - zenith;
+
+	// Solar azimuth
+	const F32 v = (sin(decl) - sin(latRad) * cos(zenith)) / (cos(latRad) * sin(zenith));
+	const F32 azRad = acos(clamp(v, -1.0f, 1.0f));
+	azimuth = azRad;
+	if(ha > 0.0)
+	{
+		azimuth = 2.0f * kPi - azimuth;
+	}
+}
+
 LightComponent::LightComponent(SceneNode* node)
 	: SceneComponent(node, kClassType)
 	, m_type(LightComponentType::kPoint)
@@ -196,6 +246,52 @@ void LightComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 	else if(m_type == LightComponentType::kDirectional)
 	{
 		m_gpuSceneLight.free();
+
+		if(updated && (m_dir.m_month >= 0 && m_dir.m_day >= 0 && m_dir.m_hour >= 0.0f))
+		{
+			F32 hour;
+			F32 lat, lon;
+			if(1)
+			{
+				// Location: Greece
+				lat = 37.983326540467026f;
+				lon = 23.722718055667336f;
+
+				// Fix hour to UTC
+				hour = m_dir.m_hour - 2.0f;
+			}
+			else
+			{
+				// Location: Norway
+				lat = 63.42239805509379f;
+				lon = 10.400744175764066f;
+
+				// Fix hour to UTC
+				hour = m_dir.m_hour - 1.0f;
+			}
+
+			F32 elevation, azimuth;
+			solarPosition(2025, m_dir.m_month, m_dir.m_day, hour, lat, lon, elevation, azimuth);
+
+			elevation = max(elevation, toRad(10.0f)); // Don't have it negative cause the renderer can't handle it
+
+			const F32 polarAng = kPi / 2.0f - elevation;
+			const Vec3 newDir = -sphericalToCartesian(polarAng, azimuth);
+
+			const Vec3 zAxis = newDir;
+			Vec3 yAxis = Vec3(0.0f, 1.0f, 0.0f);
+			Vec3 xAxis = yAxis.cross(zAxis);
+			yAxis = zAxis.cross(xAxis);
+
+			// printf("%f : %f %f\n", m_dir.m_hour, toDegrees(elevation), toDegrees(azimuth));
+
+			Mat3 rot;
+			rot.setXAxis(xAxis);
+			rot.setYAxis(yAxis);
+			rot.setZAxis(zAxis);
+
+			m_worldTransform.setRotation(rot);
+		}
 	}
 
 	m_shapeDirty = false;

+ 18 - 0
AnKi/Scene/Components/LightComponent.h

@@ -141,6 +141,15 @@ public:
 		return m_spot.m_viewMat;
 	}
 
+	/// Set the direction of the directional light by setting the date and hour.
+	void setDirectionFromTimeOfDay(I32 month, I32 day, F32 hour)
+	{
+		m_dir.m_month = month;
+		m_dir.m_day = day;
+		m_dir.m_hour = hour;
+		m_shapeDirty = true;
+	}
+
 	/// Calculate some matrices for each cascade. For dir lights.
 	/// @param cameraFrustum Who is looking at the light.
 	/// @param cascadeDistances The distances of the cascades.
@@ -183,8 +192,17 @@ private:
 		F32 m_innerAngle = toRad(15.0f);
 	};
 
+	class Dir
+	{
+	public:
+		I32 m_month = -1;
+		I32 m_day = -1;
+		F32 m_hour = -1.0;
+	};
+
 	Point m_point;
 	Spot m_spot;
+	Dir m_dir;
 
 	GpuSceneArrays::Light::Allocation m_gpuSceneLight;
 	GpuSceneArrays::LightVisibleRenderablesHash::Allocation m_hash;

+ 23 - 0
AnKi/Shaders/Functions.hlsl

@@ -945,3 +945,26 @@ TUv improvedLinearTextureFiltering(TUv uv, TUv texSize)
 	uv = (uv - 0.5) / texSize;
 	return uv;
 }
+
+template<typename T>
+T computeLuminance(vector<T, 3> color)
+{
+	return max(dot(vector<T, 3>(0.30, 0.59, 0.11), color), getEpsilon<T>());
+}
+
+template<typename T>
+vector<T, 3> rgb2ycbcr(vector<T, 3> rgb)
+{
+	const T y = computeLuminance(rgb);
+	const T cb = (rgb.b - y) * 0.565;
+	const T cr = (rgb.r - y) * 0.713;
+
+	return vector<T, 3>(y, cb, cr);
+}
+
+// YCbCr to RGB
+template<typename T>
+vector<T, 3> ycbcr2rgb(vector<T, 3> yuv)
+{
+	return vector<T, 3>(yuv.x + 1.403 * yuv.z, yuv.x - 0.344 * yuv.y - 0.714 * yuv.z, yuv.x + 1.770 * yuv.y);
+}

+ 2 - 2
AnKi/Shaders/IndirectDiffuseClipmaps.ankiprog

@@ -172,7 +172,7 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 		rayOrigin = biasedWorldPos;
 		rayDir2 = worldNormal;
 	}
-	const SampleClipmapFlag flags = kSampleClipmapFlagFullQuality & kSampleClipmapFlagBiasSamplePointSurfaceNormal;
+	const SampleClipmapFlag flags = kSampleClipmapFlagFullQuality | kSampleClipmapFlagBiasSamplePointSurfaceNormal;
 	const Vec3 irradiance =
 		sampleClipmapIrradiance(rayOrigin, rayDir2, g_globalRendererConstants.m_cameraPosition, g_globalRendererConstants.m_indirectDiffuseClipmaps,
 								g_linearAnyRepeatSampler, flags, randFactors.x);
@@ -270,7 +270,7 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 		Vec2 avgMoments = 0.0;
 		if(blendWithHistory)
 		{
-			const F32 blendFactor = 0.1;
+			const F16 blendFactor = 0.1;
 
 			const HVec3 prevValue = TEX(g_radianceVolume, actualVolumeTexCoord).xyz;
 			avgRadiance = lerp(prevValue, radiance, blendFactor);

+ 1 - 0
AnKi/Shaders/TonemappingAverageLuminance.ankiprog

@@ -6,6 +6,7 @@
 #pragma anki technique comp
 
 #include <AnKi/Shaders/TonemappingFunctions.hlsl>
+#include <AnKi/Shaders/Functions.hlsl>
 
 #define THREAD_COUNT_X 32u
 #define THREAD_COUNT_Y 16u

+ 0 - 6
AnKi/Shaders/TonemappingFunctions.hlsl

@@ -14,12 +14,6 @@ T log10(T x)
 	return log(x) / log(T(10));
 }
 
-template<typename T>
-T computeLuminance(vector<T, 3> color)
-{
-	return max(dot(vector<T, 3>(0.30, 0.59, 0.11), color), getEpsilon<T>());
-}
-
 template<typename T>
 T computeExposure(T avgLum, T threshold)
 {

+ 8 - 18
Samples/Common/SampleApp.cpp

@@ -83,26 +83,16 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "RtMaterialFetchDbg") ? "" : "RtMaterialFetchDbg");
 	}
 
-	if(in.getKey(KeyCode::kP) == 1)
+	static Bool timeOfDay = false;
+	if(in.getKey(KeyCode::kP) == 1 || timeOfDay)
 	{
-		static U32 idx = 3;
-		++idx;
-		idx %= 4;
-		if(idx == 0)
+		timeOfDay = true;
+		static F32 time = 8.0f;
+		scene.getDirectionalLight()->setDirectionFromTimeOfDay(6, 25, time);
+		time += 0.2f * F32(elapsedTime);
+		if(time > 19.0)
 		{
-			renderer.setCurrentDebugRenderTarget("IndirectDiffuseVrsSri");
-		}
-		else if(idx == 1)
-		{
-			renderer.setCurrentDebugRenderTarget("VrsSriDownscaled");
-		}
-		else if(idx == 2)
-		{
-			renderer.setCurrentDebugRenderTarget("VrsSri");
-		}
-		else
-		{
-			renderer.setCurrentDebugRenderTarget("");
+			time = 8.0f;
 		}
 	}