diff --git a/Config/GC/Callisto.atm.cfg b/Config/GC/Callisto.atm.cfg new file mode 100644 index 000000000..10d799014 --- /dev/null +++ b/Config/GC/Callisto.atm.cfg @@ -0,0 +1,70 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Moon +OrbitAlt = 250000 +AtmoVisualAlt = 70000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -8 +Srf_MPwr = -8 +Srf_Expo = 0.97077 +Srf_TGamma = 0.7447 +Srf_Tr3D = 1.0 +Srf_TWDst = 0 +Srf_Green = 0.56 +Srf_TWBri = 0 +Srf_RayO = 0 +Srf_RayI = 0.1 +Srf_TWBld = 0 +Srf_RayH = 3 +Srf_MieO = 0.01 +Srf_MieP = 0.02 +Srf_MieI = 0.01 +Srf_MieH = 0.2 +Srf_Aux2 = 0 +Srf_Aux3 = 0.01 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.001 +Low_RPwr = 4 +Low_MPwr = 1 +Low_Expo = 1 +Low_TGamma = 1 +Low_Tr3D = 1.0 +Low_TWDst = 0 +Low_Green = 0.56 +Low_TWBri = 0 +Low_RayO = 1 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 8 +Low_MieO = 0.0869 +Low_MieP = 0.9831 +Low_MieI = 1 +Low_MieH = 1 +Low_Aux2 = 0 +Low_Aux3 = 0 +Low_Aux4 = 1 +Low_Aux5 = 1.7 +Hig_RPwr = 4 +Hig_MPwr = 1 +Hig_Expo = 1 +Hig_TGamma = 1 +Hig_Tr3D = 1.0 +Hig_TWDst = 0 +Hig_Green = 0.56 +Hig_TWBri = 0 +Hig_RayO = 1 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 8 +Hig_MieO = 0.0869 +Hig_MieP = 0.9831 +Hig_MieI = 1 +Hig_MieH = 1 +Hig_Aux2 = 0 +Hig_Aux3 = 0 +Hig_Aux4 = 1 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Earth.atm.cfg b/Config/GC/Earth.atm.cfg new file mode 100644 index 000000000..41c506c80 --- /dev/null +++ b/Config/GC/Earth.atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Earth +Planet = Earth +ConfigName = Default +OrbitAlt = 250000 +AtmoVisualAlt = 90000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 1 0.6 +hcolor = 1 0.5 0.1 +acolor = 1 1 1 +Srf_RPwr = 3.968 +Srf_MPwr = -2.048 +Srf_Expo = 1.29544 +Srf_TGamma = 0.6446 +Srf_Tr3D = 1.5 +Srf_TWDst = 0.2 +Srf_Green = 0.5436 +Srf_TWBri = 0.727899 +Srf_RayO = 1.54449 +Srf_RayI = 0.532438 +Srf_TWBld = 0.240014 +Srf_RayH = 8.53045 +Srf_MieO = 0.413606 +Srf_MieP = 0.0368006 +Srf_MieI = 0.559127 +Srf_MieH = 1.01133 +Srf_Aux2 = 1.7092 +Srf_Aux3 = 0.59427 +Srf_Aux4 = 0 +Srf_Aux5 = 0.370602 +Low_RPwr = 3.968 +Low_MPwr = -2.048 +Low_Expo = 1.29544 +Low_TGamma = 0.6446 +Low_Tr3D = 1.5 +Low_TWDst = 0.057 +Low_Green = 0.5436 +Low_TWBri = 1.38446 +Low_RayO = 1.54449 +Low_RayI = 0.204104 +Low_TWBld = 0.240014 +Low_RayH = 8.53045 +Low_MieO = 0.413606 +Low_MieP = 0.0368006 +Low_MieI = 0.559127 +Low_MieH = 1.01133 +Low_Aux2 = 5.9918 +Low_Aux3 = 0.59427 +Low_Aux4 = 0 +Low_Aux5 = 0.30752 +Hig_RPwr = 3.968 +Hig_MPwr = -2.048 +Hig_Expo = 0.714944 +Hig_TGamma = 0.5536 +Hig_Tr3D = 1.5 +Hig_TWDst = 0.057 +Hig_Green = 0.5436 +Hig_TWBri = 1.38446 +Hig_RayO = 1.54449 +Hig_RayI = 0.204104 +Hig_TWBld = 0.240014 +Hig_RayH = 8.53045 +Hig_MieO = 0.413606 +Hig_MieP = 0.0368006 +Hig_MieI = 0.559127 +Hig_MieH = 1.01133 +Hig_Aux2 = 5.296 +Hig_Aux3 = 0.425732 +Hig_Aux4 = 0 +Hig_Aux5 = 0.370602 diff --git a/Config/GC/Earth.atmo.cfg b/Config/GC/Earth.atmo.cfg deleted file mode 100644 index 7dec7ec74..000000000 --- a/Config/GC/Earth.atmo.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6517 -Green = 0.55 -Blue = 0.4816 -RWaveDep = 4.08 -MWaveDep = 0 -ScaleHeight = 8.11965 -DepthClamp = 0.99875 -Exposure = 0.9185 -TGamma = 0.5976 -OutScatter = 0.6348 -InScatter = 1.7585 -RayleighPhase = -0.5085 -MiePower = 0.247808 -MiePhase = 0.924176 -Aux1 = 0.2406 -Aux2 = 0.044521 -Aux3 = 0.94 -AGamma = 0.7272 -HazeClr = 0.765 -HazeIts = 1.3912 diff --git a/Config/GC/Earth.atms.cfg b/Config/GC/Earth.atms.cfg deleted file mode 100644 index ca101f689..000000000 --- a/Config/GC/Earth.atms.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6517 -Green = 0.559 -Blue = 0.4804 -RWaveDep = 5.264 -MWaveDep = -0.912 -ScaleHeight = 8.11965 -DepthClamp = 0.99875 -Exposure = 1.1045 -TGamma = 1.0128 -OutScatter = 1.19448 -InScatter = 1.301 -RayleighPhase = -0.0345 -MiePower = 0.474338 -MiePhase = 0.962981 -Aux1 = 0.2355 -Aux2 = 0.112896 -Aux3 = 0 -AGamma = 0.7512 -HazeClr = 0.927 -HazeIts = 1.6376 diff --git a/Config/GC/Earth_A_atm.cfg b/Config/GC/Earth_A_atm.cfg new file mode 100644 index 000000000..331b06cbd --- /dev/null +++ b/Config/GC/Earth_A_atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Earth +Planet = Earth +ConfigName = 10_Ratio +OrbitAlt = 250000 +AtmoVisualAlt = 90000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 1 0.6 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = 3.968 +Srf_MPwr = -2.048 +Srf_Expo = 1.29544 +Srf_TGamma = 0.6446 +Srf_Tr3D = 1.5 +Srf_TWDst = 0.2 +Srf_Green = 0.53771 +Srf_TWBri = 2.6858 +Srf_RayO = 1.14921 +Srf_RayI = 1.04633 +Srf_TWBld = 0.458355 +Srf_RayH = 8.53045 +Srf_MieO = 0.787632 +Srf_MieP = 0.168143 +Srf_MieI = 0.826238 +Srf_MieH = 0.696992 +Srf_Aux2 = 1.3466 +Srf_Aux3 = 0.774918 +Srf_Aux4 = 1.768 +Srf_Aux5 = 0.435125 +Low_RPwr = 3.968 +Low_MPwr = -2.048 +Low_Expo = 0.441786 +Low_TGamma = 0.4795 +Low_Tr3D = 1.5 +Low_TWDst = 0.06528 +Low_Green = 0.5436 +Low_TWBri = 2.72554 +Low_RayO = 0.87025 +Low_RayI = 1.04633 +Low_TWBld = 0.842989 +Low_RayH = 8.53045 +Low_MieO = 1.34822 +Low_MieP = 0.0496402 +Low_MieI = 0.960954 +Low_MieH = 1.18233 +Low_Aux2 = 8.089 +Low_Aux3 = 1.65283 +Low_Aux4 = 0.808 +Low_Aux5 = 0.17672 +Hig_RPwr = 3.968 +Hig_MPwr = -2.048 +Hig_Expo = 0.33918 +Hig_TGamma = 0.4002 +Hig_Tr3D = 1.5 +Hig_TWDst = 0.06528 +Hig_Green = 0.5436 +Hig_TWBri = 2.72554 +Hig_RayO = 0.87025 +Hig_RayI = 1.04633 +Hig_TWBld = 0.842989 +Hig_RayH = 8.53045 +Hig_MieO = 1.34822 +Hig_MieP = 0.0496402 +Hig_MieI = 0.960954 +Hig_MieH = 1.18233 +Hig_Aux2 = 8.089 +Hig_Aux3 = 1.65283 +Hig_Aux4 = 0.808 +Hig_Aux5 = 0.17672 diff --git a/Config/GC/Earth_B_atm.cfg b/Config/GC/Earth_B_atm.cfg new file mode 100644 index 000000000..04d07a78e --- /dev/null +++ b/Config/GC/Earth_B_atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Earth +Planet = Earth +ConfigName = Hazy +OrbitAlt = 250000 +AtmoVisualAlt = 90000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 1 0.6 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = 3.968 +Srf_MPwr = -1.504 +Srf_Expo = 1.81553 +Srf_TGamma = 0.4483 +Srf_Tr3D = 1.5 +Srf_TWDst = 0.1772 +Srf_Green = 0.53771 +Srf_TWBri = 0.748557 +Srf_RayO = 2.88369 +Srf_RayI = 0.39683 +Srf_TWBld = 0.101249 +Srf_RayH = 8.53045 +Srf_MieO = 0.595054 +Srf_MieP = 0.0557149 +Srf_MieI = 0.201029 +Srf_MieH = 1.02464 +Srf_Aux2 = 1.3466 +Srf_Aux3 = 0.774918 +Srf_Aux4 = 0.616 +Srf_Aux5 = 0.644405 +Low_RPwr = 3.968 +Low_MPwr = -2.048 +Low_Expo = 1.58116 +Low_TGamma = 0.4483 +Low_Tr3D = 1.5 +Low_TWDst = 0.061 +Low_Green = 0.53771 +Low_TWBri = 1.82445 +Low_RayO = 1.98916 +Low_RayI = 0.223671 +Low_TWBld = 0.842989 +Low_RayH = 8.53045 +Low_MieO = 0.561698 +Low_MieP = 0.168143 +Low_MieI = 0.201029 +Low_MieH = 1.34931 +Low_Aux2 = 5.7272 +Low_Aux3 = 0.448664 +Low_Aux4 = 0 +Low_Aux5 = 0.231125 +Hig_RPwr = 3.968 +Hig_MPwr = -2.048 +Hig_Expo = 1.04576 +Hig_TGamma = 0.4483 +Hig_Tr3D = 1.5 +Hig_TWDst = 0.0872 +Hig_Green = 0.53771 +Hig_TWBri = 1.82445 +Hig_RayO = 1.98916 +Hig_RayI = 0.223671 +Hig_TWBld = 0.842989 +Hig_RayH = 8.53045 +Hig_MieO = 0.561698 +Hig_MieP = 0.168143 +Hig_MieI = 0.201029 +Hig_MieH = 1.34931 +Hig_Aux2 = 5.7272 +Hig_Aux3 = 0.448664 +Hig_Aux4 = 0 +Hig_Aux5 = 0.231125 diff --git a/Config/GC/Enceladus.atm.cfg b/Config/GC/Enceladus.atm.cfg new file mode 100644 index 000000000..3053efc35 --- /dev/null +++ b/Config/GC/Enceladus.atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Moon +Planet = Enceladus +ConfigName = Custom +OrbitAlt = 250000 +AtmoVisualAlt = 70000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -8 +Srf_MPwr = -8 +Srf_Expo = 0.714944 +Srf_TGamma = 1.0021 +Srf_Tr3D = 1.0 +Srf_TWDst = 0 +Srf_Green = 0.56 +Srf_TWBri = 0 +Srf_RayO = 0 +Srf_RayI = 0.1 +Srf_TWBld = 0 +Srf_RayH = 3 +Srf_MieO = 0.01 +Srf_MieP = 0.02 +Srf_MieI = 0.01 +Srf_MieH = 0.2 +Srf_Aux2 = 0 +Srf_Aux3 = 0.01 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.001 +Low_RPwr = 4 +Low_MPwr = 1 +Low_Expo = 1 +Low_TGamma = 1 +Low_Tr3D = 1.0 +Low_TWDst = 0 +Low_Green = 0.56 +Low_TWBri = 0 +Low_RayO = 1 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 8 +Low_MieO = 0.0869 +Low_MieP = 0.9831 +Low_MieI = 1 +Low_MieH = 1 +Low_Aux2 = 0 +Low_Aux3 = 0 +Low_Aux4 = 1 +Low_Aux5 = 1.7 +Hig_RPwr = 4 +Hig_MPwr = 1 +Hig_Expo = 1 +Hig_TGamma = 1 +Hig_Tr3D = 1.0 +Hig_TWDst = 0 +Hig_Green = 0.56 +Hig_TWBri = 0 +Hig_RayO = 1 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 8 +Hig_MieO = 0.0869 +Hig_MieP = 0.9831 +Hig_MieI = 1 +Hig_MieH = 1 +Hig_Aux2 = 0 +Hig_Aux3 = 0 +Hig_Aux4 = 1 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Europa.atm.cfg b/Config/GC/Europa.atm.cfg new file mode 100644 index 000000000..1658a1d28 --- /dev/null +++ b/Config/GC/Europa.atm.cfg @@ -0,0 +1,70 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Moon +OrbitAlt = 250000 +AtmoVisualAlt = 70000 +Red = 0.65 +Blue = 0.48 +SunI = 10 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -8 +Srf_MPwr = -8 +Srf_Expo = 0.697438 +Srf_TGamma = 0.6979 +Srf_Tr3D = 1.0 +Srf_TWDst = 0 +Srf_Green = 0.56 +Srf_TWBri = 0 +Srf_RayO = 0 +Srf_RayI = 0.1 +Srf_TWBld = 0 +Srf_RayH = 3 +Srf_MieO = 0.01 +Srf_MieP = 0.02 +Srf_MieI = 0.01 +Srf_MieH = 0.2 +Srf_Aux2 = 0 +Srf_Aux3 = 0.01 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.001 +Low_RPwr = 4 +Low_MPwr = 1 +Low_Expo = 1 +Low_TGamma = 1 +Low_Tr3D = 1.0 +Low_TWDst = 0 +Low_Green = 0.56 +Low_TWBri = 0 +Low_RayO = 1 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 8 +Low_MieO = 0.0869 +Low_MieP = 0.9831 +Low_MieI = 1 +Low_MieH = 1 +Low_Aux2 = 0 +Low_Aux3 = 0 +Low_Aux4 = 1 +Low_Aux5 = 1.7 +Hig_RPwr = 4 +Hig_MPwr = 1 +Hig_Expo = 1 +Hig_TGamma = 1 +Hig_Tr3D = 1.0 +Hig_TWDst = 0 +Hig_Green = 0.56 +Hig_TWBri = 0 +Hig_RayO = 1 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 8 +Hig_MieO = 0.0869 +Hig_MieP = 0.9831 +Hig_MieI = 1 +Hig_MieH = 1 +Hig_Aux2 = 0 +Hig_Aux3 = 0 +Hig_Aux4 = 1 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Ganymede.atm.cfg b/Config/GC/Ganymede.atm.cfg new file mode 100644 index 000000000..355b16d46 --- /dev/null +++ b/Config/GC/Ganymede.atm.cfg @@ -0,0 +1,70 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Moon +OrbitAlt = 250000 +AtmoVisualAlt = 70000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -8 +Srf_MPwr = -8 +Srf_Expo = 1.67144 +Srf_TGamma = 0.6238 +Srf_Tr3D = 1.0 +Srf_TWDst = 0 +Srf_Green = 0.56 +Srf_TWBri = 0 +Srf_RayO = 0 +Srf_RayI = 0.1 +Srf_TWBld = 0 +Srf_RayH = 3 +Srf_MieO = 0.01 +Srf_MieP = 0.02 +Srf_MieI = 0.01 +Srf_MieH = 0.2 +Srf_Aux2 = 0 +Srf_Aux3 = 0.01 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.001 +Low_RPwr = 4 +Low_MPwr = 1 +Low_Expo = 1 +Low_TGamma = 1 +Low_Tr3D = 1.0 +Low_TWDst = 0 +Low_Green = 0.56 +Low_TWBri = 0 +Low_RayO = 1 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 8 +Low_MieO = 0.0869 +Low_MieP = 0.9831 +Low_MieI = 1 +Low_MieH = 1 +Low_Aux2 = 0 +Low_Aux3 = 0 +Low_Aux4 = 1 +Low_Aux5 = 1.7 +Hig_RPwr = 4 +Hig_MPwr = 1 +Hig_Expo = 1 +Hig_TGamma = 1 +Hig_Tr3D = 1.0 +Hig_TWDst = 0 +Hig_Green = 0.56 +Hig_TWBri = 0 +Hig_RayO = 1 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 8 +Hig_MieO = 0.0869 +Hig_MieP = 0.9831 +Hig_MieI = 1 +Hig_MieH = 1 +Hig_Aux2 = 0 +Hig_Aux3 = 0 +Hig_Aux4 = 1 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Io.atm.cfg b/Config/GC/Io.atm.cfg new file mode 100644 index 000000000..83b5dcf36 --- /dev/null +++ b/Config/GC/Io.atm.cfg @@ -0,0 +1,70 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Mars +OrbitAlt = 250000 +AtmoVisualAlt = 25000 +Red = 0.65 +Blue = 0.48 +SunI = 10 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -2.464 +Srf_MPwr = -3.376 +Srf_Expo = 0.654778 +Srf_TGamma = 0.85 +Srf_Tr3D = 1.0 +Srf_TWDst = 0.025 +Srf_Green = 0.56 +Srf_TWBri = 0.01 +Srf_RayO = 0.08281 +Srf_RayI = 1 +Srf_TWBld = 0 +Srf_RayH = 6 +Srf_MieO = 0.302118 +Srf_MieP = 0.725664 +Srf_MieI = 1 +Srf_MieH = 0.680918 +Srf_Aux2 = 0 +Srf_Aux3 = 1.04789 +Srf_Aux4 = 0 +Srf_Aux5 = 1.7 +Low_RPwr = -2.464 +Low_MPwr = -3.376 +Low_Expo = 0.654778 +Low_TGamma = 0.85 +Low_Tr3D = 1.0 +Low_TWDst = 0.025 +Low_Green = 0.56 +Low_TWBri = 0.01 +Low_RayO = 0.08281 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 6 +Low_MieO = 0.302118 +Low_MieP = 0.725664 +Low_MieI = 1 +Low_MieH = 0.680918 +Low_Aux2 = 0 +Low_Aux3 = 1.04789 +Low_Aux4 = 0 +Low_Aux5 = 1.7 +Hig_RPwr = -2.464 +Hig_MPwr = -3.376 +Hig_Expo = 1.58116 +Hig_TGamma = 0.4353 +Hig_Tr3D = 1.0 +Hig_TWDst = 0.025 +Hig_Green = 0.56 +Hig_TWBri = 0.01 +Hig_RayO = 0.07056 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 6 +Hig_MieO = 0.674974 +Hig_MieP = 0.725664 +Hig_MieI = 1 +Hig_MieH = 0.680918 +Hig_Aux2 = 0 +Hig_Aux3 = 1.04789 +Hig_Aux4 = 0 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Jupiter.atm.cfg b/Config/GC/Jupiter.atm.cfg new file mode 100644 index 000000000..76ccb5633 --- /dev/null +++ b/Config/GC/Jupiter.atm.cfg @@ -0,0 +1,70 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Giant +OrbitAlt = 1.5e+06 +AtmoVisualAlt = 1.5e+06 +Red = 0.65 +Blue = 0.48 +SunI = 5 +zcolor = 1 1 1 +hcolor = 1 1 1 +acolor = 1 1 1 +Srf_RPwr = -3.328 +Srf_MPwr = -2.464 +Srf_Expo = 1.93047 +Srf_TGamma = 0.3872 +Srf_Tr3D = 1.0 +Srf_TWDst = 0.025 +Srf_Green = 0.56 +Srf_TWBri = 0.01 +Srf_RayO = 0.0790142 +Srf_RayI = 0.254214 +Srf_TWBld = 0 +Srf_RayH = 145.835 +Srf_MieO = 0.05 +Srf_MieP = 0.742385 +Srf_MieI = 0.0407237 +Srf_MieH = 0.5 +Srf_Aux2 = 0.533 +Srf_Aux3 = 1.02496 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.01 +Low_RPwr = -3.328 +Low_MPwr = -2.464 +Low_Expo = 1.93047 +Low_TGamma = 0.3872 +Low_Tr3D = 1.0 +Low_TWDst = 0.025 +Low_Green = 0.56 +Low_TWBri = 0.01 +Low_RayO = 0.0790142 +Low_RayI = 0.254214 +Low_TWBld = 0 +Low_RayH = 145.835 +Low_MieO = 0.05 +Low_MieP = 0.742385 +Low_MieI = 0.0407237 +Low_MieH = 0.5 +Low_Aux2 = 0.533 +Low_Aux3 = 1.02496 +Low_Aux4 = 0.02 +Low_Aux5 = 0.01 +Hig_RPwr = -3.328 +Hig_MPwr = -2.464 +Hig_Expo = 1.93047 +Hig_TGamma = 0.3872 +Hig_Tr3D = 1.0 +Hig_TWDst = 0.025 +Hig_Green = 0.56 +Hig_TWBri = 0.01 +Hig_RayO = 0.0790142 +Hig_RayI = 0.254214 +Hig_TWBld = 0 +Hig_RayH = 145.835 +Hig_MieO = 0.05 +Hig_MieP = 0.742385 +Hig_MieI = 0.0407237 +Hig_MieH = 0.5 +Hig_Aux2 = 0.533 +Hig_Aux3 = 1.02496 +Hig_Aux4 = 0.02 +Hig_Aux5 = 0.01 diff --git a/Config/GC/Jupiter.atmo.cfg b/Config/GC/Jupiter.atmo.cfg deleted file mode 100644 index 505b23f6b..000000000 --- a/Config/GC/Jupiter.atmo.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6445 -Green = 0.5923 -Blue = 0.48 -RWaveDep = -3.968 -MWaveDep = 3.12 -ScaleHeight = 400 -DepthClamp = 0.73875 -Exposure = 0.5 -TGamma = 0.3 -OutScatter = 0.386643 -InScatter = 2 -RayleighPhase = -0.0255 -MiePower = 0.039762 -MiePhase = 0.982284 -Aux1 = 0.3 -Aux2 = 1 -Aux3 = 0.92 -AGamma = 0.7392 -HazeClr = -0.492 -HazeIts = 1.5249 diff --git a/Config/GC/Jupiter.atms.cfg b/Config/GC/Jupiter.atms.cfg deleted file mode 100644 index 3d8ff58a9..000000000 --- a/Config/GC/Jupiter.atms.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6445 -Green = 0.5923 -Blue = 0.48 -RWaveDep = -1.504 -MWaveDep = 3.12 -ScaleHeight = 400 -DepthClamp = 0.7 -Exposure = 1.079 -TGamma = 0.9888 -OutScatter = 0.109443 -InScatter = 0.9575 -RayleighPhase = -0.513 -MiePower = 0.026 -MiePhase = 0.977707 -Aux1 = 0.3 -Aux2 = 1 -Aux3 = 0.718 -AGamma = 0.7464 -HazeClr = 0 -HazeIts = 1.4451 diff --git a/Config/GC/Mars.atm.cfg b/Config/GC/Mars.atm.cfg new file mode 100644 index 000000000..6a428b758 --- /dev/null +++ b/Config/GC/Mars.atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Mars +Planet = Mars +ConfigName = Custom +OrbitAlt = 150000 +AtmoVisualAlt = 120000 +Red = 0.65 +Blue = 0.48 +SunI = 20 +zcolor = 0.7 0.7 1 +hcolor = 0.7 0.7 1 +acolor = 1 0.9 0.8 +Srf_RPwr = -1.28 +Srf_MPwr = 4.02 +Srf_Expo = 0.834897 +Srf_TGamma = 0.6468 +Srf_Tr3D = 1.5056 +Srf_TWDst = 0.0618 +Srf_Green = 0.56 +Srf_TWBri = 3 +Srf_RayO = 1.33956 +Srf_RayI = 1.01035 +Srf_TWBld = 0.183805 +Srf_RayH = 7.15023 +Srf_MieO = 0.18938 +Srf_MieP = 0.0821704 +Srf_MieI = 1.11632 +Srf_MieH = 2.12041 +Srf_Aux2 = 0.2 +Srf_Aux3 = 1.04789 +Srf_Aux4 = 0 +Srf_Aux5 = 0.01 +Low_RPwr = -2.096 +Low_MPwr = -4.128 +Low_Expo = 1.21687 +Low_TGamma = 0.5887 +Low_Tr3D = 1.5536 +Low_TWDst = 0.01 +Low_Green = 0.56 +Low_TWBri = 0.01 +Low_RayO = 0.07569 +Low_RayI = 1.07812 +Low_TWBld = 0 +Low_RayH = 8.65567 +Low_MieO = 0.25939 +Low_MieP = 0.608012 +Low_MieI = 1.11632 +Low_MieH = 6.98162 +Low_Aux2 = 0.2 +Low_Aux3 = 1.04789 +Low_Aux4 = 0 +Low_Aux5 = 0.00927272 +Hig_RPwr = -2.096 +Hig_MPwr = -3.216 +Hig_Expo = 1.21687 +Hig_TGamma = 0.5887 +Hig_Tr3D = 1.52 +Hig_TWDst = 0.01 +Hig_Green = 0.56 +Hig_TWBri = 0.01 +Hig_RayO = 0.04096 +Hig_RayI = 1.07812 +Hig_TWBld = 0 +Hig_RayH = 8.65567 +Hig_MieO = 0.25939 +Hig_MieP = 0.764416 +Hig_MieI = 1.11632 +Hig_MieH = 6.98162 +Hig_Aux2 = 0.2 +Hig_Aux3 = 1.04789 +Hig_Aux4 = 0 +Hig_Aux5 = 0.00927272 diff --git a/Config/GC/Mars.atmo.cfg b/Config/GC/Mars.atmo.cfg deleted file mode 100644 index 83d428ef6..000000000 --- a/Config/GC/Mars.atmo.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6517 -Green = 0.55 -Blue = 0.4816 -RWaveDep = -1.296 -MWaveDep = 1.024 -ScaleHeight = 10.2529 -DepthClamp = 0.141 -Exposure = 1.16 -TGamma = 0.63 -OutScatter = 0.074892 -InScatter = 0.998 -RayleighPhase = -0.201 -MiePower = 0.014112 -MiePhase = 0.953628 -Aux1 = 0.3 -Aux2 = 0.414736 -Aux3 = 0.954 -AGamma = 1 -HazeClr = 0 -HazeIts = 1.3723 diff --git a/Config/GC/Mars.atms.cfg b/Config/GC/Mars.atms.cfg deleted file mode 100644 index bfd714d37..000000000 --- a/Config/GC/Mars.atms.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6517 -Green = 0.5581 -Blue = 0.4804 -RWaveDep = -2.624 -MWaveDep = 4.192 -ScaleHeight = 10.2529 -DepthClamp = 0.0885 -Exposure = 1.019 -TGamma = 0.7272 -OutScatter = 0.401868 -InScatter = 1.0085 -RayleighPhase = 0.0105 -MiePower = 0.060552 -MiePhase = 0.938305 -Aux1 = 0.3 -Aux2 = 1 -Aux3 = 0 -AGamma = 1 -HazeClr = 0 -HazeIts = 1.7 diff --git a/Config/GC/Mercury.atm.cfg b/Config/GC/Mercury.atm.cfg new file mode 100644 index 000000000..d1182b5d6 --- /dev/null +++ b/Config/GC/Mercury.atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Moon +Planet = Mercury +ConfigName = Custom +OrbitAlt = 250000 +AtmoVisualAlt = 70000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -8 +Srf_MPwr = -8 +Srf_Expo = 0.759816 +Srf_TGamma = 0.8461 +Srf_Tr3D = 1.0 +Srf_TWDst = 0 +Srf_Green = 0.56 +Srf_TWBri = 0 +Srf_RayO = 0 +Srf_RayI = 0.1 +Srf_TWBld = 0 +Srf_RayH = 3 +Srf_MieO = 0.01 +Srf_MieP = 0.02 +Srf_MieI = 0.01 +Srf_MieH = 0.2 +Srf_Aux2 = 0 +Srf_Aux3 = 0.01 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.001 +Low_RPwr = 4 +Low_MPwr = 1 +Low_Expo = 1 +Low_TGamma = 1 +Low_Tr3D = 1.0 +Low_TWDst = 0 +Low_Green = 0.56 +Low_TWBri = 0 +Low_RayO = 1 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 8 +Low_MieO = 0.0869 +Low_MieP = 0.9831 +Low_MieI = 1 +Low_MieH = 1 +Low_Aux2 = 0 +Low_Aux3 = 0 +Low_Aux4 = 1 +Low_Aux5 = 1.7 +Hig_RPwr = 4 +Hig_MPwr = 1 +Hig_Expo = 1 +Hig_TGamma = 1 +Hig_Tr3D = 1.0 +Hig_TWDst = 0 +Hig_Green = 0.56 +Hig_TWBri = 0 +Hig_RayO = 1 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 8 +Hig_MieO = 0.0869 +Hig_MieP = 0.9831 +Hig_MieI = 1 +Hig_MieH = 1 +Hig_Aux2 = 0 +Hig_Aux3 = 0 +Hig_Aux4 = 1 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Moon.atm.cfg b/Config/GC/Moon.atm.cfg new file mode 100644 index 000000000..a8c7acdcd --- /dev/null +++ b/Config/GC/Moon.atm.cfg @@ -0,0 +1,70 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Moon +OrbitAlt = 250000 +AtmoVisualAlt = 70000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -8 +Srf_MPwr = -8 +Srf_Expo = 0.991878 +Srf_TGamma = 0.4812 +Srf_Tr3D = 1.0 +Srf_TWDst = 0 +Srf_Green = 0.56 +Srf_TWBri = 0 +Srf_RayO = 0 +Srf_RayI = 0.1 +Srf_TWBld = 0 +Srf_RayH = 3 +Srf_MieO = 0.01 +Srf_MieP = 0.02 +Srf_MieI = 0.01 +Srf_MieH = 0.2 +Srf_Aux2 = 0 +Srf_Aux3 = 0.01 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.001 +Low_RPwr = 4 +Low_MPwr = 1 +Low_Expo = 1 +Low_TGamma = 1 +Low_Tr3D = 1.0 +Low_TWDst = 0 +Low_Green = 0.56 +Low_TWBri = 0 +Low_RayO = 1 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 8 +Low_MieO = 0.0869 +Low_MieP = 0.9831 +Low_MieI = 1 +Low_MieH = 1 +Low_Aux2 = 0 +Low_Aux3 = 0 +Low_Aux4 = 1 +Low_Aux5 = 1.7 +Hig_RPwr = 4 +Hig_MPwr = 1 +Hig_Expo = 1 +Hig_TGamma = 1 +Hig_Tr3D = 1.0 +Hig_TWDst = 0 +Hig_Green = 0.56 +Hig_TWBri = 0 +Hig_RayO = 1 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 8 +Hig_MieO = 0.0869 +Hig_MieP = 0.9831 +Hig_MieI = 1 +Hig_MieH = 1 +Hig_Aux2 = 0 +Hig_Aux3 = 0 +Hig_Aux4 = 1 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Moon.atmo.cfg b/Config/GC/Moon.atmo.cfg deleted file mode 100644 index 6e604d4ed..000000000 --- a/Config/GC/Moon.atmo.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.65 -Green = 0.5 -Blue = 0.48 -RWaveDep = 4 -MWaveDep = 1 -ScaleHeight = 8 -DepthClamp = 1 -Exposure = 1 -TGamma = 1 -OutScatter = 0.592 -InScatter = 1 -RayleighPhase = 0.3395 -MiePower = 0.0869 -MiePhase = 0.9831 -Aux1 = 0 -Aux2 = 0 -Aux3 = 0 -AGamma = 1 -HazeClr = 0 -HazeIts = 1.7 diff --git a/Config/GC/Moon.atms.cfg b/Config/GC/Moon.atms.cfg deleted file mode 100644 index a15e0e3f3..000000000 --- a/Config/GC/Moon.atms.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.65 -Green = 0.5 -Blue = 0.48 -RWaveDep = 4 -MWaveDep = 1 -ScaleHeight = 8 -DepthClamp = 0.0042 -Exposure = 1.004 -TGamma = 0.606 -OutScatter = 0.592 -InScatter = 1 -RayleighPhase = 0.3395 -MiePower = 0.0869 -MiePhase = 0.9831 -Aux1 = 0 -Aux2 = 0 -Aux3 = 0 -AGamma = 1 -HazeClr = 0 -HazeIts = 1.7 diff --git a/Config/GC/Phobos.atm.cfg b/Config/GC/Phobos.atm.cfg new file mode 100644 index 000000000..563444b9e --- /dev/null +++ b/Config/GC/Phobos.atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Moon +Planet = Phobos +ConfigName = Custom +OrbitAlt = 250000 +AtmoVisualAlt = 70000 +Red = 0.65 +Blue = 0.48 +SunI = 30 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = -8 +Srf_MPwr = -8 +Srf_Expo = 0.759816 +Srf_TGamma = 0.8461 +Srf_Tr3D = 0.5 +Srf_TWDst = 0 +Srf_Green = 0.56 +Srf_TWBri = 0 +Srf_RayO = 0 +Srf_RayI = 0.1 +Srf_TWBld = 0 +Srf_RayH = 3 +Srf_MieO = 0.01 +Srf_MieP = 0.02 +Srf_MieI = 0.01 +Srf_MieH = 0.2 +Srf_Aux2 = 0 +Srf_Aux3 = 0.01 +Srf_Aux4 = 0.02 +Srf_Aux5 = 0.001 +Low_RPwr = 4 +Low_MPwr = 1 +Low_Expo = 1 +Low_TGamma = 1 +Low_Tr3D = 0.5 +Low_TWDst = 0 +Low_Green = 0.56 +Low_TWBri = 0 +Low_RayO = 1 +Low_RayI = 1 +Low_TWBld = 0 +Low_RayH = 8 +Low_MieO = 0.0869 +Low_MieP = 0.9831 +Low_MieI = 1 +Low_MieH = 1 +Low_Aux2 = 0 +Low_Aux3 = 0 +Low_Aux4 = 1 +Low_Aux5 = 1.7 +Hig_RPwr = 4 +Hig_MPwr = 1 +Hig_Expo = 1 +Hig_TGamma = 1 +Hig_Tr3D = 0.5 +Hig_TWDst = 0 +Hig_Green = 0.56 +Hig_TWBri = 0 +Hig_RayO = 1 +Hig_RayI = 1 +Hig_TWBld = 0 +Hig_RayH = 8 +Hig_MieO = 0.0869 +Hig_MieP = 0.9831 +Hig_MieI = 1 +Hig_MieH = 1 +Hig_Aux2 = 0 +Hig_Aux3 = 0 +Hig_Aux4 = 1 +Hig_Aux5 = 1.7 diff --git a/Config/GC/Titan.atm.cfg b/Config/GC/Titan.atm.cfg new file mode 100644 index 000000000..226b06da9 --- /dev/null +++ b/Config/GC/Titan.atm.cfg @@ -0,0 +1,72 @@ +; = Shader(s) = [Earth, Mars, Moon, Giant, Auto] +Shader = Mars +Planet = Titan +ConfigName = Custom +OrbitAlt = 600000 +AtmoVisualAlt = 150000 +Red = 0.65 +Blue = 0.48 +SunI = 10 +zcolor = 1 0.7 0.15 +hcolor = 1 0.5 0.1 +acolor = 0.9 0.9 1 +Srf_RPwr = 6.76 +Srf_MPwr = 11.66 +Srf_Expo = 1.89748 +Srf_TGamma = 1.0073 +Srf_Tr3D = 1.0 +Srf_TWDst = 0.1114 +Srf_Green = 0.56 +Srf_TWBri = 3 +Srf_RayO = 0.22801 +Srf_RayI = 0.995287 +Srf_TWBld = 0 +Srf_RayH = 24.0468 +Srf_MieO = 0.01 +Srf_MieP = 0.0486269 +Srf_MieI = 3.33531 +Srf_MieH = 8.07577 +Srf_Aux2 = 10 +Srf_Aux3 = 0.681084 +Srf_Aux4 = 0.992 +Srf_Aux5 = 0 +Low_RPwr = 6.76 +Low_MPwr = 6.96 +Low_Expo = 1.89748 +Low_TGamma = 1.0073 +Low_Tr3D = 1.0 +Low_TWDst = 0.1652 +Low_Green = 0.56 +Low_TWBri = 1.39665 +Low_RayO = 0.22801 +Low_RayI = 0.620375 +Low_TWBld = 0.01 +Low_RayH = 39.0904 +Low_MieO = 2.17939 +Low_MieP = 0.0486269 +Low_MieI = 0.590307 +Low_MieH = 8.07577 +Low_Aux2 = 10 +Low_Aux3 = 0.681084 +Low_Aux4 = 0.992 +Low_Aux5 = 0 +Hig_RPwr = 6.76 +Hig_MPwr = 6.96 +Hig_Expo = 1.89748 +Hig_TGamma = 1.0073 +Hig_Tr3D = 1.0 +Hig_TWDst = 0.1276 +Hig_Green = 0.56 +Hig_TWBri = 1.39665 +Hig_RayO = 0.22801 +Hig_RayI = 0.620375 +Hig_TWBld = 0.01 +Hig_RayH = 55.8675 +Hig_MieO = 2.17939 +Hig_MieP = 0.0486269 +Hig_MieI = 0.590307 +Hig_MieH = 8.07577 +Hig_Aux2 = 10 +Hig_Aux3 = 0.681084 +Hig_Aux4 = 0.992 +Hig_Aux5 = 0 diff --git a/Config/GC/Titan.atmo.cfg b/Config/GC/Titan.atmo.cfg deleted file mode 100644 index 260515dfd..000000000 --- a/Config/GC/Titan.atmo.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6517 -Green = 0.55 -Blue = 0.4816 -RWaveDep = 1.552 -MWaveDep = 8 -ScaleHeight = 30.586 -DepthClamp = 0.72625 -Exposure = 0.9635 -TGamma = 0.864 -OutScatter = 0.324723 -InScatter = 0.827 -RayleighPhase = 0.75 -MiePower = 0.063368 -MiePhase = 0.975717 -Aux1 = 0.2055 -Aux2 = 0.073984 -Aux3 = 0 -AGamma = 0.7512 -HazeClr = 0 -HazeIts = 1.5865 diff --git a/Config/GC/Titan.atms.cfg b/Config/GC/Titan.atms.cfg deleted file mode 100644 index 7a7c38be6..000000000 --- a/Config/GC/Titan.atms.cfg +++ /dev/null @@ -1,20 +0,0 @@ -Red = 0.6517 -Green = 0.55 -Blue = 0.4816 -RWaveDep = -6.448 -MWaveDep = 8 -ScaleHeight = 30.586 -DepthClamp = 0.17625 -Exposure = 1.1495 -TGamma = 0.8964 -OutScatter = 0.034347 -InScatter = 1.169 -RayleighPhase = 0.75 -MiePower = 0.038088 -MiePhase = 0.939499 -Aux1 = 0.2145 -Aux2 = 0.1936 -Aux3 = 0 -AGamma = 0.7308 -HazeClr = -0.534 -HazeIts = 1.6124 diff --git a/D3D9Client.cfg b/D3D9Client.cfg deleted file mode 100644 index a72f4356a..000000000 --- a/D3D9Client.cfg +++ /dev/null @@ -1,65 +0,0 @@ -FrameRate = 200 -EnableLimiter = 0 -CustomCamMode = 1 -PlanetPreloadMode = 0 -PlanetTexLoadFreq = 20 -Anisotrophy = 4 -SceneAntialias = 4 -SketchpadFont = 1 -PreLoadBaseVisuals = 0 -EnableNormalMapping = 1 -NearClipPlaneMode = 0 -RwyLightAnimate = 1 -RwyLightAngle = 120 -RwyBrightness = 1 -NightLightsAngle = 10 -BumpMapAmplitude = 1 -PlanetGlow = 1 -EnvMapSize = 256 -EnvMapMode = 1 -EnvMapFaces = 1 -ShadowMapMode = 1 -ShadowMapFilter = 2 -ShadowMapSize = 2048 -TerrainShadowing = 2 -EnableGlass = 1 -EnableMeshDbg = 1 -TileMipmaps = 0 -TextureMips = 1 -TileDebug = 0 -StereoSeparation = 65 -StereoConvergence = 0.2 -DebugLvl = 1 -VCNearPlane = 0.1 -LightConfiguration = 2 -DisableDrvMgm = 0 -NVPerfHUD = 0 -DebugLineFontSize = 18 -DisableVisualHelperReadout = 0 -LODBias = 0 -MeshRes = 1 -MicroMode = 1 -MicroFilter = 2 -BlendMode = 1 -MicroBias = 3 -CloudMicro = 1 -PostProcess = 1 -ShaderDebug = 0 -PresentLocation = 1 -PlanetTileLoadFlags = 3 -LabelDisplayFlags = 3 -GDIOverlay = 0 -gcGUIMode = 2 -AbsoluteAnimations = 0 -NormalmappedClouds = 1 -TerrainFlats = 0 -DebugBreak = 0 -OrbitalShadowMult = 0.85 -GFXIntensity = 0.5 -GFXDistance = 0.8 -GFXThreshold = 1.1 -GFXGamma = 1 -GFXSunIntensity = 1.2 -GFXLocalMax = 0.5 -SolCfg = Sol -DebugLineFont = Fixed diff --git a/OVP/D3D9Client/AABBUtil.cpp b/OVP/D3D9Client/AABBUtil.cpp index 489cd3153..218a369fb 100644 --- a/OVP/D3D9Client/AABBUtil.cpp +++ b/OVP/D3D9Client/AABBUtil.cpp @@ -417,246 +417,3 @@ void EnvMapDirection(int dir, D3DXVECTOR3 *Dir, D3DXVECTOR3 *Up) break; } } - - -// ======================================================================= -// Compute an optical depth of a ray through an atmosphere to infinity -// alt = starting altitude of the ray above planet surface [m] -// dir = ray direction [rad] (zero = up) -// R = Planet Radius [m] -// R1 = Atmosphere Outer Radius [m] -// h0 = Atmospheric Scale Height [m] -// ======================================================================= - -double ExactOpticalDepth(double alt, double dir, double R, double R1, double h0) -{ - double delta = 0.2 * PI / 180.0; - double r0 = R + alt; - double h0ln = h0; // /log(2.0); - - if (dir<(delta*2.0)) return h0ln * exp2(-(r0-R)/h0) / cos(dir); - - dir = PI - dir; - - double m0 = r0 / sin(PI-dir-delta); - - if (m0*sin(dir)>R1) return h0ln * exp2(-(r0-R)/h0) / cos(PI-dir); - - double opt = 0.0; - double sind = sin(delta); - - while (r00.2) LogErr("Bad Match %g", dv); - - return fct; -} - - -bool SolveXScatter(double h0, double R, double R1, double *r, double angle, int m) -{ - double delta = angle / 50.0; - double x[50]; x[0]=0.0; for (int i=1;i<50;i++) x[i] = x[i-1] + delta; - - int ndata = sizeof(x)/sizeof(double); - - double *v = new double[m]; - double *q = new double[m]; - double *M = new double[m*m]; - double *y = new double[ndata]; - - memset(M, 0, m*m*sizeof(double)); - memset(q, 0, m*sizeof(double)); - - double ih0 = 1.0/h0; - - for (int i=0;i0.001) LogErr("Difference greater than 0.001 [%g], angle=%g, y=%g", prs, x[i]*DEG, y[i]); - } - - delete []v; delete []q; - v = NULL; q = NULL; - delete []y; delete []M; - y = NULL; M = NULL; - - return bRet; -} - - - diff --git a/OVP/D3D9Client/AABBUtil.h b/OVP/D3D9Client/AABBUtil.h index e13c29152..9d1a792d1 100644 --- a/OVP/D3D9Client/AABBUtil.h +++ b/OVP/D3D9Client/AABBUtil.h @@ -31,7 +31,6 @@ typedef struct { D3DXVECTOR4 min, max, bs, a, b, c; } D9BBox; - float D9NearPlane(LPDIRECT3DDEVICE9 pDev, float zmin, float zmax, float dmax, const D3DXMATRIX *pProj, bool bReduced); int D9ComputeMinMaxDistance(LPDIRECT3DDEVICE9 pDev, const D9BBox *in, const D3DXMATRIX *pWV, const D3DXVECTOR4 *F, float *zmin, float *zmax, float *dmin); void D9AddAABB(const D9BBox *in, const D3DXMATRIX *pM, D9BBox *out, bool bReset=false); @@ -45,14 +44,5 @@ D3DXVECTOR4 D9LinearFieldOfView(const D3DXMATRIX *pProj); D3DXVECTOR4 D9OffsetRange(double R, double r); void EnvMapDirection(int dir, D3DXVECTOR3 *Dir, D3DXVECTOR3 *Up); D3DXVECTOR3 WorldPickRay(float x, float y, const LPD3DXMATRIX mProj, const LPD3DXMATRIX mView); - -double ExactOpticalDepth(double alt, double dir, double R, double R1, double h0); - -D3DXVECTOR4 SolveScatter(double h0, double R, double R1); -D3DXVECTOR4 SolveScatterEx(double h0, double R, double R1); -bool SolveXScatter(double h0, double R, double R1, double *q, double angle = 95.0, int m = 8); -float FastOpticalDepth(float alt, float cd, double h0, D3DXVECTOR4 *prm); -float FastOpticalDepthEx(float alt, float cd, float h0, D3DXVECTOR4 *prm); - bool SolveLUSystem(int n, double *A, double *b, double *x, double *det=NULL); -#endif \ No newline at end of file +#endif diff --git a/OVP/D3D9Client/AtmoControls.cpp b/OVP/D3D9Client/AtmoControls.cpp index 916135867..a9543ff71 100644 --- a/OVP/D3D9Client/AtmoControls.cpp +++ b/OVP/D3D9Client/AtmoControls.cpp @@ -26,31 +26,37 @@ extern D3D9Client *g_client; // Defaut c'tor to init members ScatterParams::ScatterParams() : red ( 0.650 ), // 0.400 ... 0.700 - green ( 0.500 ), // 0.400 ... 0.700 + green ( 0.560 ), // 0.400 ... 0.700 blue ( 0.480 ), // 0.400 ... 0.700 rpow ( 4.0 ), // -8.0 ... 8.0 mpow ( 1.0 ), // -2.0 ... 2.0 - height ( 8.0 ), // 4.0 ... 40.0 [km] - depth ( 1.0 ), // 0.0 ... 1.5 + rheight ( 8.0 ), // 4.0 ... 40.0 [km] + mheight ( 1.0 ), // 0.0 ... 1.5 // ---------------------------------------- - expo ( 1.0 ), // 0.2 ... 3.0 + trb ( 1.0 ), // 0.2 ... 3.0 + tr3D ( 1.0 ), // ---------------------------------------- - rin ( 1.0 ), // 0.0 ... 3.0 - rout ( 0.592 ), // 0.0 ... 4.0 - rphase ( 0.3395 ), // 0.0 ... 3.5 + rayrat ( 1.0 ), // 0.0 ... 3.0 + ray ( 1.0 ), // 0.0 ... 4.0 + tw_bld ( 0.0 ), // 0.0 ... 3.5 // ---------------------------------------- mie ( 0.0869 ), // 0.0 ... 8.0 mphase ( 0.9831 ), // 0.85 ... 0.999 // ---------------------------------------- - aux1 ( 0.0 ), // 0.0 ... 2.0 - aux2 ( 0.0 ), // 0.0 ... 2.0 - aux3 ( 0.0 ), + mierat ( 1.0 ), // 0.0 ... 2.0 + aux2 ( 1.0 ), // 0.0 ... 2.0 + aux3 ( 2.0 ), tgamma ( 1.0 ), - hazec ( 0.0 ), - hazei ( 1.7 ), - agamma ( 1.0 ), + mphaseb ( 1.0 ), + hazei ( 1.0 ), + tw_bri ( 0.0 ), + tw_dst ( 0.0 ), // ---------------------------------------- - orbit ( false ) // [true|false] + orbalt ( 250e3 ), + visalt ( 70e3 ), + zcolor (1.0f, 1.0f, 0.9f), + hcolor (1.0f, 0.7f, 0.0f), + acolor (0.9f, 0.9f, 1.0f) { } @@ -115,48 +121,47 @@ void Create() // ATTENTION: Order of ScatterParams must match with slider indexes - Slider[0].id = IDC_ATM_RED; + Slider[0].id = IDC_ATM_TW_DST; Slider[1].id = IDC_ATM_GREEN; - Slider[2].id = IDC_ATM_BLUE; + Slider[2].id = IDC_ATM_TW_BRI; Slider[3].id = IDC_ATM_RPOW; Slider[4].id = IDC_ATM_IN; - Slider[5].id = IDC_ATM_OUT; + Slider[5].id = IDC_ATM_RAY; Slider[6].id = IDC_ATM_RPHASE; Slider[7].id = IDC_ATM_MIE; Slider[8].id = IDC_ATM_MPHASE; Slider[9].id = IDC_ATM_HEIGHT; Slider[10].id = IDC_ATM_AUX2; - Slider[11].id = IDC_ATM_DEPTH; + Slider[11].id = IDC_ATM_M_HEIGHT; Slider[12].id = IDC_ATM_MPOW; - Slider[13].id = IDC_ATM_EXPO; - Slider[14].id = IDC_ATM_AUX1; + Slider[13].id = IDC_ATM_TRB; + Slider[14].id = IDC_ATM_MIEIN; Slider[15].id = IDC_ATM_AUX3; Slider[16].id = IDC_ATM_TRGAMMA; - Slider[17].id = IDC_ATM_HAZECLR; - Slider[18].id = IDC_ATM_HAZEITS; - Slider[19].id = IDC_ATM_ATMGAMMA; - - - Slider[0].dsp = IDC_ATD_RED; + Slider[17].id = IDC_ATM_AUX4; + Slider[18].id = IDC_ATM_AUX5; + Slider[19].id = IDC_ATM_TRLIGHTSHAD; + + Slider[0].dsp = IDC_ATD_TW_DST; Slider[1].dsp = IDC_ATD_GREEN; - Slider[2].dsp = IDC_ATD_BLUE; + Slider[2].dsp = IDC_ATD_TW_BRI; Slider[3].dsp = IDC_ATD_RPOW; Slider[4].dsp = IDC_ATD_IN; - Slider[5].dsp = IDC_ATD_OUT; + Slider[5].dsp = IDC_ATD_RAY; Slider[6].dsp = IDC_ATD_RPHASE; Slider[7].dsp = IDC_ATD_MIE; Slider[8].dsp = IDC_ATD_MPHASE; Slider[9].dsp = IDC_ATD_HEIGHT; Slider[10].dsp = IDC_ATD_AUX2; - Slider[11].dsp = IDC_ATD_DEPTH; + Slider[11].dsp = IDC_ATD_M_HEIGHT; Slider[12].dsp = IDC_ATD_MPOW; - Slider[13].dsp = IDC_ATD_EXPO; - Slider[14].dsp = IDC_ATD_AUX1; + Slider[13].dsp = IDC_ATD_TRB; + Slider[14].dsp = IDC_ATD_MIEIN; Slider[15].dsp = IDC_ATD_AUX3; Slider[16].dsp = IDC_ATD_TRGAMMA; - Slider[17].dsp = IDC_ATD_HAZECLR; - Slider[18].dsp = IDC_ATD_HAZEITS; - Slider[19].dsp = IDC_ATD_ATMGAMMA; + Slider[17].dsp = IDC_ATD_AUX4; + Slider[18].dsp = IDC_ATD_AUX5; + Slider[19].dsp = IDC_ATD_TRLIGHTSHAD; } // ============================================================== @@ -168,6 +173,14 @@ bool IsActive() // ============================================================== +bool Visualize() +{ + if (!hDlg) return false; + return SendDlgItemMessage(hDlg, IDC_ATM_DISPLAY, BM_GETCHECK, 0, 0) == BST_CHECKED; +} + +// ============================================================== + void Release() { if (dwCmd) oapiUnregisterCustomCmd(dwCmd); @@ -185,10 +198,7 @@ void OpenDlgClbk(void *context) Scene *scene = g_client->GetScene(); - if (scene) { - OBJHANDLE hBody = scene->GetCameraProxyBody(); - if (hBody) vObj = static_cast(scene->GetVisObject(hBody)); - } + if (scene) vObj = scene->GetCameraNearVisual(); if (vObj) param = vObj->GetAtmoParams(atmmode); else param = &defs; @@ -198,81 +208,70 @@ void OpenDlgClbk(void *context) // Style flags // 1 = unit in [km] // 2 = same for orbital and surface setup - // 4 = call vPlanet::UpdateAtmoConfig() on change // 8 = x^2 "linearization" + // 16 = x^0.5 "linearization" + // 32 = x^4 "linearization" - ConfigSlider(IDC_ATM_RED, 0.400, 0.700); - ConfigSlider(IDC_ATM_GREEN, 0.400, 0.700); - ConfigSlider(IDC_ATM_BLUE, 0.400, 0.700); - ConfigSlider(IDC_ATM_RPOW, -8.0, 8.0); - ConfigSlider(IDC_ATM_MPOW, -8.0, 8.0); - ConfigSlider(IDC_ATM_HEIGHT, 2.0, 400.0, 1|2|4|8); - ConfigSlider(IDC_ATM_DEPTH, 0.0, 1.25); + ConfigSlider(IDC_ATM_TW_DST, 0.0, 0.2); // Twilight distance + ConfigSlider(IDC_ATM_GREEN, 0.46, 0.65); + ConfigSlider(IDC_ATM_TW_BRI, 0.01, 3.0, 8); // Twilight intensity + ConfigSlider(IDC_ATM_RPOW, -8.0, 12.0); + ConfigSlider(IDC_ATM_MPOW, -8.0, 12.0); + ConfigSlider(IDC_ATM_HEIGHT, 6.0, 200.0, 1|8); + ConfigSlider(IDC_ATM_M_HEIGHT, 0.5, 10.0, 1|8); // ------------------------------------------------------- - ConfigSlider(IDC_ATM_EXPO, 0.5, 2.0); - ConfigSlider(IDC_ATM_TRGAMMA, 0.3, 1.5); + ConfigSlider(IDC_ATM_TRB, 0.1, 8.0, 8); + ConfigSlider(IDC_ATM_TRGAMMA, 0.2, 1.5); + ConfigSlider(IDC_ATM_TRLIGHTSHAD, 0.0, 5.0, 32); // ------------------------------------------------------- - ConfigSlider(IDC_ATM_OUT, 0.0, 3.0, 8); - ConfigSlider(IDC_ATM_IN, 0.5, 2.0); - ConfigSlider(IDC_ATM_RPHASE, -0.75, 0.75); - ConfigSlider(IDC_ATM_ATMGAMMA, 0.3, 1.5); + ConfigSlider(IDC_ATM_RAY, 0.0, 10.0, 8); + ConfigSlider(IDC_ATM_IN, 0.2, 5.0, 32); + ConfigSlider(IDC_ATM_RPHASE, 0.01, 1.0, 8); // Ambient level for buildings // ------------------------------------------------------- - ConfigSlider(IDC_ATM_MIE, 0.0, 2.0, 8); - ConfigSlider(IDC_ATM_MPHASE, 0.80, 0.999); + ConfigSlider(IDC_ATM_MIE, 0.01, 10.0, 8); + ConfigSlider(IDC_ATM_MPHASE, 0.02, 0.999, 8); + ConfigSlider(IDC_ATM_MIEIN, 0.2, 5.0, 32); // ------------------------------------------------------- - ConfigSlider(IDC_ATM_AUX1, 0.0, 0.3); - ConfigSlider(IDC_ATM_AUX2, 0.0, 1.0, 8); - ConfigSlider(IDC_ATM_AUX3, 0.0, 2.0); + ConfigSlider(IDC_ATM_AUX2, 0.2, 10.0, 1); // Clouds altitude (km) + ConfigSlider(IDC_ATM_AUX3, 0.1, 4.0, 8); // HDR + ConfigSlider(IDC_ATM_AUX4, 0.0, 8.0); // Mie Phase-B + ConfigSlider(IDC_ATM_AUX5, 0.0, 5.0, 8); // Clouds intensity // ------------------------------------------------------- - ConfigSlider(IDC_ATM_HAZECLR, -1.5, 1.5); - ConfigSlider(IDC_ATM_HAZEITS, 1.1, 1.8); - // ------------------------------------------------------- - CreateToolTip(IDC_ATM_RED, hDlg, "Wavelength setting for red light (default 0.650)"); - CreateToolTip(IDC_ATM_GREEN, hDlg, "Wavelength setting for green light (default 0.600)"); - CreateToolTip(IDC_ATM_BLUE, hDlg, "Wavelength setting for blue light (default 0.480)"); + CreateToolTip(IDC_ATM_TW_DST, hDlg, "Light travel distance behind terminator"); + CreateToolTip(IDC_ATM_GREEN, hDlg, "Green wave lenght. (Green balance)"); + CreateToolTip(IDC_ATM_TW_BRI, hDlg, "Terrain brightness during twilight"); CreateToolTip(IDC_ATM_RPOW, hDlg, "Main control for atmospheric rayleigh color composition (4.0 for the Earth)"); CreateToolTip(IDC_ATM_MPOW, hDlg, "Main control for atmospheric mie color composition"); - CreateToolTip(IDC_ATM_HEIGHT, hDlg, "Atmosphere scale height (7km - 10km for the Earth)"); - CreateToolTip(IDC_ATM_DEPTH, hDlg, "Cloud layer intensity"); + CreateToolTip(IDC_ATM_HEIGHT, hDlg, "Atmosphere Ray scale height (7km - 9km for the Earth)"); + CreateToolTip(IDC_ATM_M_HEIGHT, hDlg, "Atmosphere Mie scale height (0.6km - 2km for the Earth)"); // ------------------------------------------------------- - CreateToolTip(IDC_ATM_EXPO, hDlg, "Terrain/Ocean brightness control (default 1.0)"); + CreateToolTip(IDC_ATM_TRB, hDlg, "Terrain/Ocean brightness control (default 1.0)"); CreateToolTip(IDC_ATM_TRGAMMA, hDlg, "Terrain/Ocean gamma control value (default 1.0)"); + CreateToolTip(IDC_ATM_TRLIGHTSHAD, hDlg, "Terrain light and shadow boost"); // ------------------------------------------------------- - CreateToolTip(IDC_ATM_OUT, hDlg, "Overall control for rayleigh scattering (i.e. Haze stickness)"); - CreateToolTip(IDC_ATM_IN, hDlg, "Controls in-scatter out-scatter ratio (default 1.0)"); - CreateToolTip(IDC_ATM_RPHASE, hDlg, "Controls a directional dependency of in-scattered sunlight (Most visible when camera, planet and the sun are aligned)"); - CreateToolTip(IDC_ATM_ATMGAMMA, hDlg, "Gamma control for atmospheric haze"); + CreateToolTip(IDC_ATM_RAY, hDlg, "Overall control for rayleigh scattering (i.e. Haze stickness, atmosphere transparency, optical depth"); + CreateToolTip(IDC_ATM_IN, hDlg, "Rayleigh in-scatter out-scatter ratio (1.0 nominal)"); + CreateToolTip(IDC_ATM_RPHASE, hDlg, "Ambient light level for buildings"); // ------------------------------------------------------- - CreateToolTip(IDC_ATM_MIE, hDlg, "Overall scale factor for mie scattering."); + CreateToolTip(IDC_ATM_MIE, hDlg, "Overall scale factor for mie scattering. (Mie-particle density)"); CreateToolTip(IDC_ATM_MPHASE, hDlg, "Directional strength of Henyey-Greenstein phase function"); + CreateToolTip(IDC_ATM_MIEIN, hDlg, "Mie in-scatter out-scatter ratio (1.0 nominal)"); // ------------------------------------------------------- - CreateToolTip(IDC_ATM_AUX1, hDlg, "Distance of light transfer in atmosphere behind terminator"); - CreateToolTip(IDC_ATM_AUX2, hDlg, "Horizon intensity (Twilight and Sunset setting)"); - CreateToolTip(IDC_ATM_AUX3, hDlg, "Sky color boost to compensate a lack of multible scattering. (Orbital sunrise color)"); - // ------------------------------------------------------- - CreateToolTip(IDC_ATM_HAZECLR, hDlg, "Additional (for R-POW) haze color control for max intensity (default 1.0)"); - CreateToolTip(IDC_ATM_HAZEITS, hDlg, "Controls the maximum intensity of horizon haze (default 1.7)"); + CreateToolTip(IDC_ATM_AUX2, hDlg, "Altitude for cloud lighting calculations"); + CreateToolTip(IDC_ATM_AUX3, hDlg, "'HDR' Exposure factor"); + CreateToolTip(IDC_ATM_AUX4, hDlg, "Omnidirectional mie scattering scale factor"); + CreateToolTip(IDC_ATM_AUX5, hDlg, "[Dual purpose] Clouds intensity [on surface]. Multiscatter light level [on orbit]"); SendDlgItemMessageA(hDlg, IDC_ATM_MODE, CB_RESETCONTENT, 0, 0); SendDlgItemMessageA(hDlg, IDC_ATM_MODE, CB_ADDSTRING, 0, (LPARAM)"Auto"); SendDlgItemMessageA(hDlg, IDC_ATM_MODE, CB_ADDSTRING, 0, (LPARAM)"Surface"); - SendDlgItemMessageA(hDlg, IDC_ATM_MODE, CB_ADDSTRING, 0, (LPARAM)"Orbital"); + SendDlgItemMessageA(hDlg, IDC_ATM_MODE, CB_ADDSTRING, 0, (LPARAM)"Low Orbit"); + SendDlgItemMessageA(hDlg, IDC_ATM_MODE, CB_ADDSTRING, 0, (LPARAM)"High Orbit"); SendDlgItemMessageA(hDlg, IDC_ATM_MODE, CB_SETCURSEL, atmmode, 0); SetTimer(hDlg, 0, 200, NULL); - if (vObj) { - char title[256]; - if (param->orbit) sprintf_s(title,256,"Atmospheric Controls [%s] [Orbital]", vObj->GetName()); - else sprintf_s(title,256,"Atmospheric Controls [%s] [Surface]", vObj->GetName()); - - if (param->orbit) SetWindowText(GetDlgItem(hDlg, IDC_ATM_COPYTO), "Copy to Surface"); - else SetWindowText(GetDlgItem(hDlg, IDC_ATM_COPYTO), "Copy to Orbital"); - - SetWindowTextA(hDlg, title); - } - UpdateSliders(); } @@ -306,18 +305,23 @@ void SetSlider(int id, WORD pos) if (!vObj) return; for (int i=0;iGetAtmoParams(1)->data[i] = v; vObj->GetAtmoParams(2)->data[i] = v; + vObj->GetAtmoParams(3)->data[i] = v; } else { param->data[i] = v; } - if (Slider[i].style&4) vObj->UpdateAtmoConfig(); + //vObj->UpdateAtmoConfig(); UpdateSlider(id, false); @@ -351,7 +355,9 @@ void UpdateSlider(int id, bool bSetPos) if (bSetPos) { double x = (val - Slider[i].min)/(Slider[i].max-Slider[i].min); - if (Slider[i].style&8) x = sqrt(x); + if (Slider[i].style & 8) x = sqrt(x); + if (Slider[i].style & 16) x = x * x; + if (Slider[i].style & 32) x = pow(x, 0.25); DWORD dpos = 1000 - DWORD(x*1000.0); SendDlgItemMessage(hDlg, id, TBM_SETPOS, 1, dpos); } @@ -395,7 +401,7 @@ void SetVisual(vObject *vo) vObj = static_cast(vo); - if (vObj) param = vObj->GetAtmoParams(); + if (vObj) param = vObj->GetAtmoParams(0); else param = &defs; UpdateSliders(); @@ -407,34 +413,39 @@ void SetVisual(vObject *vo) INT_PTR CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static bool bOrbOld = false; switch (uMsg) { case WM_INITDIALOG: { - vObject *vPl = NULL; - OBJHANDLE hProxy = g_client->GetScene()->GetCameraProxyBody(); - if (hProxy) vPl = g_client->GetScene()->GetVisObject(hProxy); + vObject *vPl = g_client->GetScene()->GetCameraNearVisual(); SetVisual(vPl); return true; } case WM_TIMER: { - if (vObj) { - if (param->orbit != vObj->GetAtmoParams(atmmode)->orbit) { - char title[256]; - param = vObj->GetAtmoParams(atmmode); - if (param->orbit) sprintf_s(title,256,"Atmospheric Controls [%s] [Orbital]", vObj->GetName()); - else sprintf_s(title,256,"Atmospheric Controls [%s] [Surface]", vObj->GetName()); - - if (param->orbit) SetWindowText(GetDlgItem(hWnd, IDC_ATM_COPYTO), "Copy to Surface"); - else SetWindowText(GetDlgItem(hWnd, IDC_ATM_COPYTO), "Copy to Orbital"); - - SetWindowTextA(hDlg,title); - UpdateSliders(); - } + if (vObj) { + char title[256]; string file = "??"; + sprintf_s(title, 256, "Atmospheric Controls [%s]", vObj->GetName()); + + auto cfg = Config->AtmoCfg.find(vObj->GetName()); + if (cfg != Config->AtmoCfg.end()) file = cfg->second; + + param = vObj->GetAtmoParams(atmmode); + + double vd = 0.5f; + if (atmmode == 0) vd = param->cfg_alt < 0.9999f ? param->cfg_alt : 1.0 - param->cfg_halt; + + if (vObj->GetAtmoMode() == 1) sprintf_s(title, 256, "Atmospheric Controls [%s][%s] [Surface] (%3.1f%%)", file.c_str(), vObj->GetName(), (1.0 - vd) * 100.0); + if (vObj->GetAtmoMode() == 2) sprintf_s(title, 256, "Atmospheric Controls [%s][%s] [LowOrbit] (%3.1f%%)", file.c_str(), vObj->GetName(), vd * 100.0); + if (vObj->GetAtmoMode() == 3) sprintf_s(title, 256, "Atmospheric Controls [%s][%s] [HighOrbit] (%3.1f%%)", file.c_str(), vObj->GetName(), (1.0 - vd) * 100.0); + + SetWindowTextA(hDlg, title); + UpdateSliders(); } + } case WM_VSCROLL: @@ -451,8 +462,8 @@ INT_PTR CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_COMMAND: - switch (LOWORD(wParam)) { - + switch (LOWORD(wParam)) + { case IDCANCEL: case IDOK: oapiCloseDialog(hWnd); @@ -461,29 +472,30 @@ INT_PTR CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case IDC_ATM_LOAD: if (vObj) { - vObj->LoadAtmoConfig(false); - vObj->LoadAtmoConfig(true); + vObj->LoadAtmoConfig(); UpdateSliders(); } break; case IDC_ATM_SAVE: + if (vObj) vObj->SaveAtmoConfig(); + break; + + case IDC_ATM_COPYTO: if (vObj) { - vObj->SaveAtmoConfig(false); - vObj->SaveAtmoConfig(true); + if (vObj->GetAtmoParams(1) != param) memcpy(vObj->GetAtmoParams(1), param, sizeof(ScatterParams)); } break; - case IDC_ATM_COPYTO: + case IDC_ATM_COPYLOW: + if (vObj) { + if (vObj->GetAtmoParams(2) != param) memcpy(vObj->GetAtmoParams(2), param, sizeof(ScatterParams)); + } + break; + + case IDC_ATM_COPYHIGH: if (vObj) { - if (param->orbit) { - memcpy(vObj->GetAtmoParams(1), param, sizeof(ScatterParams)); - vObj->GetAtmoParams(1)->orbit = false; - } - else { - memcpy(vObj->GetAtmoParams(2), param, sizeof(ScatterParams)); - vObj->GetAtmoParams(2)->orbit = true; - } + if (vObj->GetAtmoParams(3) != param) memcpy(vObj->GetAtmoParams(3), param, sizeof(ScatterParams)); } break; @@ -506,4 +518,3 @@ INT_PTR CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } //namespace - \ No newline at end of file diff --git a/OVP/D3D9Client/AtmoControls.h b/OVP/D3D9Client/AtmoControls.h index 3e2c3af15..451d05403 100644 --- a/OVP/D3D9Client/AtmoControls.h +++ b/OVP/D3D9Client/AtmoControls.h @@ -12,33 +12,42 @@ typedef struct ScatterParams { - ScatterParams(); ///< Default c'tor + ScatterParams(); ///< Defaut c'tor union { double data[ATM_SLIDER_COUNT]; // ATTENTION: Order of params must match with slider indexes struct { - double red; ///< Red wave length - double green; ///< Green wave length - double blue; ///< Blue wave length - double rpow; ///< Rayleigh power - double rin; ///< in-scatter strength - double rout; ///< out-scatter strength - double rphase; ///< Rayleigh phase - double mie; ///< scale factor for mie scattering - double mphase; ///< g-constant in HG phase function - double height; ///< atmospheric scale height - double aux2; ///< auxiliary parameter - double depth; ///< Cloud layer intensity - double mpow; ///< Mie power - double expo; ///< exposure for terrain - double aux1; ///< auxiliary parameter - double aux3; ///< auxiliary parameter - double tgamma; ///< Terrain gamma - double hazec; ///< Haze color - double hazei; ///< Haze intensity - double agamma; ///< Atmosphere gamma + double tw_dst; ///< 0 Twilight distance + double green; ///< 1 Green wavw length + double tw_bri; ///< 2 Twilight brightness + double rpow; ///< 3 Rayleigh power + double rayrat; ///< 4 Rayleigh ratio + double ray; ///< 5 Rayleigh out-scatter strength + double tw_bld; ///< 6 Building ambient level at twilight + double mie; ///< 7 scale factor for mie out-scattering + double mphase; ///< 8 g-constant in HG phase function + double rheight; ///< 9 atmospheric rayleigh scale height + double aux2; ///< 10 cloud lighting altitude [km] + double mheight; ///< 11 Mie scale height + double mpow; ///< 12 Mie power + double trb; ///< 13 Terrain brightness + double mierat; ///< 14 Mie ratio + double aux3; ///< 15 auxiliary parameter + double tgamma; ///< 16 Terrain gamma + double mphaseb; ///< 17 MiePhase-B + double hazei; ///< 18 cloud intensity + double tr3D; ///< 19 Terrain light and shadow boost }; }; - bool orbit; + double orbalt; + double visalt; + double red; + double blue; + double suni; + FVECTOR3 zcolor; // sun-glare color at zenith (camera at sealevel) + FVECTOR3 hcolor; // sun-glare color at horizon (camera at sealevel) + FVECTOR3 acolor; // Abmient color at sealevel + double cfg_alt; + double cfg_halt; } ScatterParams; class vPlanet; @@ -61,44 +70,9 @@ namespace AtmoControls { void ConfigSlider(int id, double min, double max, int style=0); void SetSlider(int id, WORD pos); void UpdateSliders(); + bool Visualize(); INT_PTR CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); }; - - - -/* -class Scatter { - -public: - Scatter(ScatterParams *prm, OBJHANDLE hPlanet, DWORD dAmbient); - ~Scatter(); - - double AngleCoEff(double cos_dir); - - void ComputeSunLightColorMap(LPDIRECT3DDEVICE9 pDev, LPDIRECT3DTEXTURE9 *pOutSM, bool bSave=false); - void ComputeInscatterColorMap(LPDIRECT3DDEVICE9 pDev, LPDIRECT3DTEXTURE9 *pOutSM, bool bSave=false); - -private: - - double fRadius; - double fAtmRad; - double fMaxDepth; - double fHorizonAlt; - double fScaleHeight; - double fInvScaleHeight; - double fCoEff[12]; - double fMieA, fMieB, fMieC; - - float fGlobalAmb, fSunAppRad, fAmbient0; - - D3DXVECTOR3 vLambda4, vLambda1; - D3DXVECTOR3 vRayTot, vMieTot, vRaySun, vRayIns, vRaySrf; - - const ATMCONST *atm; -};*/ - - - #endif // !__ATMOCONTROLS_H diff --git a/OVP/D3D9Client/BeaconArray.h b/OVP/D3D9Client/BeaconArray.h index 78fe1d2cf..4dd534f94 100644 --- a/OVP/D3D9Client/BeaconArray.h +++ b/OVP/D3D9Client/BeaconArray.h @@ -65,7 +65,7 @@ class BeaconArray : private D3D9Effect */ void Render(LPDIRECT3DDEVICE9 dev, const LPD3DXMATRIX pW, float time=0.5f); - void Update(DWORD nCount, vPlanet *vP); + void Update(DWORD nCount, class vPlanet *vP); private: diff --git a/OVP/D3D9Client/CMakeLists.txt b/OVP/D3D9Client/CMakeLists.txt index f2eb6e1f1..ff34154ee 100644 --- a/OVP/D3D9Client/CMakeLists.txt +++ b/OVP/D3D9Client/CMakeLists.txt @@ -47,7 +47,6 @@ set(SourceFiles MeshMgr.cpp OapiExtension.cpp Particle.cpp - PlanetRenderer.cpp RingMgr.cpp RunwayLights.cpp Scene.cpp @@ -61,6 +60,7 @@ set(SourceFiles VideoTab.cpp VObject.cpp VPlanet.cpp + VPlanetAtmo.cpp VStar.cpp VVessel.cpp WindowMgr.cpp @@ -96,7 +96,6 @@ set(IncludeFiles MeshMgr.h OapiExtension.h Particle.h - PlanetRenderer.h Qtree.h resource.h RingMgr.h @@ -137,6 +136,11 @@ set(ShaderFiles ${ShaderDir}/IrradianceInteg.hlsl ${ShaderDir}/LensFlare.hlsl ${ShaderDir}/LightBlur.hlsl + ${ShaderDir}/CelSphere.hlsl + ${ShaderDir}/NewMesh.hlsl + ${ShaderDir}/NewPlanet.hlsl + ${ShaderDir}/Scatter.hlsl + ${ShaderDir}/Glare.hlsl ${ShaderDir}/Mesh.fx ${ShaderDir}/Metalness.fx ${ShaderDir}/Particle.fx @@ -144,7 +148,6 @@ set(ShaderFiles ${ShaderDir}/Planet.fx ${ShaderDir}/SceneTech.fx ${ShaderDir}/Sketchpad.fx - ${ShaderDir}/Surface.fx ${ShaderDir}/Vessel.fx ) diff --git a/OVP/D3D9Client/CSphereMgr.cpp b/OVP/D3D9Client/CSphereMgr.cpp index 4029c2248..57bccacba 100644 --- a/OVP/D3D9Client/CSphereMgr.cpp +++ b/OVP/D3D9Client/CSphereMgr.cpp @@ -16,6 +16,7 @@ using namespace oapi; + // ======================================================================= // Externals @@ -53,7 +54,7 @@ void ReleaseTex(LPDIRECT3DTEXTURE9 pTex); // ======================================================================= // Class CSphereManager -CSphereManager::CSphereManager(D3D9Client *gclient, const Scene *scene) : PlanetRenderer(), texname(), RenderParam() +CSphereManager::CSphereManager(D3D9Client *gc, const Scene *scene) : gc(gc), texname(), RenderParam() { scn = scene; @@ -63,6 +64,13 @@ CSphereManager::CSphereManager(D3D9Client *gclient, const Scene *scene) : Planet NLNG = TileManager::NLNG; NLAT = TileManager::NLAT; + pShader = new ShaderClass(gc->GetDevice(), "Modules/D3D9Client/CelSphere.hlsl", "CelVS", "CelPS", "CelSphere", ""); + + // Get Handles for faster access + hTexA = pShader->GetPSHandle("tTexA"); + hTexB = pShader->GetPSHandle("tTexB"); + hVSConst = pShader->GetVSHandle("Const"); + m_bBkgImg = *(bool*)gc->GetConfigParam(CFGPRM_CSPHEREUSEBGIMAGE); if (m_bBkgImg) { char* c = (char*)gc->GetConfigParam(CFGPRM_CSPHERETEXTURE); @@ -421,20 +429,17 @@ void CSphereManager::Render (LPDIRECT3DDEVICE9 dev, int level, double bglvl) WaitForSingleObject (tilebuf->hQueueMutex, INFINITE); - HR(Shader()->SetTechnique(eSkyDomeTech)); - HR(Shader()->SetMatrix(smViewProj, scn->GetProjectionViewMatrix())); - HR(Shader()->SetFloat(sfAlpha, intens)); - HR(Shader()->SetFloat(sfNight, bgscale)); - HR(Shader()->SetBool(sbLights, m_bBkgImg)); - HR(Shader()->SetBool(sbLocals, m_bStarImg)); - - pDev->SetVertexDeclaration(pPatchVertexDecl); + CelFlow.bAlpha = m_bBkgImg; + CelFlow.bBeta = m_bStarImg; + CelData.fAlpha = intens; + CelData.fBeta = bgscale; + CelData.mViewProj = *scn->GetProjectionViewMatrix(); - UINT numPasses = 0; - HR(Shader()->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); + pShader->Setup(pPatchVertexDecl, false, 0); + pShader->ClearTextures(); + pShader->SetPSConstants("Flow", &CelFlow, sizeof(CelFlow)); + pShader->SetPSConstants("Const", &CelData, sizeof(CelData)); - Shader()->BeginPass(0); - for (hemisp = idx = 0; hemisp < 2; hemisp++) { if (hemisp) { // flip world transformation to southern hemisphere D3DXMatrixMultiply(&RenderParam.wmat, &TileManager::Rsouth, &RenderParam.wmat); @@ -449,9 +454,6 @@ void CSphereManager::Render (LPDIRECT3DDEVICE9 dev, int level, double bglvl) } } - HR(Shader()->EndPass()); - HR(Shader()->End()); - ReleaseMutex (tilebuf->hQueueMutex); } @@ -500,11 +502,14 @@ void CSphereManager::RenderTile (int lvl, int hemisp, int ilat, int nlat, int il D3D9Stats.Old.Tiles[lvl]++; - Shader()->SetMatrix(smWorld, &mWorld); - Shader()->SetTexture(stDiff, tex); - Shader()->SetTexture(stMask, ltex); - Shader()->CommitChanges(); + CelData.mWorld = mWorld; + + pShader->SetTexture(hTexA, tex, IPF_CLAMP | IPF_ANISOTROPIC); + pShader->SetTexture(hTexB, ltex, IPF_CLAMP | IPF_ANISOTROPIC); + pShader->SetVSConstants(hVSConst, &CelData, sizeof(CelData)); + pShader->UpdateTextures(); + LPDIRECT3DDEVICE9 pDev = pShader->GetDevice(); pDev->SetStreamSource(0, mesh.pVB, 0, sizeof(VERTEX_2TEX)); pDev->SetIndices(mesh.pIB); pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh.nv, 0, mesh.nf); diff --git a/OVP/D3D9Client/CSphereMgr.h b/OVP/D3D9Client/CSphereMgr.h index 8bbb0f444..0f8be2e62 100644 --- a/OVP/D3D9Client/CSphereMgr.h +++ b/OVP/D3D9Client/CSphereMgr.h @@ -12,16 +12,32 @@ #define STRICT 1 #include "TileMgr.h" -#include "PlanetRenderer.h" class D3D9Config; // ======================================================================= // Class CSphereManager -class CSphereManager : private PlanetRenderer +class CSphereManager { public: + +#pragma pack(push, 4) + struct CelDataStruct + { + float4x4 mWorld; + float4x4 mViewProj; + float fAlpha; + float fBeta; + } CelData; + + struct CelDataFlow + { + BOOL bAlpha; + BOOL bBeta; + } CelFlow; +#pragma pack(pop) + /** * \brief Constructs a new sphere manager object * \param gclient client instance pointer @@ -101,6 +117,9 @@ class CSphereManager : private PlanetRenderer static int *NLAT; private: + HANDLE hTexA, hTexB, hVSConst; + ShaderClass* pShader; + D3D9Client* gc; char texname[128]; char starfieldname[128]; float intensity; // opacity of background image diff --git a/OVP/D3D9Client/Cloudmgr2.cpp b/OVP/D3D9Client/Cloudmgr2.cpp index 6eff27446..43f313dac 100644 --- a/OVP/D3D9Client/Cloudmgr2.cpp +++ b/OVP/D3D9Client/Cloudmgr2.cpp @@ -93,43 +93,40 @@ void CloudTile::Load () // ----------------------------------------------------------------------- -void CloudTile::Render () +void CloudTile::Render() { - UINT numPasses = 0; - LPDIRECT3DDEVICE9 pDev = mgr->Dev(); - ID3DXEffect *Shader = mgr->Shader(); + vPlanet* vPlanet = mgr->GetPlanet(); + PlanetShader* pShader = mgr->GetShader(); + ShaderParams* sp = vPlanet->GetTerrainParams(); + + int cfg = vPlanet->GetShaderID(); // --------------------------------------------------------------------- // Feed tile specific data to shaders // - // --------------------------------------------------------------------------------------------------- - HR(Shader->SetTexture(TileManager2Base::stDiff, tex)); - HR(Shader->SetVector(TileManager2Base::svCloudOff, &GetTexRangeDX(&texrange))); - HR(Shader->SetVector(TileManager2Base::svMicroOff, &GetTexRangeDX(µrange))); - // --------------------------------------------------------------------------------------------------- - - Shader->CommitChanges(); + // ---------------------------------------------------------------------- + pShader->SetTexture(pShader->tDiff, tex, IPF_ANISOTROPIC | IPF_CLAMP, Config->Anisotrophy); - HR(Shader->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); + sp->vCloudOff = GetTexRangeDX(&texrange); + sp->vMicroOff = GetTexRangeDX(µrange); + sp->fAlpha = 1.0f; + sp->fBeta = 1.0f; + sp->mWorld = mWorld; // ------------------------------------------------------------------- // render surface mesh + if (cfg != PLT_GIANT) { + if (Config->CloudMicro) + pShader->SetPSConstants(pShader->Prm, sp, sizeof(ShaderParams)); + } + pShader->SetVSConstants(pShader->PrmVS, sp, sizeof(ShaderParams)); + pShader->UpdateTextures(); - // While viewing the Moon/Brighton Beach. Earth's cloudlayer rendering throwed through D3DX9_43.dll: - // Exception thrown at 0x759635D2 (KernelBase.dll) in orbiter.exe: 0x000006BA : The RPC server is unavailable. - // Exception thrown at 0x759635D2 (KernelBase.dll) in orbiter.exe: 0xC0000002 : The requested operation is not implemented. - // Unhandled exception at 0x759635D2 (KernelBase.dll) in orbiter.exe : 0xC0000002 : The requested operation is not implemented. - // What is this, why ? - - HR(Shader->BeginPass(0)); - pDev->SetVertexDeclaration(pPatchVertexDecl); pDev->SetStreamSource(0, mesh->pVB, 0, sizeof(VERTEX_2TEX)); pDev->SetIndices(mesh->pIB); pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh->nv, 0, mesh->nf); - HR(Shader->EndPass()); - HR(Shader->End()); } @@ -142,9 +139,7 @@ void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlan // set generic parameters SetRenderPrm (dwmat, rprm.cloudrot, use_zbuf, rprm); - double np = 0.0, fp = 0.0; int i; - class Scene *scene = GetClient()->GetScene(); // adjust scaling parameters (can only be done if no z-buffering is in use) @@ -162,9 +157,7 @@ void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlan } zmin = max (2.0, min (zmax*1e-4, zmin)); - np = scene->GetCameraNearPlane(); - fp = scene->GetCameraFarPlane(); - scene->SetCameraFrustumLimits (zmin, zmax); + vp->GetScatterConst()->mVP = scene->PushCameraFrustumLimits(zmin, zmax); } // build a transformation matrix for frustum testing @@ -176,13 +169,38 @@ void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlan // --------------------------------------------------------------------- // Initialize shading technique and feed planet specific data to shaders // - HR(Shader()->SetTechnique(eCloudTech)); - HR(Shader()->SetMatrix(smViewProj, scene->GetProjectionViewMatrix())); - HR(Shader()->SetBool(sbCloudNorm, Config->bCloudNormals != 0)); - HR(Shader()->SetBool(sbEarth, strcmp(CbodyName(), "Earth") == 0)); + + ElevMode = eElevMode::Spherical; + ElevModeLvl = 0; + + FlowControlPS fc = { 0 }; + fc.bBelowClouds = vp->CameraAltitude() < rprm.cloudalt; + + int cfg = vp->GetShaderID(); + + // Select cloud layer shader + pShader = (cfg == PLT_GIANT ? vp->GetShader(PLT_G_CLOUDS) : vp->GetShader(PLT_CLOUDS)); - if (rprm.bCloudBrighten) { HR(Shader()->SetFloat(sfAlpha, 2.0f)); } - else { HR(Shader()->SetFloat(sfAlpha, 1.0f)); } + pShader->ClearTextures(); + pShader->Setup(pPatchVertexDecl, false, 1); + + pShader->SetPSConstants("Const", vp->GetScatterConst(), sizeof(ConstParams)); + pShader->SetVSConstants("Const", vp->GetScatterConst(), sizeof(ConstParams)); + pShader->SetPSConstants("Flow", &fc, sizeof(FlowControlPS)); + + if (cfg != PLT_GIANT) + { + if (Config->CloudMicro) { + pShader->SetTexture("tCloudMicro", hCloudMicro, IPF_ANISOTROPIC | IPF_WRAP, Config->Anisotrophy); + if (Config->bCloudNormals) + pShader->SetTexture("tCloudMicroNorm", hCloudMicroNorm, IPF_ANISOTROPIC | IPF_WRAP, Config->Anisotrophy); + } + pShader->SetTexture("tSun", vp->GetScatterTable(SUN_COLOR), IPF_LINEAR | IPF_CLAMP); + pShader->SetTexture("tLndRay", vp->GetScatterTable(RAY_LAND), IPF_LINEAR | IPF_CLAMP); + pShader->SetTexture("tLndAtn", vp->GetScatterTable(ATN_LAND), IPF_LINEAR | IPF_CLAMP); + //pShader->SetTexture("tSkyRayColor", vp->GetScatterTable(RAY_COLOR), IPF_LINEAR | IPF_CLAMP); + //pShader->SetTexture("tSkyMieColor", vp->GetScatterTable(MIE_COLOR), IPF_LINEAR | IPF_CLAMP); + } // TODO: render full sphere for levels < 4 @@ -198,8 +216,8 @@ void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlan loader->ReleaseMutex (); - if (np) - scene->SetCameraFrustumLimits(np,fp); + // Pop previous frustum configuration, must initialize mVP + if (!use_zbuf) vp->GetScatterConst()->mVP = scene->PopCameraFrustumLimits(); } // ----------------------------------------------------------------------- diff --git a/OVP/D3D9Client/D3D9Client.cpp b/OVP/D3D9Client/D3D9Client.cpp index 68d335d83..5d4941fbc 100644 --- a/OVP/D3D9Client/D3D9Client.cpp +++ b/OVP/D3D9Client/D3D9Client.cpp @@ -73,6 +73,7 @@ set SurfaceCatalog; unordered_map SharedTextures; unordered_map ClonedTextures; unordered_map MeshMap; +unordered_map MicroTextures; DWORD uCurrentMesh = 0; vObject *pCurrentVisual = 0; @@ -155,12 +156,23 @@ DLLCLBK void InitModule(HINSTANCE hDLL) LogAlw("[Not Compiled With nVidia API]"); #endif - g_pConst = new gcConst(); Config = new D3D9Config(); + + if (Config->ShaderCacheUse) { + DWORD fa = GetFileAttributesA("Cache"); + if (fa == INVALID_FILE_ATTRIBUTES) CreateDirectoryA("Cache", NULL); + fa = GetFileAttributesA("Cache/D3D9Client"); + if (fa == INVALID_FILE_ATTRIBUTES) CreateDirectoryA("Cache/D3D9Client", NULL); + fa = GetFileAttributesA("Cache/D3D9Client/Shaders"); + if (fa == INVALID_FILE_ATTRIBUTES) CreateDirectoryA("Cache/D3D9Client/Shaders", NULL); + } + + g_pConst = new gcConst(); TileCatalog = new D3D9Catalog(); DebugControls::Create(); AtmoControls::Create(); + vPlanet::ParseMicroTexturesFile(); g_hInst = hDLL; g_client = new D3D9Client(hDLL); @@ -442,7 +454,6 @@ HWND D3D9Client::clbkCreateRenderWindow() TileManager::GlobalInit(this); TileManager2Base::GlobalInit(this); - PlanetRenderer::GlobalInit(this); RingManager::GlobalInit(this); HazeManager::GlobalInit(this); HazeManager2::GlobalInit(this); @@ -451,10 +462,12 @@ HWND D3D9Client::clbkCreateRenderWindow() vStar::GlobalInit(this); vObject::GlobalInit(this); vVessel::GlobalInit(this); + vPlanet::GlobalInit(this); OapiExtension::GlobalInit(*Config); OutputLoadStatus("SceneTech.fx",1); Scene::D3D9TechInit(pDevice, fld); + D3D9Mesh::GlobalInit(pDevice); // Create scene instance scene = new Scene(this, viewW, viewH); @@ -828,12 +841,12 @@ void D3D9Client::clbkDestroyRenderWindow (bool fastclose) HazeManager2::GlobalExit(); TileManager::GlobalExit(); TileManager2Base::GlobalExit(); - PlanetRenderer::GlobalExit(); D3D9ParticleStream::GlobalExit(); CSphereManager::GlobalExit(); vStar::GlobalExit(); vVessel::GlobalExit(); vObject::GlobalExit(); + D3D9Mesh::GlobalExit(); SAFE_DELETE(defpen); SAFE_DELETE(deffont); @@ -856,7 +869,12 @@ void D3D9Client::clbkDestroyRenderWindow (bool fastclose) LogAlw("============ Checking Object Catalogs ==========="); - + // Clear microtextures -------------------------------------------------------------------------------------- + // + for (auto& it : MicroTextures) SAFE_RELEASE(it.second); + MicroTextures.clear(); + + // Check surface catalog -------------------------------------------------------------------------------------- // if (SharedTextures.size() > 0) @@ -982,8 +1000,8 @@ void D3D9Client::PushRenderTarget(LPDIRECT3DSURFACE9 pColor, LPDIRECT3DSURFACE9 pDevice->SetViewport(&vp); } - pDevice->SetRenderTarget(0, pColor); - pDevice->SetDepthStencilSurface(pDepthStencil); + if (pDepthStencil) if (pDevice->SetDepthStencilSurface(pDepthStencil) != S_OK) assert(false); + if (pColor) if (pDevice->SetRenderTarget(0, pColor) != S_OK) assert(false); RenderStack.push_front(data); LogDbg("Plum", "PUSH:RenderStack[%lu]={%s, %s} %s", RenderStack.size(), _PTR(data.pColor), _PTR(data.pDepthStencil), labels[data.code]); @@ -1664,6 +1682,8 @@ LRESULT D3D9Client::RenderWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l xpos = GET_X_LPARAM(lParam); ypos = GET_Y_LPARAM(lParam); + GetScene()->vPickRay = GetScene()->GetPickingRay(xpos, ypos); + TRACKMOUSEEVENT te; te.cbSize = sizeof(TRACKMOUSEEVENT); te.dwFlags = TME_LEAVE; te.hwndTrack = hRenderWnd; TrackMouseEvent(&te); diff --git a/OVP/D3D9Client/D3D9Client.rc b/OVP/D3D9Client/D3D9Client.rc index f3079536f..11d3a4943 100644 --- a/OVP/D3D9Client/D3D9Client.rc +++ b/OVP/D3D9Client/D3D9Client.rc @@ -3,6 +3,8 @@ // http://www.resedit.net #include +#include +#include #include "resource.h" @@ -93,12 +95,12 @@ FONT 8, "Ms Shell Dlg" EDITTEXT IDC_DBG_VARA, 280, 262, 30, 12, ES_AUTOHSCROLL, WS_EX_LEFT EDITTEXT IDC_DBG_VARC, 230, 262, 30, 12, ES_AUTOHSCROLL, WS_EX_LEFT EDITTEXT IDC_DBG_VARB, 330, 262, 30, 12, ES_AUTOHSCROLL, WS_EX_LEFT - COMBOBOX IDC_DBG_ENVMAP, 315, 115, 46, 15, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT - COMBOBOX IDC_DBG_SCENEDBG, 265, 100, 96, 15, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT + COMBOBOX IDC_DBG_ENVMAP, 275, 115, 86, 15, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT + COMBOBOX IDC_DBG_SCENEDBG, 255, 100, 106, 15, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT COMBOBOX IDC_DBG_ACTION, 265, 193, 95, 15, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT COMBOBOX IDC_DBG_TARGET, 235, 242, 126, 15, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT LTEXT "Debug Mode", IDC_STATIC, 205, 102, 42, 8, SS_LEFT, WS_EX_LEFT - LTEXT "Display env map for level:", IDC_STATIC, 205, 117, 82, 8, SS_LEFT, WS_EX_LEFT + LTEXT "Display special buffer", IDC_STATIC, 205, 117, 68, 9, SS_LEFT, WS_EX_LEFT LTEXT "Resolution Bias", IDC_STATIC, 205, 40, 50, 8, SS_LEFT, WS_EX_LEFT LTEXT "Select Action", IDC_STATIC, 216, 195, 43, 8, SS_LEFT, WS_EX_LEFT LTEXT "Target", IDC_STATIC, 207, 244, 25, 8, SS_LEFT, WS_EX_LEFT @@ -123,89 +125,92 @@ FONT 8, "Ms Shell Dlg" AUTOCHECKBOX "Use and Save the property", IDC_DBG_DEFINED, 20, 335, 101, 8, 0, WS_EX_LEFT AUTOCHECKBOX "Extend material range", IDC_DBG_EXTEND, 20, 321, 84, 8, 0, WS_EX_LEFT AUTOCHECKBOX "FPS Limiter", IDC_DBG_FPSLIM, 205, 25, 51, 8, 0, WS_EX_LEFT + PUSHBUTTON "Export textures", IDC_DBG_EXPTEX, 315, 410, 52, 14, 0, WS_EX_LEFT } LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK -IDD_D3D9SCATTER DIALOG 0, 0, 803, 295 +IDD_D3D9SCATTER DIALOG 0, 0, 823, 295 STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_GROUP | WS_POPUP | WS_SYSMENU CAPTION "Atmospheric Controls" FONT 8, "Ms Shell Dlg" { - AUTOCHECKBOX "Display Gamma Test", IDC_ATM_GAMMATEST, 262, 267, 81, 8, 0, WS_EX_LEFT - PUSHBUTTON "Copy To", IDC_ATM_COPYTO, 161, 265, 80, 14, 0, WS_EX_LEFT - GROUPBOX "Wavelength, Scale height settings", IDC_STATIC, 10, 5, 255, 250, 0, WS_EX_LEFT - CTEXT "Red", IDC_STATIC, 21, 21, 25, 8, SS_CENTER, WS_EX_LEFT - CTEXT "Configuration", IDC_STATIC, 20, 267, 42, 8, SS_CENTER, WS_EX_LEFT - CONTROL "", IDC_ATM_RED, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 25, 30, 15, 200, WS_EX_LEFT - EDITTEXT IDC_ATD_RED, 20, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - EDITTEXT IDC_ATD_GREEN, 55, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_GREEN, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 60, 30, 15, 200, WS_EX_LEFT - CTEXT "Green", IDC_STATIC, 56, 21, 25, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_BLUE, 90, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_BLUE, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 95, 30, 15, 200, WS_EX_LEFT - CTEXT "Blue", IDC_STATIC, 91, 21, 25, 8, SS_CENTER, WS_EX_LEFT - GROUPBOX "Rayleigh Settings", IDC_STATIC, 360, 5, 150, 250, 0, WS_EX_LEFT - EDITTEXT IDC_ATD_RPOW, 125, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_RPOW, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 130, 30, 15, 200, WS_EX_LEFT - CTEXT "R-Pow", IDC_STATIC, 125, 20, 22, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_MPOW, 160, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_MPOW, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 165, 30, 15, 200, WS_EX_LEFT - CTEXT "M-Pow", IDC_STATIC, 160, 20, 23, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_IN, 405, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_IN, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 410, 30, 15, 200, WS_EX_LEFT - CTEXT "Ratio", IDC_STATIC, 408, 20, 18, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_OUT, 370, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_OUT, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 375, 30, 15, 200, WS_EX_LEFT - CTEXT "Density", IDC_STATIC, 370, 20, 24, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_RPHASE, 440, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_RPHASE, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 445, 30, 15, 200, WS_EX_LEFT - CTEXT "Phase", IDC_STATIC, 440, 20, 26, 8, SS_CENTER, WS_EX_LEFT - GROUPBOX "Mie Settings", IDC_STATIC, 515, 5, 80, 250, 0, WS_EX_LEFT - GROUPBOX "Terrain", IDC_STATIC, 270, 5, 85, 250, 0, WS_EX_LEFT - EDITTEXT IDC_ATD_MIE, 526, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - EDITTEXT IDC_ATD_MPHASE, 561, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_MPHASE, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 566, 30, 15, 200, WS_EX_LEFT - CONTROL "", IDC_ATM_MIE, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 531, 30, 15, 200, WS_EX_LEFT - CTEXT "Density", IDC_STATIC, 520, 20, 36, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_ATMGAMMA, 475, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_ATMGAMMA, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 480, 30, 15, 200, WS_EX_LEFT - CTEXT "Gamma", IDC_STATIC, 475, 20, 25, 8, SS_CENTER, WS_EX_LEFT - CTEXT "Phase", IDC_STATIC, 561, 20, 25, 8, SS_CENTER, WS_EX_LEFT - GROUPBOX "Custom Settings", IDC_STATIC, 600, 5, 115, 250, 0, WS_EX_LEFT - GROUPBOX "Horizon Haze", IDC_STATIC, 720, 5, 75, 250, 0, WS_EX_LEFT - EDITTEXT IDC_ATD_AUX1, 610, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - EDITTEXT IDC_ATD_AUX2, 645, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_AUX2, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 650, 30, 15, 200, WS_EX_LEFT - CONTROL "", IDC_ATM_AUX1, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 615, 30, 15, 200, WS_EX_LEFT - CTEXT "Aux1", IDC_STATIC, 610, 20, 25, 8, SS_CENTER, WS_EX_LEFT - CTEXT "Aux2", IDC_STATIC, 645, 20, 25, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_AUX3, 680, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_AUX3, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 685, 30, 15, 200, WS_EX_LEFT - CTEXT "Aux3", IDC_STATIC, 680, 20, 25, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_HAZECLR, 725, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_HAZECLR, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 730, 30, 15, 200, WS_EX_LEFT - CTEXT "Color", IDC_STATIC, 729, 20, 17, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_HAZEITS, 760, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_HAZEITS, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 765, 30, 15, 200, WS_EX_LEFT - CTEXT "Intensity", IDC_STATIC, 759, 20, 27, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_HEIGHT, 195, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_HEIGHT, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 200, 30, 15, 200, WS_EX_LEFT - EDITTEXT IDC_ATD_TRGAMMA, 320, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CTEXT "Gamma", IDC_STATIC, 319, 20, 25, 8, SS_CENTER, WS_EX_LEFT - CONTROL "", IDC_ATM_TRGAMMA, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 325, 30, 15, 200, WS_EX_LEFT - EDITTEXT IDC_ATD_EXPO, 279, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_EXPO, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 284, 30, 15, 200, WS_EX_LEFT - CTEXT "Brightness", IDC_STATIC, 274, 20, 34, 8, SS_CENTER, WS_EX_LEFT - CTEXT "Height", IDC_STATIC, 195, 20, 22, 8, SS_CENTER, WS_EX_LEFT - EDITTEXT IDC_ATD_DEPTH, 230, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT - CONTROL "", IDC_ATM_DEPTH, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 235, 30, 15, 200, WS_EX_LEFT - CTEXT "Cloud Ints", IDC_STATIC, 226, 20, 32, 8, SS_CENTER, WS_EX_LEFT - PUSHBUTTON "Close", IDOK, 745, 265, 50, 14, 0, WS_EX_LEFT - PUSHBUTTON "Save Settings", IDC_ATM_SAVE, 570, 265, 60, 14, 0, WS_EX_LEFT - COMBOBOX IDC_ATM_MODE, 70, 265, 65, 14, CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_LEFT - PUSHBUTTON "Load Settings", IDC_ATM_LOAD, 505, 265, 60, 14, 0, WS_EX_LEFT + GROUPBOX "Twilight and Ambient settings", 0, 10, 5, 115, 250, 0, WS_EX_LEFT + AUTOCHECKBOX "Visualize Scatter Tables", IDC_ATM_DISPLAY, 361, 268, 91, 8, 0, WS_EX_LEFT + CONTROL "", IDC_ATM_AUX4, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 617, 30, 15, 200, WS_EX_LEFT + PUSHBUTTON "Copy To Surface", IDC_ATM_COPYTO, 140, 265, 60, 14, 0, WS_EX_LEFT + GROUPBOX "Wavelength, Scale height settings", IDC_STATIC, 130, 5, 190, 250, 0, WS_EX_LEFT + CTEXT "Configuration", IDC_STATIC, 14, 267, 42, 8, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_TW_DST, 20, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_TW_DST, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 25, 30, 15, 200, WS_EX_LEFT + CTEXT "Distance", IDC_STATIC, 20, 20, 29, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_GREEN, 140, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_GREEN, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 146, 30, 15, 200, WS_EX_LEFT + CTEXT "Green", IDC_STATIC, 145, 20, 20, 9, SS_CENTER, WS_EX_LEFT + GROUPBOX "Rayleigh Settings", IDC_STATIC, 450, 5, 75, 250, 0, WS_EX_LEFT + EDITTEXT IDC_ATD_RPOW, 175, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_RPOW, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 180, 30, 15, 200, WS_EX_LEFT + CTEXT "R-Pow", IDC_STATIC, 175, 20, 22, 8, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_MPOW, 210, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_MPOW, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 215, 30, 15, 200, WS_EX_LEFT + CTEXT "M-Pow", IDC_STATIC, 210, 20, 23, 8, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_IN, 495, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_IN, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 500, 30, 15, 200, WS_EX_LEFT + CTEXT "Ratio", IDC_STATIC, 498, 20, 18, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_RAY, 458, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_RAY, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 464, 30, 15, 200, WS_EX_LEFT + CTEXT "Density", IDC_STATIC, 460, 20, 24, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_RPHASE, 91, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_RPHASE, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 99, 30, 15, 200, WS_EX_LEFT + CTEXT "Building", IDC_STATIC, 94, 20, 26, 9, SS_CENTER, WS_EX_LEFT + GROUPBOX "Mie Settings", IDC_STATIC, 530, 5, 150, 250, 0, WS_EX_LEFT + GROUPBOX "Terrain", IDC_STATIC, 325, 5, 120, 250, 0, WS_EX_LEFT + EDITTEXT IDC_ATD_MIE, 541, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + EDITTEXT IDC_ATD_MPHASE, 576, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_MPHASE, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 581, 30, 15, 200, WS_EX_LEFT + CONTROL "", IDC_ATM_MIE, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 546, 30, 15, 200, WS_EX_LEFT + CTEXT "Density", IDC_STATIC, 538, 20, 30, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_TW_BRI, 55, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_TW_BRI, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 63, 30, 15, 200, WS_EX_LEFT + CTEXT "Terrain", IDC_STATIC, 60, 20, 23, 9, SS_CENTER, WS_EX_LEFT + CTEXT "Phase-A", IDC_STATIC, 577, 20, 28, 9, SS_CENTER, WS_EX_LEFT + GROUPBOX "Custom Settings", IDC_STATIC, 685, 5, 115, 250, 0, WS_EX_LEFT + EDITTEXT IDC_ATD_MIEIN, 645, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + EDITTEXT IDC_ATD_AUX2, 695, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_AUX2, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 700, 30, 15, 200, WS_EX_LEFT + CONTROL "", IDC_ATM_MIEIN, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 650, 30, 15, 200, WS_EX_LEFT + CTEXT "Ratio", IDC_STATIC, 647, 20, 25, 9, SS_CENTER, WS_EX_LEFT + CTEXT "CloudAlt", IDC_ATL_1, 695, 20, 27, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_AUX3, 730, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_AUX3, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 735, 30, 15, 200, WS_EX_LEFT + CTEXT "HDR", IDC_STATIC, 730, 20, 25, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_AUX4, 610, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CTEXT "Phase-B", IDC_STATIC, 611, 20, 28, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_AUX5, 765, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_AUX5, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 772, 30, 15, 200, WS_EX_LEFT + CTEXT "Intensity", IDC_ATL_2, 765, 20, 27, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_HEIGHT, 245, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_HEIGHT, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 250, 30, 15, 200, WS_EX_LEFT + EDITTEXT IDC_ATD_TRGAMMA, 373, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CTEXT "Gamma", IDC_STATIC, 375, 20, 25, 8, SS_CENTER, WS_EX_LEFT + CONTROL "", IDC_ATM_TRGAMMA, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 380, 30, 15, 200, WS_EX_LEFT + EDITTEXT IDC_ATD_TRB, 334, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_TRB, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 340, 30, 15, 200, WS_EX_LEFT + CTEXT "Brightness", IDC_STATIC, 330, 20, 34, 8, SS_CENTER, WS_EX_LEFT + CTEXT "R-Height", IDC_STATIC, 242, 20, 29, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_M_HEIGHT, 280, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT + CONTROL "", IDC_ATM_M_HEIGHT, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 285, 30, 15, 200, WS_EX_LEFT + CTEXT "M-Height", IDC_STATIC, 277, 20, 30, 9, SS_CENTER, WS_EX_LEFT + PUSHBUTTON "Close", IDOK, 730, 265, 50, 14, 0, WS_EX_LEFT + PUSHBUTTON "Save Settings", IDC_ATM_SAVE, 660, 265, 60, 14, 0, WS_EX_LEFT + COMBOBOX IDC_ATM_MODE, 59, 265, 65, 14, CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_LEFT + PUSHBUTTON "Load Settings", IDC_ATM_LOAD, 595, 265, 60, 14, 0, WS_EX_LEFT + PUSHBUTTON "Copy to Low Orbit", IDC_ATM_COPYLOW, 205, 265, 65, 14, 0, WS_EX_LEFT + PUSHBUTTON "Copy to High Orbit", IDC_ATM_COPYHIGH, 275, 265, 70, 14, 0, WS_EX_LEFT + CONTROL "", IDC_ATM_TRLIGHTSHAD, TRACKBAR_CLASS, WS_TABSTOP | TBS_VERT | TBS_BOTH | TBS_NOTICKS, 417, 30, 15, 200, WS_EX_LEFT + CTEXT "Light/Shad", IDC_STATIC, 407, 20, 36, 9, SS_CENTER, WS_EX_LEFT + EDITTEXT IDC_ATD_TRLIGHTSHAD, 410, 235, 30, 12, ES_CENTER | ES_AUTOHSCROLL | ES_READONLY, WS_EX_LEFT } @@ -232,15 +237,15 @@ FONT 8, "MS Sans Serif", 0, 0, 0 LTEXT "Render Mode", IDC_STATIC, 380, 166, 44, 8, SS_LEFT, WS_EX_LEFT COMBOBOX IDC_AF, 85, 125, 35, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT EDITTEXT IDC_PLANETGLOW, 85, 142, 35, 14, ES_AUTOHSCROLL, WS_EX_LEFT - AUTOCHECKBOX "Pre-load base visuals at startup", IDC_BASEVIS, 20, 220, 114, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Cloud micro-textures", IDC_CLOUDMICRO, 20, 280, 79, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Cloud normal maps", IDC_CLOUDNORM, 20, 294, 75, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Enable GDI Overlay", IDC_GDIOVERLAY, 20, 308, 79, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Enable absolute animation handling", IDC_ABSANIM, 20, 323, 127, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Enable terrain flattening", IDC_FLATS, 20, 337, 90, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Enable advanced texture maps", IDC_NORMALMAPS, 20, 235, 114, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Enable improved glass shading", IDC_GLASSSHADE, 20, 250, 113, 8, 0, WS_EX_LEFT - AUTOCHECKBOX "Disable near clip plane compatibility mode", IDC_NEARPLANE, 20, 265, 147, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Pre-load base visuals at startup", IDC_BASEVIS, 20, 240, 114, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable cloud micro-textures", IDC_CLOUDMICRO, 20, 292, 103, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable cloud normal maps", IDC_CLOUDNORM, 20, 305, 99, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable GDI Overlay", IDC_GDIOVERLAY, 20, 318, 79, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable absolute animation handling", IDC_ABSANIM, 20, 331, 127, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable terrain flattening", IDC_FLATS, 370, 286, 90, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable advanced texture maps", IDC_NORMALMAPS, 20, 252, 114, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable improved glass shading", IDC_GLASSSHADE, 20, 265, 113, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Disable near clip plane compatibility mode", IDC_NEARPLANE, 20, 279, 147, 8, 0, WS_EX_LEFT CONTROL "", IDC_LODBIAS, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS | TBS_TOP, 256, 147, 95, 20, WS_EX_LEFT CONTROL "", IDC_MESHRES, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS | TBS_TOP, 258, 182, 70, 20, WS_EX_LEFT CONTROL "", IDC_MICROBIAS, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS | TBS_TOP, 435, 222, 95, 20, WS_EX_LEFT @@ -253,14 +258,14 @@ FONT 8, "MS Sans Serif", 0, 0, 0 COMBOBOX IDC_SELFSHADOWS, 196, 310, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT COMBOBOX IDC_SHADOWFILTER, 291, 310, 65, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT COMBOBOX IDC_TERRAIN, 196, 335, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT - AUTOCHECKBOX "Enable mesh debugger", IDC_MESH_DEBUGGER, 200, 85, 89, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable Development Tools", IDC_MESH_DEBUGGER, 200, 85, 101, 8, 0, WS_EX_LEFT CONTROL "", IDC_CONVERGENCE, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS | TBS_TOP, 425, 20, 85, 20, WS_EX_LEFT CONTROL "", IDC_SEPARATION, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS | TBS_TOP, 425, 40, 85, 20, WS_EX_LEFT COMBOBOX IDC_ENVMODE, 440, 90, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT - COMBOBOX IDC_TEXMIPS, 85, 160, 80, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT - COMBOBOX IDC_POSTPROCESS, 85, 177, 80, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT - COMBOBOX IDC_GUIMODE, 85, 195, 80, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT - COMBOBOX IDC_ARCHIVE, 85, 60, 80, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT + COMBOBOX IDC_TEXMIPS, 85, 160, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT + COMBOBOX IDC_POSTPROCESS, 85, 177, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT + COMBOBOX IDC_GUIMODE, 85, 194, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT + COMBOBOX IDC_ARCHIVE, 85, 60, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT COMBOBOX IDC_CAMMODE, 440, 106, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT COMBOBOX IDC_ENVFACES, 440, 122, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT DEFPUSHBUTTON "OK", IDOK, 460, 355, 75, 19, 0, WS_EX_LEFT @@ -302,6 +307,13 @@ FONT 8, "MS Sans Serif", 0, 0, 0 LTEXT "Texture Bias", IDC_STATIC, 201, 153, 40, 8, SS_LEFT, WS_EX_LEFT LTEXT "Mesh resolution", IDC_STATIC, 201, 185, 50, 8, SS_LEFT, WS_EX_LEFT AUTOCHECKBOX "Enable debug break", IDC_BREAK, 200, 99, 80, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable sun glare", IDC_ESUNGLARE, 370, 274, 69, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable local lights glare", IDC_ELIGHTSGLARE, 370, 299, 90, 8, NOT WS_VISIBLE | WS_DISABLED, WS_EX_LEFT + AUTOCHECKBOX "Enable dynamic ambient light", IDC_EIRRAD, 370, 262, 107, 8, 0, WS_EX_LEFT + COMBOBOX IDC_EARTHVISCFG, 85, 212, 90, 15, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT + LTEXT "Earth visual config", IDC_STATIC, 17, 215, 59, 9, SS_LEFT, WS_EX_LEFT + AUTOCHECKBOX "Enable shader cache for faster startup", IDC_ESCACHE, 370, 250, 136, 8, 0, WS_EX_LEFT + AUTOCHECKBOX "Enable increased atmosphere quality", IDC_EAQUALITY, 20, 344, 131, 8, 0, WS_EX_LEFT } @@ -319,7 +331,7 @@ FONT 8, "Ms Shell Dlg" LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK -IDD_GRAPHICS DIALOG 0, 0, 277, 168 +IDD_GRAPHICS DIALOG 0, 0, 277, 214 STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU CAPTION "Graphics Controls" FONT 8, "Ms Shell Dlg" @@ -333,18 +345,19 @@ FONT 8, "Ms Shell Dlg" LTEXT "Value", IDC_GFX_VAL4, 235, 75, 19, 8, SS_LEFT, WS_EX_LEFT LTEXT "Value", IDC_GFX_VAL3, 235, 60, 19, 8, SS_LEFT, WS_EX_LEFT LTEXT "Light glow distance", IDC_STATIC, 15, 45, 62, 8, SS_LEFT, WS_EX_LEFT - LTEXT "Sunlight Intensity", IDC_STATIC, 15, 115, 54, 8, SS_LEFT, WS_EX_LEFT - LTEXT "Indirect Lighting", IDC_STATIC, 15, 130, 51, 8, SS_LEFT, WS_EX_LEFT - LTEXT "Local Lights Max", IDC_STATIC, 15, 145, 54, 8, SS_LEFT, WS_EX_LEFT + LTEXT "Sunlight Intensity", IDC_STATIC, 12, 115, 54, 8, SS_LEFT, WS_EX_LEFT + LTEXT "Indirect Lighting", IDC_STATIC, 12, 130, 51, 8, SS_LEFT, WS_EX_LEFT + LTEXT "Local Lights Max", IDC_STATIC, 12, 145, 54, 8, SS_LEFT, WS_EX_LEFT LTEXT "Gamma", IDC_STATIC, 15, 75, 25, 8, SS_LEFT, WS_EX_LEFT LTEXT "Glow threshold", IDC_STATIC, 15, 60, 48, 8, SS_LEFT, WS_EX_LEFT GROUPBOX "Post Processing Configuration", IDC_STATIC, 5, 10, 266, 80, 0, WS_EX_LEFT - GROUPBOX "Light Configuration", IDC_STATIC, 5, 100, 266, 65, 0, WS_EX_LEFT + GROUPBOX "Light Configuration", IDC_STATIC, 5, 100, 266, 80, 0, WS_EX_LEFT + PUSHBUTTON "ReCreate Sun/Glares", IDC_GFX_RECOMPILE, 200, 195, 73, 14, 0, WS_EX_LEFT CONTROL "", IDC_GFX_INTENSITY, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 30, 144, 12, WS_EX_LEFT CONTROL "", IDC_GFX_DISTANCE, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 45, 144, 12, WS_EX_LEFT CONTROL "", IDC_GFX_SUNLIGHT, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 115, 144, 12, WS_EX_LEFT CONTROL "", IDC_GFX_IRRADIANCE, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 130, 144, 12, WS_EX_LEFT - CONTROL "", IDC_GFX_LOCALMAX, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 145, 144, 12, WS_EX_LEFT + CONTROL "", IDC_GFX_LOCALMAX, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 146, 144, 12, WS_EX_LEFT CONTROL "", IDC_GFX_GAMMA, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 75, 144, 12, WS_EX_LEFT CONTROL "", IDC_GFX_THRESHOLD, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 60, 144, 12, WS_EX_LEFT PUSHBUTTON "", IDC_GFX_INTENSITY_RESET, 255, 27, 12, 12, BS_BITMAP, WS_EX_LEFT @@ -354,6 +367,10 @@ FONT 8, "Ms Shell Dlg" PUSHBUTTON "", IDC_GFX_LOCALMAX_RESET, 254, 145, 12, 12, BS_BITMAP, WS_EX_LEFT PUSHBUTTON "", IDC_GFX_GAMMA_RESET, 255, 73, 12, 12, BS_BITMAP, WS_EX_LEFT PUSHBUTTON "", IDC_GFX_THRESHOLD_RESET, 255, 57, 12, 12, BS_BITMAP, WS_EX_LEFT + LTEXT "Sun glare intensity", IDC_STATIC, 12, 161, 58, 9, SS_LEFT, WS_EX_LEFT + CONTROL "", IDC_GFX_GLARE, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 85, 161, 144, 12, WS_EX_LEFT + LTEXT "Value", IDC_GFX_VAL8, 233, 161, 19, 8, SS_LEFT, WS_EX_LEFT + PUSHBUTTON "", IDC_GFX_GLARE_RESET, 254, 160, 12, 12, BS_BITMAP, WS_EX_LEFT } diff --git a/OVP/D3D9Client/D3D9Config.cpp b/OVP/D3D9Client/D3D9Config.cpp index e9a26bc95..126cc8260 100644 --- a/OVP/D3D9Client/D3D9Config.cpp +++ b/OVP/D3D9Client/D3D9Config.cpp @@ -39,7 +39,7 @@ void D3D9Config::Reset () SceneAntialias = 4; DebugLvl = 1; VCNearPlane = 0.1; - LightConfig = 0; + LightConfig = 2; NearClipPlane = 0; NVPerfHUD = 0; PreLBaseVis = 0; @@ -55,7 +55,7 @@ void D3D9Config::Reset () BumpAmp = 1.0; PlanetGlow = 1.0; EnvMapSize = 256; - EnvMapMode = 0; + EnvMapMode = 1; EnvMapFaces = 1; EnableGlass = 1; EnableMeshDbg = 1; @@ -65,7 +65,7 @@ void D3D9Config::Reset () FrameRate = 200.0; EnableLimiter = 0; CustomCamMode = 1; - TileMipmaps = 0; + TileMipmaps = 1; TextureMips = 1; LODBias = 0.0; MeshRes = 1; @@ -78,29 +78,37 @@ void D3D9Config::Reset () ShaderDebug = 0; PresentLocation = 1; PlanetTileLoadFlags = 0x3; - TerrainShadowing = 1; + TerrainShadowing = 2; LabelDisplayFlags = LABEL_DISPLAY_RECORD | LABEL_DISPLAY_REPLAY; CloudMicro = 1; GDIOverlay = 0; gcGUIMode = 0; bAbsAnims = 0; bCloudNormals = 1; - bFlats = 0; + bFlats = 1; + bGlares = 1; + bLocalGlares = 0; DebugBreak = 0; ShaderCacheUse = 0; - + bIrradiance = 1; + bAtmoQuality = 1; + NoPlanetAA = 0; + GFXIntensity = 0.5; GFXDistance = 0.8; GFXThreshold = 1.1; GFXGamma = 1.0; GFXSunIntensity = 1.2; GFXLocalMax = 0.5; + GFXGlare = 0.3; DisableDriverManagement = 0; DisableVisualHelperReadout = 0; - SolCfg = new char[64]; strcpy_s(SolCfg,64,"Sol"); - DebugFont = new char[64]; strcpy_s(DebugFont,64,"Fixed"); + AtmoCfg["Earth"] = "Earth.atm.cfg"; + + SolCfg = new char[64]; strcpy_s(SolCfg,64,"Sol"); + DebugFont = new char[64]; strcpy_s(DebugFont,64,"Fixed"); } int D3D9Config::MaxLights() @@ -174,8 +182,13 @@ bool D3D9Config::ReadParams () if (oapiReadItem_int (hFile, "AbsoluteAnimations", i)) bAbsAnims = max(0, min(1, i)); if (oapiReadItem_int (hFile, "NormalmappedClouds", i)) bCloudNormals = max(0, min(1, i)); if (oapiReadItem_int (hFile, "TerrainFlats", i)) bFlats = max(0, min(1, i)); + if (oapiReadItem_int (hFile, "SunGlare", i)) bGlares = max(0, min(1, i)); + if (oapiReadItem_int (hFile, "LightsGlare", i)) bLocalGlares = max(0, min(1, i)); + if (oapiReadItem_int (hFile, "Irradiance", i)) bIrradiance = max(0, min(1, i)); + if (oapiReadItem_int (hFile, "AtmoQuality", i)) bAtmoQuality = max(0, min(1, i)); if (oapiReadItem_int (hFile, "DebugBreak", i)) DebugBreak = max(0, min(1, i)); - //if (oapiReadItem_int (hFile, "ShaderCacheUse", i)) ShaderCacheUse = max(0, min(1, i)); + if (oapiReadItem_int (hFile, "ShaderCacheUse", i)) ShaderCacheUse = max(0, min(1, i)); + if (oapiReadItem_int (hFile, "NoPlanetAA", i)) NoPlanetAA = max(0, min(1, i)); if (oapiReadItem_float (hFile, "OrbitalShadowMult", d)) OrbitalShadowMult = max(0.5, min(10.0, d)); if (oapiReadItem_float (hFile, "GFXIntensity", d)) GFXIntensity = max(0.0, min(1.0, d)); @@ -184,11 +197,15 @@ bool D3D9Config::ReadParams () if (oapiReadItem_float (hFile, "GFXGamma", d)) GFXGamma = max(0.3, min(2.5, d)); if (oapiReadItem_float (hFile, "GFXSunIntensity", d)) GFXSunIntensity = max(0.5, min(2.5, d)); if (oapiReadItem_float (hFile, "GFXLocalMax", d)) GFXLocalMax = max(0.001, min(1.0, d)); + if (oapiReadItem_float (hFile, "GFXGlare", d)) GFXGlare = max(0.1, min(10.0, d)); oapiReadItem_string (hFile, "SolCfg", SolCfg); oapiReadItem_string (hFile, "DebugLineFont", DebugFont); + char Temp[256]; + if (oapiReadItem_string(hFile, "EarthAtmoCfg", Temp)) AtmoCfg["Earth"] = Temp; + oapiCloseFile (hFile, FILE_IN_ZEROONFAIL); return true; @@ -254,19 +271,27 @@ void D3D9Config::WriteParams () oapiWriteItem_int (hFile, "AbsoluteAnimations", bAbsAnims); oapiWriteItem_int (hFile, "NormalmappedClouds", bCloudNormals); oapiWriteItem_int (hFile, "TerrainFlats", bFlats); + oapiWriteItem_int (hFile, "SunGlare", bGlares); + oapiWriteItem_int (hFile, "LightsGlare", bLocalGlares); + oapiWriteItem_int (hFile, "Irradiance", bIrradiance); + oapiWriteItem_int (hFile, "AtmoQuality", bAtmoQuality); oapiWriteItem_int (hFile, "DebugBreak", DebugBreak); oapiWriteItem_int (hFile, "ShaderCacheUse", ShaderCacheUse); - oapiWriteItem_float (hFile, "OrbitalShadowMult", OrbitalShadowMult); + oapiWriteItem_int (hFile, "NoPlanetAA", NoPlanetAA); + oapiWriteItem_float (hFile, "OrbitalShadowMult", OrbitalShadowMult); oapiWriteItem_float (hFile, "GFXIntensity", GFXIntensity); oapiWriteItem_float (hFile, "GFXDistance", GFXDistance); oapiWriteItem_float (hFile, "GFXThreshold", GFXThreshold); oapiWriteItem_float (hFile, "GFXGamma", GFXGamma); oapiWriteItem_float (hFile, "GFXSunIntensity", GFXSunIntensity); oapiWriteItem_float (hFile, "GFXLocalMax", GFXLocalMax); + oapiWriteItem_float (hFile, "GFXGlare", GFXGlare); oapiWriteItem_string (hFile, "SolCfg", SolCfg); oapiWriteItem_string (hFile, "DebugLineFont", DebugFont); + oapiWriteItem_string(hFile, "EarthAtmoCfg", (char *)AtmoCfg["Earth"].c_str()); + oapiCloseFile (hFile, FILE_OUT); } diff --git a/OVP/D3D9Client/D3D9Config.h b/OVP/D3D9Client/D3D9Config.h index fd9caeca2..de2cbcedc 100644 --- a/OVP/D3D9Client/D3D9Config.h +++ b/OVP/D3D9Client/D3D9Config.h @@ -7,6 +7,8 @@ #ifndef __D3D9CONFIG_H #define __D3D9CONFIG_H +#include +#include extern class D3D9Config *Config; @@ -90,6 +92,11 @@ class D3D9Config { int bAbsAnims; ///< Absolute animations int bCloudNormals; ///< Felix24's Cloud normals implementation test int bFlats; ///< Face's terrain flattening + int bGlares; + int bLocalGlares; + int bIrradiance; + int bAtmoQuality; + int NoPlanetAA; ///< Disable planet surface anti-aliasing to prevent white pixels at horizon char *DebugFont; ///< Font face for debug lines (default="Fixed") char *SolCfg; ///< Solar system to use (default="Sol") double GFXIntensity; ///< Post Processing | Light glow intensity (0.0...1.0, default=0.5) @@ -98,6 +105,9 @@ class D3D9Config { double GFXGamma; ///< Post Processing | Gamma (0.3...2.5, default=1.0) double GFXSunIntensity; ///< Light Configuration| Sunlight Intensity (0.5...2.5, default=1.2) double GFXLocalMax; ///< Light Configuration| Local Lights Max (0.001...1.0, default=0.5) + double GFXGlare; ///< Sun glare intensity| (0.001...1.0, default=0.5) + + std::map AtmoCfg; private: diff --git a/OVP/D3D9Client/D3D9Effect.cpp b/OVP/D3D9Client/D3D9Effect.cpp index 28b2a4c64..873754ed1 100644 --- a/OVP/D3D9Client/D3D9Effect.cpp +++ b/OVP/D3D9Client/D3D9Effect.cpp @@ -100,6 +100,7 @@ D3DXHANDLE D3D9Effect::eAtmColor = 0; D3DXHANDLE D3D9Effect::eProxySize = 0; D3DXHANDLE D3D9Effect::eMtrlAlpha = 0; D3DXHANDLE D3D9Effect::eKernel = 0; +D3DXHANDLE D3D9Effect::eAtmoParams = 0; // Shader Flow Controls D3DXHANDLE D3D9Effect::eFlow = 0; @@ -343,6 +344,7 @@ void D3D9Effect::D3D9TechInit(D3D9Client *_gc, LPDIRECT3DDEVICE9 _pDev, const ch if (Config->EnableMeshDbg) macro[m++].Name = "_DEBUG"; if (Config->EnvMapMode) macro[m++].Name = "_ENVMAP"; if (Config->PostProcess == PP_DEFAULT) macro[m++].Name = "_LIGHTGLOW"; + if (Config->bIrradiance && Config->EnvMapMode) macro[m++].Name = "_IRRADIANCE"; HR(D3DXCreateEffectFromFileA(pDev, name, macro, 0, D3DXSHADER_NO_PRESHADER|D3DXSHADER_PREFER_FLOW_CONTROL, 0, &FX, &errors)); @@ -448,6 +450,7 @@ void D3D9Effect::D3D9TechInit(D3D9Client *_gc, LPDIRECT3DDEVICE9 _pDev, const ch eGlowConst = FX->GetParameterByName(0,"gGlowConst"); eSHD = FX->GetParameterByName(0,"gSHD"); eKernel = FX->GetParameterByName(0,"kernel"); + eAtmoParams = FX->GetParameterByName(0,"gAtmo"); // ---------------------------------------------------------------------- eVP = FX->GetParameterByName(0,"gVP"); eW = FX->GetParameterByName(0,"gW"); @@ -650,6 +653,7 @@ void D3D9Effect::InitLegacyAtmosphere(OBJHANDLE hPlanet, float GlobalAmbient) void D3D9Effect::Render2DPanel(const MESHGROUP *mg, const SURFHANDLE pTex, const LPD3DXMATRIX pW, float alpha, float scale, bool additive) { UINT numPasses = 0; + if (!pTex || !mg || !pW) return; if (SURFACE(pTex)->IsPowerOfTwo() || (!gc->IsLimited())) FX->SetTechnique(ePanelTech); // ANISOTROPIC filter else FX->SetTechnique(ePanelTechB); // POINT filter (for non-pow2 conditional) @@ -747,14 +751,15 @@ void D3D9Effect::RenderSpot(float alpha, const LPD3DXCOLOR pColor, const LPD3DXM // =========================================================================================== // Used by Render Star only // -void D3D9Effect::RenderBillboard(const LPD3DXMATRIX pW, SURFHANDLE pTex) +void D3D9Effect::RenderBillboard(const LPD3DXMATRIX pW, LPDIRECT3DTEXTURE9 pTex, float alpha) { UINT numPasses = 0; HR(pDev->SetVertexDeclaration(pNTVertexDecl)); HR(FX->SetTechnique(eSimple)); HR(FX->SetMatrix(eW, pW)); - HR(FX->SetTexture(eTex0, SURFACE(pTex)->GetTexture())); + HR(FX->SetFloat(eMix, alpha)); + HR(FX->SetTexture(eTex0, pTex)); HR(FX->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); HR(FX->BeginPass(0)); HR(pDev->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, billboard_idx, D3DFMT_INDEX16, billboard_vtx, sizeof(NTVERTEX))); diff --git a/OVP/D3D9Client/D3D9Effect.h b/OVP/D3D9Client/D3D9Effect.h index cd2862a76..a9e2f8a31 100644 --- a/OVP/D3D9Client/D3D9Effect.h +++ b/OVP/D3D9Client/D3D9Effect.h @@ -59,7 +59,7 @@ class D3D9Effect { static void RenderTileBoundingBox(const LPD3DXMATRIX pW, VECTOR4 *pVtx, const LPD3DXVECTOR4 color); static void RenderBoundingBox(const LPD3DXMATRIX pW, const LPD3DXMATRIX pGT, const D3DXVECTOR4 *bmin, const D3DXVECTOR4 *bmax, const LPD3DXVECTOR4 color); static void RenderBoundingSphere(const LPD3DXMATRIX pW, const LPD3DXMATRIX pGT, const D3DXVECTOR4 *bs, const LPD3DXVECTOR4 color); - static void RenderBillboard(const LPD3DXMATRIX pW, SURFHANDLE pTex); + static void RenderBillboard(const LPD3DXMATRIX pW, LPDIRECT3DTEXTURE9 pTex, float alpha = 1.0f); static void RenderExhaust(const LPD3DXMATRIX pW, VECTOR3 &cdir, EXHAUSTSPEC *es, SURFHANDLE def); static void RenderSpot(float intens, const LPD3DXCOLOR color, const LPD3DXMATRIX pW, SURFHANDLE pTex); static void Render2DPanel(const MESHGROUP *mg, const SURFHANDLE pTex, const LPD3DXMATRIX pW, float alpha, float scale, bool additive); @@ -122,6 +122,7 @@ class D3D9Effect { static D3DXHANDLE eSun; ///< Sun static D3DXHANDLE eLights; ///< Additional light sources static D3DXHANDLE eKernel; + static D3DXHANDLE eAtmoParams; // Auxiliary params ---------------------------------------------- static D3DXHANDLE eModAlpha; ///< BOOL multiply material alpha with texture alpha diff --git a/OVP/D3D9Client/D3D9Frame.cpp b/OVP/D3D9Client/D3D9Frame.cpp index 6056b3622..7edb76540 100644 --- a/OVP/D3D9Client/D3D9Frame.cpp +++ b/OVP/D3D9Client/D3D9Frame.cpp @@ -33,6 +33,7 @@ IDirect3DVertexDeclaration9 *pVector4Decl = NULL; IDirect3DVertexDeclaration9 *pPosTexDecl = NULL; IDirect3DVertexDeclaration9 *pPatchVertexDecl = NULL; IDirect3DVertexDeclaration9 *pSketchpadDecl = NULL; +IDirect3DVertexDeclaration9 *pLocalLightsDecl = NULL; static char *d3dmessage={"Required DirectX version (June 2010 or newer) not found\0"}; @@ -125,6 +126,7 @@ HRESULT CD3DFramework9::DestroyObjects () SAFE_RELEASE(pMeshVertexDecl); SAFE_RELEASE(pPatchVertexDecl); SAFE_RELEASE(pSketchpadDecl); + SAFE_RELEASE(pLocalLightsDecl); Sleep(200); @@ -301,18 +303,6 @@ HRESULT CD3DFramework9::Initialize(HWND _hWnd, GraphicsClient::VIDEODATA *vData) // Do Some Additional Hardware Checks =================================================================== - - // Check vertex texture support - // - if (pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)==S_OK) { - bVertexTexture = true; - LogOapi("Vertex Texture.......... : Yes"); - } - else { - bVertexTexture = false; - LogOapi("Vertex Texture.......... : No"); - } - if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) { LogOapi("Separate AlphaBlend..... : Yes"); } @@ -337,6 +327,23 @@ HRESULT CD3DFramework9::Initialize(HWND _hWnd, GraphicsClient::VIDEODATA *vData) if (bFloat16BB) LogOapi("D3DFMT_A16B16G16R16F.... : Yes"); else LogOapi("D3DFMT_A16B16G16R16F.... : No"); + HRESULT VT16BB = pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F); + HRESULT VT32BB = pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F); + HRESULT VT16BC = pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F); + HRESULT VT32BC = pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R32F); + + if (VT16BB == S_OK) LogOapi("Vertex_A16B16G16R16F.... : Yes"); + else LogOapi("Vertex_A16B16G16R16F.... : No"); + if (VT32BB == S_OK) LogOapi("Vertex_A32B32G32R32F.... : Yes"); + else LogOapi("Vertex_A32B32G32R32F.... : No"); + if (VT16BC == S_OK) LogOapi("Vertex_R16F............. : Yes"); + else LogOapi("Vertex_R16F............. : No"); + if (VT32BC == S_OK) LogOapi("Vertex_R32F............. : Yes"); + else LogOapi("Vertex_R32F............. : No"); + + if (VT16BB != S_OK || VT32BB != S_OK || VT16BC != S_OK || VT32BC != S_OK) bFail = true; + + bool bFloat32BB = true; if (pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)!=S_OK) bFloat32BB = false; @@ -432,8 +439,9 @@ HRESULT CD3DFramework9::Initialize(HWND _hWnd, GraphicsClient::VIDEODATA *vData) HR(pDevice->CreateVertexDeclaration(MeshVertexDecl, &pMeshVertexDecl)); HR(pDevice->CreateVertexDeclaration(PatchVertexDecl, &pPatchVertexDecl)); HR(pDevice->CreateVertexDeclaration(SketchpadDecl, &pSketchpadDecl)); + HR(pDevice->CreateVertexDeclaration(LocalLightsDecl, &pLocalLightsDecl)); - // Setup some default fomts + // Setup some default fonts // D3DXFONT_DESC fontDesc; fontDesc.Height = 30; diff --git a/OVP/D3D9Client/D3D9Pad.h b/OVP/D3D9Client/D3D9Pad.h index 586e1d355..4eaadac73 100644 --- a/OVP/D3D9Client/D3D9Pad.h +++ b/OVP/D3D9Client/D3D9Pad.h @@ -533,6 +533,7 @@ class D3D9Pad : public Sketchpad void Clear(DWORD color = 0, bool bColor = true, bool bDepth = true); void SetClipDistance(float _near, float _far); void ColorKeyStretch(const SURFHANDLE hSrc, const LPRECT _s = NULL, const LPRECT t = NULL); + void SetWorldBillboard(const FVECTOR3& wpos, float utp = 1.0f, bool bFixed = true, const FVECTOR3* index = NULL); // =============================================================================== diff --git a/OVP/D3D9Client/D3D9Pad2.cpp b/OVP/D3D9Client/D3D9Pad2.cpp index d7f99f837..fa5879d16 100644 --- a/OVP/D3D9Client/D3D9Pad2.cpp +++ b/OVP/D3D9Client/D3D9Pad2.cpp @@ -358,9 +358,9 @@ void D3D9Pad::CopyTetragon(const SURFHANDLE hSrc, const LPRECT _s, const FVECTOR Log("CopyTetragon(0x%X)", DWORD(pSrc)); #endif FVECTOR2 sp[4]; - FVECTOR2 a, b, c, d; + FVECTOR2 a, b, c, d; static const int n = 6; - static const float step = 1.0 / float(n - 1); + static const float step = 1.0 / float(n - 1); DWORD fn = SKPSW_TEXTURE | SKPSW_CENTER; @@ -666,6 +666,29 @@ void D3D9Pad::SetWorldTransform(const FMATRIX4 *pWT) } +// =============================================================================================== +// +void D3D9Pad::SetWorldBillboard(const FVECTOR3& wpos, float scale, bool bFixed, const FVECTOR3* index) +{ +#ifdef SKPDBG + Log("SetWorldBillboard()"); +#endif + scale *= (mP._11 + mP._22) * 0.5f; + Change |= SKPCHG_TRANSFORM; + FVECTOR3 up = unit(wpos); + FVECTOR3 y = unit(cross((index ? *index : FVECTOR3(mV._11, mV._21, mV._31)), up)); + FVECTOR3 x = cross(up, y); + float d = (bFixed ? dot(up, wpos) / float(tgt_desc.Width) : 1.0f) * scale; + FMATRIX4 mWorld; + mWorld._x.xyz = x * d; + mWorld._y.xyz = y * d; + mWorld._z.xyz = up * d; + mWorld._p.xyz = wpos; + mWorld.m44 = 1.0f; + memcpy(&mW, &mWorld, sizeof(FMATRIX4)); +} + + // =============================================================================================== // void D3D9Pad::SetGlobalLineScale(float width, float pat) diff --git a/OVP/D3D9Client/D3D9Util.cpp b/OVP/D3D9Client/D3D9Util.cpp index 432a62dc4..e39e17596 100644 --- a/OVP/D3D9Client/D3D9Util.cpp +++ b/OVP/D3D9Client/D3D9Util.cpp @@ -35,6 +35,19 @@ DWORD BuildDate() return (year % 100) * 10000 + m * 100 + day; } +WORD crc16(const char *data, int length) +{ + DWORD crc = 0; + for (int i = 0; i < length; ++i) { + crc = crc ^ (DWORD(data[i]) << 8); + for (int j = 0; j < 8; j++) { + if (crc & 0x8000) crc = (crc << 1) ^ 0x1021; + else crc = (crc << 1); + crc &= 0xFFFF; + } + } + return WORD(crc & 0xFFFF); +} #if _WIN64 #define PTR_FMT_STRING "0x%llX" @@ -108,10 +121,10 @@ bool CopyBuffer(LPDIRECT3DRESOURCE9 _pDst, LPDIRECT3DRESOURCE9 _pSrc) void LogMatrix(D3DXMATRIX *pM, const char *name) { LogAlw("%s", name); - LogAlw("[%2.2g, %2.2g, %2.2g %2.2g]", pM->_11, pM->_12, pM->_13, pM->_14); - LogAlw("[%2.2g, %2.2g, %2.2g %2.2g]", pM->_21, pM->_22, pM->_23, pM->_24); - LogAlw("[%2.2g, %2.2g, %2.2g %2.2g]", pM->_31, pM->_32, pM->_33, pM->_34); - LogAlw("[%2.2g, %2.2g, %2.2g %2.2g]", pM->_41, pM->_42, pM->_43, pM->_44); + LogAlw("[%9.9g, %9.9g, %9.9g, %9.9g]", pM->_11, pM->_12, pM->_13, pM->_14); + LogAlw("[%9.9g, %9.9g, %9.9g, %9.9g]", pM->_21, pM->_22, pM->_23, pM->_24); + LogAlw("[%9.9g, %9.9g, %9.9g, %9.9g]", pM->_31, pM->_32, pM->_33, pM->_34); + LogAlw("[%9.9g, %9.9g, %9.9g, %9.9g]", pM->_41, pM->_42, pM->_43, pM->_44); } inline D3DXVECTOR4 CV2VEC4(const D3DCOLORVALUE &in) @@ -249,98 +262,10 @@ void SurfaceLighting(D3D9Sun *light, OBJHANDLE hP, OBJHANDLE hO, float ao) lcol *= 1.0f-amb*0.5f; // reduce direct light component to avoid overexposure } - light->Color = D3DXCOLOR(lcol.x, lcol.y, lcol.z, 1.0f); + light->Color = D3DXCOLOR(lcol.x, lcol.y, lcol.z, 1.0f); light->Ambient = D3DXCOLOR(amb, amb, amb, 1.0f); light->Dir = D3DXVEC(S) * (-1.0f/s); } - -void OrbitalLighting(D3D9Sun *light, const vPlanet *vP, const VECTOR3 &GO, float ao) -{ - VECTOR3 GS, GP; - - OBJHANDLE hP = vP->GetObject(); - - D3DXVECTOR3 _one(1,1,1); - - OBJHANDLE hS = oapiGetGbodyByIndex(0); // the central star - oapiGetGlobalPos(hS, &GS); // sun position - oapiGetGlobalPos(hP, &GP); // planet position - - VECTOR3 S = GS-GO; // sun's position from object - VECTOR3 P = GO-GP; - - double s = length(S); - - float pwr = 1.0f; - - if (hP==hS) { - light->Color = D3DXCOLOR(pwr, pwr, pwr, 1.0f); - light->Ambient = D3DXCOLOR(ao, ao, ao, 1.0f); - light->Dir = D3DXVEC(S) * (-1.0f / float(s)); - return; - } - - double r = length(P); - double pres = 1000.0; - double size = oapiGetSize(hP) + vP->GetMinElevation(); - double grav = oapiGetMass(hP) * 6.67259e-11 / (size*size); - - float aalt = 1.0f; - float amb0 = 0.0f; - float disp = 0.0f; - float amb = 0.0f; - float aq = 0.342f; - float ae = 0.242f; - float al = 0.0f; - float k = float(sqrt(r*r-size*size)); // HOrizon distance - float alt = float(r-size); - float rs = float(oapiGetSize(hS) / s); - float ac = float(-dotp(S,P)/(r*s)); // sun elevation - - // Avoid some fault conditions - if (alt<0) alt=0, k=1e3, size = r; - - if (ac>1.0f) ac=1.0f; if (ac<-1.0f) ac=-1.0f; - - ac = acos(ac) - asin(float(size/r)); - - if (ac>1.39f) ac = 1.39f; - if (ac<-1.39f) ac = -1.39f; - - float h = tan(ac); - - const ATMCONST *atm = (oapiGetObjectType(hP)==OBJTP_PLANET ? oapiGetPlanetAtmConstants (hP) : NULL); - - if (atm) { - aalt = float(atm->p0 * log(atm->p0/pres) / (atm->rho0*grav)); - amb0 = float(min (0.7, log1p(atm->rho0)*0.4)); - disp = float(max (0.02, min(0.9, log1p(atm->rho0)))); - } - - if (alt>10e3f) al = aalt / k; - else al = 0.173f; - - D3DXVECTOR3 lcol(1,1,1); - //D3DXVECTOR3 r0 = _one - D3DXVECTOR3(0.65f, 0.75f, 1.0f) * disp; - D3DXVECTOR3 r0 = _one - D3DXVECTOR3(1.15f, 1.65f, 2.35f) * disp; - - if (atm) { - lcol = (r0 + (_one-r0) * saturate((h/al))) * saturate((h+rs)/(2.0f*rs)); - amb = amb0 / (alt*0.5e-4f + 1.0f); - amb = saturate(max(amb*saturate(((h+ae)/aq)-0.05f), ao)); - lcol *= 1.0f-amb*0.5f; // reduce direct light component to avoid overexposure - } - else { - lcol = r0 * saturate((h+rs)/(2.0f*rs)); - amb = ao; - lcol *= 1.0f-amb*0.5f; // reduce direct light component to avoid overexposure - } - - light->Color = D3DXCOLOR(lcol.x*pwr, lcol.y*pwr, lcol.z*pwr, 1.0f); - light->Ambient = D3DXCOLOR(amb, amb, amb, 1.0f); - light->Dir = D3DXVEC(S) * (-1.0f / float(s)); -} - // =========================================== // Remove unecessary spaces and tablations // when reading a file. @@ -972,11 +897,14 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(LPDIRECT3DDEVICE9 pDev, const char *fi char *str = NULL; char *tok = NULL; + WORD crc = 0; + if (options) crc = crc16(options, strlen(options)); + string path(file); char filename[MAX_PATH]; string last = path.substr(path.find_last_of("\\/") + 1); - sprintf_s(filename, MAX_PATH, "Cache/Shaders/%s_%s_%s.bin", name, function, last.c_str()); + sprintf_s(filename, MAX_PATH, "Cache/D3D9Client/Shaders/%s_%s_%hX_%s.bin", name, function, crc, last.c_str()); if (Config->ShaderCacheUse) { @@ -997,7 +925,8 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(LPDIRECT3DDEVICE9 pDev, const char *fi { DWORD size = GetFileSize(hCacheRead, NULL); DWORD* buffer = new DWORD[(size >> 2) + 1]; - if (ReadFile(hCacheRead, buffer, size, NULL, NULL)) { + DWORD bytesRead; + if (ReadFile(hCacheRead, buffer, size, &bytesRead, NULL)) { HR(pDev->CreatePixelShader(buffer, &pShader)); HR(D3DXGetShaderConstantTable(buffer, pConst)); } @@ -1010,7 +939,7 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(LPDIRECT3DDEVICE9 pDev, const char *fi CloseHandle(hCacheRead); if (pShader) { - LogOapi("Shader Created From Cache: %s", filename); + //LogOapi("Shader Created From Cache: %s", filename); return pShader; } } @@ -1024,7 +953,7 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(LPDIRECT3DDEVICE9 pDev, const char *fi memset(¯o, 0, 16*sizeof(D3DXMACRO)); bool bDisassemble = false; - LogAlw("Compiling a Shader [%s] function [%s]...", file, function); + LogAlw("Compiling a Shader [%s] function [%s] name [%s]...", file, function, name); if (options) { int m = 0; @@ -1062,7 +991,8 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(LPDIRECT3DDEVICE9 pDev, const char *fi { HANDLE hCache = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hCache != INVALID_HANDLE_VALUE) { - if (!WriteFile(hCache, pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, NULL)) + DWORD bytesWritten; + if (!WriteFile(hCache, pCode->GetBufferPointer(), pCode->GetBufferSize(), &bytesWritten, NULL)) { LogErr("CreateShaderCache: WriteFile Error: 0x%X", GetLastError()); } @@ -1107,12 +1037,14 @@ LPDIRECT3DVERTEXSHADER9 CompileVertexShader(LPDIRECT3DDEVICE9 pDev, const char * LPDIRECT3DVERTEXSHADER9 pShader = NULL; DWORD flags = 0; + WORD crc = 0; + if (options) crc = crc16(options, strlen(options)); string path(file); char filename[MAX_PATH]; string last = path.substr(path.find_last_of("\\/") + 1); - sprintf_s(filename, MAX_PATH, "Cache/Shaders/%s_%s_%s.bin", name, function, last.c_str()); + sprintf_s(filename, MAX_PATH, "Cache/D3D9Client/Shaders/%s_%s_%hX_%s.bin", name, function, crc, last.c_str()); if (Config->ShaderCacheUse) { @@ -1133,7 +1065,8 @@ LPDIRECT3DVERTEXSHADER9 CompileVertexShader(LPDIRECT3DDEVICE9 pDev, const char * { DWORD size = GetFileSize(hCacheRead, NULL); DWORD* buffer = new DWORD[(size >> 2) + 1]; - if (ReadFile(hCacheRead, buffer, size, NULL, NULL)) { + DWORD bytesRead; + if (ReadFile(hCacheRead, buffer, size, &bytesRead, NULL)) { HR(pDev->CreateVertexShader(buffer, &pShader)); HR(D3DXGetShaderConstantTable(buffer, pConst)); } @@ -1146,7 +1079,7 @@ LPDIRECT3DVERTEXSHADER9 CompileVertexShader(LPDIRECT3DDEVICE9 pDev, const char * CloseHandle(hCacheRead); if (pShader) { - LogOapi("Shader Created From Cache: %s", filename); + //LogOapi("Shader Created From Cache: %s", filename); return pShader; } } @@ -1194,7 +1127,8 @@ LPDIRECT3DVERTEXSHADER9 CompileVertexShader(LPDIRECT3DDEVICE9 pDev, const char * HANDLE hCache = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hCache != INVALID_HANDLE_VALUE) { - if (!WriteFile(hCache, pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, NULL)) + DWORD bytesWritten; + if (!WriteFile(hCache, pCode->GetBufferPointer(), pCode->GetBufferSize(), &bytesWritten, NULL)) { LogErr("CreateShaderCache: WriteFile Error: 0x%X", GetLastError()); } @@ -1305,7 +1239,7 @@ D3D9Light::D3D9Light() : cosp(0), tanp(0), cosu(0), range(0), range2(0), intensity(-1.0), - le(NULL) + le(NULL), cone(1.0f), GPUId(-1) { } @@ -1322,6 +1256,8 @@ D3D9Light::~D3D9Light() void D3D9Light::Reset() { intensity = -1.0f; + cone = 1.0f; + GPUId = -1; } // ============================================================================ @@ -1376,6 +1312,7 @@ void D3D9Light::UpdateLight(const LightEmitter *_le, const class vObject *vo) tanp = 0.0f; cosu = 1.0f; cosp = 1.0f; + cone = 1.0f; float P = 0.0f; float U = 0.0f; @@ -1436,6 +1373,8 @@ void D3D9Light::UpdateLight(const LightEmitter *_le, const class vObject *vo) // ----------------------------------------------------------------------------- if (Type != 0) { D3DXVec3TransformNormal(&Direction, &D3DXVEC(le->GetDirection()), vo->MWorld()); + float angle = acos(dot(unit(Position), Direction)); + cone = ilerp(U * 0.5f, P * 0.5f, angle); } } @@ -1591,7 +1530,9 @@ SketchMesh::SketchMesh(LPDIRECT3DDEVICE9 _pDev) : pDev(_pDev), Tex(NULL), Grp(NULL), - Mtrl(NULL) + Mtrl(NULL), + pIB(NULL), + pVB(NULL) { } @@ -1744,7 +1685,7 @@ D3DXCOLOR SketchMesh::GetMaterial(DWORD idx) ShaderClass::ShaderClass(LPDIRECT3DDEVICE9 pDev, const char* file, const char* vs, const char* ps, const char *name, const char* options) : pPS(), pVS(), pPSCB(NULL), pVSCB(NULL), pDev(pDev), fn(file), psn(ps), vsn(vs), sn(name) { - for (int i = 0; i < ARRAYSIZE(pTextures); i++) pTextures[i] = {}; + for (int i = 0; i < ARRAYSIZE(pTextures); i++) pTextures[i] = {0}; pPS = CompilePixelShader(pDev, file, ps, name, options, &pPSCB); pVS = CompileVertexShader(pDev, file, vs, name, options, &pVSCB); } @@ -1762,14 +1703,77 @@ ShaderClass::~ShaderClass() void ShaderClass::ClearTextures() { - for (int idx = 0; idx < ARRAYSIZE(pTextures); idx++) pTextures[idx].pTex = NULL; + for (int idx = 0; idx < ARRAYSIZE(pTextures); idx++) + { + pTextures[idx].pAssigned = NULL; + pTextures[idx].pTex = NULL; + pTextures[idx].bSamplerSet = false; + } +} + +void ShaderClass::DetachTextures() +{ + ClearTextures(); + for (int i = 0; i < 16; i++) HR(pDev->SetTexture(i, NULL)); + + HR(pDev->SetTexture(D3DVERTEXTEXTURESAMPLER0, NULL)); + HR(pDev->SetTexture(D3DVERTEXTEXTURESAMPLER1, NULL)); + HR(pDev->SetTexture(D3DVERTEXTEXTURESAMPLER2, NULL)); + HR(pDev->SetTexture(D3DVERTEXTEXTURESAMPLER3, NULL)); } -void ShaderClass::Activate() +void ShaderClass::UpdateTextures() { - HR(pDev->SetVertexShader(pVS)); - HR(pDev->SetPixelShader(pPS)); + // Set textures and samplers ----------------------------------------------- + // + for (int idx = 0; idx < ARRAYSIZE(pTextures); idx++) + { + int sid = idx > 15 ? idx - 16 + D3DVERTEXTEXTURESAMPLER0 : idx; + + if (pTextures[idx].pTex == NULL) continue; + + // If sampler state is not set, then set it + // + if (!pTextures[idx].bSamplerSet) + { + pTextures[idx].bSamplerSet = true; + DWORD flags = pTextures[idx].Flags; + + if (flags & IPF_CLAMP_U) pDev->SetSamplerState(sid, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + else if (flags & IPF_MIRROR_U) pDev->SetSamplerState(sid, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR); + else pDev->SetSamplerState(sid, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); + + if (flags & IPF_CLAMP_V) pDev->SetSamplerState(sid, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + else if (flags & IPF_MIRROR_V) pDev->SetSamplerState(sid, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR); + else pDev->SetSamplerState(sid, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); + + if (flags & IPF_CLAMP_W) pDev->SetSamplerState(sid, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP); + else if (flags & IPF_MIRROR_W) pDev->SetSamplerState(sid, D3DSAMP_ADDRESSW, D3DTADDRESS_MIRROR); + else pDev->SetSamplerState(sid, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP); + + DWORD filter = D3DTEXF_POINT; + + if (flags & IPF_LINEAR) filter = D3DTEXF_LINEAR; + if (flags & IPF_PYRAMIDAL) filter = D3DTEXF_PYRAMIDALQUAD; + if (flags & IPF_GAUSSIAN) filter = D3DTEXF_GAUSSIANQUAD; + if (flags & IPF_ANISOTROPIC) filter = D3DTEXF_ANISOTROPIC; + + HR(pDev->SetSamplerState(sid, D3DSAMP_SRGBTEXTURE, false)); + HR(pDev->SetSamplerState(sid, D3DSAMP_MAXANISOTROPY, pTextures[idx].AnisoLvl)); + HR(pDev->SetSamplerState(sid, D3DSAMP_MAGFILTER, filter)); + HR(pDev->SetSamplerState(sid, D3DSAMP_MINFILTER, filter)); + if (idx <= 15) { HR(pDev->SetSamplerState(sid, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR)); } + else { HR(pDev->SetSamplerState(sid, D3DSAMP_MIPFILTER, D3DTEXF_POINT)); } + } + + // If texture has changed then assign it + if (pTextures[idx].pTex != pTextures[idx].pAssigned) + { + pTextures[idx].pAssigned = pTextures[idx].pTex; + HR(pDev->SetTexture(sid, pTextures[idx].pTex)); + } + } } @@ -1800,7 +1804,8 @@ void ShaderClass::Setup(LPDIRECT3DVERTEXDECLARATION9 pDecl, bool bZ, int blend) HR(pDev->SetVertexShader(pVS)); HR(pDev->SetPixelShader(pPS)); - HR(pDev->SetVertexDeclaration(pDecl)); + + if (pDecl) HR(pDev->SetVertexDeclaration(pDecl)); HR(pDev->SetRenderState(D3DRS_POINTSPRITEENABLE, false)); HR(pDev->SetRenderState(D3DRS_ALPHATESTENABLE, false)); @@ -1824,97 +1829,157 @@ void ShaderClass::Setup(LPDIRECT3DVERTEXDECLARATION9 pDecl, bool bZ, int blend) HR(pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)); } - // Set textures and samplers ----------------------------------------------- - // - for (int idx = 0; idx < ARRAYSIZE(pTextures); idx++) - { - if (pTextures[idx].pTex == NULL) continue; + if (blend == 3) { + HR(pDev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX)); + HR(pDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE)); + HR(pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE)); + } - DWORD flags = pTextures[idx].Flags; + if (blend == 4) { + HR(pDev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD)); + HR(pDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)); + HR(pDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE)); + } +} - if (flags & IPF_CLAMP_U) pDev->SetSamplerState(idx, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - else if (flags & IPF_MIRROR_U) pDev->SetSamplerState(idx, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR); - else pDev->SetSamplerState(idx, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); - if (flags & IPF_CLAMP_V) pDev->SetSamplerState(idx, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - else if (flags & IPF_MIRROR_V) pDev->SetSamplerState(idx, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR); - else pDev->SetSamplerState(idx, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); +HANDLE ShaderClass::GetPSHandle(const char* name) +{ + D3DXHANDLE hVar = pPSCB->GetConstantByName(NULL, name); + return HANDLE(hVar); +} - if (flags & IPF_CLAMP_W) pDev->SetSamplerState(idx, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP); - else if (flags & IPF_MIRROR_W) pDev->SetSamplerState(idx, D3DSAMP_ADDRESSW, D3DTADDRESS_MIRROR); - else pDev->SetSamplerState(idx, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP); - DWORD filter = D3DTEXF_POINT; +HANDLE ShaderClass::GetVSHandle(const char* name) +{ + D3DXHANDLE hVar = pVSCB->GetConstantByName(NULL, name); + return HANDLE(hVar); +} - if (flags & IPF_LINEAR) filter = D3DTEXF_LINEAR; - if (flags & IPF_PYRAMIDAL) filter = D3DTEXF_PYRAMIDALQUAD; - if (flags & IPF_GAUSSIAN) filter = D3DTEXF_GAUSSIANQUAD; - if (flags & IPF_ANISOTROPIC) filter = D3DTEXF_ANISOTROPIC; - HR(pDev->SetSamplerState(idx, D3DSAMP_SRGBTEXTURE, false)); - HR(pDev->SetSamplerState(idx, D3DSAMP_MAXANISOTROPY, pTextures[idx].AnisoLvl)); - HR(pDev->SetSamplerState(idx, D3DSAMP_MAGFILTER, filter)); - HR(pDev->SetSamplerState(idx, D3DSAMP_MINFILTER, filter)); - HR(pDev->SetSamplerState(idx, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR)); - HR(pDev->SetTexture(idx, pTextures[idx].pTex)); - } +void ShaderClass::SetTexture(const char* name, LPDIRECT3DTEXTURE9 pTex, UINT flags, UINT aniso) +{ + D3DXHANDLE hVar = pPSCB->GetConstantByName(NULL, name); + SetTexture((HANDLE)hVar, pTex, flags, aniso); } +void ShaderClass::SetTextureVS(const char* name, LPDIRECT3DTEXTURE9 pTex, UINT flags, UINT aniso) +{ + D3DXHANDLE hVar = pVSCB->GetConstantByName(NULL, name); + SetTextureVS((HANDLE)hVar, pTex, flags, aniso); +} -void ShaderClass::SetTexture(const char* name, LPDIRECT3DTEXTURE9 pTex, UINT flags, UINT aniso) +void ShaderClass::SetPSConstants(const char* name, void* data, UINT bytes) { D3DXHANDLE hVar = pPSCB->GetConstantByName(NULL, name); +#ifdef SHDCLSDBG + if (!hVar) { + LogErr("Shader::SetPSConstants() Invalid variable name [%s]. File[%s], Entrypoint[%s], Shader[%s]", name, fn.c_str(), psn.c_str(), sn.c_str()); + assert(false); + } +#endif + if (!hVar) return; + if (pPSCB->SetValue(pDev, hVar, data, bytes) != S_OK) { + LogErr("Shader::SetPSConstants() Failed. Variable[%s], File[%s], Entrypoint[%s]", name, fn.c_str(), psn.c_str()); + } +} +void ShaderClass::SetVSConstants(const char* name, void* data, UINT bytes) +{ + D3DXHANDLE hVar = pVSCB->GetConstantByName(NULL, name); +#ifdef SHDCLSDBG if (!hVar) { - LogErr("Shader::SetTexture() Invalid variable name [%s]. File[%s], Entrypoint[%s], Shader[%s]", name, fn.c_str(), psn.c_str(), sn.c_str()); - return; + LogErr("Shader::SetVSConstants() Invalid variable name [%s]. File[%s], Entrypoint[%s], Shader[%s]", name, fn.c_str(), psn.c_str(), sn.c_str()); + assert(false); + } +#endif + if (!hVar) return; + if (pVSCB->SetValue(pDev, hVar, data, bytes) != S_OK) { + LogErr("Shader::SetVSConstants() Failed. Variable[%s], File[%s], Entrypoint[%s]", name, fn.c_str(), vsn.c_str()); } +} + - DWORD idx = pPSCB->GetSamplerIndex(hVar); - assert(idx < 16); +void ShaderClass::SetTexture(HANDLE hVar, LPDIRECT3DTEXTURE9 pTex, UINT flags, UINT aniso) +{ +#ifdef SHDCLSDBG + if (!hVar) { + LogErr("Shader::SetTexture() Invalid handle. File[%s], Entrypoint[%s], Shader[%s]", fn.c_str(), psn.c_str(), sn.c_str()); + assert(false); + } +#endif + if (!hVar) return; + DWORD idx = pPSCB->GetSamplerIndex(D3DXHANDLE(hVar)); if (!pTex) { pTextures[idx].pTex = NULL; return; } + if (pTextures[idx].Flags != flags) pTextures[idx].bSamplerSet = false; + if (pTextures[idx].AnisoLvl != aniso) pTextures[idx].bSamplerSet = false; + pTextures[idx].pTex = pTex; pTextures[idx].Flags = flags; pTextures[idx].AnisoLvl = aniso; } - -void ShaderClass::SetPSConstants(const char* name, void* data, UINT bytes) +void ShaderClass::SetTextureVS(HANDLE hVar, LPDIRECT3DTEXTURE9 pTex, UINT flags, UINT aniso) { - D3DXHANDLE hVar = pPSCB->GetConstantByName(NULL, name); - +#ifdef SHDCLSDBG if (!hVar) { - LogErr("Shader::SetPSConstants() Invalid variable name [%s]. File[%s], Entrypoint[%s], Shader[%s]", name, fn.c_str(), psn.c_str(), sn.c_str()); - return; + LogErr("Shader::SetTextureVS() Invalid handle. File[%s], Entrypoint[%s], Shader[%s]", fn.c_str(), psn.c_str(), sn.c_str()); + assert(false); } +#endif + if (!hVar) return; + DWORD idx = pVSCB->GetSamplerIndex(D3DXHANDLE(hVar)) + 16; + assert(idx < 20); - if (pPSCB->SetValue(pDev, hVar, data, bytes) != S_OK) { - LogErr("Shader::SetPSConstants() Failed. Variable[%s], File[%s], Entrypoint[%s]", name, fn.c_str(), psn.c_str()); + if (!pTex) { + pTextures[idx].pTex = NULL; + return; } + + if (pTextures[idx].Flags != flags) pTextures[idx].bSamplerSet = false; + if (pTextures[idx].AnisoLvl != aniso) pTextures[idx].bSamplerSet = false; + + pTextures[idx].pTex = pTex; + pTextures[idx].Flags = flags | IPF_VERTEXTEX; + pTextures[idx].AnisoLvl = aniso; } -void ShaderClass::SetVSConstants(const char* name, void* data, UINT bytes) -{ - D3DXHANDLE hVar = pVSCB->GetConstantByName(NULL, name); +void ShaderClass::SetPSConstants(HANDLE hVar, void* data, UINT bytes) +{ +#ifdef SHDCLSDBG if (!hVar) { - LogErr("Shader::SetVSConstants() Invalid variable name [%s]. File[%s], Entrypoint[%s], Shader[%s]", name, fn.c_str(), psn.c_str(), sn.c_str()); - return; + LogErr("Shader::SetPSConstants() Invalid handle. File[%s], Entrypoint[%s], Shader[%s]", fn.c_str(), psn.c_str(), sn.c_str()); + assert(false); } - - if (pVSCB->SetValue(pDev, hVar, data, bytes) != S_OK) { - LogErr("Shader::SetVSConstants() Failed. Variable[%s], File[%s], Entrypoint[%s]", name, fn.c_str(), vsn.c_str()); +#endif + if (!hVar) return; + if (pVSCB->SetValue(pDev, D3DXHANDLE(hVar), data, bytes) != S_OK) { + LogErr("Shader::SetPSConstants() Failed. File[%s], Entrypoint[%s]", fn.c_str(), vsn.c_str()); } } - +void ShaderClass::SetVSConstants(HANDLE hVar, void* data, UINT bytes) +{ +#ifdef SHDCLSDBG + if (!hVar) { + LogErr("Shader::SetVSConstants() Invalid handle. File[%s], Entrypoint[%s], Shader[%s]", fn.c_str(), psn.c_str(), sn.c_str()); + assert(false); + } +#endif + if (!hVar) return; + if (pVSCB->SetValue(pDev, D3DXHANDLE(hVar), data, bytes) != S_OK) { + LogErr("Shader::SetVSConstants() Failed. File[%s], Entrypoint[%s]", fn.c_str(), vsn.c_str()); + } +} + diff --git a/OVP/D3D9Client/D3D9Util.h b/OVP/D3D9Client/D3D9Util.h index d5e875c9a..c84c08285 100644 --- a/OVP/D3D9Client/D3D9Util.h +++ b/OVP/D3D9Client/D3D9Util.h @@ -147,6 +147,19 @@ const D3DVERTEXELEMENT9 HazeVertexDecl[] = { D3DDECL_END() }; +const D3DVERTEXELEMENT9 LocalLightsDecl[] = { + {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, //Primitive Index + {0, 4, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, //Position .xyz and cone .w + D3DDECL_END() +}; + +typedef struct +{ + float index; + FVECTOR3 pos; + float cone; +} LocalLightsCompute; + typedef struct { float x; ///< vertex x position float y; ///< vertex y position @@ -204,6 +217,9 @@ class D3D9Light : public LightStruct void UpdateLight(const LightEmitter *le, const class vObject *vo); void Reset(); const LightEmitter *GetEmitter() const; + + float cone; + int GPUId; private: float cosp, tanp, cosu; float range, range2; @@ -255,10 +271,14 @@ class SketchMesh D3DXCOLOR* Mtrl; }; +#pragma pack(push, 4) + typedef struct { - D3DXVECTOR3 Dir; ///< Direction of sunlight - D3DXCOLOR Color; ///< Color of sunlight - D3DXCOLOR Ambient; ///< Ambient environment color + FVECTOR3 Dir; + FVECTOR3 Color; // Color and Intensity of received sunlight + FVECTOR3 Ambient; // Ambient light level (Base Objects Only, Vessels are using dynamic methods) + FVECTOR3 Transmission; // Visibility through atmosphere (1.0 = fully visible, 0.0 = obscured) + FVECTOR3 Incatter; // Amount of incattered light from haze } D3D9Sun; @@ -304,6 +324,7 @@ typedef struct { D3DCOLORVALUE Rghn; // Tune roughness map } D3D9Tune; +#pragma pack(pop) typedef struct { class D3D9Mesh *pMesh; ///< Mesh handle @@ -341,6 +362,7 @@ extern IDirect3DVertexDeclaration9 *pVector4Decl; extern IDirect3DVertexDeclaration9 *pPosTexDecl; extern IDirect3DVertexDeclaration9 *pPatchVertexDecl; extern IDirect3DVertexDeclaration9 *pSketchpadDecl; +extern IDirect3DVertexDeclaration9 *pLocalLightsDecl; @@ -350,13 +372,23 @@ class ShaderClass public: ShaderClass(LPDIRECT3DDEVICE9 pDev, const char* file, const char* vs, const char* ps, const char* name, const char* options); - ~ShaderClass(); + ~ShaderClass(); void ClearTextures(); - void Activate(); + void UpdateTextures(); + void DetachTextures(); void Setup(LPDIRECT3DVERTEXDECLARATION9 pDecl, bool bZ, int blend); + HANDLE GetPSHandle(const char* name); + HANDLE GetVSHandle(const char* name); + void SetTexture(const char* name, LPDIRECT3DTEXTURE9 pTex, UINT Flags = IPF_CLAMP | IPF_ANISOTROPIC, UINT AnisoLvl = 4); + void SetTextureVS(const char* name, LPDIRECT3DTEXTURE9 pTex, UINT flags = IPF_CLAMP | IPF_POINT, UINT AnisoLvl = 0); void SetPSConstants(const char* name, void* data, UINT bytes); void SetVSConstants(const char* name, void* data, UINT bytes); + + void SetTexture(HANDLE hVar, LPDIRECT3DTEXTURE9 pTex, UINT flags = IPF_CLAMP | IPF_POINT, UINT AnisoLvl = 0); + void SetTextureVS(HANDLE hVar, LPDIRECT3DTEXTURE9 pTex, UINT flags, UINT aniso); + void SetPSConstants(HANDLE hVar, void* data, UINT bytes); + void SetVSConstants(HANDLE hVar, void* data, UINT bytes); LPDIRECT3DDEVICE9 GetDevice() { return pDev; } private: @@ -364,9 +396,11 @@ class ShaderClass struct TexParams { LPDIRECT3DTEXTURE9 pTex; + LPDIRECT3DTEXTURE9 pAssigned; UINT Flags; UINT AnisoLvl; - } pTextures[16]; + bool bSamplerSet; + } pTextures[20]; LPD3DXCONSTANTTABLE pPSCB, pVSCB; LPDIRECT3DPIXELSHADER9 pPS; @@ -391,6 +425,14 @@ inline double wrap(double a) } void LogMatrix(D3DXMATRIX *pM, const char *name); +inline void LogSunLight(D3D9Sun& s) +{ + LogAlw("Sunlight.Dir = [%f, %f, %f]", s.Dir.x, s.Dir.y, s.Dir.z); + LogAlw("Sunlight.Color = [%f, %f, %f]", s.Color.x, s.Color.y, s.Color.z); + LogAlw("Sunlight.Ambie = [%f, %f, %f]", s.Ambient.x, s.Ambient.y, s.Ambient.z); + LogAlw("Sunlight.Trans = [%f, %f, %f]", s.Transmission.x, s.Transmission.y, s.Transmission.z); + LogAlw("Sunlight.Incat = [%f, %f, %f]", s.Incatter.x, s.Incatter.y, s.Incatter.z); +} // ----------------------------------------------------------------------------------- // Conversion functions @@ -520,9 +562,6 @@ int fgets2(char *buf, int cmax, FILE *file, DWORD param=0); float D3DXVec3Angle(D3DXVECTOR3 a, D3DXVECTOR3 b); D3DXVECTOR3 Perpendicular(D3DXVECTOR3 *a); -void SurfaceLighting(D3D9Sun *light, OBJHANDLE hP, OBJHANDLE hO, float ao); -void OrbitalLighting(D3D9Sun *light, const class vPlanet *vP, const VECTOR3 &GO, float ao); - const char *RemovePath(const char *in); SketchMesh * GetSketchMesh(const MESHHANDLE hMesh); diff --git a/OVP/D3D9Client/DebugControls.cpp b/OVP/D3D9Client/DebugControls.cpp index 749598eae..100728a9d 100644 --- a/OVP/D3D9Client/DebugControls.cpp +++ b/OVP/D3D9Client/DebugControls.cpp @@ -439,6 +439,9 @@ void OpenDlgClbk(void *context) SendDlgItemMessageA(hDlg, IDC_DBG_ENVMAP, CB_ADDSTRING, 0, (LPARAM)"ShadowMap"); SendDlgItemMessageA(hDlg, IDC_DBG_ENVMAP, CB_ADDSTRING, 0, (LPARAM)"Irradiance"); SendDlgItemMessageA(hDlg, IDC_DBG_ENVMAP, CB_ADDSTRING, 0, (LPARAM)"GlowMask"); + SendDlgItemMessageA(hDlg, IDC_DBG_ENVMAP, CB_ADDSTRING, 0, (LPARAM)"ScreenDepth"); + SendDlgItemMessageA(hDlg, IDC_DBG_ENVMAP, CB_ADDSTRING, 0, (LPARAM)"Normals"); + SendDlgItemMessageA(hDlg, IDC_DBG_ENVMAP, CB_ADDSTRING, 0, (LPARAM)"LightVisbil."); SendDlgItemMessageA(hDlg, IDC_DBG_ENVMAP, CB_SETCURSEL, 0, 0); @@ -2118,6 +2121,12 @@ void OpenGFXDlgClbk(void *context) SendDlgItemMessage(hGfxDlg, IDC_GFX_LOCALMAX, TBM_SETTICFREQ, 1, 0); SendDlgItemMessage(hGfxDlg, IDC_GFX_LOCALMAX, TBM_SETPOS, 1, 0); + // slider + SendDlgItemMessage(hGfxDlg, IDC_GFX_GLARE, TBM_SETRANGEMAX, 1, 255); + SendDlgItemMessage(hGfxDlg, IDC_GFX_GLARE, TBM_SETRANGEMIN, 1, 0); + SendDlgItemMessage(hGfxDlg, IDC_GFX_GLARE, TBM_SETTICFREQ, 1, 0); + SendDlgItemMessage(hGfxDlg, IDC_GFX_GLARE, TBM_SETPOS, 1, 0); + // reset-button(s) @@ -2130,6 +2139,7 @@ void OpenGFXDlgClbk(void *context) SendMessage(GetDlgItem(hGfxDlg, IDC_GFX_SUNLIGHT_RESET), BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hImg); SendMessage(GetDlgItem(hGfxDlg, IDC_GFX_IRRADIANCE_RESET), BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hImg); SendMessage(GetDlgItem(hGfxDlg, IDC_GFX_LOCALMAX_RESET), BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hImg); + SendMessage(GetDlgItem(hGfxDlg, IDC_GFX_GLARE_RESET), BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hImg); CreateToolTip(IDC_GFX_INTENSITY_RESET, hGfxDlg, "Reset to default"); CreateToolTip(IDC_GFX_DISTANCE_RESET, hGfxDlg, "Reset to default"); @@ -2138,6 +2148,7 @@ void OpenGFXDlgClbk(void *context) CreateToolTip(IDC_GFX_SUNLIGHT_RESET, hGfxDlg, "Reset to default"); CreateToolTip(IDC_GFX_IRRADIANCE_RESET, hGfxDlg, "Reset to default"); CreateToolTip(IDC_GFX_LOCALMAX_RESET, hGfxDlg, "Reset to default"); + CreateToolTip(IDC_GFX_GLARE_RESET, hGfxDlg, "Reset to default"); SetGFXSliders(); } @@ -2181,6 +2192,11 @@ void SetGFXSliders() sprintf_s(lbl, 32, "%1.2f", fpos); SetWindowTextA(GetDlgItem(hGfxDlg, IDC_GFX_VAL7), lbl); SendDlgItemMessage(hGfxDlg, IDC_GFX_LOCALMAX, TBM_SETPOS, 1, WORD(fpos*255.0)); + + fpos = Config->GFXGlare; + sprintf_s(lbl, 32, "%1.2f", fpos); + SetWindowTextA(GetDlgItem(hGfxDlg, IDC_GFX_VAL8), lbl); + SendDlgItemMessage(hGfxDlg, IDC_GFX_GLARE, TBM_SETPOS, 1, WORD(fpos * 255.0)); } void ReadGFXSliders() @@ -2222,6 +2238,11 @@ void ReadGFXSliders() sprintf_s(lbl, 32, "%1.2f", fpos); SetWindowTextA(GetDlgItem(hGfxDlg, IDC_GFX_VAL7), lbl); Config->GFXLocalMax = fpos; + + fpos = (1.0 / 255.0) * double(SendDlgItemMessage(hGfxDlg, IDC_GFX_GLARE, TBM_GETPOS, 0, 0)); + sprintf_s(lbl, 32, "%1.2f", fpos); + SetWindowTextA(GetDlgItem(hGfxDlg, IDC_GFX_VAL8), lbl); + Config->GFXGlare = fpos; } INT_PTR CALLBACK WndProcGFX(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -2243,6 +2264,7 @@ INT_PTR CALLBACK WndProcGFX(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (HWND(lParam) == GetDlgItem(hWnd, IDC_GFX_SUNLIGHT)) ReadGFXSliders(); if (HWND(lParam) == GetDlgItem(hWnd, IDC_GFX_IRRADIANCE)) ReadGFXSliders(); if (HWND(lParam) == GetDlgItem(hWnd, IDC_GFX_LOCALMAX)) ReadGFXSliders(); + if (HWND(lParam) == GetDlgItem(hWnd, IDC_GFX_GLARE)) ReadGFXSliders(); } return false; } @@ -2255,6 +2277,11 @@ INT_PTR CALLBACK WndProcGFX(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) CloseGFX(); break; + case IDC_GFX_RECOMPILE: + g_client->GetScene()->CreateSunGlare(); + break; + + case IDC_GFX_INTENSITY_RESET: Config->GFXIntensity = 0.5; SetGFXSliders(); @@ -2290,6 +2317,11 @@ INT_PTR CALLBACK WndProcGFX(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) SetGFXSliders(); break; + case IDC_GFX_GLARE_RESET: + Config->GFXGlare = 0.3; + SetGFXSliders(); + break; + default: LogErr("WndProcGFX() LOWORD(%hu), HIWORD(0x%hX)", LOWORD(wParam), HIWORD(wParam)); break; @@ -2306,4 +2338,3 @@ INT_PTR CALLBACK WndProcGFX(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } //namespace - \ No newline at end of file diff --git a/OVP/D3D9Client/HazeMgr.cpp b/OVP/D3D9Client/HazeMgr.cpp index 8966c5c6f..bfa397d0a 100644 --- a/OVP/D3D9Client/HazeMgr.cpp +++ b/OVP/D3D9Client/HazeMgr.cpp @@ -238,8 +238,7 @@ SURFHANDLE HazeManager::horizon = 0; // Planetary atmospheric haze rendering with scattering technique // ============================================================================ -HazeManager2::HazeManager2(const D3D9Client *gclient, const vPlanet *vplanet) -: PlanetRenderer() +HazeManager2::HazeManager2(vPlanet *vplanet) { vp = vplanet; obj = vp->Object(); @@ -248,8 +247,17 @@ HazeManager2::HazeManager2(const D3D9Client *gclient, const vPlanet *vplanet) // ----------------------------------------------------------------------- +HazeManager2::~HazeManager2() +{ + +} + +// ----------------------------------------------------------------------- + void HazeManager2::GlobalInit(D3D9Client *gclient) { + pDev = gclient->GetDevice(); + pNoise = gclient->GetNoiseTex(); for (int i=0;i<6;i++) pSkyVB[i]=NULL; CreateRingBuffers(); CreateSkydomeBuffers(0); @@ -258,6 +266,9 @@ void HazeManager2::GlobalInit(D3D9Client *gclient) CreateSkydomeBuffers(3); CreateSkydomeBuffers(4); CreateSkydomeBuffers(5); + + pDome = new ShaderClass(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "HorizonVS", "HorizonPS", "Dome", NULL); + pRing = new ShaderClass(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "HorizonVS", "HorizonRingPS", "Ring", NULL); } // ----------------------------------------------------------------------- @@ -266,16 +277,19 @@ void HazeManager2::GlobalExit() { for (int i=0;i<6;i++) { SAFE_RELEASE(pSkyVB[i]); } SAFE_RELEASE(pRingVB); + SAFE_DELETE(pDome); + SAFE_DELETE(pRing); } // ----------------------------------------------------------------------- void HazeManager2::Render(D3DXMATRIX &wmat, float horizontal_aperture_deg) { - VECTOR3 cdir = vp->GetScene()->GetCameraGDir(); + Scene* scn = vp->GetScene(); + VECTOR3 cdir = scn->GetCameraGDir(); double calt = vp->CamDist() - rad; // Camera altitude double halt = vp->GetHorizonAlt(); - double melv = vp->prm.horizon_minelev; // vp->GetMinElevation(); + double melv = vp->GetMinElevation(); melv -= 1000.0; @@ -307,9 +321,23 @@ void HazeManager2::RenderSky(VECTOR3 cpos, VECTOR3 cdir, double rad, double apr) D3DXVECTOR3 vTileCenter = D3DXVECTOR3(float(sin(15.0*RAD)), 1.0f, float(1.0+cos(15.0*RAD))) * 0.5; D3DXMatrixRotationAxis(&mL, &_D3DXVECTOR3(ur), float(-a*0.5)); D3DXMatrixMultiply(&mWL, &mWL, &mL); - D3DXMatrixRotationAxis(&mL, &_D3DXVECTOR3(ur), float(-a)); + //vp->GetScatterConst()->mVP = vp->GetScene()->PushCameraFrustumLimits(hd * 0.1, hd * 5.0); + + pDome->Setup(pPositionDecl, false, 2); + pDome->ClearTextures(); + + pDome->SetTexture("tSkyRayColor", vp->GetScatterTable(RAY_COLOR), IPF_LINEAR | IPF_CLAMP); + pDome->SetTexture("tSkyMieColor", vp->GetScatterTable(MIE_COLOR), IPF_LINEAR | IPF_CLAMP); + pDome->SetTexture("tGlare", vp->GetScene()->GetSunGlareAtm(), IPF_LINEAR | IPF_CLAMP); + pDome->SetTexture("tNoise", pNoise, IPF_POINT | IPF_WRAP); + pDome->SetPSConstants("Const", vp->GetScatterConst(), sizeof(ConstParams)); + pDome->SetVSConstants("Const", vp->GetScatterConst(), sizeof(ConstParams)); + pDome->UpdateTextures(); + + pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + for (int i=0;i<24;i++) { double x = al; D3DXMatrixMultiply(&mWL, &mWL, &mL); @@ -322,7 +350,10 @@ void HazeManager2::RenderSky(VECTOR3 cpos, VECTOR3 cdir, double rad, double apr) x+=b; } } - HR(Shader()->SetVector(svTexOff, &D3DXVECTOR4(1, 0, 1, 0))); + + pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); + + //vp->GetScatterConst()->mVP = vp->GetScene()->PopCameraFrustumLimits(); } // ----------------------------------------------------------------------- @@ -334,24 +365,18 @@ void HazeManager2::RenderSkySegment(D3DXMATRIX &wmat, double rad, double dmin, d float r2 = float(rad * sin(dmax)); float h2 = -float(rad * cos(dmax)); - HR(Shader()->SetTechnique(eHorizonTech)); - HR(Shader()->SetMatrix(smWorld, &wmat)); - HR(Shader()->SetVector(svTexOff, &D3DXVECTOR4(r1, r2, h1, h2))); + ShaderParams sprm; + memcpy_s(&sprm.mWorld, sizeof(sprm.mWorld), &wmat, sizeof(wmat)); + sprm.vTexOff = FVECTOR4(r1, r2, h1, h2); - int xres = (Config->LODBias<-0.5 ? xlreslvl[index] : xreslvl[index]); - int yres = (Config->LODBias<-0.5 ? ylreslvl[index] : yreslvl[index]); + int xres = xreslvl[index]; + int yres = yreslvl[index]; UINT prims = xres * yres * 2 - 2; - UINT numPasses = 0; - HR(Shader()->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); - HR(Shader()->BeginPass(0)); - Dev()->SetVertexDeclaration(pPositionDecl); - Dev()->SetStreamSource(0, pSkyVB[index], 0, sizeof(D3DXVECTOR3)); - Dev()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - Dev()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, prims); - Dev()->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - HR(Shader()->EndPass()); - HR(Shader()->End()); + + pDome->SetVSConstants("Prm", &sprm, sizeof(ShaderParams)); + pDev->SetStreamSource(0, pSkyVB[index], 0, sizeof(D3DXVECTOR3)); + pDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, prims); } @@ -373,6 +398,7 @@ void HazeManager2::RenderRing(VECTOR3 cpos, VECTOR3 cdir, double rad, double hra double r2 = r1 + qw * cos(al); double h2 = h1 + qw * sin(al); + vp->GetScatterConst()->mVP = vp->GetScene()->PushCameraFrustumLimits(hd * 0.1, hd * 5.0); VECTOR3 ur = unit(cpos); VECTOR3 ux = unit(crossp(cdir, ur)); @@ -382,33 +408,29 @@ void HazeManager2::RenderRing(VECTOR3 cpos, VECTOR3 cdir, double rad, double hra D3DMAT_Identity(&mW); D3DMAT_FromAxisT(&mW, &_D3DXVECTOR3(ux), &_D3DXVECTOR3(ur), &_D3DXVECTOR3(uy)); - class Scene *scene = Client()->GetScene(); - double np = scene->GetCameraNearPlane(); - double fp = scene->GetCameraFarPlane(); - scene->SetCameraFrustumLimits(cr*0.02,cr*10.0); - - HR(Shader()->SetTechnique(eRingTech)); - HR(Shader()->SetMatrix(smWorld, &mW)); - HR(Shader()->SetMatrix(smViewProj, scene->GetProjectionViewMatrix())); - HR(Shader()->SetVector(svTexOff, &D3DXVECTOR4(float(r1), float(r2), float(h1), float(h2)))); - HR(Shader()->SetFloat(sfAlpha, float(qw))); - - UINT numPasses = 0; - UINT nPrims = HORIZON2_NSEG * HORIZON2_NRING * 2 - 2; + ShaderParams sprm; + memcpy_s(&sprm.mWorld, sizeof(sprm.mWorld), &mW, sizeof(mW)); + sprm.vTexOff = FVECTOR4(r1, r2, h1, h2); + sprm.fAlpha = float(qw); - HR(Shader()->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); - HR(Shader()->BeginPass(0)); - - Dev()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - Dev()->SetVertexDeclaration(pPositionDecl); - Dev()->SetStreamSource(0, pRingVB, 0, sizeof(D3DXVECTOR3)); - Dev()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, nPrims); - Dev()->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); + pRing->Setup(pPositionDecl, false, 2); + pRing->ClearTextures(); + pRing->SetTexture("tSkyRayColor", vp->GetScatterTable(RAY_COLOR), IPF_LINEAR | IPF_CLAMP); + pRing->SetTexture("tSkyMieColor", vp->GetScatterTable(MIE_COLOR), IPF_LINEAR | IPF_CLAMP); + pRing->SetPSConstants("Const", vp->GetScatterConst(), sizeof(ConstParams)); + pRing->SetVSConstants("Const", vp->GetScatterConst(), sizeof(ConstParams)); + pRing->SetVSConstants("Prm", &sprm, sizeof(ShaderParams)); + pRing->UpdateTextures(); + + UINT nPrims = HORIZON2_NSEG * HORIZON2_NRING * 2 - 2; - HR(Shader()->EndPass()); - HR(Shader()->End()); + pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + pDev->SetStreamSource(0, pRingVB, 0, sizeof(D3DXVECTOR3)); + pDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, nPrims); + pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - scene->SetCameraFrustumLimits(np, fp); + // Pop previous frustum configuration, must initialize mVP + vp->GetScatterConst()->mVP = vp->GetScene()->PopCameraFrustumLimits(); } @@ -440,7 +462,7 @@ void HazeManager2::CreateRingBuffers() y+=d; } - HR(Dev()->CreateVertexBuffer(v*sizeof(D3DXVECTOR3), 0, 0, D3DPOOL_DEFAULT, &pRingVB, NULL)); + HR(pDev->CreateVertexBuffer(v*sizeof(D3DXVECTOR3), 0, 0, D3DPOOL_DEFAULT, &pRingVB, NULL)); if (pRingVB->Lock(0, 0, (void **)&pBuf,0)==S_OK) { memcpy(pBuf, pVrt, v*sizeof(D3DXVECTOR3)); @@ -456,8 +478,8 @@ void HazeManager2::CreateSkydomeBuffers(int index) { int k = 0; - int xseg = (Config->LODBias<-0.5 ? xlreslvl[index] : xreslvl[index]); - int yseg = (Config->LODBias<-0.5 ? ylreslvl[index] : yreslvl[index]); + int xseg = xreslvl[index]; + int yseg = yreslvl[index]; D3DXVECTOR3 *pVrt = new D3DXVECTOR3[xseg*yseg*2+2]; D3DXVECTOR3 *pBuf = NULL; @@ -477,7 +499,7 @@ void HazeManager2::CreateSkydomeBuffers(int index) ds = -ds; dc = -dc; sa += ds; ca -= dc; b += db; } - HR(Dev()->CreateVertexBuffer(k*sizeof(D3DXVECTOR3), 0, 0, D3DPOOL_DEFAULT, &pSkyVB[index], NULL)); + HR(pDev->CreateVertexBuffer(k*sizeof(D3DXVECTOR3), 0, 0, D3DPOOL_DEFAULT, &pSkyVB[index], NULL)); if (pSkyVB[index]->Lock(0, 0, (void **)&pBuf,0)==S_OK) { memcpy(pBuf, pVrt, k*sizeof(D3DXVECTOR3)); @@ -490,10 +512,12 @@ void HazeManager2::CreateSkydomeBuffers(int index) // ----------------------------------------------------------------------- +ShaderClass* HazeManager2::pDome; +ShaderClass* HazeManager2::pRing; +LPDIRECT3DDEVICE9 HazeManager2::pDev; +LPDIRECT3DTEXTURE9 HazeManager2::pNoise; LPDIRECT3DVERTEXBUFFER9 HazeManager2::pSkyVB[6]; LPDIRECT3DVERTEXBUFFER9 HazeManager2::pRingVB = NULL; -int HazeManager2::xreslvl[6] = {28,18,14,10,8,6}; -int HazeManager2::yreslvl[6] = {48,28,18,18,16,14}; -int HazeManager2::xlreslvl[6] = {18,12,10,6,6,4}; -int HazeManager2::ylreslvl[6] = {22,16,12,12,10,8}; +int HazeManager2::xreslvl[6] = {9,6,5,4,3,2}; +int HazeManager2::yreslvl[6] = {11,8,6,5,5,4}; diff --git a/OVP/D3D9Client/HazeMgr.h b/OVP/D3D9Client/HazeMgr.h index 8abf83500..fc3279702 100644 --- a/OVP/D3D9Client/HazeMgr.h +++ b/OVP/D3D9Client/HazeMgr.h @@ -18,11 +18,10 @@ #include "D3D9Client.h" #include "D3D9Effect.h" -#include "PlanetRenderer.h" -#define HORIZON_NSEG 128 // number of mesh segments -#define HORIZON2_NSEG 400 // Horizon ring segments -#define HORIZON2_NRING 50 // Horizon ring ring count +#define HORIZON_NSEG 32 // number of mesh segments +#define HORIZON2_NSEG 200 // Horizon ring segments +#define HORIZON2_NRING 5 // Horizon ring ring count class vPlanet; @@ -78,10 +77,11 @@ class HazeManager : private D3D9Effect // HazeManager2 is used with TileManager2 // ============================================================== -class HazeManager2 : public PlanetRenderer +class HazeManager2 { public: - HazeManager2 (const oapi::D3D9Client *gclient, const vPlanet *vplanet); + HazeManager2 (vPlanet *vplanet); + ~HazeManager2(); static void GlobalInit (oapi::D3D9Client *gclient); @@ -98,13 +98,15 @@ class HazeManager2 : public PlanetRenderer void RenderSkySegment(D3DXMATRIX &wmat, double rad, double dmin, double dmax, int index); OBJHANDLE obj; - const vPlanet *vp; + vPlanet *vp; double rad; + static ShaderClass* pRing; + static ShaderClass* pDome; + static LPDIRECT3DDEVICE9 pDev; + static LPDIRECT3DTEXTURE9 pNoise; static int xreslvl[6]; static int yreslvl[6]; - static int xlreslvl[6]; - static int ylreslvl[6]; static LPDIRECT3DVERTEXBUFFER9 pSkyVB[6]; static LPDIRECT3DVERTEXBUFFER9 pRingVB; }; diff --git a/OVP/D3D9Client/IProcess.cpp b/OVP/D3D9Client/IProcess.cpp index fcd1e08c1..4936bd405 100644 --- a/OVP/D3D9Client/IProcess.cpp +++ b/OVP/D3D9Client/IProcess.cpp @@ -225,30 +225,22 @@ void ImageProcessing::SetMesh(const MESHHANDLE hMesh, const char *tex, gcIPInter // bool ImageProcessing::Execute(bool bInScene) { - return Execute(0, 0, 0, bInScene, gcIPInterface::ipitemplate::Rect); + return Execute(0, bInScene, gcIPInterface::ipitemplate::Rect); } // ================================================================================================ // -bool ImageProcessing::Execute(const char *shader, bool bInScene) +bool ImageProcessing::Execute(const char *shader, bool bInScene, DWORD blendop) { Activate(shader); - return Execute(0, 0, 0, bInScene, gcIPInterface::ipitemplate::Rect); + return Execute(blendop, bInScene, gcIPInterface::ipitemplate::Rect); } // ================================================================================================ // -bool ImageProcessing::ExecuteTemplate(bool bInScene, gcIPInterface::ipitemplate mode) -{ - return Execute(0, 0, 0, bInScene, mode); -} - - -// ================================================================================================ -// -bool ImageProcessing::Execute(DWORD blendop, DWORD src, DWORD dest, bool bInScene, gcIPInterface::ipitemplate mode, int grp) +bool ImageProcessing::Execute(DWORD blendop, bool bInScene, gcIPInterface::ipitemplate mode, int grp) { if (!IsOK()) return false; if (!SetupViewPort()) return false; @@ -269,10 +261,10 @@ bool ImageProcessing::Execute(DWORD blendop, DWORD src, DWORD dest, bool bInScen HR(pDevice->SetRenderState(D3DRS_STENCILENABLE, false)); HR(pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xF)); - if (blendop) { - HR(pDevice->SetRenderState(D3DRS_BLENDOP, blendop)); - HR(pDevice->SetRenderState(D3DRS_SRCBLEND, src)); - HR(pDevice->SetRenderState(D3DRS_DESTBLEND, dest)); + if (blendop == 1) { + HR(pDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD)); + HR(pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)); + HR(pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)); } // Define vertices -------------------------------------------------------- @@ -806,14 +798,9 @@ bool gcIPInterface::Execute(bool bInScene) return pIPI->Execute(bInScene); } -bool gcIPInterface::ExecuteTemplate(bool bInScene, ipitemplate it) -{ - return pIPI->ExecuteTemplate(bInScene, it); -} - -bool gcIPInterface::Execute(DWORD blendop, DWORD src, DWORD dest, bool bInScene, ipitemplate mde) +bool gcIPInterface::Execute(DWORD blendop, bool bInScene, ipitemplate mde) { - return pIPI->Execute(blendop, src, dest, bInScene, mde); + return pIPI->Execute(blendop, bInScene, mde); } int gcIPInterface::FindDefine(const char *key) diff --git a/OVP/D3D9Client/IProcess.h b/OVP/D3D9Client/IProcess.h index 7f38f450f..195968849 100644 --- a/OVP/D3D9Client/IProcess.h +++ b/OVP/D3D9Client/IProcess.h @@ -104,9 +104,8 @@ class ImageProcessing { void SetMesh(const MESHHANDLE hMesh, const char *tex = NULL, gcIPInterface::ipicull = gcIPInterface::ipicull::None); bool Execute(bool bInScene = false); - bool Execute(const char *shader, bool bInScene); - bool ExecuteTemplate(bool bInScene = false, gcIPInterface::ipitemplate tmp = gcIPInterface::ipitemplate::Rect); - bool Execute(DWORD blendop, DWORD src, DWORD dest, bool bInScene = false, gcIPInterface::ipitemplate tmp = gcIPInterface::ipitemplate::Rect, int gpr = -1); + bool Execute(const char *shader, bool bInScene, DWORD blendop); + bool Execute(DWORD blendop, bool bInScene = false, gcIPInterface::ipitemplate tmp = gcIPInterface::ipitemplate::Rect, int gpr = -1); // ---------------------------------------------------------------------------------- int FindDefine(const char *key); diff --git a/OVP/D3D9Client/Log.cpp b/OVP/D3D9Client/Log.cpp index 65ad99a0c..8cc70a1a1 100644 --- a/OVP/D3D9Client/Log.cpp +++ b/OVP/D3D9Client/Log.cpp @@ -135,6 +135,14 @@ void D3D9DebugLog(const char *format, ...) D3D9DebugQueue.push(std::string(ErrBuf)); } +//------------------------------------------------------------------------------------------- +// +void D3D9DebugLogVec(const char* lbl, oapi::FVECTOR4 &v) +{ + sprintf_s(ErrBuf, ERRBUF, "%s = [%f, %f, %f, %f]", lbl, v.x, v.y, v.z, v.w); + D3D9DebugQueue.push(std::string(ErrBuf)); +} + //------------------------------------------------------------------------------------------- // void D3D9InitLog(char *file) diff --git a/OVP/D3D9Client/Log.h b/OVP/D3D9Client/Log.h index 2b9f61bae..34bb7c08f 100644 --- a/OVP/D3D9Client/Log.h +++ b/OVP/D3D9Client/Log.h @@ -21,6 +21,7 @@ #include #include #include +#include "DrawAPI.h" #define WIN32_LEAN_AND_MEAN #include // DWORD, LPCSTR #undef WIN32_LEAN_AND_MEAN @@ -45,6 +46,7 @@ extern std::queue D3D9DebugQueue; void RuntimeError(const char* File, const char* Fnc, UINT Line); void D3D9DebugLog(const char *format, ...); +void D3D9DebugLogVec(const char* lbl, oapi::FVECTOR4 &v); void D3D9InitLog(char *file); void D3D9CloseLog(); void LogTrace(const char *format, ...); diff --git a/OVP/D3D9Client/Mesh.cpp b/OVP/D3D9Client/Mesh.cpp index d5e46bafa..ac5d5f312 100644 --- a/OVP/D3D9Client/Mesh.cpp +++ b/OVP/D3D9Client/Mesh.cpp @@ -25,6 +25,12 @@ using namespace oapi; +MeshShader* D3D9Mesh::s_pShader[16] = {}; +MeshShader::VSConst MeshShader::vs_const = {}; +MeshShader::PSConst MeshShader::ps_const = {}; +MeshShader::PSBools MeshShader::ps_bools = {}; + + int compare_lights(const void * a, const void * b) { register float fa = static_cast(a)->illuminace; @@ -181,7 +187,6 @@ void D3D9Mesh::Null(const char *meshName /* = NULL */) pBuf = NULL; Mtrl = NULL; pGrpTF = NULL; - sunLight = NULL; cAmbient = 0; MaxFace = 0; MaxVert = 0; @@ -217,7 +222,7 @@ D3D9Mesh::D3D9Mesh(const char *fname) : D3D9Effect() } MeshCatalog.insert(this); - pBuf->Map(pDev); + if (pBuf) pBuf->Map(pDev); } // =========================================================================================== @@ -228,7 +233,7 @@ D3D9Mesh::D3D9Mesh(MESHHANDLE hMesh, bool asTemplate, D3DXVECTOR3 *reorig, float LoadMeshFromHandle(hMesh, reorig, scale); bIsTemplate = asTemplate; MeshCatalog.insert(this); - pBuf->Map(pDev); + if (pBuf) pBuf->Map(pDev); } @@ -708,6 +713,7 @@ void D3D9Mesh::SetGroupRec(DWORD i, const MESHGROUPEX *mg) // bool D3D9Mesh::CopyVertices(GROUPREC *grp, const MESHGROUPEX *mg, D3DXVECTOR3 *reorig, float *scale) { + if (!pBuf) return false; NTVERTEX *pNT = mg->Vtx; SMVERTEX *pShad = pBuf->pSBSys + grp->VertOff; NMVERTEX *pVert = pBuf->pVBSys + grp->VertOff; @@ -780,6 +786,7 @@ int D3D9Mesh::EditGroup(DWORD grp, GROUPEDITSPEC *ges) _TRACE; if (!IsOK()) return 1; if (grp >= nGrp) return 1; + if (!pBuf) return 1; bBSRecompute = true; @@ -864,6 +871,8 @@ NTVERTEX Convert(NMVERTEX &v) int D3D9Mesh::GetGroup (DWORD grp, GROUPREQUESTSPEC *grs) { + if (!pBuf) return 1; + static NTVERTEX zero = {0,0,0, 0,0,0, 0,0}; if (grp >= nGrp) return 1; DWORD nv = Grp[grp].nVert; @@ -993,7 +1002,7 @@ void D3D9Mesh::SetTexMixture(DWORD ntex, float mix) // void D3D9Mesh::SetSunLight(const D3D9Sun *light) { - sunLight = light; + memcpy(&sunLight, light, sizeof(D3D9Sun)); } // =========================================================================================== @@ -1321,6 +1330,7 @@ void D3D9Mesh::RenderGroup(const GROUPREC *grp) _TRACE; if (!IsOK()) return; if (!grp) return; + pBuf->Map(pDev); pDev->SetVertexDeclaration(pMeshVertexDecl); @@ -1409,6 +1419,15 @@ void D3D9Mesh::CheckMeshStatus() } +// =========================================================================================== +// +void D3D9Mesh::ConfigureAtmo() +{ + //LogSunLight(sunLight); + float x = 1.0f - saturate(max(sunLight.Color.r, sunLight.Color.b) * 2.0f); + FX->SetFloat(eNight, x); + FX->SetValue(eSun, &sunLight, sizeof(D3D9Sun)); +} // ================================================================================================ @@ -1518,14 +1537,6 @@ void D3D9Mesh::Render(const LPD3DXMATRIX pW, int iTech, LPDIRECT3DCUBETEXTURE9 * if (flags&DBG_FLAGS_DUALSIDED) pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - if (sunLight) { - D3D9Sun sun = *sunLight; - float x = 1.0f - saturate(max(sun.Color.r, sun.Color.b)*2.0f); - FX->SetFloat(eNight, x); - sun.Color *= float(Config->GFXSunIntensity); - FX->SetValue(eSun, &sun, sizeof(D3D9Sun)); - } - FX->SetTechnique(eVesselTech); FX->SetBool(eFresnel, false); FX->SetBool(eEnvMapEnable, false); @@ -1534,6 +1545,8 @@ void D3D9Mesh::Render(const LPD3DXMATRIX pW, int iTech, LPDIRECT3DCUBETEXTURE9 * FX->SetBool(eOITEnable, false); FX->SetVector(eColor, &D3DXVECTOR4(0, 0, 0, 0)); + ConfigureAtmo(); + if (DebugControls::IsActive()) if (pTune) FX->SetBool(eTuneEnabled, true); @@ -1988,7 +2001,7 @@ void D3D9Mesh::RenderSimplified(const LPD3DXMATRIX pW, LPDIRECT3DCUBETEXTURE9 *p FX->SetVector(eColor, &D3DXVECTOR4(0, 0, 0, 0)); FX->SetMatrix(eW, pW); - if (sunLight) FX->SetValue(eSun, sunLight, sizeof(D3D9Sun)); + ConfigureAtmo(); // Process Local Light Sources ------------------------------------------------------------ // @@ -2276,13 +2289,14 @@ void D3D9Mesh::RenderFast(const LPD3DXMATRIX pW, int iTech) if (flags&DBG_FLAGS_DUALSIDED) pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - if (sunLight) FX->SetValue(eSun, sunLight, sizeof(D3D9Sun)); FX->SetTechnique(eVesselTech); FX->SetBool(eTuneEnabled, false); FX->SetBool(eLightsEnabled, false); FX->SetVector(eColor, &D3DXVECTOR4(0, 0, 0, 0)); + ConfigureAtmo(); + if (DebugControls::IsActive()) if (pTune) FX->SetBool(eTuneEnabled, true); TexFlow FC; reset(FC); @@ -2593,16 +2607,13 @@ void D3D9Mesh::RenderBaseTile(const LPD3DXMATRIX pW) pDev->SetStreamSource(0, pBuf->pVB, 0, sizeof(NMVERTEX)); pDev->SetIndices(pBuf->pIB); - if (sunLight) FX->SetValue(eSun, sunLight, sizeof(D3D9Sun)); FX->SetTechnique(eBaseTile); FX->SetVector(eColor, &D3DXVECTOR4(0, 0, 0, 0)); FX->SetMatrix(eGT, gc->GetIdentity()); FX->SetMatrix(eW, pW); - //FX->SetBool(eUseSpec, false); - //FX->SetBool(eUseEmis, false); - //FX->SetBool(eUseRefl, false); + ConfigureAtmo(); UINT numPasses = 0; HR(FX->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); @@ -2696,37 +2707,103 @@ void D3D9Mesh::RenderBaseTile(const LPD3DXMATRIX pW) // ================================================================================================ // -void D3D9Mesh::RenderShadows(float alpha, const LPD3DXMATRIX pP, const LPD3DXMATRIX pW, bool bShadowMap, const D3DXVECTOR4 *elev) +void D3D9Mesh::RenderShadowMap(const LPD3DXMATRIX pW, const LPD3DXMATRIX pVP, int opt) { if (!IsOK()) return; - DWORD Pass = 0; - D3DXMATRIX GroupMatrix, mWorldMesh; UINT numPasses = 0; + pBuf->Map(pDev); + + D3DXMATRIX GroupMatrix, mWorldMesh; + MeshShader* pShader = nullptr; + + MeshShader::vs_const.mVP = *pVP; + + D3DXMatrixIdentity(MeshShader::vs_const.mW); + if (bGlobalTF) D3DXMatrixMultiply(&mWorldMesh, &mTransform, pW); else mWorldMesh = *pW; - pDev->SetIndices(pBuf->pIB); - - if (bShadowMap) { + if (opt == 1) { + // Screenspace Depth and Normal buffer rendering + pDev->SetStreamSource(0, pBuf->pVB, 0, sizeof(NMVERTEX)); + pShader = s_pShader[SHADER_NORMAL_DEPTH]; + pShader->Setup(pMeshVertexDecl, true, 0); + } + else { if (Flags & 0x20) { - pDev->SetVertexDeclaration(pPosTexDecl); + // Regular shadowmap with OIT support pDev->SetStreamSource(0, pBuf->pSB, 0, sizeof(SMVERTEX)); - Pass = 1; + pShader = s_pShader[SHADER_SHADOWMAP_OIT]; + pShader->Setup(pPosTexDecl, true, 0); } else { - pDev->SetVertexDeclaration(pVector4Decl); + // Regular shadowmap for self shadowing pDev->SetStreamSource(0, pBuf->pGB, 0, sizeof(D3DXVECTOR4)); + pShader = s_pShader[SHADER_SHADOWMAP]; + pShader->Setup(pVector4Decl, true, 0); } - FX->SetTechnique(eGeometry); } - else { - pDev->SetVertexDeclaration(pPosTexDecl); - pDev->SetStreamSource(0, pBuf->pSB, 0, sizeof(SMVERTEX)); - FX->SetTechnique(eShadowTech); + pDev->SetIndices(pBuf->pIB); + pShader->ClearTextures(); + + bool bInit = true; + bool bCurrentState = false; + + for (DWORD g = 0; g < nGrp; g++) + { + if (Grp[g].UsrFlag & 0x2) continue; + if (Grp[g].UsrFlag & 0x1) continue; + + MeshShader::ps_bools.bOIT = (Grp[g].UsrFlag & 0x20) != 0; + + if (MeshShader::ps_bools.bOIT) { + DWORD ti = Grp[g].TexIdx; + if (ti) { + auto hTex = Tex[ti]->GetTexture(); + if (hTex) pShader->SetTexture(pShader->hPST[0], hTex, IPF_WRAP | IPF_POINT); + else MeshShader::ps_bools.bOIT = false; + } + else MeshShader::ps_bools.bOIT = false; + } + + if (Grp[g].bTransform) { + D3DXMatrixMultiply(MeshShader::vs_const.mW, &pGrpTF[g], pW); // Apply Animations to instance matrices + bInit = true; + } + else { + if (bInit) MeshShader::vs_const.mW = mWorldMesh; + bInit = false; + } + + if (pShader->hVSC) pShader->SetVSConstants(pShader->hVSC, &MeshShader::vs_const, sizeof(MeshShader::vs_const)); + if (pShader->hPSC) pShader->SetPSConstants(pShader->hPSC, &MeshShader::ps_const, sizeof(MeshShader::ps_const)); + if (pShader->hPSB) pShader->SetPSConstants(pShader->hPSB, &MeshShader::ps_bools, sizeof(MeshShader::ps_bools)); + pShader->UpdateTextures(); + + pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, Grp[g].VertOff, 0, Grp[g].nVert, Grp[g].IdexOff, Grp[g].nFace); } +} + + +// ================================================================================================ +// +void D3D9Mesh::RenderStencilShadows(float alpha, const LPD3DXMATRIX pP, const LPD3DXMATRIX pW, bool bShadowMap, const D3DXVECTOR4 *elev) +{ + if (!IsOK()) return; - if (elev && bShadowMap==false) FX->SetVector(eInScatter, elev); + DWORD Pass = 0; + D3DXMATRIX GroupMatrix, mWorldMesh; UINT numPasses = 0; + + if (bGlobalTF) D3DXMatrixMultiply(&mWorldMesh, &mTransform, pW); + else mWorldMesh = *pW; + + pDev->SetIndices(pBuf->pIB); + pDev->SetVertexDeclaration(pPosTexDecl); + pDev->SetStreamSource(0, pBuf->pSB, 0, sizeof(SMVERTEX)); + FX->SetTechnique(eShadowTech); + + if (elev) FX->SetVector(eInScatter, elev); else FX->SetVector(eInScatter, &D3DXVECTOR4(0,1,0,0)); FX->SetFloat(eMix, alpha); @@ -2760,42 +2837,22 @@ void D3D9Mesh::RenderShadows(float alpha, const LPD3DXMATRIX pP, const LPD3DXMAT if (Grp[g].bTransform) { D3DXMatrixMultiply(&GroupMatrix, &pGrpTF[g], pW); // Apply Animations to instance matrices - FX->SetValue(eW, GroupMatrix, sizeof(D3DXMATRIX)); + FX->SetValue(eW, &GroupMatrix, sizeof(D3DXMATRIX)); bInit = true; } else { if (bInit) { - FX->SetValue(eW, mWorldMesh, sizeof(D3DXMATRIX)); + FX->SetValue(eW, &mWorldMesh, sizeof(D3DXMATRIX)); } bInit = false; } FX->CommitChanges(); - - if (bShadowMap) { - - bool bDisable = (Grp[g].UsrFlag & 0x1) != 0; - - if (bDisable != bCurrentState) { - if (bDisable) pDev->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - else pDev->SetRenderState(D3DRS_COLORWRITEENABLE, 0xF); - bCurrentState = bDisable; - } - } - pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, Grp[g].VertOff, 0, Grp[g].nVert, Grp[g].IdexOff, Grp[g].nFace); - - D3D9Stats.Mesh.Vertices += Grp[g].nVert; - D3D9Stats.Mesh.MeshGrps++; } FX->EndPass(); FX->End(); - - if (bShadowMap) { - pDev->SetRenderState(D3DRS_COLORWRITEENABLE, 0xF); - pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - } } @@ -2833,7 +2890,7 @@ void D3D9Mesh::RenderShadowsEx(float alpha, const LPD3DXMATRIX pP, const LPD3DXM if (bOIT) { DWORD ti = Grp[g].TexIdx; if (ti) { - auto hTex = Tex[ti]->GetTexture(); + auto hTex = (Tex[ti] ? Tex[ti]->GetTexture() : NULL); if (hTex) { HR(FX->SetTexture(eTex0, hTex)); } @@ -3289,7 +3346,7 @@ void D3D9Mesh::RenderRings(const LPD3DXMATRIX pW, LPDIRECT3DTEXTURE9 pTex) HR(FX->SetTechnique(eRingTech)); HR(FX->SetMatrix(eW, pW)); HR(FX->SetTexture(eTex0, pTex)); - if (sunLight) FX->SetValue(eSun, sunLight, sizeof(D3D9Sun)); + FX->SetValue(eSun, &sunLight, sizeof(D3D9Sun)); HR(FX->SetValue(eMtrl, &defmat, sizeof(D3D9MatExt)-4)); HR(FX->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); HR(FX->BeginPass(0)); @@ -3313,7 +3370,7 @@ void D3D9Mesh::RenderRings2(const LPD3DXMATRIX pW, LPDIRECT3DTEXTURE9 pTex, floa HR(FX->SetTechnique(eRingTech2)); HR(FX->SetMatrix(eW, pW)); HR(FX->SetTexture(eTex0, pTex)); - if (sunLight) FX->SetValue(eSun, sunLight, sizeof(D3D9Sun)); + FX->SetValue(eSun, &sunLight, sizeof(D3D9Sun)); HR(FX->SetValue(eMtrl, &defmat, sizeof(D3D9MatExt)-4)); HR(FX->SetVector(eTexOff, &D3DXVECTOR4(irad, orad, 0, 0))); HR(FX->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); @@ -3322,3 +3379,23 @@ void D3D9Mesh::RenderRings2(const LPD3DXMATRIX pW, LPDIRECT3DTEXTURE9 pTex, floa HR(FX->EndPass()); HR(FX->End()); } + + +// =========================================================================================== +// +void D3D9Mesh::GlobalInit(LPDIRECT3DDEVICE9 pDev) +{ + memset(s_pShader, 0, sizeof(s_pShader)); + + s_pShader[SHADER_SHADOWMAP] = new MeshShader(pDev, "Modules/D3D9Client/NewMesh.hlsl", "ShdMapVS", "ShdMapPS"); + s_pShader[SHADER_SHADOWMAP_OIT] = new MeshShader(pDev, "Modules/D3D9Client/NewMesh.hlsl", "ShdMapOIT_VS", "ShdMapOIT_PS"); + s_pShader[SHADER_NORMAL_DEPTH] = new MeshShader(pDev, "Modules/D3D9Client/NewMesh.hlsl", "NormalDepth_VS", "NormalDepth_PS"); +} + + +// =========================================================================================== +// +void D3D9Mesh::GlobalExit() +{ + for (auto x : s_pShader) if (x) delete x; +} diff --git a/OVP/D3D9Client/Mesh.h b/OVP/D3D9Client/Mesh.h index c41739386..7c9429104 100644 --- a/OVP/D3D9Client/Mesh.h +++ b/OVP/D3D9Client/Mesh.h @@ -38,31 +38,75 @@ const DWORD SPEC_INHERIT = (DWORD)(-2); // "inherit" material/texture flag #define ENVMAP_MAIN 0 - -#define SHADER_NULL 0xFFFF -#define SHADER_PBR 0 -#define SHADER_ADV 1 -#define SHADER_LEGACY 2 // Shader most compatible with DX7 Inline -#define SHADER_XR2HUD 3 // XR2 HUD shader -#define SHADER_METALNESS 4 +// Mesh Shaders +#define SHADER_NULL 0xFFFF +#define SHADER_PBR 0 +#define SHADER_ADV 1 +#define SHADER_LEGACY 2 // Shader most compatible with DX7 Inline +#define SHADER_XR2HUD 3 // XR2 HUD shader +#define SHADER_METALNESS 4 +#define SHADER_SHADOWMAP 10 +#define SHADER_SHADOWMAP_OIT 11 +#define SHADER_NORMAL_DEPTH 12 #define VCLASS_AMSO 1 #define VCLASS_XR2 2 #define VCLASS_ULTRA 3 #define VCLASS_SSU_CENTAUR 4 +// Mesh memory mapping mode #define MAPMODE_UNKNOWN 0 #define MAPMODE_CURRENT 1 #define MAPMODE_STATIC 2 #define MAPMODE_DYNAMIC 3 + + + struct _LightList { int idx; float illuminace; }; +class MeshShader : public ShaderClass +{ +public: + + static struct VSConst { + float4x4 mVP; // View Projection Matrix + float4x4 mW; // World Matrix + } vs_const; + + static struct PSConst { + float3 Cam_X; + float3 Cam_Y; + float3 Cam_Z; + } ps_const; + + static struct PSBools { + BOOL bOIT; // Enable order independent transparency + } ps_bools; + + + MeshShader(LPDIRECT3DDEVICE9 pDev, const char *file, const char *vs, const char *ps, const char *opt = NULL) : + ShaderClass(pDev, "Modules/D3D9Client/NewMesh.hlsl", vs, ps, "MeshShader", opt) + { + memset(hPST, 0, sizeof(hPST)); + hVSC = GetVSHandle("vs_const"); + hPSC = GetPSHandle("ps_const"); + hPSB = GetPSHandle("ps_bools"); + hPST[0] = GetPSHandle("tDiff"); + } + + ~MeshShader() + { + + } + + HANDLE hPSB, hVSC, hPSC, hPST[16]; +}; @@ -247,7 +291,8 @@ class D3D9Mesh : private D3D9Effect void RenderBoundingBox(const LPD3DXMATRIX pW); void Render(const LPD3DXMATRIX pW, int iTech=RENDER_VESSEL, LPDIRECT3DCUBETEXTURE9 *pEnv=NULL, int nEnv=0); void RenderFast(const LPD3DXMATRIX pW, int iTech); - void RenderShadows(float alpha, const LPD3DXMATRIX pP, const LPD3DXMATRIX pW, bool bShadowMap = false, const D3DXVECTOR4 *elev = NULL); + void RenderShadowMap(const LPD3DXMATRIX pW, const LPD3DXMATRIX pVP, int flags); + void RenderStencilShadows(float alpha, const LPD3DXMATRIX pP, const LPD3DXMATRIX pW, bool bShadowMap = false, const D3DXVECTOR4 *elev = NULL); void RenderShadowsEx(float alpha, const LPD3DXMATRIX pP, const LPD3DXMATRIX pW, const D3DXVECTOR4 *light, const D3DXVECTOR4 *param); void RenderRings(const LPD3DXMATRIX pW, LPDIRECT3DTEXTURE9 pTex); void RenderRings2(const LPD3DXMATRIX pW, LPDIRECT3DTEXTURE9 pTex, float irad, float orad); @@ -282,6 +327,9 @@ class D3D9Mesh : private D3D9Effect */ inline void EnableMatAlpha (bool enable) { bModulateMatAlpha = enable; } + static void GlobalInit(LPDIRECT3DDEVICE9 pDev); + static void GlobalExit(); + private: @@ -291,6 +339,7 @@ class D3D9Mesh : private D3D9Effect void SetGroupRec(DWORD i, const MESHGROUPEX *mg); void Null(const char *meshName = NULL); void UpdateFlags(); + void ConfigureAtmo(); WORD DefShader; DWORD MaxVert; @@ -307,7 +356,7 @@ class D3D9Mesh : private D3D9Effect D3DXMATRIX mTransform; D3DXMATRIX mTransformInv; D3DXMATRIX *pGrpTF; - const D3D9Sun *sunLight; + D3D9Sun sunLight; D3DCOLOR cAmbient; LightStruct null_light; @@ -320,7 +369,7 @@ class D3D9Mesh : private D3D9Effect char name[128]; - + static MeshShader* s_pShader[16]; }; #endif // !__MESH_H diff --git a/OVP/D3D9Client/PlanetRenderer.cpp b/OVP/D3D9Client/PlanetRenderer.cpp deleted file mode 100644 index 166404abc..000000000 --- a/OVP/D3D9Client/PlanetRenderer.cpp +++ /dev/null @@ -1,574 +0,0 @@ - -// ============================================================== -// Part of the ORBITER VISUALISATION PROJECT (OVP) -// Dual licensed under GPL v3 and LGPL v3 -// Copyright (C) 2014 - 2016 Jarmo Nikkanen -// ============================================================== - - -#include "PlanetRenderer.h" -#include "D3D9Config.h" -#include "AABBUtil.h" -#include "VectorHelpers.h" -#include "Scene.h" -#include "VPlanet.h" -#include "D3D9Surface.h" -#include "DebugControls.h" - - -// ------------------------------------------------------------ -class oapi::D3D9Client *PlanetRenderer::gc = NULL; -LPDIRECT3DDEVICE9 PlanetRenderer::pDev = NULL; -LPDIRECT3DTEXTURE9 PlanetRenderer::hOcean = NULL; -LPDIRECT3DTEXTURE9 PlanetRenderer::hCloudMicro = NULL; -LPDIRECT3DTEXTURE9 PlanetRenderer::hCloudMicroNorm = NULL; -VECTOR3 PlanetRenderer::vLPosOld = _V(1,0,0); -bool PlanetRenderer::bEnvMapEnabled = false; -// ------------------------------------------------------------ -ID3DXEffect *PlanetRenderer::pShader = NULL; -D3DXHANDLE PlanetRenderer::eTileTech = NULL; -D3DXHANDLE PlanetRenderer::eCloudTech = NULL; -D3DXHANDLE PlanetRenderer::eRingTech = NULL; -D3DXHANDLE PlanetRenderer::eHorizonTech = NULL; -D3DXHANDLE PlanetRenderer::eSkyDomeTech = NULL; -// ------------------------------------------------------------ -D3DXHANDLE PlanetRenderer::ssLight = NULL; -// ------------------------------------------------------------ -D3DXHANDLE PlanetRenderer::smWorld = NULL; -D3DXHANDLE PlanetRenderer::smViewProj = NULL; -D3DXHANDLE PlanetRenderer::smLVP = NULL; -// ------------------------------------------------------------ -D3DXHANDLE PlanetRenderer::svTexOff = NULL; -D3DXHANDLE PlanetRenderer::svWater = NULL; -D3DXHANDLE PlanetRenderer::svSunDir = NULL; -D3DXHANDLE PlanetRenderer::svCloudOff = NULL; -D3DXHANDLE PlanetRenderer::svMicroOff = NULL; -D3DXHANDLE PlanetRenderer::svOverlayOff = NULL; -D3DXHANDLE PlanetRenderer::svOverlayCtrl = NULL; -D3DXHANDLE PlanetRenderer::svTangent = NULL; -D3DXHANDLE PlanetRenderer::svBiTangent = NULL; -D3DXHANDLE PlanetRenderer::svPolarAxis = NULL; -D3DXHANDLE PlanetRenderer::svMicroScale0 = NULL; -D3DXHANDLE PlanetRenderer::svMicroScale1 = NULL; -D3DXHANDLE PlanetRenderer::svMicroScale2 = NULL; -D3DXHANDLE PlanetRenderer::svSHD = NULL; -// ------------------------------------------------------------ -D3DXHANDLE PlanetRenderer::sfDistScale = NULL; -D3DXHANDLE PlanetRenderer::sfAlpha = NULL; -D3DXHANDLE PlanetRenderer::sfNight = NULL; -// ------------------------------------------------------------ -D3DXHANDLE PlanetRenderer::sbCloudSh = NULL; -D3DXHANDLE PlanetRenderer::sbLights = NULL; -D3DXHANDLE PlanetRenderer::sbLocals = NULL; -D3DXHANDLE PlanetRenderer::sbInSpace = NULL; -D3DXHANDLE PlanetRenderer::sbOnOff = NULL; -D3DXHANDLE PlanetRenderer::sbEnvEnable = NULL; -D3DXHANDLE PlanetRenderer::sbMicroNormals = NULL; -D3DXHANDLE PlanetRenderer::siTileLvl = NULL; -D3DXHANDLE PlanetRenderer::siDebug = NULL; -D3DXHANDLE PlanetRenderer::sbDebug = NULL; -D3DXHANDLE PlanetRenderer::sbShadows = NULL; -D3DXHANDLE PlanetRenderer::sbOverlay = NULL; -D3DXHANDLE PlanetRenderer::sbElevOvrl = NULL; -D3DXHANDLE PlanetRenderer::sbSpherical = NULL; -D3DXHANDLE PlanetRenderer::sbCloudNorm = NULL; -D3DXHANDLE PlanetRenderer::sbEarth = NULL; -// ------------------------------------------------------------ -D3DXHANDLE PlanetRenderer::stDiff = NULL; -D3DXHANDLE PlanetRenderer::stMask = NULL; -D3DXHANDLE PlanetRenderer::stCloud = NULL; -D3DXHANDLE PlanetRenderer::stCloud2 = NULL; -D3DXHANDLE PlanetRenderer::stNoise = NULL; -D3DXHANDLE PlanetRenderer::stOcean = NULL; -D3DXHANDLE PlanetRenderer::stEnvMap = NULL; -D3DXHANDLE PlanetRenderer::stMicroA = NULL; -D3DXHANDLE PlanetRenderer::stMicroB = NULL; -D3DXHANDLE PlanetRenderer::stMicroC = NULL; -D3DXHANDLE PlanetRenderer::stMicroRot = NULL; -D3DXHANDLE PlanetRenderer::stShadowMap = NULL; -D3DXHANDLE PlanetRenderer::stCloudMicro = NULL; -D3DXHANDLE PlanetRenderer::stCloudMicroNorm = NULL; -D3DXHANDLE PlanetRenderer::stOverlay = NULL; -D3DXHANDLE PlanetRenderer::stMskOverlay = NULL; -D3DXHANDLE PlanetRenderer::stElvOverlay = NULL; -// ------------------------------------------------------------ -D3DXHANDLE PlanetRenderer::sfGlobalAmb = NULL; -D3DXHANDLE PlanetRenderer::sfAmbient0 = NULL; -// Scatter model ---------------------------------------------- -D3DXHANDLE PlanetRenderer::svMPhase = NULL; -D3DXHANDLE PlanetRenderer::svODCoEff = NULL; -D3DXHANDLE PlanetRenderer::svODCoEffEx = NULL; -D3DXHANDLE PlanetRenderer::svMieInSct = NULL; -D3DXHANDLE PlanetRenderer::svRayInSct = NULL; -D3DXHANDLE PlanetRenderer::svTotOutSct = NULL; -D3DXHANDLE PlanetRenderer::svColorShift = NULL; -D3DXHANDLE PlanetRenderer::svHazeMax = NULL; -D3DXHANDLE PlanetRenderer::svCameraPos = NULL; -D3DXHANDLE PlanetRenderer::svUnitCameraPos = NULL; -D3DXHANDLE PlanetRenderer::sfCloudInts = NULL; -D3DXHANDLE PlanetRenderer::sfScaleHeight = NULL; -D3DXHANDLE PlanetRenderer::sfInvScaleHeight = NULL; -D3DXHANDLE PlanetRenderer::sfSunAlt = NULL; -D3DXHANDLE PlanetRenderer::sfRadius = NULL; -D3DXHANDLE PlanetRenderer::sfCameraAlt = NULL; -D3DXHANDLE PlanetRenderer::sfHorizonAlt = NULL; -D3DXHANDLE PlanetRenderer::sfAtmRad2 = NULL; -D3DXHANDLE PlanetRenderer::sfRPhase = NULL; -D3DXHANDLE PlanetRenderer::sfHorizonDst = NULL; -D3DXHANDLE PlanetRenderer::sfExposure = NULL; -D3DXHANDLE PlanetRenderer::sfAux1 = NULL; -D3DXHANDLE PlanetRenderer::sfAux2 = NULL; -D3DXHANDLE PlanetRenderer::sfTrGamma = NULL; -D3DXHANDLE PlanetRenderer::sfAtmGamma = NULL; -D3DXHANDLE PlanetRenderer::sfInvAux1 = NULL; -D3DXHANDLE PlanetRenderer::sfInvParameter = NULL; -D3DXHANDLE PlanetRenderer::sfTime = NULL; -// ------------------------------------------------------------ - - - -PlanetRenderer::PlanetRenderer() -{ - -} - - -PlanetRenderer::~PlanetRenderer() -{ - -} - - -void PlanetRenderer::GlobalInit (class oapi::D3D9Client *gclient) -{ - char name[MAX_PATH] = "Modules\\D3D9Client\\"; - char *sh_name = "Surface.fx"; - - strcat_s(name, ARRAYSIZE(name), sh_name); - - LogAlw("Starting to initialize %s a shading technique...", sh_name); - - gc = gclient; - pDev = gc->GetDevice(); - gc->OutputLoadStatus(sh_name, 1); - - // Create the Effect from a .fx file. - ID3DXBuffer* errors = 0; - D3DXMACRO macro[16]; memset(¯o, 0, 16*sizeof(D3DXMACRO)); - - bool bRiples = *(bool*)gc->GetConfigParam(CFGPRM_SURFACERIPPLE); - bool bShadows = *(bool*)gc->GetConfigParam(CFGPRM_CLOUDSHADOWS); - - // ------------------------------------------------------------------------------ - int m=0; - macro[m].Name = "ANISOTROPY_MACRO"; - macro[m].Definition = new char[32]; - sprintf_s((char*)macro[m].Definition,32,"%d",max(2,Config->Anisotrophy)); - // ------------------------------------------------------------------------------ - m=1; - macro[m].Name = "MICRO_ANISOTROPY"; - macro[m].Definition = new char[32]; - int micro_aniso = (1 << (max(1,Config->MicroFilter) - 1)); - sprintf_s((char*)macro[m].Definition,32,"%d", micro_aniso); - // ------------------------------------------------------------------------------ - m=2; - macro[m].Name = "MICRO_FILTER"; - macro[m].Definition = new char[32]; - switch(Config->MicroFilter) { - case 0: strcpy_s((char*)macro[m].Definition, 32, "POINT"); break; - case 1: strcpy_s((char*)macro[m].Definition, 32, "LINEAR"); break; - default: strcpy_s((char*)macro[m].Definition, 32, "ANISOTROPIC"); break; - } - // ------------------------------------------------------------------------------ - m=3; - macro[m].Name = "BLEND"; - macro[m].Definition = new char[4]; - switch(Config->BlendMode) { - case 0: strcpy_s((char*)macro[m].Definition, 4, "0"); break; - case 1: strcpy_s((char*)macro[m].Definition, 4, "1"); break; - default: strcpy_s((char*)macro[m].Definition, 4, "2"); break; - } - // ------------------------------------------------------------------------------ - m=4; - macro[m].Name = "MICRO_BIAS"; - macro[m].Definition = new char[8]; - sprintf_s((char*)macro[m].Definition,8,"%1.1f",float(Config->MicroBias)*0.1f); - // ------------------------------------------------------------------------------ - m=5; - if (Config->EnvMapMode && bRiples) { - macro[m].Name = "_ENVMAP"; - bEnvMapEnabled = true; - } else bEnvMapEnabled = false; - // ------------------------------------------------------------------------------ - m = 6; - macro[m].Name = "LMODE"; - macro[m].Definition = new char[32]; - sprintf_s((char*)macro[m].Definition, 32, "%d", Config->LightConfig); - // ------------------------------------------------------------------------------ - m = 7; - macro[m].Name = "SHDMAP"; - macro[m].Definition = new char[32]; - sprintf_s((char*)macro[m].Definition, 32, "%d", Config->ShadowFilter + 1); - // ------------------------------------------------------------------------------ - m++; - // ------------------------------------------------------------------------------ - if (bShadows) macro[m++].Name = "_CLOUDSHADOWS"; - // ------------------------------------------------------------------------------ - if (Config->ShadowMapMode) macro[m++].Name = "_SHDMAP"; - // ------------------------------------------------------------------------------ - if (Config->CloudMicro) macro[m++].Name = "_CLOUDMICRO"; - // ------------------------------------------------------------------------------ - if (Config->bCloudNormals) macro[m++].Name = "_CLOUDNORMALS"; - - HR(D3DXCreateEffectFromFileA(pDev, name, macro, 0, 0, 0, &pShader, &errors)); - - for (auto &i : macro) - { - if (i.Definition) { - delete[]i.Definition; - i.Definition = NULL; - } - } - - if (errors) { - LogErr("Effect Error: %s",(char*)errors->GetBufferPointer()); - MessageBoxA(0, (char*)errors->GetBufferPointer(), "Surface.fx Error", 0); - FatalAppExitA(0,"Critical error has occured. See Orbiter.log for details"); - } - - if (!pShader) { - LogErr("Failed to create an Effect (%s)",name); - return; - } - - if (Config->ShaderDebug) { - LPD3DXBUFFER pBuffer = NULL; - if (D3DXDisassembleEffect(pShader, true, &pBuffer) == S_OK) { - FILE *fp = NULL; - if (!fopen_s(&fp, "D9D9Planet_asm.html", "w")) { - pBuffer->GetBufferPointer(); - fwrite(pBuffer->GetBufferPointer(), 1, pBuffer->GetBufferSize(), fp); - fclose(fp); - } - pBuffer->Release(); - } - } - - - // --------------------------------------------------------------------- - // Bind shader-side variables and constants to local handles - // - - - - - // Techniques ---------------------------------------------------------- - eTileTech = pShader->GetTechniqueByName("TileTech"); - eCloudTech = pShader->GetTechniqueByName("CloudTech"); - eRingTech = pShader->GetTechniqueByName("RingTech"); - eHorizonTech = pShader->GetTechniqueByName("HorizonTech"); - eSkyDomeTech = pShader->GetTechniqueByName("SkyDomeTech"); - // ------------------------------------------------------------ - ssLight = pShader->GetParameterByName(0,"sLights"); - // ------------------------------------------------------------ - smWorld = pShader->GetParameterByName(0,"mWorld"); - smViewProj = pShader->GetParameterByName(0,"mViewProj"); - smLVP = pShader->GetParameterByName(0,"mLVP"); - // ------------------------------------------------------------ - svTexOff = pShader->GetParameterByName(0,"vTexOff"); - svCloudOff = pShader->GetParameterByName(0,"vCloudOff"); - svMicroOff = pShader->GetParameterByName(0,"vMicroOff"); - svOverlayOff = pShader->GetParameterByName(0,"vOverlayOff"); - svOverlayCtrl = pShader->GetParameterByName(0,"vOverlayCtrl"); - svWater = pShader->GetParameterByName(0,"vWater"); - svSunDir = pShader->GetParameterByName(0,"vSunDir"); - svTangent = pShader->GetParameterByName(0,"vTangent"); - svBiTangent = pShader->GetParameterByName(0,"vBiTangent"); - svPolarAxis = pShader->GetParameterByName(0,"vPolarAxis"); - svMicroScale0 = pShader->GetParameterByName(0,"vMSc0"); - svMicroScale1 = pShader->GetParameterByName(0,"vMSc1"); - svMicroScale2 = pShader->GetParameterByName(0,"vMSc2"); - svSHD = pShader->GetParameterByName(0,"vSHD"); - // ------------------------------------------------------------ - sfDistScale = pShader->GetParameterByName(0,"fDistScale"); - sfAlpha = pShader->GetParameterByName(0,"fAlpha"); - sfNight = pShader->GetParameterByName(0,"fNight"); - // ------------------------------------------------------------ - sbCloudSh = pShader->GetParameterByName(0,"bCloudSh"); - sbLights = pShader->GetParameterByName(0,"bLights"); - sbInSpace = pShader->GetParameterByName(0,"bInSpace"); - sbOnOff = pShader->GetParameterByName(0,"bOnOff"); - sbEnvEnable = pShader->GetParameterByName(0,"bEnvEnable"); - sbMicroNormals = pShader->GetParameterByName(0,"bMicroNormals"); - siTileLvl = pShader->GetParameterByName(0,"iTileLvl"); - siDebug = pShader->GetParameterByName(0,"iDebug"); - sbDebug = pShader->GetParameterByName(0,"bDebug"); - sbLocals = pShader->GetParameterByName(0,"bLocals"); - sbShadows = pShader->GetParameterByName(0,"bShadows"); - sbOverlay = pShader->GetParameterByName(0,"bOverlay"); - sbElevOvrl = pShader->GetParameterByName(0,"bElevOvrl"); - sbSpherical = pShader->GetParameterByName(0,"bSpherical"); - sbCloudNorm = pShader->GetParameterByName(0,"bCloudNorm"); - sbEarth = pShader->GetParameterByName(0,"bEarth"); - // ------------------------------------------------------------ - stDiff = pShader->GetParameterByName(0,"tDiff"); - stMask = pShader->GetParameterByName(0,"tMask"); - stCloud = pShader->GetParameterByName(0,"tCloud"); - stCloud2 = pShader->GetParameterByName(0,"tCloud2"); - stNoise = pShader->GetParameterByName(0,"tNoise"); - stOcean = pShader->GetParameterByName(0,"tOcean"); - stCloudMicro = pShader->GetParameterByName(0,"tCloudMicro"); - stCloudMicroNorm = pShader->GetParameterByName(0,"tCloudMicroNorm"); - stEnvMap = pShader->GetParameterByName(0,"tEnvMap"); - stMicroA = pShader->GetParameterByName(0,"tMicroA"); - stMicroB = pShader->GetParameterByName(0,"tMicroB"); - stMicroC = pShader->GetParameterByName(0,"tMicroC"); - stMicroRot = pShader->GetParameterByName(0,"tMicroRot"); - stShadowMap = pShader->GetParameterByName(0,"tShadowMap"); - stOverlay = pShader->GetParameterByName(0,"tOverlay"); - stMskOverlay = pShader->GetParameterByName(0,"tMskOverlay"); - stElvOverlay = pShader->GetParameterByName(0,"tElvOverlay"); - // ------------------------------------------------------------ - sfGlobalAmb = pShader->GetParameterByName(0,"fGlobalAmb"); - sfAmbient0 = pShader->GetParameterByName(0,"fAmbient"); - // Scatter model ---------------------------------------------- - svMPhase = pShader->GetParameterByName(0,"vMPhase"); - svODCoEff = pShader->GetParameterByName(0,"vODCoEff"); - svODCoEffEx = pShader->GetParameterByName(0,"vODCoEffEx"); - svMieInSct = pShader->GetParameterByName(0,"vMieInSct"); - svRayInSct = pShader->GetParameterByName(0,"vRayInSct"); - svTotOutSct = pShader->GetParameterByName(0,"vTotOutSct"); - svColorShift = pShader->GetParameterByName(0,"vColorShift"); - svHazeMax = pShader->GetParameterByName(0,"vHazeMax"); - svCameraPos = pShader->GetParameterByName(0,"vCameraPos"); - svUnitCameraPos = pShader->GetParameterByName(0,"vUnitCameraPos"); - sfCloudInts = pShader->GetParameterByName(0,"fCloudInts"); - sfScaleHeight = pShader->GetParameterByName(0,"fScaleHeight"); - sfInvScaleHeight = pShader->GetParameterByName(0,"fInvScaleHeight"); - sfSunAlt = pShader->GetParameterByName(0,"fSunAlt"); - sfRadius = pShader->GetParameterByName(0,"fRadius"); - sfCameraAlt = pShader->GetParameterByName(0,"fCameraAlt"); - sfHorizonAlt = pShader->GetParameterByName(0,"fHorizonAlt"); - sfAtmRad2 = pShader->GetParameterByName(0,"fAtmRad2"); - sfRPhase = pShader->GetParameterByName(0,"fRPhase"); - sfHorizonDst = pShader->GetParameterByName(0,"fHorizonDst"); - sfExposure = pShader->GetParameterByName(0,"fExposure"); - sfAux1 = pShader->GetParameterByName(0,"fAux1"); - sfAux2 = pShader->GetParameterByName(0,"fAux2"); - sfTrGamma = pShader->GetParameterByName(0,"fTrGamma"); - sfAtmGamma = pShader->GetParameterByName(0,"fAtmGamma"); - sfInvAux1 = pShader->GetParameterByName(0,"fInvAux1"); - sfInvParameter = pShader->GetParameterByName(0,"fInvParameter"); - sfTime = pShader->GetParameterByName(0,"fTime"); - // ------------------------------------------------------------ - - if (gc->TexturePath("D3D9Ocean.dds", name)) { - HR(D3DXCreateTextureFromFileA(pDev, name, &hOcean)); - } - - if (gc->TexturePath("cloud1.dds", name)) { - HR(D3DXCreateTextureFromFileA(pDev, name, &hCloudMicro)); - } - - if (gc->TexturePath("cloud1_norm.dds", name)) { - HR(D3DXCreateTextureFromFileA(pDev, name, &hCloudMicroNorm)); - } - - if (hOcean) { - HR(pShader->SetTexture(stOcean, hOcean)); - } - - if (hCloudMicro) { - HR(pShader->SetTexture(stCloudMicro, hCloudMicro)); - } - if (hCloudMicroNorm) { - HR(pShader->SetTexture(stCloudMicroNorm, hCloudMicroNorm)); - } -} - -// ----------------------------------------------------------------------- - -void PlanetRenderer::GlobalExit () -{ - SAFE_RELEASE(pShader); - SAFE_RELEASE(hOcean); - SAFE_RELEASE(hCloudMicro); - SAFE_RELEASE(hCloudMicroNorm); -} - -// ----------------------------------------------------------------------- - -void PlanetRenderer::SetWorldMatrix (const D3DXMATRIX &W) -{ - pShader->SetMatrix(smWorld, &W); -} - -// ----------------------------------------------------------------------- - -void PlanetRenderer::SetViewProjectionMatrix (const D3DXMATRIX *VP) -{ - pShader->SetMatrix(smViewProj, VP); -} - -// ----------------------------------------------------------------------- - -void PlanetRenderer::InitializeScattering(vPlanet *pPlanet) -{ - D3DXVECTOR3 ucam, cam = -_D3DXVECTOR3(pPlanet->PosFromCamera()); - D3DXVec3Normalize(&ucam, &cam); - - OBJHANDLE hPlanet = pPlanet->GetObject(); - D3DXVECTOR3 SunDir = _D3DXVECTOR3(pPlanet->SunDirection()); - - const ScatterParams *atmo = pPlanet->GetAtmoParams(); - - DWORD dAmbient = *(DWORD*)gc->GetConfigParam(CFGPRM_AMBIENTLEVEL); - float fAmbient = float(dAmbient)*0.0039f; - - - double pr = pPlanet->GetSize(); // Planet radius - double cr = pPlanet->CamDist(); // Camera distance from a planet center - double ca = cr - pr; // Camera altitude - - float fSunAlt = -D3DXVec3Dot(&cam, &SunDir); - - if (fSunAlt < 0) fSunAlt = float(ca); - else fSunAlt = float(sqrt(cr*cr - fSunAlt*fSunAlt) - pr); - - - // Initialize rendering for all bodies ----------------------------------------------------- - // - HR(Shader()->SetBool(sbOnOff, false)); - HR(Shader()->SetBool(sbDebug, (DebugControls::GetSceneDebug()>0))); - HR(Shader()->SetInt (siDebug, DebugControls::GetSceneDebug())); - HR(Shader()->SetValue(svCameraPos, &cam, sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svUnitCameraPos, &ucam, sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svSunDir, &SunDir, sizeof(D3DXVECTOR3))); - HR(Shader()->SetFloat(sfAmbient0, 0.0f)); - HR(Shader()->SetFloat(sfGlobalAmb, fAmbient)); - HR(Shader()->SetFloat(sfExposure, float(atmo->expo))); - HR(Shader()->SetFloat(sfTrGamma, 1.0f/float(atmo->tgamma))); - HR(Shader()->SetFloat(sfRadius, float(pr))); - HR(Shader()->SetFloat(sfCameraAlt, float(ca))); - HR(Shader()->SetFloat(sfSunAlt, fSunAlt)); - HR(Shader()->SetTexture(stNoise, gc->GetNoiseTex())); - - // --------------------------------------------------------------------- - // Initialize camera centric tangent frame for normal mapped water - // - MATRIX3 mRot; - oapiGetRotationMatrix(hPlanet, &mRot); - VECTOR3 vCPos = pPlanet->PosFromCamera(); - VECTOR3 vNrm = mul(mRot, pPlanet->ReferencePoint()); - VECTOR3 vRot = unit(mul(mRot, _V(0, 1, 0))); - VECTOR3 vTan = unit(crossp(vRot, vNrm)); - VECTOR3 vBiT = unit(crossp(vTan ,vNrm)); - - // --------------------------------------------------------------------- - HR(Shader()->SetValue(svTangent, &D3DXVEC(vTan), sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svBiTangent, &D3DXVEC(vBiT), sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svPolarAxis, &D3DXVEC(vRot), sizeof(D3DXVECTOR3))); - - // Initialize atmospheric rendering --------------------------------------------------- - // - const ATMCONST *atm = oapiGetPlanetAtmConstants(hPlanet); - if (atm==NULL) return; // No atmosphere... skip the rest - - - // Initialize atmospheric rendering constants ---------------------------------------------- - // - double *pCoEff = pPlanet->prm.ScatterCoEff; - - D3DXVECTOR4 ODCoEff = D3DXVECTOR4(float(pCoEff[0]), float(pCoEff[1]), float(pCoEff[2]), float(pCoEff[3])); - D3DXVECTOR4 ODCoEffEx = D3DXVECTOR4(float(pCoEff[4]), float(pCoEff[5]), float(pCoEff[6]), float(pCoEff[7])); - - // Phase function variables - float g = float(atmo->mphase); - float a = float((1.0f-g*g) / (4.0f*3.14f)); - float b = (1.0f+g*g); - float d = (-2.0f*g); - float rp = -float(atmo->rpow); - float h0 = float(atmo->height*1e3); // Scale height - float mp = -float(atmo->mpow); - float hp = -float(atmo->hazec); - - double ha = pPlanet->GetHorizonAlt(); - double me = pPlanet->GetMinElevation(); // Minimum elevation - double mr = pr + me; // Minimum radius - double ur = pr + ha; // Atmosphere upper radius (Skydome radius) - double ub = pr + ha*8.0; - double hd = 0; - double tm = fmod(oapiGetSimTime(), 3600.0f); - - if (cr>mr) hd = sqrt(cr*cr - mr*mr); // Camera to horizon distance - - if (hd < 1e3) hd = 1e3; - - float fS = D3DXVec3Dot(&SunDir, &ucam); - float fA = 0.0f; - float fC = 0.0f; - - if (cr>mr) fA = float(sqrt(1.0 - (mr*mr) / (cr*cr))); - if (cr>ub) fC = float(sqrt(1.0 - (ub*ub) / (cr*cr))); - - float fB = (-fS-fA) / (float(atmo->aux1+0.01)*0.64f); - float fP = float(pPlanet->AngleCoEff(0.0)); - - float fCorrect = 0.5f + saturate(fB)*1.5f; - - float fX = float(saturate((ca / (ha*0.3)) - 1.0)); - float fY = float(saturate((-fS - fC)*3.0f)); - - float fSuns = fX * fY; - - // 1.0 / lambda^4 - D3DXVECTOR3 lambda_ray = D3DXVECTOR3(pow(float(atmo->red), rp), pow(float(atmo->green), rp), pow(float(atmo->blue), rp)); - D3DXVECTOR3 lambda_mie = D3DXVECTOR3(pow(float(atmo->red), mp), pow(float(atmo->green), mp), pow(float(atmo->blue), mp)); - D3DXVECTOR3 lambda_haze = D3DXVECTOR3(pow(float(atmo->red), hp), pow(float(atmo->green), hp), pow(float(atmo->blue), hp)); - - D3DXVec3Normalize(&lambda_ray, &lambda_ray); - D3DXVec3Normalize(&lambda_mie, &lambda_mie); - D3DXVec3Normalize(&lambda_haze, &lambda_haze); - - D3DXVECTOR3 vTotOutSct = lambda_ray*float(atmo->rout) + lambda_mie*float(atmo->mie); - D3DXVECTOR3 vMieInSct = lambda_mie*float(atmo->mie); - D3DXVECTOR3 vRayInSct = lambda_ray*float(atmo->rin * atmo->rout); - D3DXVECTOR3 vColorShift = lerp(D3DXVECTOR3(1,1,1), lambda_ray, float(atmo->aux3)*fCorrect); - - vColorShift *= float(saturate((150e3 / abs(ca)) + fY + 0.3f)); - - D3DXVECTOR3 vHaze = lambda_haze * float(atmo->hazei); - vHaze = lerp(vHaze, D3DXVECTOR3(1, 1, 1), fSuns); - - // Camara altitude dependency multiplier for ambient color of atmosphere - float fMult = saturate((h0-float(ca*0.1))/h0); - - float fAmbLoc = fMult * float(min(0.7, log1p(atm->rho0)*0.4)); - - - // Upload parameters to shaders - HR(Shader()->SetFloat(sfAmbient0, fAmbLoc)); - HR(Shader()->SetValue(svMPhase, &D3DXVECTOR4(a,b,0,d), sizeof(D3DXVECTOR4))); - HR(Shader()->SetValue(svODCoEff, &D3DXVECTOR4(float(pCoEff[0]), float(pCoEff[1]), float(pCoEff[2]), float(pCoEff[3])), sizeof(D3DXVECTOR4))); - HR(Shader()->SetValue(svODCoEffEx, &D3DXVECTOR4(float(pCoEff[4]), float(pCoEff[5]), float(pCoEff[6]), float(pCoEff[7])), sizeof(D3DXVECTOR4))); - HR(Shader()->SetValue(svTotOutSct, &vTotOutSct, sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svMieInSct, &vMieInSct, sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svRayInSct, &vRayInSct, sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svColorShift, &vColorShift, sizeof(D3DXVECTOR3))); - HR(Shader()->SetValue(svHazeMax, &vHaze, sizeof(D3DXVECTOR3))); - HR(Shader()->SetFloat(sfAtmGamma, 1.0f/float(atmo->agamma))); - HR(Shader()->SetFloat(sfCloudInts, float(atmo->depth))); - HR(Shader()->SetFloat(sfRPhase, float(atmo->rphase))); - HR(Shader()->SetFloat(sfAux1, float(atmo->aux1))); - HR(Shader()->SetFloat(sfAux2, float(atmo->aux2))); - HR(Shader()->SetFloat(sfInvAux1, 1.0f/float(atmo->aux1))); - HR(Shader()->SetFloat(sfInvParameter, 1.0f/fP)); - HR(Shader()->SetFloat(sfScaleHeight, h0)); - HR(Shader()->SetFloat(sfInvScaleHeight, 1.0f/h0)); - HR(Shader()->SetFloat(sfHorizonAlt, float(ur-pr))); - HR(Shader()->SetFloat(sfAtmRad2, float(ur*ur))); - HR(Shader()->SetFloat(sfHorizonDst, float(hd))); - HR(Shader()->SetFloat(sfTime, float(tm))); - HR(Shader()->SetBool(sbInSpace, (cr>ur))); - HR(Shader()->SetBool(sbOnOff, true)); -} diff --git a/OVP/D3D9Client/PlanetRenderer.h b/OVP/D3D9Client/PlanetRenderer.h deleted file mode 100644 index 8be28d9b6..000000000 --- a/OVP/D3D9Client/PlanetRenderer.h +++ /dev/null @@ -1,159 +0,0 @@ -// ============================================================== -// Part of the ORBITER VISUALISATION PROJECT (OVP) -// Dual licensed under GPL v3 and LGPL v3 -// Copyright (C) 2014-2016 Jarmo Nikkanen -// ============================================================== - -#ifndef __PLANETRENDERER_H -#define __PLANETRENDERER_H - -#include "D3D9Client.h" - -/** - * \brief Global planet renderer object - * - * The global planet renderer object provides objects and handles - * (like D3DX Tech HANDLEs) useful to all rendering instances. - */ -class PlanetRenderer { - -public: - /** - * \brief Constructs a new planet renderer object - */ - PlanetRenderer(); - - /** - * \brief Destroys the planet renderer object - */ - ~PlanetRenderer(); - - /** - * \brief Set up global parameters shared by all instances - * \param gclient client instance pointer - */ - static void GlobalInit(class oapi::D3D9Client *gclient); - - /** - * \brief Release global parameters - */ - static void GlobalExit(); - static void InitializeScattering(class vPlanet *pPlanet); - - static LPDIRECT3DDEVICE9 Dev() { return pDev; } - static ID3DXEffect * Shader() { return pShader; } - static oapi::D3D9Client * Client() { return gc; } - - static void SetWorldMatrix (const D3DXMATRIX &W); - static void SetViewProjectionMatrix (const D3DXMATRIX *VP); - - // ------------------------------------------------------------ - static oapi::D3D9Client *gc; - static LPDIRECT3DDEVICE9 pDev; - static ID3DXEffect *pShader; - static LPDIRECT3DTEXTURE9 hOcean; - static LPDIRECT3DTEXTURE9 hCloudMicro; - static LPDIRECT3DTEXTURE9 hCloudMicroNorm; - static VECTOR3 vLPosOld; - static bool bEnvMapEnabled; - // ------------------------------------------------------------ - static D3DXHANDLE eTileTech; - static D3DXHANDLE eCloudTech; - static D3DXHANDLE eRingTech; - static D3DXHANDLE eHorizonTech; - static D3DXHANDLE eSkyDomeTech; - // ------------------------------------------------------------ - static D3DXHANDLE ssLight; - // ------------------------------------------------------------ - static D3DXHANDLE smWorld; - static D3DXHANDLE smViewProj; - static D3DXHANDLE smLVP; - // ------------------------------------------------------------ - static D3DXHANDLE svTexOff; - static D3DXHANDLE svWater; - static D3DXHANDLE svSunDir; - static D3DXHANDLE svCloudOff; - static D3DXHANDLE svMicroOff; - static D3DXHANDLE svOverlayOff; - static D3DXHANDLE svOverlayCtrl; - static D3DXHANDLE svTangent; - static D3DXHANDLE svBiTangent; - static D3DXHANDLE svPolarAxis; - static D3DXHANDLE svMicroScale0; - static D3DXHANDLE svMicroScale1; - static D3DXHANDLE svMicroScale2; - static D3DXHANDLE svSHD; - // ------------------------------------------------------------ - static D3DXHANDLE sfDistScale; - static D3DXHANDLE sfAlpha; - static D3DXHANDLE sfNight; - // ------------------------------------------------------------ - static D3DXHANDLE sbCloudSh; - static D3DXHANDLE sbLights; - static D3DXHANDLE sbLocals; - static D3DXHANDLE sbInSpace; - static D3DXHANDLE sbOnOff; - static D3DXHANDLE sbEnvEnable; - static D3DXHANDLE sbMicroNormals; - static D3DXHANDLE siTileLvl; - static D3DXHANDLE siDebug; - static D3DXHANDLE sbDebug; - static D3DXHANDLE sbShadows; - static D3DXHANDLE sbOverlay; - static D3DXHANDLE sbElevOvrl; - static D3DXHANDLE sbSpherical; - static D3DXHANDLE sbCloudNorm; - static D3DXHANDLE sbEarth; - // ------------------------------------------------------------ - static D3DXHANDLE stDiff; - static D3DXHANDLE stMask; - static D3DXHANDLE stCloud; - static D3DXHANDLE stCloud2; - static D3DXHANDLE stCloudMicro; - static D3DXHANDLE stCloudMicroNorm; - static D3DXHANDLE stNoise; - static D3DXHANDLE stOcean; - static D3DXHANDLE stEnvMap; - static D3DXHANDLE stMicroA; - static D3DXHANDLE stMicroB; - static D3DXHANDLE stMicroC; - static D3DXHANDLE stMicroRot; - static D3DXHANDLE stShadowMap; - static D3DXHANDLE stOverlay; - static D3DXHANDLE stMskOverlay; - static D3DXHANDLE stElvOverlay; - // ------------------------------------------------------------ - static D3DXHANDLE sfGlobalAmb; - static D3DXHANDLE sfAmbient0; - // Scatter model ---------------------------------------------- - static D3DXHANDLE svMPhase; - static D3DXHANDLE svODCoEff; - static D3DXHANDLE svODCoEffEx; - static D3DXHANDLE svMieInSct; - static D3DXHANDLE svRayInSct; - static D3DXHANDLE svTotOutSct; - static D3DXHANDLE svColorShift; - static D3DXHANDLE svHazeMax; - static D3DXHANDLE svCameraPos; - static D3DXHANDLE svUnitCameraPos; - static D3DXHANDLE sfCloudInts; - static D3DXHANDLE sfSunAlt; - static D3DXHANDLE sfScaleHeight; - static D3DXHANDLE sfInvScaleHeight; - static D3DXHANDLE sfRadius; - static D3DXHANDLE sfCameraAlt; - static D3DXHANDLE sfHorizonAlt; - static D3DXHANDLE sfAtmRad2; - static D3DXHANDLE sfRPhase; - static D3DXHANDLE sfHorizonDst; - static D3DXHANDLE sfExposure; - static D3DXHANDLE sfAux1; - static D3DXHANDLE sfAux2; - static D3DXHANDLE sfTrGamma; - static D3DXHANDLE sfAtmGamma; - static D3DXHANDLE sfInvAux1; - static D3DXHANDLE sfInvParameter; - static D3DXHANDLE sfTime; -}; - -#endif diff --git a/OVP/D3D9Client/Scene.cpp b/OVP/D3D9Client/Scene.cpp index 56c85e68a..86c54e6a9 100644 --- a/OVP/D3D9Client/Scene.cpp +++ b/OVP/D3D9Client/Scene.cpp @@ -11,7 +11,7 @@ #include "VVessel.h" #include "VBase.h" #include "Particle.h" -#include "PlanetRenderer.h" +#include "CSphereMgr.h" #include "D3D9Util.h" #include "D3D9Config.h" #include "D3D9Surface.h" @@ -21,9 +21,10 @@ #include "OapiExtension.h" #include "DebugControls.h" #include "IProcess.h" +#include "VectorHelpers.h" #include +#include -#define saturate(x) max(min(x, 1.0f), 0.0f) #define IKernelSize 150 using namespace oapi; @@ -77,6 +78,9 @@ Scene::Scene(D3D9Client *_gc, DWORD w, DWORD h) pDebugFont = NULL; pBlur = NULL; pOffscreenTarget = NULL; + pLocalCompute = NULL; + pRenderGlares = NULL; + pCreateGlare = NULL; viewH = h; viewW = w; nLights = 0; @@ -84,12 +88,24 @@ Scene::Scene(D3D9Client *_gc, DWORD w, DWORD h) dwFrameId = 0; surfLabelsActive = false; + pSunTex = NULL; + pLightGlare = NULL; + pSunGlare = NULL; + pSunGlareAtm = NULL; pEnvDS = NULL; pIrradDS = NULL; pIrradiance = NULL; pIrradTemp = NULL; pIrradTemp2 = NULL; pIrradTemp3 = NULL; + pDepthNormalDS = NULL; + pVisDepth = NULL; + pLocalResults = NULL; + pLocalResultsSL = NULL; + + fDisplayScale = float(viewH) / 1080.0f; + + for (auto& a : DepthSampleKernel) a = FVECTOR2(0, 0); memset(&psShmDS, 0, sizeof(psShmDS)); memset(&ptShmRT, 0, sizeof(ptShmRT)); @@ -143,10 +159,49 @@ Scene::Scene(D3D9Client *_gc, DWORD w, DWORD h) IKernel[i].z = sqrt(1.0f - saturate(d)); IKernel[i].w = sqrt(IKernel[i].z); } - - + + // ------------------------------------------------------------------------------ + // Read Sun glare sampling kernel file + + ifstream fs("Modules/D3D9Client/GKernel.txt"); + if (fs.good()) { + string line; vector data; + while (getline(fs, line)) { + std::istringstream iss(line); + char c; float a, b; iss >> a >> c >> b; + data.push_back(FVECTOR2(a, b)); + } + if (data.size() != ARRAYSIZE(DepthSampleKernel)) LogErr("Modules/D3D9Client/GKernel.txt Size missmatch. Expecting 57 entries"); + else for (int i = 0; i < ARRAYSIZE(DepthSampleKernel); i++) DepthSampleKernel[i] = data[i]; + data.clear(); + } else LogErr("Failed to read: Modules/D3D9Client/GKernel.txt"); + fs.close(); + + CreateSunGlare(); + + + // ------------------------------------------------------------------------------ + // Initialize a shaders for local lights visibility checks and rendering + + if (Config->bGlares || Config->bLocalGlares) + { + pRenderGlares = new ShaderClass(pDevice, "Modules/D3D9Client/Glare.hlsl", "GlareVS", "GlarePS", "RenderGlares", ""); + pLocalCompute = new ShaderClass(pDevice, "Modules/D3D9Client/Glare.hlsl", "VisibilityVS", "VisibilityPS", "LocalVisCheck", ""); + D3DXCreateTexture(pDevice, 32, 1, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R16F, D3DPOOL_DEFAULT, &pLocalResults); + HR(pLocalResults->GetSurfaceLevel(0, &pLocalResultsSL)); + } + + + // Render screen depth and screen space normals + // + + if (Config->bGlares || Config->bLocalGlares) { + pVisDepth = new ImageProcessing(pDevice, "Modules/D3D9Client/LightBlur.hlsl", "PSDepth", NULL); + pVisDepth->CompileShader("PSNormal"); + } + // Initialize envmapping and shadow maps ----------------------------------------------------------------------------------------------- // DWORD EnvMapSize = Config->EnvMapSize; @@ -154,6 +209,9 @@ Scene::Scene(D3D9Client *_gc, DWORD w, DWORD h) if (Config->EnvMapMode) { HR(pDevice->CreateDepthStencilSurface(EnvMapSize, EnvMapSize, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, true, &pEnvDS, NULL)); + } + + if (Config->bIrradiance) { HR(pDevice->CreateDepthStencilSurface(128, 128, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, true, &pIrradDS, NULL)); } @@ -181,6 +239,14 @@ Scene::Scene(D3D9Client *_gc, DWORD w, DWORD h) else pGDIOverlay = NULL; + // Create an auxiliary screen space normal and depth buffer (i.e. Shader readable depth buffer) + // + if (Config->bGlares || Config->bLocalGlares) { + HR(pDevice->CreateDepthStencilSurface(viewW, viewH, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, true, &pDepthNormalDS, NULL)); + HR(D3DXCreateTexture(pDevice, viewW, viewH, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &ptgBuffer[GBUF_DEPTH])); + } + + // Initialize post processing effects -------------------------------------------------------------------------------------------------- // pLightBlur = NULL; @@ -268,15 +334,27 @@ Scene::~Scene () SAFE_DELETE(pGDIOverlay); SAFE_DELETE(pBlur); + SAFE_DELETE(pVisDepth); SAFE_DELETE(pLightBlur); SAFE_DELETE(pIrradiance); SAFE_DELETE(m_celSphere); + SAFE_DELETE(pLocalCompute); + SAFE_DELETE(pRenderGlares); + SAFE_DELETE(pCreateGlare); + SAFE_RELEASE(pOffscreenTarget); SAFE_RELEASE(pEnvDS); SAFE_RELEASE(pIrradDS); SAFE_RELEASE(pIrradTemp); SAFE_RELEASE(pIrradTemp2); SAFE_RELEASE(pIrradTemp3); + SAFE_RELEASE(pDepthNormalDS); + SAFE_RELEASE(pLocalResults); + SAFE_RELEASE(pLocalResultsSL); + SAFE_RELEASE(pSunTex); + SAFE_RELEASE(pLightGlare); + SAFE_RELEASE(pSunGlare); + SAFE_RELEASE(pSunGlareAtm); for (int i = 0; i < ARRAYSIZE(psShmDS); i++) SAFE_RELEASE(psShmDS[i]); for (int i = 0; i < ARRAYSIZE(ptShmRT); i++) SAFE_RELEASE(ptShmRT[i]); @@ -303,6 +381,57 @@ Scene::~Scene () } +// =========================================================================================== +// +void Scene::CreateSunGlare() +{ + // ------------------------------------------------------------------------------ + // Create sun texture and glares + + if (pCreateGlare) SAFE_DELETE(pCreateGlare); + + pCreateGlare = new ImageProcessing(pDevice, "Modules/D3D9Client/Glare.hlsl", "CreateSunGlarePS"); + pCreateGlare->CompileShader("CreateLocalGlarePS"); + pCreateGlare->CompileShader("CreateSunGlareAtmPS"); + pCreateGlare->CompileShader("CreateSunTexPS"); + + + if (!pSunTex) { + UINT ts = (viewH >> 4) & 0xFFFC; // "ts" will be 64 for a Full HD display; + HR(D3DXCreateTexture(pDevice, ts * 5, ts * 5, 0, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSunTex)); + HR(D3DXCreateTexture(pDevice, ts * 4, ts * 4, 0, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_R16F, D3DPOOL_DEFAULT, &pLightGlare)); + HR(D3DXCreateTexture(pDevice, ts * 12, ts * 12, 0, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_R16F, D3DPOOL_DEFAULT, &pSunGlare)); + HR(D3DXCreateTexture(pDevice, ts * 12, ts * 12, 0, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_R16F, D3DPOOL_DEFAULT, &pSunGlareAtm)); + } + + LPDIRECT3DSURFACE9 pTgt = NULL; + + pCreateGlare->Activate("CreateSunGlarePS"); + pSunGlare->GetSurfaceLevel(0, &pTgt); + pCreateGlare->SetOutputNative(0, pTgt); + if (!pCreateGlare->Execute(false)) LogErr("pCreateGlare Execute Failed (CreateSunGlarePS)"); + SAFE_RELEASE(pTgt); + + pCreateGlare->Activate("CreateSunGlareAtmPS"); + pSunGlareAtm->GetSurfaceLevel(0, &pTgt); + pCreateGlare->SetOutputNative(0, pTgt); + if (!pCreateGlare->Execute(false)) LogErr("pCreateGlare Execute Failed (CreateSunGlareAtmPS)"); + SAFE_RELEASE(pTgt); + + pCreateGlare->Activate("CreateLocalGlarePS"); + pLightGlare->GetSurfaceLevel(0, &pTgt); + pCreateGlare->SetOutputNative(0, pTgt); + if (!pCreateGlare->Execute(false)) LogErr("pCreateGlare Execute Failed (CreateLocalGlarePS)"); + SAFE_RELEASE(pTgt); + + pCreateGlare->Activate("CreateSunTexPS"); + pSunTex->GetSurfaceLevel(0, &pTgt); + pCreateGlare->SetOutputNative(0, pTgt); + if (!pCreateGlare->Execute(false)) LogErr("pCreateGlare Execute Failed (CreateSunTexPS)"); + SAFE_RELEASE(pTgt); +} + + // =========================================================================================== // void Scene::Initialise() @@ -315,23 +444,17 @@ void Scene::Initialise() // Setup sunlight ------------------------------- // - float pwr = 1.0f; - - sunLight.Color.r = pwr; - sunLight.Color.g = pwr; - sunLight.Color.b = pwr; - sunLight.Color.a = 1.0f; - sunLight.Ambient.r = float(ambient)*0.0039f; - sunLight.Ambient.g = float(ambient)*0.0039f; - sunLight.Ambient.b = float(ambient)*0.0039f; - sunLight.Ambient.a = 1.0f; + sunLight.Color = 1.0f; + sunLight.Ambient = float(ambient)*0.0039f; + sunLight.Transmission = 1.0f; + sunLight.Incatter = 0.0f; // Update Sunlight direction ------------------------------------- // VECTOR3 rpos, cpos; oapiGetGlobalPos(hSun, &rpos); oapiCameraGlobalPos(&cpos); rpos-=cpos; - D3DVEC(-unit(rpos), sunLight.Dir); + sunLight.Dir = -unit(rpos); // Do not "pre-create" visuals here. Will cause changed call order for vessel callbacks } @@ -904,7 +1027,6 @@ float Scene::ComputeNearClipPlane() void Scene::UpdateCamVis() { - dwFrameId++; // Advance to a next frame // Update camera parameters -------------------------------------- // and call vObject::Update() for all visuals @@ -918,7 +1040,7 @@ void Scene::UpdateCamVis() VECTOR3 rpos; oapiGetGlobalPos(hSun, &rpos); rpos -= Camera.pos; - D3DVEC(-unit(rpos), sunLight.Dir); + sunLight.Dir = -unit(rpos); // Get focus visual ----------------------------------------------- // @@ -1022,6 +1144,92 @@ void Scene::AddLocalLight(const LightEmitter *le, const vObject *vo) } } +// =========================================================================================== +// +void Scene::ComputeLocalLightsVisibility() +{ + + if (!ptgBuffer[GBUF_DEPTH] || !pLocalCompute) { + Config->bGlares = false; + Config->bLocalGlares = false; + return; + } + + VECTOR3 gsun; + oapiGetGlobalPos(oapiGetObjectByIndex(0), &gsun); + + // Put the Sun on a top of the list + LLCBuf[0].index = 0.0f; + LLCBuf[0].pos = FVECTOR3(unit(gsun - Camera.pos)) * 10e4; + LLCBuf[0].cone = 1.0f; + + int nGlares = 1; + + for (int i = 0; i < nLights; i++) + { + if (Lights[i].cone > 0.0f) { + LLCBuf[nGlares].index = float(nGlares); + LLCBuf[nGlares].pos = Lights[i].Position; + LLCBuf[nGlares].cone = Lights[i].cone; + Lights[i].GPUId = nGlares; + nGlares++; + } + } + + struct { + D3DXMATRIX mVP; + D3DXMATRIX mSVP; + FVECTOR4 vSrc; + FVECTOR3 vDir; + } ComputeData; + + D3DSURFACE_DESC desc; + pLocalResultsSL->GetDesc(&desc); + + D3DXMatrixOrthoOffCenterLH(&ComputeData.mVP, 0.0f, (float)desc.Width, (float)desc.Height, 0.0f, 0.0f, 1.0f); + + psgBuffer[GBUF_DEPTH]->GetDesc(&desc); + + ComputeData.vSrc = FVECTOR4((float)desc.Width, (float)desc.Height, 1.0f / (float)desc.Width, 1.0f / (float)desc.Height); + ComputeData.vDir = Camera.z; + ComputeData.mSVP = Camera.mProjView; + + // Must setup render target before calling Setup() + gc->PushRenderTarget(pLocalResultsSL, NULL, RENDERPASS_UNKNOWN); + + pLocalCompute->ClearTextures(); + pLocalCompute->SetPSConstants("cbPS", &ComputeData, sizeof(ComputeData)); + pLocalCompute->SetPSConstants("cbKernel", DepthSampleKernel, sizeof(DepthSampleKernel)); + pLocalCompute->SetVSConstants("cbPS", &ComputeData, sizeof(ComputeData)); + pLocalCompute->SetTexture("tDepth", ptgBuffer[GBUF_DEPTH], IPF_CLAMP | IPF_POINT); + pLocalCompute->Setup(pLocalLightsDecl, false, 0); + pLocalCompute->UpdateTextures(); + + // Compute local lights visibility + HR(pDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nGlares, &LLCBuf, sizeof(LocalLightsCompute))); + + pLocalCompute->DetachTextures(); + gc->PopRenderTargets(); +} + + +// =========================================================================================== +// +void Scene::RecallDefaultState() +{ + HR(pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID)); + HR(pDevice->SetRenderState(D3DRS_STENCILENABLE, false)); + HR(pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xF)); + HR(pDevice->SetRenderState(D3DRS_ZENABLE, true)); + HR(pDevice->SetRenderState(D3DRS_ZWRITEENABLE, true)); + HR(pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false)); + HR(pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false)); + HR(pDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD)); + HR(pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)); + HR(pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)); + HR(pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW)); +} + // =========================================================================================== // @@ -1029,15 +1237,17 @@ void Scene::RenderMainScene() { _TRACE; + dwFrameId++; // Advance to a next frame + double scene_time = D3D9GetTime(); D3D9SetTime(D3D9Stats.Timer.CamVis, scene_time); UpdateCamVis(); + // Update Vessel Animations // for (VOBJREC *pv = vobjFirst; pv; pv = pv->next) { - if (!pv->vobj->IsActive() || !pv->vobj->IsVisible() || pv->vobj->GetMeshCount() < 1) continue; if (pv->type == OBJTP_VESSEL) { vVessel *vv = (vVessel *)pv->vobj; vv->UpdateAnimations(); @@ -1062,10 +1272,11 @@ void Scene::RenderMainScene() // ------------------------------------------------------------------------------------------------------- // Render Custom Camera and Environment Views // ------------------------------------------------------------------------------------------------------- + bool bIrrad = Config->EnvMapMode && Config->bIrradiance; if (Config->CustomCamMode == 0 && dwTurn == RENDERTURN_CUSTOMCAM) dwTurn++; if (Config->EnvMapMode == 0 && dwTurn == RENDERTURN_ENVCAM) dwTurn++; - if (Config->EnvMapMode == 0 && dwTurn == RENDERTURN_IRRADIANCE) dwTurn++; + if (!bIrrad && dwTurn == RENDERTURN_IRRADIANCE) dwTurn++; if (dwTurn>RENDERTURN_LAST) dwTurn = 0; @@ -1112,7 +1323,7 @@ void Scene::RenderMainScene() if (Config->EnvMapMode) { DWORD flags = 0; if (Config->EnvMapMode == 1) flags |= 0x01; - if (Config->EnvMapMode == 2) flags |= 0x03; + if (Config->EnvMapMode == 2) flags |= (0x03 | 0x20); if (vobjEnv == NULL) vobjEnv = vobjFirst; @@ -1136,10 +1347,10 @@ void Scene::RenderMainScene() if (dwTurn == RENDERTURN_IRRADIANCE) { - if (Config->EnvMapMode) { + if (Config->EnvMapMode && Config->bIrradiance) { DWORD flags = 0; if (Config->EnvMapMode == 1) flags |= 0x01; - if (Config->EnvMapMode == 2) flags |= 0x03; + if (Config->EnvMapMode == 2) flags |= (0x03 | 0x20); if (vobjIrd == NULL) vobjIrd = vobjFirst; @@ -1156,20 +1367,71 @@ void Scene::RenderMainScene() } + // --------------------------------------------------------------------------------------------- + // Init. camera setup and create a render list + // --------------------------------------------------------------------------------------------- + + VOBJREC* pv = NULL; + LPDIRECT3DTEXTURE9 pShdMap = NULL; + + UpdateCameraFromOrbiter(RENDERPASS_MAINSCENE); + UpdateCamVis(); + + RenderList.clear(); + + for (pv = vobjFirst; pv; pv = pv->next) { + if (!pv->vobj->IsActive()) continue; + if (!pv->vobj->IsVisible()) continue; + if (pv->type == OBJTP_VESSEL) { + vVessel* vV = (vVessel*)pv->vobj; + RenderList.push_back(vV); + vV->bStencilShadow = true; + } + } + + float znear_for_vessels = ComputeNearClipPlane(); + + + + + // --------------------------------------------------------------------------------------------- + // Start Rendering of Normal and Depth Buffer for SSAO and (point in scene) visibility checks + // --------------------------------------------------------------------------------------------- + + if (psgBuffer[GBUF_DEPTH] && pDepthNormalDS) + { + SetCameraFrustumLimits(0.1f, 1e6f); + BeginPass(RENDERPASS_NORMAL_DEPTH); + + gc->PushRenderTarget(psgBuffer[GBUF_DEPTH], pDepthNormalDS, RENDERPASS_NORMAL_DEPTH); + + RecallDefaultState(); + + // Clear buffers + HR(pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0, 1.0f, 0L)); + + // Render vessels + for (auto* vVes : RenderList) vVes->Render(pDevice, false); + // Render Cockpit + if (oapiCameraInternal() && vFocus) vFocus->Render(pDevice, true); + gc->PopRenderTargets(); + PopPass(); + } + // --------------------------------------------------------------------------------------------- + // Compute visibility of the Sun and Local light sources. After field depth render ! ! ! + // --------------------------------------------------------------------------------------------- + ComputeLocalLightsVisibility(); // ------------------------------------------------------------------------------------------------------- // Start Main Scene Rendering // ------------------------------------------------------------------------------------------------------- - UpdateCameraFromOrbiter(RENDERPASS_MAINSCENE); - - UpdateCamVis(); - + RenderFlags = 0xFFFFFFFF; // Not used for main scene, set to 0xFFFFFFFF // Push main render target and depth surfaces // @@ -1188,7 +1450,6 @@ void Scene::RenderMainScene() } - float znear_for_vessels = ComputeNearClipPlane(); // Do we use z-clear render mode or not ? bool bClearZBuffer = false; @@ -1211,11 +1472,6 @@ void Scene::RenderMainScene() vPlanet *vPl = GetCameraProxyVisual(); - if (vPl) { - bEnableAtmosphere = vPl->CameraInAtmosphere(); - PlanetRenderer::InitializeScattering(vPl); - } - // ------------------------------------------------------------------------------------------------------- // Render the celestial sphere (background image, stars, planetarium features) // ------------------------------------------------------------------------------------------------------- @@ -1226,27 +1482,10 @@ void Scene::RenderMainScene() m_celSphere->Render(pDevice, sky_color); // Set Initial Near clip plane distance - if (bClearZBuffer) SetCameraFrustumLimits(1e3, 1e8f); - else SetCameraFrustumLimits(znear_for_vessels, 1e8f); + if (bClearZBuffer) SetCameraFrustumLimits(1e3, 3e8f); + else SetCameraFrustumLimits(znear_for_vessels, 3e8f); - // --------------------------------------------------------------------------------------------- - // Create a render list for shadow mapping - // --------------------------------------------------------------------------------------------- - - VOBJREC *pv = NULL; - LPDIRECT3DTEXTURE9 pShdMap = NULL; - - RenderList.clear(); - - for (pv = vobjFirst; pv; pv = pv->next) { - if (!pv->vobj->IsActive()) continue; - if (!pv->vobj->IsVisible()) continue; - if (pv->type == OBJTP_VESSEL) { - vVessel *vV = (vVessel *)pv->vobj; - RenderList.push_back(vV); - vV->bStencilShadow = true; - } - } + pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // --------------------------------------------------------------------------------------------- // Create a caster list for shadow mapping @@ -1472,6 +1711,17 @@ void Scene::RenderMainScene() pSketch->EndDrawing(); // SKETCHPAD_PLANETARIUM } + /*for (DWORD i = 0; i < nplanets; ++i) + { + OBJHANDLE hObj = plist[i].vo->Object(); + if (oapiGetObjectType(hObj) != OBJTP_PLANET) continue; + D3D9Pad* pSketch = GetPooledSketchpad(SKETCHPAD_PLANETARIUM); + pSketch->LoadDefaults(); + pSketch->SetViewMode(Sketchpad::USER); + pSketch->SetViewProj(GetViewMatrix(), GetProjectionMatrix()); + static_cast(plist[i].vo)->TestComputations(pSketch); + pSketch->EndDrawing(); // SKETCHPAD_PLANETARIUM + }*/ // ------------------------------------------------------------------------------------------------------- // render new-style surface markers @@ -1762,7 +2012,6 @@ void Scene::RenderMainScene() pDevice->StretchRect(pOffscreenTarget, NULL, psgBuffer[GBUF_COLOR], NULL, D3DTEXF_POINT); pLightBlur->SetFloat("vSB", &sbf, sizeof(D3DXVECTOR2)); - //pLightBlur->SetFloat("vBB", &scr, sizeof(D3DXVECTOR2)); pLightBlur->SetBool("bBlendIn", false); pLightBlur->SetBool("bBlur", false); @@ -1774,7 +2023,6 @@ void Scene::RenderMainScene() // ----------------------------------------------------- pLightBlur->SetBool("bSample", true); pLightBlur->SetTextureNative("tBack", ptgBuffer[GBUF_COLOR], IPF_POINT | IPF_CLAMP); - //pLightBlur->SetTextureNative("tCLUT", pTextures[TEX_CLUT], IPF_LINEAR | IPF_CLAMP); pLightBlur->SetOutputNative(0, psgBuffer[GBUF_BLUR]); if (!pLightBlur->Execute(true)) LogErr("pLightBlur Execute Failed"); @@ -1785,8 +2033,6 @@ void Scene::RenderMainScene() for (int i = 0; i < iGensPerFrame; i++) { - //pLightBlur->SetInt("PassId", i); - pLightBlur->SetBool("bDir", false); pLightBlur->SetTextureNative("tBlur", ptgBuffer[GBUF_BLUR], IPF_POINT | IPF_CLAMP); pLightBlur->SetOutputNative(0, psgBuffer[GBUF_TEMP]); @@ -1813,7 +2059,15 @@ void Scene::RenderMainScene() } } - + + // ------------------------------------------------------------------------------------------------------- + // Render glares for the Sun and local lights + // ------------------------------------------------------------------------------------------------------- + + gc->PushRenderTarget(gc->GetBackBuffer(), gc->GetDepthStencil(), RENDERPASS_MAINSCENE); + RenderGlares(); + gc->PopRenderTargets(); + // ------------------------------------------------------------------------------------------------------- // Render GDI Overlay to backbuffer directly @@ -1848,7 +2102,11 @@ void Scene::RenderMainScene() if (pSketch) { gc->MakeRenderProcCall(pSketch, RENDERPROC_HUD_1ST, NULL, NULL); - gc->Render2DOverlay(); + pSketch->EndDrawing(); // SKETCHPAD_2D_OVERLAY + } + gc->Render2DOverlay(); + pSketch = GetPooledSketchpad(SKETCHPAD_2D_OVERLAY); + if (pSketch) { gc->MakeRenderProcCall(pSketch, RENDERPROC_HUD_2ND, NULL, NULL); pSketch->EndDrawing(); // SKETCHPAD_2D_OVERLAY } @@ -1899,12 +2157,85 @@ void Scene::RenderMainScene() pSketch->EndDrawing(); } break; + case 11: + if (ptgBuffer[GBUF_DEPTH]) { + if (pVisDepth) { + if (pVisDepth->IsOK()) { + pVisDepth->Activate("PSDepth"); + pVisDepth->SetTextureNative("tBack", ptgBuffer[GBUF_DEPTH], IPF_POINT | IPF_CLAMP); + pVisDepth->SetOutputNative(0, gc->GetBackBuffer()); + pVisDepth->Execute(true); + } + } + } + break; + case 12: + if (ptgBuffer[GBUF_DEPTH]) { + if (pVisDepth) { + if (pVisDepth->IsOK()) { + pVisDepth->Activate("PSNormal"); + pVisDepth->SetTextureNative("tBack", ptgBuffer[GBUF_DEPTH], IPF_POINT | IPF_CLAMP); + pVisDepth->SetOutputNative(0, gc->GetBackBuffer()); + pVisDepth->Execute(true); + } + } + } + break; + case 13: + if (pLocalResults) { + pSketch = GetPooledSketchpad(SKETCHPAD_2D_OVERLAY); + pSketch->SetBlendState(Sketchpad::BlendState::FILTER_POINT); + pSketch->StretchRectNative(pLocalResults, NULL, &_RECT(0, 0, viewW, 10)); + pSketch->SetBlendState(Sketchpad::BlendState::FILTER_LINEAR); + pSketch->EndDrawing(); + } + break; default: break; } } + if (AtmoControls::Visualize()) + { + vPlanet* vP = GetCameraProxyVisual(); + pSketch = GetPooledSketchpad(SKETCHPAD_2D_OVERLAY); + pSketch->SetBlendState(Sketchpad::COPY); + int x = 0, y = ViewH(); + + LPDIRECT3DTEXTURE9 pTab = vP->GetScatterTable(RAY_LAND); + D3DSURFACE_DESC desc; + if (pTab) { + pTab->GetLevelDesc(0, &desc); + pSketch->StretchRectNative(pTab, NULL, &_R(0, y - desc.Height, desc.Width, y)); + y -= (desc.Height + 5); + } + pTab = vP->GetScatterTable(MIE_LAND); + if (pTab) { + pTab->GetLevelDesc(0, &desc); + pSketch->StretchRectNative(pTab, NULL, &_R(0, y - desc.Height, desc.Width, y)); + y -= (desc.Height + 5); + } + pTab = vP->GetScatterTable(ATN_LAND); + if (pTab) { + pTab->GetLevelDesc(0, &desc); + pSketch->StretchRectNative(pTab, NULL, &_R(0, y - desc.Height, desc.Width, y)); + y -= (desc.Height + 5); + } + for (int i=0;i<9;i++) + { + if (i == RAY_LAND || i == MIE_LAND || i == ATN_LAND) continue; + pTab = vP->GetScatterTable(i); + if (!pTab) continue; + pTab->GetLevelDesc(0, &desc); + pSketch->CopyRectNative(pTab, NULL, x, y - desc.Height); + x += desc.Width + 5; + } + pSketch->SetBlendState(Sketchpad::ALPHABLEND); + pSketch->EndDrawing(); + } + + // ------------------------------------------------------------------------------------------------------- // Draw Debug String on a bottom of the screen // ------------------------------------------------------------------------------------------------------- @@ -1970,38 +2301,6 @@ void Scene::RenderVesselMarker(vVessel *vV, D3D9Pad *pSketch) // Scene::SUNVISPARAMS Scene::GetSunScreenVisualState() { - /* - SUNVISPARAMS result = SUNVISPARAMS(); - - VECTOR3 cam = GetCameraGPos(); - VECTOR3 sunGPos; - oapiGetGlobalPos(oapiGetGbodyByIndex(0), &sunGPos); - sunGPos -= cam; - DWORD w, h; - oapiGetViewportSize(&w, &h); - - MATRIX4 mVP = _MATRIX4(GetProjectionViewMatrix()); - VECTOR4 temp = _V(sunGPos.x, sunGPos.y, sunGPos.z, 1.0); - VECTOR4 pos = mul(temp, mVP); - - result.brightness = float(saturate(pos.z)); - - D3DXVECTOR2 scrPos = D3DXVECTOR2(float(pos.x), float(pos.y)); - scrPos /= float(pos.w); - scrPos *= 0.5f; - scrPos.x *= float(w / h); - - result.position = scrPos; - result.position.x *= 1.8f; - - short xpos = short((scrPos.x + 0.5f) * w); - short ypos = short((1 - (scrPos.y + 0.5f)) * h); - - result.visible = true; - result.color = GetSunDiffColor(); - - return result;*/ - SUNVISPARAMS result = SUNVISPARAMS(); VECTOR3 cam = GetCameraGPos(); @@ -2240,6 +2539,7 @@ int Scene::RenderShadowMap(D3DXVECTOR3 &pos, D3DXVECTOR3 &ld, float rad, bool bI void Scene::RenderSecondaryScene(std::set &RndList, std::set &LightsList, DWORD flags) { _TRACE; + RenderFlags = flags; // Process Local Light Sources ------------------------------------- // And toggle external lights on @@ -2281,7 +2581,7 @@ void Scene::RenderSecondaryScene(std::set &RndList, std::set if (flags & 0x01) { for (DWORD i = 0; iIsActive(); - if (isActive) plist[i].vo->Render(pDevice); // TODO: Should pass the flags to surface base level + if (isActive) plist[i].vo->Render(pDevice); else plist[i].vo->RenderDot(pDevice); } } @@ -2319,6 +2619,8 @@ void Scene::RenderSecondaryScene(std::set &RndList, std::set if (flags & 0x10) { for (DWORD n = 0; n < nstream; n++) pstream[n]->Render(pDevice); } + + // Flags 0x20 = BaseStructures } @@ -2535,7 +2837,7 @@ bool Scene::IntegrateIrradiance(vVessel *vV, LPDIRECT3DCUBETEXTURE9 pSrc, LPDIRE pIrradiance->SetBool("bUp", false); pIrradiance->SetTemplate(0.5f, 1.0f, 0.0f, 0.0f); - if (!pIrradiance->ExecuteTemplate(true)) { + if (!pIrradiance->Execute(true)) { LogErr("pIrradiance Execute Failed"); return false; } @@ -2543,7 +2845,7 @@ bool Scene::IntegrateIrradiance(vVessel *vV, LPDIRECT3DCUBETEXTURE9 pSrc, LPDIRE pIrradiance->SetBool("bUp", true); pIrradiance->SetTemplate(0.5f, 1.0f, 0.5f, 0.0f); - if (!pIrradiance->ExecuteTemplate(true)) { + if (!pIrradiance->Execute(true)) { LogErr("pIrradiance Execute Failed"); return false; } @@ -2681,7 +2983,8 @@ bool Scene::WorldToScreenSpace(const VECTOR3 &wpos, oapi::IVECTOR2 *pt, D3DXMATR D3DXVECTOR4 homog; D3DXVECTOR3 pos(float(wpos.x), float(wpos.y), float(wpos.z)); - D3DXVec3Transform(&homog, &pos, pVP); + if (pVP) D3DXVec3Transform(&homog, &pos, pVP); + else D3DXVec3Transform(&homog, &pos, GetProjectionViewMatrix()); if (homog.w < 0.0f) return false; @@ -2703,6 +3006,36 @@ bool Scene::WorldToScreenSpace(const VECTOR3 &wpos, oapi::IVECTOR2 *pt, D3DXMATR return !bClip; } + +// =========================================================================================== +// +bool Scene::WorldToScreenSpace2(const VECTOR3& wpos, oapi::FVECTOR2* pt, D3DXMATRIX* pVP, float clip) +{ + D3DXVECTOR4 homog; + D3DXVECTOR3 pos(float(wpos.x), float(wpos.y), float(wpos.z)); + + if (pVP) D3DXVec3Transform(&homog, &pos, pVP); + else D3DXVec3Transform(&homog, &pos, GetProjectionViewMatrix()); + + homog.x /= homog.w; + homog.y /= homog.w; + + bool bClip = false; + if (homog.w < 0.0f) bClip = true; + if (homog.x < -clip || homog.x > clip || homog.y < -clip || homog.y > clip) bClip = true; + + if (_hypot(homog.x, homog.y) < 1e-6) { + pt->x = viewW / 2; + pt->y = viewH / 2; + } + else { + pt->x = (float(viewW) * 0.5f * (1.0f + homog.x)) + 0.5f; + pt->y = (float(viewH) * 0.5f * (1.0f - homog.y)) + 0.5f; + } + + return !bClip; +} + // =========================================================================================== // void Scene::RenderObjectMarker(oapi::Sketchpad *pSkp, const VECTOR3 &gpos, const std::string& label1, const std::string& label2, int mode, int scale) @@ -2797,16 +3130,25 @@ float Scene::GetDepthResolution(float dist) const return fabs( (Camera.nearplane-Camera.farplane)*(dist*dist) / (Camera.farplane * Camera.nearplane * 16777215.0f) ); } +// =========================================================================================== +// +float Scene::CameraInSpace() const +{ + if (Camera.vProxy) { + if (Camera.vProxy->HasAtmosphere()) { + ConstParams* cp = Camera.vProxy->GetScatterConst(); + if (cp) return 1.0f - exp(-cp->CamAlt * cp->iH.x); + } + } + return 1.0f; +} + // =========================================================================================== // void Scene::GetCameraLngLat(double *lng, double *lat) const { - double rad; VECTOR3 rpos; MATRIX3 grot; - OBJHANDLE hPlanet = GetCameraProxyBody(); - oapiGetGlobalPos(hPlanet, &rpos); - oapiGetRotationMatrix(hPlanet, &grot); - rpos = GetCameraGPos() - rpos; - oapiLocalToEqu(hPlanet, tmul(grot, rpos), lng, lat, &rad); + if (lng) *lng = Camera.lng; + if (lat) *lat = Camera.lat; } // =========================================================================================== @@ -2824,6 +3166,25 @@ void Scene::PopCamera() CameraStack.pop(); } +// =========================================================================================== +// +FMATRIX4 Scene::PushCameraFrustumLimits(float nearlimit, float farlimit) +{ + FRUSTUM fr = { Camera.nearplane, Camera.farplane }; + FrustumStack.push(fr); + SetCameraFrustumLimits(nearlimit, farlimit); + return FMATRIX4(GetProjectionViewMatrix()); +} + +// =========================================================================================== +// +FMATRIX4 Scene::PopCameraFrustumLimits() +{ + SetCameraFrustumLimits(FrustumStack.top().znear, FrustumStack.top().zfar); + FrustumStack.pop(); + return FMATRIX4(GetProjectionViewMatrix()); +} + // =========================================================================================== // void Scene::BeginPass(DWORD dwPass) @@ -3055,9 +3416,10 @@ void Scene::SetupInternalCamera(D3DXMATRIX *mNew, VECTOR3 *gpos, double apr, dou Camera.upos = D3DXVEC(unit(Camera.pos)); - // find a logical reference gody + // find a logical reference body Camera.hObj_proxy = oapiCameraProxyGbody(); - + Camera.hNear = NULL; + // find the planet closest to the current camera position double closest = 1e32; int n = oapiGetGbodyCount(); @@ -3071,6 +3433,12 @@ void Scene::SetupInternalCamera(D3DXMATRIX *mNew, VECTOR3 *gpos, double apr, dou } } + if (Camera.hNear) { + // If the near body is not visible enough, switch to proxy. + double apr = oapiGetSize(Camera.hNear) / closest; + if (apr < 4e-3) Camera.hNear = Camera.hObj_proxy; + } + // find the visual Camera.vProxy = (vPlanet *)GetVisObject(Camera.hObj_proxy); Camera.vNear = (vPlanet *)GetVisObject(Camera.hNear); @@ -3079,9 +3447,15 @@ void Scene::SetupInternalCamera(D3DXMATRIX *mNew, VECTOR3 *gpos, double apr, dou if (Camera.hObj_proxy == NULL || Camera.vProxy == NULL || Camera.vNear == NULL) return; // Camera altitude over the proxy - VECTOR3 pos; + VECTOR3 pos; MATRIX3 grot; double rad; oapiGetGlobalPos(Camera.hObj_proxy, &pos); + oapiGetRotationMatrix(Camera.hObj_proxy, &grot); + + oapiLocalToEqu(Camera.hObj_proxy, tmul(grot, Camera.pos - pos), &Camera.lng, &Camera.lat, &rad); + Camera.alt_proxy = dist(Camera.pos, pos) - oapiGetSize(Camera.hObj_proxy); + Camera.vProxy->GetElevation(Camera.lng, Camera.lat, &rad); + Camera.elev = Camera.alt_proxy - rad; // Camera altitude over the proxy oapiGetGlobalPos(Camera.hNear, &pos); @@ -3217,6 +3591,98 @@ void Scene::RenderCustomCameraView(CAMREC *cCur) } +// =========================================================================================== +// +void Scene::RenderGlares() +{ + // ------------------------------------------------------------------------------------------------------- + // Render glares for the Sun and local lights + // ------------------------------------------------------------------------------------------------------- + + if (pRenderGlares && pLocalResultsSL) + { + static SMVERTEX Vertex[4] = { {-1, -1, 0, 0, 0}, {-1, 1, 0, 0, 1}, {1, 1, 0, 1, 1}, {1, -1, 0, 1, 0} }; + static WORD cIndex[6] = { 0, 2, 1, 0, 3, 2 }; + D3DSURFACE_DESC desc; FVECTOR2 pt; + struct { D3DXMATRIX mVP; float4 Pos, Color; float GPUId, Alpha, Blend; } Const; + + Const.Color = FVECTOR4(1, 1, 1, 1); + D3DXMatrixOrthoOffCenterLH(&Const.mVP, 0.0f, (float)viewW, (float)viewH, 0.0f, 0.0f, 1.0f); + pLocalResultsSL->GetDesc(&desc); + + pRenderGlares->ClearTextures(); + pRenderGlares->Setup(pPosTexDecl, false, 1); + pRenderGlares->SetTextureVS("tVis", pLocalResults, IPF_CLAMP | IPF_POINT); // Set texture containing pre-cumputed visibility factors + + if (Config->bGlares && pSunGlare) + { + pRenderGlares->SetTexture("tTex0", pSunGlare, IPF_CLAMP | IPF_LINEAR); + pRenderGlares->UpdateTextures(); + + // Render Sun glare + VECTOR3 gsun; oapiGetGlobalPos(oapiGetObjectByIndex(0), &gsun); + double sdst = length(gsun - Camera.pos); + VECTOR3 pos = (gsun - Camera.pos) * 10e4 / sdst; + + if (WorldToScreenSpace2(pos, &pt)) + { + float cis = 1.0f, glare = float(Config->GFXGlare) * saturate(8.0 * AU / sdst); + FVECTOR4 clr = FVECTOR4(1, 1, 1, 1); + + vPlanet* vp = GetCameraNearVisual(); + + if (vp && vp->IsActive()) + { + VECTOR3 crp = vp->CameraPos(); + clr = vp->SunLightColor(crp, 2.0); + cis = CameraInSpace(); + glare *= pow(clr.MaxRGB(), 0.33f) * cis; + } + + float cd = length(pt - FVECTOR2(viewW, viewH) * 0.5f) / float(viewW); // Glare distance from a screen center + float alpha = 2.0f * glare * max(0.5f, 1.0f - cd); + float size = 300.0f * GetDisplayScale() * pow(alpha, 0.25f); + + Const.GPUId = 0.5f / float(desc.Width); + Const.Pos = FVECTOR4(pt.x, pt.y, size, size); + Const.Color.rgb = clr.rgb / (clr.MaxRGB() + 0.0001f); + Const.Alpha = alpha * 2.0f; + Const.Blend = sqrt(cis); + + pRenderGlares->SetVSConstants("Const", &Const, sizeof(Const)); + pRenderGlares->SetPSConstants("Const", &Const, sizeof(Const)); + HR(pDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &cIndex, D3DFMT_INDEX16, &Vertex, sizeof(SMVERTEX))); + } + } + + if (Config->bLocalGlares && pLightGlare) + { + pRenderGlares->SetTexture("tTex0", pLightGlare, IPF_CLAMP | IPF_LINEAR); + pRenderGlares->UpdateTextures(); + + // Render glares for local lights + for (int i = 0; i < nLights; ++i) { + int GPUId = Lights[i].GPUId; + if (GPUId >= 0) { + if (WorldToScreenSpace2(_V(Lights[i].Position), &pt)) { + float size = 40.0f; + Const.GPUId = (float(GPUId) + 0.5f) / desc.Width; + Const.Pos = FVECTOR4(pt.x, pt.y, size, size); + Const.Alpha = Lights[i].cone; + Const.Color = Lights[i].Diffuse; + Const.Blend = 1.0f; + pRenderGlares->SetVSConstants("Const", &Const, sizeof(Const)); + pRenderGlares->SetPSConstants("Const", &Const, sizeof(Const)); + HR(pDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &cIndex, D3DFMT_INDEX16, &Vertex, sizeof(SMVERTEX))); + } + } + } + } + pRenderGlares->DetachTextures(); + } +} + + // =========================================================================================== // bool Scene::IsVisibleInCamera(D3DXVECTOR3 *pCnt, float radius) diff --git a/OVP/D3D9Client/Scene.h b/OVP/D3D9Client/Scene.h index a594934ad..9482428f4 100644 --- a/OVP/D3D9Client/Scene.h +++ b/OVP/D3D9Client/Scene.h @@ -45,6 +45,7 @@ class D3D9Pad; #define TEX_CLUT 1 #define TEX_COUNT 2 +#define RENDERPASS_UNKNOWN 0x0000 #define RENDERPASS_MAINSCENE 0x0001 #define RENDERPASS_ENVCAM 0x0002 #define RENDERPASS_CUSTOMCAM 0x0003 @@ -52,6 +53,7 @@ class D3D9Pad; #define RENDERPASS_PICKSCENE 0x0005 #define RENDERPASS_SKETCHPAD 0x0006 #define RENDERPASS_MAINOVERLAY 0x0007 +#define RENDERPASS_NORMAL_DEPTH 0x0008 #define RESTORE ((LPDIRECT3DSURFACE9)(-1)) #define CURRENT ((LPDIRECT3DSURFACE9)(-2)) @@ -84,6 +86,13 @@ class Scene { public: + FVECTOR3 vPickRay; + + struct FRUSTUM { + float znear; + float zfar; + }; + // Custom camera parameters ======================================================== // struct CAMREC { @@ -134,6 +143,7 @@ class Scene { OBJHANDLE hNear; // closest celestial body vPlanet * vNear; // closest celestial body (visual) double alt_near; + double lng, lat, elev; }; // Screen space sun visual parameters ================================================== @@ -179,9 +189,14 @@ class Scene { const D3D9Light *GetLight(int index) const; const D3D9Light *GetLights() const { return Lights; } DWORD GetLightCount() const { return nLights; } + D3D9Pad* GetPooledSketchpad(int id); + void RecallDefaultState(); + float GetDisplayScale() const { return fDisplayScale; } + void CreateSunGlare(); DWORD GetRenderPass() const; + DWORD GetRenderFlags() const { return RenderFlags; } void BeginPass(DWORD dwPass); void PopPass(); @@ -238,6 +253,8 @@ class Scene { LPDIRECT3DSURFACE9 GetIrradianceDepthStencil() const { return pIrradDS; } LPDIRECT3DSURFACE9 GetEnvDepthStencil() const { return pEnvDS; } LPDIRECT3DSURFACE9 GetBuffer(int id) const { return psgBuffer[id]; } + LPDIRECT3DTEXTURE9 GetSunTexture() const { return pSunTex; } + LPDIRECT3DTEXTURE9 GetSunGlareAtm() const { return pSunGlareAtm; } /** * \brief Render any shadows cast by vessels on planet surfaces @@ -313,6 +330,7 @@ class Scene { void SetCameraAperture(float _ap, float _as); void SetCameraFrustumLimits(double nearlimit, double farlimit); float GetDepthResolution(float dist) const; + float CameraInSpace() const; // Acquire camera information from the Orbiter and initialize internal camera setup void UpdateCameraFromOrbiter(DWORD dwPass); @@ -340,9 +358,10 @@ class Scene { OBJHANDLE GetCameraNearBody() const { return Camera.hNear; } vPlanet * GetCameraNearVisual() const { return Camera.vNear; } double GetCameraNearAltitude() const { return Camera.alt_near; } - + double GetCameraElevation() const { return Camera.elev; } void GetCameraLngLat(double *lng, double *lat) const; - bool WorldToScreenSpace(const VECTOR3 &rdir, oapi::IVECTOR2 *pt, D3DXMATRIX *pVP, float clip = 1.0f); + bool WorldToScreenSpace(const VECTOR3& rdir, oapi::IVECTOR2* pt, D3DXMATRIX* pVP = NULL, float clip = 1.0f); + bool WorldToScreenSpace2(const VECTOR3& rdir, oapi::FVECTOR2* pt, D3DXMATRIX* pVP = NULL, float clip = 1.0f); DWORD GetFrameId() const { return dwFrameId; } @@ -354,6 +373,9 @@ class Scene { void PushCamera(); // Push current camera onto a stack void PopCamera(); // Restore a camera from a stack + FMATRIX4 PushCameraFrustumLimits(float nearlimit, float farlimit); + FMATRIX4 PopCameraFrustumLimits(); + // Visual Management ========================================================================================================= @@ -383,8 +405,10 @@ class Scene { */ void RenderObjectMarker(oapi::Sketchpad *pSkp, const VECTOR3 &gpos, const std::string& label1, const std::string& label2, int mode, int scale); -private: + void RenderGlares(); +private: + void ComputeLocalLightsVisibility(); DWORD GetActiveParticleEffectCount(); float ComputeNearClipPlane(); void VisualizeCubeMap(LPDIRECT3DCUBETEXTURE9 pCube, int mip); @@ -407,8 +431,7 @@ class Scene { void InitGDIResources(); void ExitGDIResources(); - D3D9Pad *GetPooledSketchpad(int id); ///< Get pooled Sketchpad instance (lazy instantiation) - void FreePooledSketchpads(); ///< Release pooled Sketchpad instances + void FreePooledSketchpads(); ///< Release pooled Sketchpad instances @@ -420,7 +443,6 @@ class Scene { DWORD stencilDepth; // stencil buffer bit depth D3D9CelestialSphere* m_celSphere; // celestial sphere background DWORD iVCheck; // index of last object checked for visibility - //DWORD dwRenderPass; // Currently active render pass bool bLocalLight; // enable local light sources bool surfLabelsActive; // v.2 surface labels activated? @@ -441,6 +463,7 @@ class Scene { std::list Casters; std::stack CameraStack; std::stack PassStack; + std::stack FrustumStack; CAMERA Camera; @@ -450,12 +473,14 @@ class Scene { VECTOR3 sky_color; double bglvl; + float fDisplayScale; float lmaxdst2; DWORD nLights; DWORD nplanets; // Number of distance sorted planets to render DWORD dwTurn; DWORD dwFrameId; DWORD camIndex; + DWORD RenderFlags; bool bRendering; oapi::Font *pAxisFont; @@ -464,12 +489,19 @@ class Scene { SurfNative *pLblSrf; - class ImageProcessing *pLightBlur, *pBlur, *pGDIOverlay, *pIrradiance; + class ImageProcessing *pLightBlur, *pBlur, *pGDIOverlay, *pIrradiance, *pVisDepth, *pCreateGlare; + class ShaderClass *pLocalCompute, *pRenderGlares; class vVessel *vFocus; VOBJREC *vobjEnv, *vobjIrd; double dVisualAppRad; + FVECTOR2 DepthSampleKernel[57]; + + LPDIRECT3DTEXTURE9 pSunTex, pLightGlare, pSunGlare, pSunGlareAtm; + LPDIRECT3DTEXTURE9 pLocalResults; + LPDIRECT3DSURFACE9 pLocalResultsSL; + // Blur Sampling Kernel ============================================================== LPDIRECT3DCUBETEXTURE9 pBlrTemp[5]; LPDIRECT3DCUBETEXTURE9 pIrradTemp; @@ -482,11 +514,13 @@ class Scene { LPDIRECT3DSURFACE9 pOffscreenTarget; LPDIRECT3DTEXTURE9 pTextures[TEX_COUNT]; - LPDIRECT3DSURFACE9 pEnvDS, pIrradDS; + LPDIRECT3DSURFACE9 pEnvDS, pIrradDS, pDepthNormalDS; LPDIRECT3DSURFACE9 psShmDS[SHM_LOD_COUNT]; LPDIRECT3DSURFACE9 psShmRT[SHM_LOD_COUNT]; LPDIRECT3DTEXTURE9 ptShmRT[SHM_LOD_COUNT]; + LocalLightsCompute LLCBuf[MAX_SCENE_LIGHTS + 1]; + // Rendering Technique related parameters ============================================ // static ID3DXEffect *FX; diff --git a/OVP/D3D9Client/Surfmgr2.cpp b/OVP/D3D9Client/Surfmgr2.cpp index 156e40702..5419fc66e 100644 --- a/OVP/D3D9Client/Surfmgr2.cpp +++ b/OVP/D3D9Client/Surfmgr2.cpp @@ -26,6 +26,16 @@ // ======================================================================= extern void FilterElevationGraphics(OBJHANDLE hPlanet, int lvl, int ilat, int ilng, float *elev); +#pragma pack(push, 4) +struct LightF +{ + float3 position[4]; /* position in world space */ + float3 direction[4]; /* direction in world space */ + float3 diffuse[4]; /* diffuse color of light */ + float3 attenuation[4]; /* Attenuation */ + float4 param[4]; /* range, falloff, theta, phi */ +}; +#pragma pack(pop) // ======================================================================= @@ -719,14 +729,14 @@ double SurfTile::GetCameraDistance() // ----------------------------------------------------------------------- -D3DXVECTOR4 SurfTile::MicroTexRange(SurfTile *pT, int ml) const +FVECTOR4 SurfTile::MicroTexRange(SurfTile *pT, int ml) const { float rs = 1.0f / float( 1 << (lvl-pT->Level()) ); // Range subdivision float xo = pT->MicroRep[ml].x * texrange.tumin; float yo = pT->MicroRep[ml].y * texrange.tvmin; xo -= floor(xo); // Micro texture offset for current tile yo -= floor(yo); // Micro texture offset for current tile - return D3DXVECTOR4(xo, yo, pT->MicroRep[ml].x * rs, pT->MicroRep[ml].y * rs); + return FVECTOR4(xo, yo, pT->MicroRep[ml].x * rs, pT->MicroRep[ml].y * rs); } // ----------------------------------------------------------------------- @@ -736,7 +746,6 @@ D3DXVECTOR4 SurfTile::MicroTexRange(SurfTile *pT, int ml) const void SurfTile::StepIn () { LPDIRECT3DDEVICE9 pDev = mgr->Dev(); - ID3DXEffect *Shader = mgr->Shader(); const vPlanet *vPlanet = mgr->GetPlanet(); if (vPlanet != mgr->GetScene()->GetCameraProxyVisual()) return; @@ -757,21 +766,14 @@ void SurfTile::StepIn () void SurfTile::Render () { - bool render_lights = mgr->Cprm().bLights; - bool render_shadows = mgr->GetPlanet()->CloudMgr2()!=NULL; // && !mgr->prm.rprm->bCloudFlatShadows); - + if (!mesh) return; // DEBUG : TEMPORARY - UINT numPasses = 0; - LPDIRECT3DDEVICE9 pDev = mgr->Dev(); - ID3DXEffect *Shader = mgr->Shader(); - const vPlanet *vPlanet = mgr->GetPlanet(); + vPlanet *vPlanet = mgr->GetPlanet(); const Scene *scene = mgr->GetScene(); const D3D9Client *pClient = mgr->GetClient(); - if (scene->GetRenderPass() == RENDERPASS_MAINSCENE) mgr->SetMinMaxElev(ehdr.emin, ehdr.emax); - static const double rad0 = sqrt(2.0)*PI05; double sdist, rad; bool has_specular = false; @@ -780,41 +782,63 @@ void SurfTile::Render () bool has_microtex = false; bool has_atmosphere = vPlanet->HasAtmosphere(); bool has_ripples = vPlanet->HasRipples(); + bool bUseZBuf = mgr->IsUsingZBuf(); + if (vPlanet->CameraAltitude()>20e3) has_ripples = false; - if (ltex || render_shadows) { - sdist = acos (dotp (mgr->prm.sdir, cnt)); - rad = rad0/(double)(2<CameraAltitude() / 150e3) * Config->OrbitalShadowMult; + + PlanetShader* pShader = mgr->GetShader(); + ShaderParams* sp = vPlanet->GetTerrainParams(); + FlowControlPS* fc = vPlanet->GetFlowControl(); + FlowControlVS* fcv = vPlanet->GetFlowControlVS(); + + bool render_lights = pShader->bNightlights; + bool render_shadows = (mgr->GetPlanet()->CloudMgr2() != NULL) && mgr->GetClient()->GetConfigParam(CFGPRM_CLOUDSHADOWS) && pShader->bCloudShd; + + if (ltex) { + sdist = acos(dotp(mgr->prm.sdir, cnt)); + rad = rad0 / (double)(2 << lvl); // tile radius + has_specular = (ltex != NULL) && sdist < (1.75 + rad); has_lights = (render_lights && ltex && sdist > 1.35); + has_shadows = (render_shadows && sdist < (PI05 + rad)); } + + has_specular &= pShader->bWater; + has_ripples &= pShader->bRipples & has_specular; + has_lights &= pShader->bNightlights; + has_atmosphere &= pShader->bAtmosphere; - if (vPlanet->CameraAltitude()>20e3) has_ripples = false; - - double ca = 1.0 + saturate(vPlanet->CameraAltitude() / 150e3) * Config->OrbitalShadowMult; + sp->vCloudOff = FVECTOR4(0, 0, 1, 1); - HR(Shader->SetVector(TileManager2Base::svCloudOff, &D3DXVECTOR4(0, 0, 1, 1))); + D3DXVECTOR3 bs_pos; + D3DXVec3TransformCoord(&bs_pos, &mesh->bsCnt, &mWorld); + // ---------------------------------------------------------------------- + // Assign micro texture range information to shaders + // ---------------------------------------------------------------------- - // Assign micro texture range information to shaders ------------------------- - // SurfTile *pT = getTextureOwner(); - if (pT && vPlanet->MicroCfg.bEnabled) { - HR(Shader->SetVector(TileManager2Base::svMicroScale0, &MicroTexRange(pT, 0))); - HR(Shader->SetVector(TileManager2Base::svMicroScale1, &MicroTexRange(pT, 1))); - HR(Shader->SetVector(TileManager2Base::svMicroScale2, &MicroTexRange(pT, 2))); + if (pT && vPlanet->MicroCfg.bEnabled && pShader->bMicrotex) + { + sp->vMSc[0] = MicroTexRange(pT, 0); + sp->vMSc[1] = MicroTexRange(pT, 1); + sp->vMSc[2] = MicroTexRange(pT, 2); has_microtex = true; } - // Setup cloud shadows ------------------------------------------------------- - // - if (has_shadows) { + // ---------------------------------------------------------------------- + // Setup cloud shadows + // ---------------------------------------------------------------------- - has_shadows = false; + has_shadows = false; + + if (render_shadows) + { + LPDIRECT3DTEXTURE9 pCloud = NULL, pCloud2 = NULL; const TileManager2 *cmgr = vPlanet->CloudMgr2(); int maxlvl = min(lvl,9); @@ -838,9 +862,10 @@ void SurfTile::Render () double v1 = v0 + (bnd.maxlat - bnd.minlat) * icsize; // Feed uv-offset and uv-range to the shaders - HR(Shader->SetVector(TileManager2Base::svCloudOff, &D3DXVECTOR4(float(u0), float(v0), float(u1-u0), float(v1-v0)))); - HR(Shader->SetFloat(TileManager2Base::sfAlpha, float(ca))); - HR(Shader->SetTexture(TileManager2Base::stCloud, ctile->Tex())); + sp->vCloudOff = FVECTOR4(float(u0), float(v0), float(u1-u0), float(v1-v0)); + sp->fAlpha = float(ca); + pCloud = ctile->Tex(); + // Texture uv range extends to another tile if (u1 > 1.0) { @@ -855,7 +880,7 @@ void SurfTile::Render () if (ctile2) { if (ctile2->Level() == ctile->Level()) { // Rendering with dual texture - HR(Shader->SetTexture(TileManager2Base::stCloud2, ctile2->Tex())); + pCloud2 = ctile2->Tex(); has_shadows = true; break; } @@ -874,69 +899,85 @@ void SurfTile::Render () } } } - } + pShader->SetTexture(pShader->tCloud, pCloud, IPF_CLAMP | IPF_ANISOTROPIC, Config->Anisotrophy); + pShader->SetTexture(pShader->tCloud2, pCloud2, IPF_CLAMP | IPF_ANISOTROPIC, Config->Anisotrophy); + } - // --------------------------------------------------------------------------------------------------- - // Render with overlay image - // - D3DXVECTOR4 texcoord; + + fc->bCloudShd = has_shadows; + fc->bMicroTex = has_microtex; + fc->bLocals = false; + fc->bOverlay = false; + fc->bMask = false; + fc->bShadows = false; + fc->bInSpace = !vPlanet->CameraInAtmosphere(); + fc->bPlanetShadow = vPlanet->SphericalShadow(); + fcv->bElevOvrl = false; + + + // ---------------------------------------------------------------------- + // DevTools: Render with overlay image + // ---------------------------------------------------------------------- + + FVECTOR4 texcoord; const vPlanet::sOverlay *oLay = vPlanet->IntersectOverlay(bnd.vec, &texcoord); - if (oLay) + if (pShader->bDevtools) { - bool bOlayEnable = false; for (auto x : oLay->pSurf) if (x) bOlayEnable = true; - - if (bOlayEnable) + if (oLay) { - // Global large-scale overlay - HR(Shader->SetTexture(TileManager2Base::stOverlay, oLay->pSurf[0])); - HR(Shader->SetTexture(TileManager2Base::stMskOverlay, oLay->pSurf[1])); - HR(Shader->SetTexture(TileManager2Base::stElvOverlay, oLay->pSurf[2])); - HR(Shader->SetVectorArray(TileManager2Base::svOverlayCtrl, oLay->Blend, 4)); - HR(Shader->SetVector(TileManager2Base::svOverlayOff, &texcoord)); - - if (oLay->pSurf[0] || oLay->pSurf[1]) { - HR(Shader->SetBool(TileManager2Base::sbOverlay, true)); - } - if (oLay->pSurf[2]) { - HR(Shader->SetBool(TileManager2Base::sbElevOvrl, true)); + bool bOlayEnable = false; for (auto x : oLay->pSurf) if (x) bOlayEnable = true; + + if (bOlayEnable) + { + // Global large-scale overlay + pShader->SetTexture("tOverlay", oLay->pSurf[0]); + pShader->SetTexture("tMskOverlay", oLay->pSurf[1]); + pShader->SetTexture("tElvOverlay", oLay->pSurf[2]); + + memcpy(&sp->vOverlayCtrl, &oLay->Blend, sizeof(FVECTOR4) * 4); + sp->vOverlayOff = texcoord; + + if (oLay->pSurf[0] || oLay->pSurf[1]) fc->bOverlay = true; + if (oLay->pSurf[2]) fcv->bElevOvrl = true; } } - else { - // No Overlay - HR(Shader->SetTexture(TileManager2Base::stOverlay, NULL)); - HR(Shader->SetTexture(TileManager2Base::stMskOverlay, NULL)); - HR(Shader->SetTexture(TileManager2Base::stElvOverlay, NULL)); - HR(Shader->SetBool(TileManager2Base::sbOverlay, false)); - HR(Shader->SetBool(TileManager2Base::sbElevOvrl, false)); + else if (overlay) { + // Local tile specific overlay + pShader->SetTexture("tOverlay", overlay); + sp->vOverlayOff = GetTexRangeDX(&overlayrange); + fc->bOverlay = true; } - } else if (overlay) { - // Local tile specific overlay - HR(Shader->SetTexture(TileManager2Base::stOverlay, overlay)); - HR(Shader->SetVector(TileManager2Base::svOverlayOff, &GetTexRangeDX(&overlayrange))); - HR(Shader->SetBool(TileManager2Base::sbOverlay, true)); - } else { - // No Overlay - HR(Shader->SetTexture(TileManager2Base::stOverlay, NULL)); - HR(Shader->SetBool(TileManager2Base::sbOverlay, false)); } - // --------------------------------------------------------------------------------------------------- - // Feed tile specific data to shaders - // - // --------------------------------------------------------------------------------------------------- - HR(Shader->SetTexture(TileManager2Base::stDiff, tex)); - HR(Shader->SetTexture(TileManager2Base::stMask, ltex)); - HR(Shader->SetVector(TileManager2Base::svTexOff, &GetTexRangeDX(&texrange))); - HR(Shader->SetVector(TileManager2Base::svMicroOff, &GetTexRangeDX(µrange))); - // --------------------------------------------------------------------------------------------------- - HR(Shader->SetBool(TileManager2Base::sbCloudSh, has_shadows)); - HR(Shader->SetBool(TileManager2Base::sbLights, has_lights)); - // --------------------------------------------------------------------------------------------------- - if (has_lights) { HR(Shader->SetFloat(TileManager2Base::sfNight, float(mgr->Cprm().lightfac))); } - else { HR(Shader->SetFloat(TileManager2Base::sfNight, 0.0f)); } + // ---------------------------------------------------------------------- + // Setup Main Texture + // ---------------------------------------------------------------------- + + pShader->SetTexture(pShader->tDiff, tex, IPF_CLAMP | IPF_ANISOTROPIC, Config->Anisotrophy); + + // ---------------------------------------------------------------------- + // Night Lights and Water Specular + // ---------------------------------------------------------------------- + + if (pShader->bNightlights || pShader->bWater) + { + if ((has_specular || has_lights) && ltex) { + pShader->SetTexture(pShader->tMask, ltex, IPF_CLAMP | IPF_ANISOTROPIC, Config->Anisotrophy); + fc->bMask = true; + } + else pShader->SetTexture(pShader->tMask, NULL, IPF_CLAMP | IPF_ANISOTROPIC, Config->Anisotrophy); + } + + sp->vTexOff = GetTexRangeDX(&texrange); + sp->vMicroOff = GetTexRangeDX(µrange); + sp->mWorld = mWorld; + sp->fTgtScale = tgtscale; + + if (has_lights) sp->fBeta = float(mgr->Cprm().lightfac); + else sp->fBeta = 0.0f; @@ -945,14 +986,7 @@ void SurfTile::Render () // Setup shadow maps // --------------------------------------------------------------------- - D3DXMATRIX wmx; - HR(Shader->GetMatrix(TileManager2Base::smWorld, &wmx)); - HR(Shader->SetBool(TileManager2Base::sbShadows, false)); - - D3DXVECTOR3 bs_pos; - D3DXVec3TransformCoord(&bs_pos, &mesh->bsCnt, &wmx); - - if (scene->GetRenderPass() == RENDERPASS_MAINSCENE) + if (pShader->bShdMap) { const Scene::SHADOWMAPPARAM* shd = scene->GetSMapData(); @@ -969,101 +1003,119 @@ void SurfTile::Render () if (sqrt(D3DXVec3Dot(&bc, &bc) - x * x) < (shd->rad + mesh->bsRad)) { float s = float(shd->size); float sr = 2.0f * shd->rad / s; - HR(Shader->SetMatrix(TileManager2Base::smLVP, &shd->mViewProj)); - HR(Shader->SetVector(TileManager2Base::svSHD, &D3DXVECTOR4(sr, 1.0f / s, 0, 1.0f / shd->depth))); - HR(Shader->SetTexture(TileManager2Base::stShadowMap, shd->pShadowMap)); - HR(Shader->SetBool(TileManager2Base::sbShadows, true)); + sp->mLVP = shd->mViewProj; + sp->vSHD = FVECTOR4(sr, 1.0f / s, 0.0f, 1.0f / shd->depth); + fc->bShadows = true; } } } + + pShader->SetTexture(pShader->tShadowMap, shd->pShadowMap); } // --------------------------------------------------------------------- // Setup local light sources //--------------------------------------------------------------------- - const D3D9Light *pLights = scene->GetLights(); - int nSceneLights = scene->GetLightCount(); - - LightStruct Locals[4]; - - HR(Shader->SetBool(TileManager2Base::sbLocals, false)); - - - if (pLights && nSceneLights>0) { + int cfg = vPlanet->GetShaderID(); - int nMeshLights = 0; + LightF Locals; + BOOL Spots[4]; - _LightList LightList[MAX_SCENE_LIGHTS]; - - // Find all local lights effecting this mesh ------------------------------------------ - // - for (int i = 0; i < nSceneLights; i++) { - float il = pLights[i].GetIlluminance(bs_pos, mesh->bsRad); - if (il > 0.005f) { - LightList[nMeshLights].illuminace = il; - LightList[nMeshLights++].idx = i; - } + if (cfg != PLT_GIANT) + { + for (int i = 0; i < 4; i++) + { + Locals.attenuation[i] = FVECTOR3(1.0f, 1.0f, 1.0f); + Locals.diffuse[i] = FVECTOR3(0.0f, 0.0f, 0.0f); + Locals.direction[i] = FVECTOR3(1.0f, 0.0f, 0.0f); + Locals.param[i] = FVECTOR4(0.0f, 0.0f, 0.0f, 0.0f); + Locals.position[i] = FVECTOR3(0.0f, 0.0f, 0.0f); + Spots[i] = false; } - if (nMeshLights > 0) { + if (scene->GetRenderPass() == RENDERPASS_MAINSCENE) + { + const D3D9Light* pLights = scene->GetLights(); + int nSceneLights = min(scene->GetLightCount(), MAX_SCENE_LIGHTS); + + if (pLights && nSceneLights > 0 && pShader->bLocals) + { + int nMeshLights = 0; + + _LightList LightList[MAX_SCENE_LIGHTS]; + + // Find all local lights effecting this mesh ------------------------------------------ + // + for (int i = 0; i < nSceneLights; i++) { + float il = pLights[i].GetIlluminance(bs_pos, mesh->bsRad); + if (il > 0.005f) { + LightList[nMeshLights].illuminace = il; + LightList[nMeshLights++].idx = i; + } + } + + if (nMeshLights > 0) { - // If any, Sort the list based on illuminance ------------------------------------------- - qsort(LightList, nMeshLights, sizeof(_LightList), compare_lights); + // If any, Sort the list based on illuminance ------------------------------------------- + qsort(LightList, nMeshLights, sizeof(_LightList), compare_lights); - nMeshLights = min(nMeshLights, 4); + nMeshLights = min(nMeshLights, 4); - // Create a list of N most effective lights --------------------------------------------- - for (int i = 0; i < nMeshLights; i++) memcpy(&Locals[i], &pLights[LightList[i].idx], sizeof(LightStruct)); + // Create a list of N most effective lights --------------------------------------------- + for (int i = 0; i < nMeshLights; i++) + { + auto pL = pLights[LightList[i].idx]; + Locals.attenuation[i] = pL.Attenuation; + Locals.diffuse[i] = FVECTOR4(pL.Diffuse).rgb; + Locals.direction[i] = pL.Direction; + Locals.param[i] = pL.Param; + Locals.position[i] = pL.Position; + Spots[i] = (pL.Type == 1); + } - HR(Shader->SetBool(TileManager2Base::sbLocals, true)); - HR(Shader->SetValue(TileManager2Base::ssLight, &Locals, sizeof(Locals))); + // Enable local lights and feed data to shader + fc->bLocals = true; + } + } } } - Shader->CommitChanges(); + // ------------------------------------------------------------------- - // Find suitable technique + // render surface mesh + // + pShader->SetVSConstants(pShader->PrmVS, sp, sizeof(ShaderParams)); + pShader->SetPSConstants(pShader->Prm, sp, sizeof(ShaderParams)); - int iTech = 0; + if (cfg != PLT_GIANT) + { + pShader->SetVSConstants(pShader->FlowVS, fcv, sizeof(FlowControlVS)); + pShader->SetPSConstants(pShader->Flow, fc, sizeof(FlowControlPS)); - if (has_atmosphere) { - if (has_shadows) { - if (has_ripples) iTech = 0; // Earth - else iTech = 1; // Earth, no ripples - } - else { - if (has_microtex) iTech = 2; // Mars - else iTech = 3; // Mars, no micro + if (fc->bLocals) + { + pShader->SetPSConstants(pShader->Lights, &Locals, sizeof(Locals)); + pShader->SetPSConstants(pShader->Spotlight, Spots, sizeof(Spots)); } } - else { - if (has_microtex) iTech = 4; // Luna - else iTech = 5; // Luna, no micro - } + pShader->UpdateTextures(); - // ------------------------------------------------------------------- - // render surface mesh - // - HR(Shader->Begin(&numPasses, D3DXFX_DONOTSAVESTATE)); - HR(Shader->BeginPass(iTech)); - pDev->SetVertexDeclaration(pPatchVertexDecl); pDev->SetStreamSource(0, mesh->pVB, 0, sizeof(VERTEX_2TEX)); pDev->SetIndices(mesh->pIB); pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh->nv, 0, mesh->nf); - HR(Shader->EndPass()); - HR(Shader->End()); - + // Render tile bounding box // + /* if (DebugControls::IsActive()) { DWORD flags = *(DWORD*)mgr->GetClient()->GetConfigParam(CFGPRM_GETDEBUGFLAGS); if (flags&DBG_FLAGS_TILEBOXES) { D3D9Effect::RenderTileBoundingBox(&mWorld, mesh->Box, &D3DXVECTOR4(1,0,0,1)); } - } + }*/ } // ----------------------------------------------------------------------- @@ -1304,10 +1356,12 @@ void SurfTile::RenderLabels(D3D9Pad *skp, oapi::Font **labelfont, int *fontidx) template<> void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlanet::RenderPrm &rprm) { + bUseZ = use_zbuf; + ElevModeLvl = 0; + // set generic parameters SetRenderPrm (dwmat, 0, use_zbuf, rprm); - double np = 0.0, fp = 0.0; int i; class Scene *scene = GetClient()->GetScene(); @@ -1317,72 +1371,88 @@ void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlane double D = prm.cdist*R; double zmax = (D - R*R/D) * 1.5; double zmin = max (2.0, min (zmax*1e-4, (D-R) * 0.8)); - //double zscale = 1.0; - np = scene->GetCameraNearPlane(); - fp = scene->GetCameraFarPlane(); - scene->SetCameraFrustumLimits (zmin, zmax); + vp->GetScatterConst()->mVP = scene->PushCameraFrustumLimits(zmin, zmax); } // build a transformation matrix for frustum testing MATRIX4 Mproj = _MATRIX4(scene->GetProjectionMatrix()); Mproj.m33 = 1.0; Mproj.m43 = -1.0; // adjust near plane to 1, far plane to infinity MATRIX4 Mview = _MATRIX4(scene->GetViewMatrix()); - prm.dviewproj = mul(Mview,Mproj); + prm.dviewproj = mul(Mview, Mproj); // --------------------------------------------------------------------- static float spec_base = 0.7f; // 0.95f; - // --------------------------------------------------------------------- - // Initialize shading technique and feed planet specific data to shaders + bool has_ripples = vp->HasRipples(); + + // Choose a proper shader for a body // - Shader()->SetTechnique(eTileTech); + pShader = vp->GetShader(); + int cfg = vp->GetShaderID(); - HR(Shader()->SetBool(sbSpherical, false)); + pShader->ClearTextures(); + pShader->Setup(pPatchVertexDecl, bUseZ, 0); + pShader->GetDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); + + ShaderParams* sp = vp->GetTerrainParams(); + FlowControlPS* fc = vp->GetFlowControl(); + FlowControlVS* fcv = vp->GetFlowControlVS(); + ConstParams* cp = vp->GetScatterConst(); + + memset(fc, 0, sizeof(FlowControlPS)); + memset(fcv, 0, sizeof(FlowControlVS)); + + pShader->SetVSConstants("Const", cp, sizeof(ConstParams)); + pShader->SetPSConstants("Const", cp, sizeof(ConstParams)); + + if (pShader->bAtmosphere && cfg != PLT_GIANT) + { + pShader->SetTexture("tLndRay", vp->GetScatterTable(RAY_LAND), IPF_LINEAR | IPF_CLAMP); + pShader->SetTexture("tLndMie", vp->GetScatterTable(MIE_LAND), IPF_LINEAR | IPF_CLAMP); + pShader->SetTexture("tLndAtn", vp->GetScatterTable(ATN_LAND), IPF_LINEAR | IPF_CLAMP); + pShader->SetTexture("tSun", vp->GetScatterTable(SUN_COLOR), IPF_LINEAR | IPF_CLAMP); + pShader->SetTexture("tNoise", GetClient()->GetNoiseTex(), IPF_LINEAR | IPF_WRAP); + + if (pShader->bWater) { + pShader->SetTexture("tAmbient", vp->GetScatterTable(SKY_AMBIENT), IPF_LINEAR | IPF_CLAMP); + } + } if (ElevMode == eElevMode::Spherical) { // Force spherical rendering at shader level - HR(Shader()->SetBool(sbSpherical, true)); + fcv->bSpherical = true; } - if (use_zbuf) { - pDev->SetRenderState(D3DRS_ZENABLE, 1); - pDev->SetRenderState(D3DRS_ZWRITEENABLE, 1); - } - else { - pDev->SetRenderState(D3DRS_ZENABLE, 0); - pDev->SetRenderState(D3DRS_ZWRITEENABLE, 0); - HR(Shader()->SetBool(sbSpherical, true)); - } - - HR(Shader()->SetMatrix(smViewProj, scene->GetProjectionViewMatrix())); - HR(Shader()->SetVector(svWater, &D3DXVECTOR4(spec_base*1.2f, spec_base*1.0f, spec_base*0.8f, 50.0f))); - HR(Shader()->SetBool(sbEnvEnable, false)); + if (!use_zbuf) fcv->bSpherical = true; // ------------------------------------------------------------------- vVessel *vFocus = scene->GetFocusVisual(); vPlanet *vProxy = scene->GetCameraProxyVisual(); - // Setup Environment map --------------------------------------------- - // - if (vFocus && bEnvMapEnabled) { - LPDIRECT3DCUBETEXTURE9 pEnv = vFocus->GetEnvMap(0); - if (pEnv) { - HR(Shader()->SetTexture(stEnvMap, pEnv)); - HR(Shader()->SetBool(sbEnvEnable, true)); - } - } // Setup micro textures --------------------------------------------- // - if (vp->MicroCfg.bEnabled) { - HR(Shader()->SetTexture(stMicroA, vp->MicroCfg.Level[0].pTex)); - HR(Shader()->SetTexture(stMicroB, vp->MicroCfg.Level[1].pTex)); - HR(Shader()->SetTexture(stMicroC, vp->MicroCfg.Level[2].pTex)); - HR(Shader()->SetBool(sbMicroNormals, vp->MicroCfg.bNormals)); + if (vp->MicroCfg.bEnabled && pShader->bMicrotex) + { + UINT Filter = IPF_ANISOTROPIC; + if (Config->MicroFilter == 0) Filter = IPF_POINT; + if (Config->MicroFilter == 1) Filter = IPF_LINEAR; + UINT micro_aniso = (1 << (max(1, Config->MicroFilter) - 1)); + pShader->SetTexture("tMicroA", vp->MicroCfg.Level[0].pTex, IPF_WRAP | Filter, micro_aniso); + pShader->SetTexture("tMicroB", vp->MicroCfg.Level[1].pTex, IPF_WRAP | Filter, micro_aniso); + pShader->SetTexture("tMicroC", vp->MicroCfg.Level[2].pTex, IPF_WRAP | Filter, micro_aniso); + + fc->bMicroNormals = vp->MicroCfg.bNormals; } + if (has_ripples && pShader->bRipples) { + fc->bRipples = true; + pShader->SetTexture("tOcean", hOcean, IPF_WRAP | IPF_ANISOTROPIC, 4); + } + + if (Config->NoPlanetAA) pShader->GetDevice()->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, 0); // ------------------------------------------------------------------ // TODO: render full sphere for levels < 4 @@ -1395,14 +1465,13 @@ void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlane vp->tile_cache = NULL; - if (scene->GetRenderPass() == RENDERPASS_MAINSCENE) ResetMinMaxElev(); - // render the tree for (i = 0; i < 2; i++) RenderNode (tiletree+i); loader->ReleaseMutex(); + if (Config->NoPlanetAA) pShader->GetDevice()->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, 1); // Backup the stats and clear counters if (scene->GetRenderPass() == RENDERPASS_MAINSCENE) prevstat = elvstat; @@ -1417,8 +1486,8 @@ void TileManager2::Render (MATRIX4 &dwmat, bool use_zbuf, const vPlane } }*/ - if (np) - scene->SetCameraFrustumLimits(np,fp); + // Pop previous frustum configuration, must initialize mVP + if (!use_zbuf) vp->GetScatterConst()->mVP = scene->PopCameraFrustumLimits(); } // ----------------------------------------------------------------------- diff --git a/OVP/D3D9Client/Surfmgr2.h b/OVP/D3D9Client/Surfmgr2.h index c5c4da1db..919b099f3 100644 --- a/OVP/D3D9Client/Surfmgr2.h +++ b/OVP/D3D9Client/Surfmgr2.h @@ -11,25 +11,6 @@ #include "TileLabel.h" #include "D3D9Pad.h" -/* -#pragma pack(push,1) - -struct ELEVFILEHEADER { // file header for patch elevation data file - char id[4]; // ID string + version ('E','L','E',1) - int hdrsize; // header size (76 expected) - int dtype; // data format (0=flat, no data block; 8=uint8; -8=int8; 16=uint16; -16=int16) - int xgrd, ygrd; // data grid size (259 x 259 expected) - int xpad, ypad; // horizontal, vertical padding width (1, 1 expected) - double scale; // data scaling factor (1.0 expected) - double offset; // data offset (elevation = raw value * scale + offset) - double latmin, latmax; // latitude range [rad] - double lngmin, lngmax; // longitude range [rad] - double emin, emax, emean; // min, max, mean elevation [m] -}; - -#pragma pack(pop) -*/ - /** * \brief Planetary surface rendering engine. * @@ -100,8 +81,9 @@ class SurfTile: public Tile { float *ElevationData () const; void ComputeElevationData(const float *elev) const; float fixinput(double, int); - D3DXVECTOR4 MicroTexRange(SurfTile *pT, int lvl) const; + FVECTOR4 MicroTexRange(SurfTile *pT, int lvl) const; + PlanetShader* pShader; mutable ELEVFILEHEADER ehdr;///< Let's store the complete header for later use D3DXVECTOR2 MicroRep[3]; DWORD MaxRep; diff --git a/OVP/D3D9Client/TileLabel.cpp b/OVP/D3D9Client/TileLabel.cpp index a305e6dc7..8a815a327 100644 --- a/OVP/D3D9Client/TileLabel.cpp +++ b/OVP/D3D9Client/TileLabel.cpp @@ -168,7 +168,7 @@ bool TileLabel::Read () if (tile->smgr->DoLoadIndividualFiles(4)) { // try loading from individual tile file sprintf_s(path, MAX_PATH, "%s\\Label\\%02d\\%06d\\%06d.lab", tile->mgr->CbodyName(), lvl+4, ilat, ilng); - tile->mgr->Client()->TexturePath(path, texpath); + tile->mgr->GetClient()->TexturePath(path, texpath); std::ifstream ifs(texpath); while (ifs >> typestr >> lat >> lng >> altstr >> std::ws) { @@ -270,7 +270,7 @@ void TileLabel::Render (D3D9Pad *skp, oapi::Font **labelfont, int *fontidx) VECTOR3 sp, dir; bool active; const OBJHANDLE &hPlanet = tile->mgr->Cbody(); - Scene *pScene = tile->mgr->Client()->GetScene(); + Scene *pScene = tile->mgr->GetClient()->GetScene(); if (pScene->GetCameraProxyBody() != hPlanet) { return; } // do not render other body's labels @@ -297,9 +297,8 @@ void TileLabel::Render (D3D9Pad *skp, oapi::Font **labelfont, int *fontidx) dir = unit(sp); if (pScene->CameraDirection2Viewport(dir, x, y)) { - active = false; // default for label types not listed in the legend symbol = 0; // undefined - if (nl = tile->smgr->Client()->GetSurfaceMarkerLegend(hPlanet, &lspec)) { + if (nl = tile->smgr->GetClient()->GetSurfaceMarkerLegend(hPlanet, &lspec)) { for (int j = 0; j < nl; ++j) { if (renderlabel[i]->labeltype == lspec[j].labelId) { symbol = lspec[j].markerId; diff --git a/OVP/D3D9Client/Tilemgr2.cpp b/OVP/D3D9Client/Tilemgr2.cpp index 5242343c6..f3b7296c5 100644 --- a/OVP/D3D9Client/Tilemgr2.cpp +++ b/OVP/D3D9Client/Tilemgr2.cpp @@ -53,6 +53,7 @@ Tile::Tile (TileManager2Base *_mgr, int _lvl, int _ilat, int _ilng) double x = PI * (0.5 - double(ilat+1) * f); width = float(PI * cos(x) * f); height = float(PI * f); + tgtscale = 1.0f; Extents(&bnd.minlat, &bnd.maxlat, &bnd.minlng, &bnd.maxlng); D3D9Stats.TilesAllocated++; bMipmaps = false; @@ -234,9 +235,9 @@ bool Tile::GetParentMicroTexRange(TEXCRDRANGE2 *subrange) // ----------------------------------------------------------------------- -D3DXVECTOR4 Tile::GetTexRangeDX (const TEXCRDRANGE2 *subrange) const +FVECTOR4 Tile::GetTexRangeDX (const TEXCRDRANGE2 *subrange) const { - return D3DXVECTOR4(subrange->tumin, subrange->tvmin, subrange->tumax - subrange->tumin, subrange->tvmax - subrange->tvmin); + return FVECTOR4(subrange->tumin, subrange->tvmin, subrange->tumax - subrange->tumin, subrange->tvmax - subrange->tvmin); } // ----------------------------------------------------------------------- @@ -1058,16 +1059,21 @@ TileManager2Base::ConfigPrm TileManager2Base::cprm = { false, // bCloudShadow 0.5 // lightfac }; +oapi::D3D9Client* TileManager2Base::gc = NULL; +LPDIRECT3DDEVICE9 TileManager2Base::pDev = NULL; TileLoader *TileManager2Base::loader = NULL; double TileManager2Base::resolutionBias = 4.0; double TileManager2Base::resolutionScale = 1.0; bool TileManager2Base::bTileLoadThread = true; HFONT TileManager2Base::hFont = NULL; +LPDIRECT3DTEXTURE9 TileManager2Base::hOcean = NULL; +LPDIRECT3DTEXTURE9 TileManager2Base::hCloudMicro = NULL; +LPDIRECT3DTEXTURE9 TileManager2Base::hCloudMicroNorm = NULL; // ----------------------------------------------------------------------- -TileManager2Base::TileManager2Base (const vPlanet *vplanet, int _maxres, int _gridres) -: vp(vplanet), gridRes(_gridres), ElevMode(eElevMode::DontCare) +TileManager2Base::TileManager2Base (vPlanet *vplanet, int _maxres, int _gridres) +: vp(vplanet), gridRes(_gridres), ElevMode(eElevMode::DontCare), ElevModeLvl(0) { // set persistent parameters prm.maxlvl = max (0, _maxres-4); @@ -1077,7 +1083,6 @@ TileManager2Base::TileManager2Base (const vPlanet *vplanet, int _maxres, int _gr emgr = oapiElevationManager(obj); elevRes = *(double*)oapiGetObjectParam (obj, OBJPRM_PLANET_ELEVRESOLUTION); for (int i=0;iGetName(), elevRes); char path[1024]; @@ -1135,6 +1140,12 @@ void TileManager2Base::GlobalInit (class oapi::D3D9Client *gclient) loader = new TileLoader (gc); hFont = CreateFont(42, 0, 0, 0, 600, false, false, 0, 0, 0, 2, CLEARTYPE_QUALITY, 49, "Arial"); + + char name[MAX_PATH]; + + if (gc->TexturePath("D3D9Ocean.dds", name)) D3DXCreateTextureFromFileA(pDev, name, &hOcean); + if (gc->TexturePath("cloud1.dds", name)) D3DXCreateTextureFromFileA(pDev, name, &hCloudMicro); + if (gc->TexturePath("cloud1_norm.dds", name)) D3DXCreateTextureFromFileA(pDev, name, &hCloudMicroNorm); } // ----------------------------------------------------------------------- @@ -1189,29 +1200,6 @@ void TileManager2Base::SetRenderPrm (MATRIX4 &dwmat, double prerot, bool use_zbu // ----------------------------------------------------------------------- -void TileManager2Base::ResetMinMaxElev() -{ - min_elev = 0.0; - max_elev = 0.0; - bSet = true; -} - -// ----------------------------------------------------------------------- - -void TileManager2Base::SetMinMaxElev(double mi, double ma) -{ - if (bSet) { - min_elev = mi; - max_elev = ma; - bSet = false; - return; - } - min_elev = min(min_elev, mi); - max_elev = max(max_elev, ma); -} - -// ----------------------------------------------------------------------- - MATRIX4 TileManager2Base::WorldMatrix(Tile *tile) { int lvl = tile->lvl; diff --git a/OVP/D3D9Client/Tilemgr2.h b/OVP/D3D9Client/Tilemgr2.h index 9e9a641e5..6811c6929 100644 --- a/OVP/D3D9Client/Tilemgr2.h +++ b/OVP/D3D9Client/Tilemgr2.h @@ -15,7 +15,6 @@ #include "D3D9Client.h" #include "D3D9Util.h" -#include "PlanetRenderer.h" #include "VPlanet.h" #include "Spherepatch.h" #include "D3D9Pad.h" @@ -129,7 +128,7 @@ class Tile float GetBoundingSphereRad() const; D3DXVECTOR3 GetBoundingSpherePos() const; bool Pick(const LPD3DXMATRIX pW, const D3DXVECTOR3 *vDir, TILEPICK &result); - D3DXVECTOR4 GetTexRangeDX (const TEXCRDRANGE2 *subrange) const; + FVECTOR4 GetTexRangeDX (const TEXCRDRANGE2 *subrange) const; inline const TEXCRDRANGE2 *GetTexRange () const { return &texrange; } // Returns the tile's texture coordinate range @@ -212,6 +211,7 @@ class Tile DWORD FrameId; float width; // tile width [rad] (widest section i.e base) float height; // tile height [rad] + float tgtscale; public: D3DXMATRIX mWorld; @@ -277,7 +277,8 @@ namespace eElevMode { * Rendering of planetary surfaces using texture tiles at * variable resolutions (new version). */ -class TileManager2Base : public PlanetRenderer { +class TileManager2Base +{ friend class Tile; public: @@ -317,14 +318,14 @@ class TileManager2Base : public PlanetRenderer { int Sphe; ///< Number of spherical tiles rendered } elvstat, prevstat; - int ElevMode; + int ElevMode, ElevModeLvl; /** * \brief Constructs a new tile manager object * \param vplanet planet instance pointer * \param _maxres maximum resolution */ - TileManager2Base (const vPlanet *vplanet, int _maxres, int _gridres); + TileManager2Base (vPlanet *vplanet, int _maxres, int _gridres); /** * \brief Destroys the tile manager object @@ -348,7 +349,6 @@ class TileManager2Base : public PlanetRenderer { static bool ShutDown (); static LPDIRECT3DDEVICE9 Dev() { return pDev; } - static ID3DXEffect * Shader() { return pShader; } static HFONT GetDebugFont() { return hFont; } void TileLabel(LPDIRECT3DTEXTURE9 tex, int lvl, int ilat, int ilng); @@ -384,21 +384,20 @@ class TileManager2Base : public PlanetRenderer { inline class Scene * GetScene() const { return gc->GetScene(); } inline oapi::D3D9Client *GetClient() const { return gc; } - inline const vPlanet *GetPlanet() const { return vp; } + inline oapi::D3D9Client* Client() const { return gc; } + inline vPlanet *GetPlanet() { return vp; } + inline vPlanet* GetPlanet() const { return vp; } + inline PlanetShader* GetShader() { return pShader; } + inline bool IsUsingZBuf() const { return bUseZ; } inline const OBJHANDLE &Cbody() const { return obj; } inline const ConfigPrm &Cprm() const { return cprm; } inline const char *CbodyName() const { return cbody_name; } inline const double CbodySize() const { return obj_size; } inline const ELEVHANDLE ElevMgr() const { return emgr; } inline const int GridRes() const { return gridRes; } - inline const double ElevRes() const { return elevRes; } //(Mostly Obsolete) not needed since elevation is float based + inline const double ElevRes() const { return elevRes; } inline OBJHANDLE GetHandle() const { return obj; } - - double GetMinElev() const { return min_elev; } - double GetMaxElev() const { return max_elev; } - void SetMinMaxElev(double min, double max); - void ResetMinMaxElev(); /// \brief Return the root directory containing the body's texture data (surface, elevation, mask, cloud tiles) inline const std::string& DataRootDir() const { return m_dataRootDir; } @@ -412,14 +411,13 @@ class TileManager2Base : public PlanetRenderer { // loads one of the four subnodes of 'node', given by 'idx' double obj_size; // planet radius - double min_elev; // minimum rendered elevation - double max_elev; // maximum rendered elevation static TileLoader *loader; - const vPlanet *vp; // the planet visual + vPlanet *vp; // the planet visual + PlanetShader* pShader; std::string m_dataRootDir; // the root directory (usually ending in the cbody's name) for all tile data (textures, elevations, etc.) + bool bUseZ; private: - bool bSet; // This is related to GetMin/MaxElevation OBJHANDLE obj; // the planet object char cbody_name[256]; ELEVHANDLE emgr; // elevation data query handle @@ -431,10 +429,16 @@ class TileManager2Base : public PlanetRenderer { std::stack VtxPool[NPOOLS]; std::stack IdxPool[NPOOLS]; + static oapi::D3D9Client* gc; + static LPDIRECT3DDEVICE9 pDev; static HFONT hFont; static double resolutionBias; static double resolutionScale; static bool bTileLoadThread; // load tiles on separate thread +public: + static LPDIRECT3DTEXTURE9 hOcean; + static LPDIRECT3DTEXTURE9 hCloudMicro; + static LPDIRECT3DTEXTURE9 hCloudMicroNorm; }; // ======================================================================= @@ -444,7 +448,7 @@ class TileManager2: public TileManager2Base { friend class Tile; public: - TileManager2 (const vPlanet *vplanet, int _maxres, int _gridres); + TileManager2 (vPlanet *vplanet, int _maxres, int _gridres); ~TileManager2 (); void Render (MATRIX4 &dwmat, bool use_zbuf, const vPlanet::RenderPrm &rprm); diff --git a/OVP/D3D9Client/Tilemgr2_imp.hpp b/OVP/D3D9Client/Tilemgr2_imp.hpp index f3a27451e..4853d025c 100644 --- a/OVP/D3D9Client/Tilemgr2_imp.hpp +++ b/OVP/D3D9Client/Tilemgr2_imp.hpp @@ -167,6 +167,7 @@ void TileManager2Base::ProcessNode (QuadTreeNode *node) double apr = tdist * scene->GetTanAp() * resolutionScale; tgtres = (apr < 1e-6 ? maxlvl : max(0, min(maxlvl, (int)(bias - log(apr)*res_scale)))); bstepdown = (lvl < tgtres); + tile->tgtscale = pow(2.0f, float(tgtres - lvl)); } if (!bstepdown) { @@ -178,7 +179,10 @@ void TileManager2Base::ProcessNode (QuadTreeNode *node) if (!bstepdown) { // Search elevated tiles from sub-trees // This can severally impact in performance if used incorrectly - if ((ElevMode == eElevMode::ForcedElevated) && (tile->IsElevated() == false)) bstepdown = true; + if ((ElevMode == eElevMode::ForcedElevated) && (tile->IsElevated() == false)) { + if (ElevModeLvl == 0) ElevModeLvl = lvl + 1; + bstepdown = ElevModeLvl >= lvl; + } } // Recursion to next level: subdivide into 2x2 patch @@ -219,7 +223,6 @@ void TileManager2Base::RenderNode (QuadTreeNode *node) if (tile->state == Tile::ForRender) { int lvl = tile->lvl; if (scene->GetRenderPass() == RENDERPASS_MAINSCENE) tile->MatchEdges (); - SetWorldMatrix (tile->mWorld); tile->StepIn (); tile->Render (); tile->FrameId = scene->GetFrameId(); // Keep a record about when this tile is actually rendered. @@ -261,7 +264,7 @@ void TileManager2Base::RenderNodeLabels(QuadTreeNode *node, D3D9Pad *s // ======================================================================= template -TileManager2::TileManager2 (const vPlanet *vplanet, int _maxres, int _gridres) +TileManager2::TileManager2 (vPlanet *vplanet, int _maxres, int _gridres) : TileManager2Base (vplanet, _maxres, _gridres), ntreeMgr(0) { diff --git a/OVP/D3D9Client/VBase.cpp b/OVP/D3D9Client/VBase.cpp index 9c9875105..d6c5efb1a 100644 --- a/OVP/D3D9Client/VBase.cpp +++ b/OVP/D3D9Client/VBase.cpp @@ -352,13 +352,9 @@ bool vBase::Update (bool bMainScene) double simt = oapiGetSimTime(); - if (fabs(simt-Tlghtchk)>0.1) { - sunLight = *scn->GetSun(); - - DWORD dAmbient = *(DWORD*)gc->GetConfigParam(CFGPRM_AMBIENTLEVEL); - float fAmbient = float(dAmbient)*0.0039f; - - SurfaceLighting(&sunLight, oapiGetBasePlanet(hObj), hObj, fAmbient); + if (fabs(simt-Tlghtchk)>0.1 || oapiGetPause()) { + VECTOR3 rpos = gpos - vP->GlobalPos(); + sunLight = vP->GetObjectAtmoParams(rpos); Tlghtchk = simt; } @@ -428,7 +424,10 @@ bool vBase::RenderStructures(LPDIRECT3DDEVICE9 dev) // render generic objects above shadows for (DWORD i=0; iSetSunLight(&sunLight); + FVECTOR3 bs = structure_as[i]->GetBoundingSpherePos(); + FVECTOR3 qw = TransformCoord(bs, mWorld); + D3D9Sun sp = vP->GetObjectAtmoParams(qw._V() + vP->CameraPos()); + structure_as[i]->SetSunLight(&sp); structure_as[i]->Render(&mWorld, RENDER_BASE); ++uCurrentMesh; } diff --git a/OVP/D3D9Client/VBase.h b/OVP/D3D9Client/VBase.h index 0affbdf9d..5544ad006 100644 --- a/OVP/D3D9Client/VBase.h +++ b/OVP/D3D9Client/VBase.h @@ -85,8 +85,7 @@ class vBase: public vObject { D3D9Mesh **structure_as; DWORD nstructure_bs, nstructure_as; bool lights; // use nighttextures for base objects - bool bLocalLight; // true if lighting is modified - //D3D9Light localLight; // current local lighting parameters + //bool bLocalLight; // true if lighting is modified class vPlanet *vP; VECTOR3 vLocalPos; MATRIX3 mGlobalRot; diff --git a/OVP/D3D9Client/VObject.h b/OVP/D3D9Client/VObject.h index 4f7d858e5..e54b530c4 100644 --- a/OVP/D3D9Client/VObject.h +++ b/OVP/D3D9Client/VObject.h @@ -21,6 +21,7 @@ extern class D3D9Config *Config; class D3D9Pad; + // ============================================================== // class vObject (interface) // ============================================================== @@ -170,6 +171,7 @@ class vObject: public oapi::VisObject { * \note The returned vector is expressed in the ecliptic frame. */ inline const VECTOR3 &SunDirection() const { return sundir; } + inline const double SunDistance() const { return sundst; } /** * \brief Per-frame object parameter updates diff --git a/OVP/D3D9Client/VPlanet.cpp b/OVP/D3D9Client/VPlanet.cpp index e67db5d09..761d91f6b 100644 --- a/OVP/D3D9Client/VPlanet.cpp +++ b/OVP/D3D9Client/VPlanet.cpp @@ -35,6 +35,7 @@ #include "AtmoControls.h" #include "VectorHelpers.h" #include "OapiExtension.h" +#include "IProcess.h" using namespace oapi; @@ -44,12 +45,19 @@ static double farplane = 1e6; static double max_surf_dist = 1e4; // Buffered MicroTex.cfg file read: -static bool bMicroTexFileRead = false; static std::map MicroCfgs; typedef std::map::iterator MicroCfgsIterator; +ImageProcessing* vPlanet::pIP; +LPDIRECT3DDEVICE9 vPlanet::pDev; + +int vPlanet::Qc = 0; +int vPlanet::Wc = 0; +int vPlanet::Nc = 0; + extern int SURF_MAX_PATCHLEVEL; extern D3D9Client* g_client; +extern unordered_map MicroTextures; // ============================================================== // Face's Terrain Flattening section @@ -310,6 +318,13 @@ void FilterElevationGraphics(OBJHANDLE hPlanet, int lvl, int ilat, int ilng, flo } + + + + + +// ============================================================== + void vPlanet::GlobalExit() { // Face's Cleanup ShapeStore ----------------------- @@ -324,28 +339,41 @@ void vPlanet::GlobalExit() g_ShapeStore.clear(); g_ElevationFlatteningShapes.clear(); g_ShapesLoaded.clear(); -} - - - + SAFE_DELETE(pIP); + for (int i=0;i<8;i++) SAFE_DELETE(pRender[i]); +} +// ============================================================== +void vPlanet::GlobalInit(oapi::D3D9Client* gc) +{ + pDev = gc->GetDevice(); + LoadMicroTextures(pDev); + GlobalInitAtmosphere(gc); +} // ============================================================== -vPlanet::vPlanet (OBJHANDLE _hObj, const Scene *scene): vObject (_hObj, scene) +vPlanet::vPlanet (OBJHANDLE _hObj, const Scene *scene) : + vObject (_hObj, scene), + pSunColor(), pRaySkyView(), pMieSkyView(), pLandViewRay(), pLandViewMie(), pAmbientSky(), pLandViewAtn(), ShaderName("Auto\0") { memset(&MicroCfg, 0, sizeof(MicroCfg)); vRefPoint = _V(1,0,0); - bScatter = false; + atm_mode = 0; + iConfig = 0; dist_scale = 1.0f; threshold = 1e16; + dwSctFrame = 0; max_centre_dist = 0.9*scene->GetCameraFarPlane(); maxdist = max (max_centre_dist, max_surf_dist + size); DWORD elev_mode = *(DWORD*)gc->GetConfigParam(CFGPRM_ELEVATIONMODE); + minelev = *(double*)oapiGetObjectParam(_hObj, OBJPRM_PLANET_MINELEVATION); + maxelev = *(double*)oapiGetObjectParam(_hObj, OBJPRM_PLANET_MAXELEVATION); + physics_patchres = *(DWORD*)oapiGetObjectParam (_hObj, OBJPRM_PLANET_SURFACEMAXLEVEL); physics_patchres = min (physics_patchres, *(DWORD*)gc->GetConfigParam (CFGPRM_SURFACEMAXLEVEL)); @@ -361,16 +389,15 @@ vPlanet::vPlanet (OBJHANDLE _hObj, const Scene *scene): vObject (_hObj, scene) surfmgr = new SurfaceManager (gc, this); surfmgr2 = NULL; } else { - bScatter = LoadAtmoConfig(false); - if (bScatter) LoadAtmoConfig(true); + LoadAtmoConfig(); surfmgr = NULL; int patchlvl = 1 << (4 + Config->MeshRes); surfmgr2 = new TileManager2 (this, max_patchres, patchlvl); prm.horizon_excess = *(double*)oapiGetObjectParam (_hObj, OBJPRM_PLANET_HORIZONEXCESS); prm.tilebb_excess = *(double*)oapiGetObjectParam (_hObj, OBJPRM_PLANET_TILEBBEXCESS); } - prm.horizon_minelev = *(double*)oapiGetObjectParam(_hObj, OBJPRM_PLANET_MINELEVATION); - prm.horizon_minrad = min (1.0 + prm.horizon_minelev / size, 1.0 - 1e-4); + + prm.horizon_minrad = min (1.0 + minelev / size, 1.0 - 1e-4); prm.bAtm = oapiPlanetHasAtmosphere (_hObj); if (prm.bAtm) { @@ -392,7 +419,7 @@ vPlanet::vPlanet (OBJHANDLE _hObj, const Scene *scene): vObject (_hObj, scene) if (surfmgr) surfmgr->SetMicrotexture ("waves.dds"); } - shadowalpha = (float)(/*1.0f -*/ *(double*)oapiGetObjectParam (_hObj, OBJPRM_PLANET_SHADOWCOLOUR)); + shadowalpha = (float)(*(double*)oapiGetObjectParam (_hObj, OBJPRM_PLANET_SHADOWCOLOUR)); bVesselShadow = (shadowalpha < 0.98); bObjectShadow = (shadowalpha < 0.98); @@ -443,9 +470,6 @@ vPlanet::vPlanet (OBJHANDLE _hObj, const Scene *scene): vObject (_hObj, scene) patchres = 0; - //if (*(bool*)gc->GetConfigParam(CFGPRM_ATMFOG)==false) prm.bFogEnabled = false; - - nbase = oapiGetBaseCount (_hObj); if (nbase) vbase = new vBase*[nbase]; else vbase = NULL; @@ -482,10 +506,13 @@ vPlanet::vPlanet (OBJHANDLE _hObj, const Scene *scene): vObject (_hObj, scene) MicroCfg.bEnabled = ParseMicroTextures(); ParseConfig(oapiGetObjectFileName(hObj)); + + UpdateScatter(); } -// ============================================================== +// =========================================================================================== +// vPlanet::~vPlanet () { @@ -499,12 +526,6 @@ vPlanet::~vPlanet () else if (surfmgr2) delete surfmgr2; if (cloudmgr2) delete cloudmgr2; - if (MicroCfg.bLoaded) { - for (int i = 0; i < ARRAYSIZE(MicroCfg.Level); ++i) { - SAFE_RELEASE(MicroCfg.Level[i].pTex); - } - } - for (auto x : overlays) for (auto y : x->pSurf) if (y) y->Release(); if (clouddata) { @@ -515,9 +536,20 @@ vPlanet::~vPlanet () if (hazemgr2) delete hazemgr2; if (ringmgr) delete ringmgr; if (mesh) delete mesh; + + SAFE_RELEASE(pSunColor); + SAFE_RELEASE(pRaySkyView); + SAFE_RELEASE(pMieSkyView); + SAFE_RELEASE(pLandViewRay); + SAFE_RELEASE(pLandViewMie); + SAFE_RELEASE(pAmbientSky); + SAFE_RELEASE(pLandViewAtn); } + + + // =========================================================================================== // bool vPlanet::ParseConfig(const char* fname) @@ -569,24 +601,8 @@ bool vPlanet::CameraInAtmosphere() const double vPlanet::GetHorizonAlt() const { if (!prm.bAtm) return 0.0; - if (!bScatter) return prm.atm_hzalt; - return SPrm.height*11e3; -} - -// ============================================================== - -double vPlanet::GetMinElevation() const -{ - if (surfmgr2) return surfmgr2->GetMinElev(); - return 0.0; // return prm.horizon_minelev; ?!? -} - -// ============================================================== - -double vPlanet::GetMaxElevation() const -{ - if (surfmgr2) return surfmgr2->GetMaxElev(); - return 0.0; + if (!surfmgr2) return prm.atm_hzalt; + return SPrm.visalt; } // ============================================================== @@ -617,6 +633,13 @@ VECTOR3 vPlanet::ToLocal(VECTOR3 &glob) const // ============================================================== +VECTOR3 vPlanet::CameraPos() const +{ + return scn->GetCameraGPos() - gpos; +} + +// ============================================================== + void vPlanet::GetLngLat(VECTOR3 &loc, double *lng, double *lat) const { *lat = asin(loc.y); @@ -684,6 +707,14 @@ void vPlanet::UpdateBoundingBox() // ============================================================== +void vPlanet::ReOrigin(VECTOR3 global_pos) +{ + vObject::ReOrigin(global_pos); + if (vbase) for (int i = 0; i < nbase; i++) if (vbase[i]) vbase[i]->ReOrigin(global_pos); +} + +// ============================================================== + bool vPlanet::Update (bool bMainScene) { _TRACE; @@ -691,14 +722,12 @@ bool vPlanet::Update (bool bMainScene) vObject::Update(bMainScene); - // Update Sunlight direction ------------------------------------- - D3DVEC(-sundir, sunLight.Dir); + // Update Atmospheric Scattering Tables + UpdateScatter(); + if (patchres==0) return true; - // Check if micro textures needs loading - if (MicroCfg.bEnabled && !MicroCfg.bLoaded && scn->GetCameraProxyVisual()==this) LoadMicroTextures(); - int i, j; float rad_scale = float(size); bool rescale = false; @@ -730,9 +759,6 @@ bool vPlanet::Update (bool bMainScene) prm.cloudrot = posangle(prm.cloudrot); prm.cloudvis = (cdist < cloudrad ? 1:0); if (cdist > cloudrad*(1.0-1.5e-4)) prm.cloudvis |= 2; - //prm.bCloudFlatShadows = (cdist >= 1.05*size); - //prm.bCloudFlatShadows = (cdist >= (size+GetHorizonAlt())); - //prm.bCloudFlatShadows = false; if (clouddata) { if (prm.cloudvis & 1) { @@ -834,8 +860,8 @@ void vPlanet::CheckResolution() if (hazemgr) { delete hazemgr; hazemgr = NULL; } if (hazemgr2) { delete hazemgr2; hazemgr2 = NULL; } } else { - if (tilever>1 && bScatter) { - if (!hazemgr2) hazemgr2 = new HazeManager2 (scn->GetClient(), this); + if (tilever>1) { + if (!hazemgr2) hazemgr2 = new HazeManager2 (this); } else if (!hazemgr) hazemgr = new HazeManager (scn->GetClient(), this); } @@ -865,36 +891,8 @@ bool vPlanet::Render(LPDIRECT3DDEVICE9 dev) _TRACE; if (!active) return false; - D3D9Effect::UpdateEffectCamera(hObj); - D3D9Effect::FX->SetFloat(D3D9Effect::eDistScale, 1.0f/float(dist_scale)); - const Scene::SHADOWMAPPARAM *shd = scn->GetSMapData(); - float s = float(shd->size); - float is = 1.0f / s; - float qw = 1.0f / float(Config->ShadowMapSize); - - // Clear setting for a mesh based body - // - HR(D3D9Effect::FX->SetBool(D3D9Effect::eEnvMapEnable, false)); - HR(D3D9Effect::FX->SetBool(D3D9Effect::eShadowToggle, false)); - - // Initialize projected shadows for a mesh based body - // - if (shd->pShadowMap && (scn->GetRenderPass() == RENDERPASS_MAINSCENE) && (Config->TerrainShadowing == 2)) { - if (scn->GetCameraAltitude() < 10e3 && IsMesh()) { - HR(D3D9Effect::FX->SetMatrix(D3D9Effect::eLVP, &shd->mViewProj)); - HR(D3D9Effect::FX->SetTexture(D3D9Effect::eShadowMap, shd->pShadowMap)); - HR(D3D9Effect::FX->SetVector(D3D9Effect::eSHD, &D3DXVECTOR4(s, is, qw, 0))); - HR(D3D9Effect::FX->SetBool(D3D9Effect::eShadowToggle, true)); - } - } - - if (!mesh) { // Skip for a mesh - PlanetRenderer::InitializeScattering(this); - PlanetRenderer::SetViewProjectionMatrix(scn->GetProjectionViewMatrix()); - } - if (DebugControls::IsActive()) { // DWORD flags = *(DWORD*)gc->GetConfigParam(CFGPRM_GETDEBUGFLAGS); DWORD displ = *(DWORD*)gc->GetConfigParam(CFGPRM_GETDISPLAYMODE); @@ -910,9 +908,34 @@ bool vPlanet::Render(LPDIRECT3DDEVICE9 dev) if (renderpix) { // render as 2x2 pixel block RenderDot (dev); - } else { // render as sphere + } + else // render as sphere ------------------------ + { + + // Must update the latest view projection matrix + cp.mVP = *scn->GetProjectionViewMatrix(); + + // Setup shadow maps for surface base objects and mesh based bodies --------------- + // + D3D9Effect::UpdateEffectCamera(hObj); + D3D9Effect::FX->SetFloat(D3D9Effect::eDistScale, 1.0f / float(dist_scale)); + + HR(D3D9Effect::FX->SetBool(D3D9Effect::eEnvMapEnable, false)); + HR(D3D9Effect::FX->SetBool(D3D9Effect::eShadowToggle, false)); + + if (shd->pShadowMap && (scn->GetRenderPass() == RENDERPASS_MAINSCENE) && (Config->TerrainShadowing == 2)) { + if (scn->GetCameraAltitude() < 10e3 || IsMesh()) { + float s = float(shd->size); + float is = 1.0f / s; + float qw = 1.0f / float(Config->ShadowMapSize); + HR(D3D9Effect::FX->SetMatrix(D3D9Effect::eLVP, &shd->mViewProj)); + HR(D3D9Effect::FX->SetTexture(D3D9Effect::eShadowMap, shd->pShadowMap)); + HR(D3D9Effect::FX->SetVector(D3D9Effect::eSHD, &D3DXVECTOR4(s, is, qw, 0))); + HR(D3D9Effect::FX->SetBool(D3D9Effect::eShadowToggle, true)); + } + } + DWORD amb = prm.amb0col; -// bool ringpostrender = false; float fogfactor; D3DCOLOR bg = scn->GetBgColour(); @@ -955,7 +978,6 @@ bool vPlanet::Render(LPDIRECT3DDEVICE9 dev) double fog_0 = fog.dens_0; // 5e-5; double fog_ref = fog.dens_ref; // 3e-5; double h_max = size*1.5; // At this altitude, fog effect drops to zero -// double scl = h_ref*fog_ref; if (h < h_ref) { // linear zone @@ -1036,13 +1058,6 @@ void vPlanet::RenderVectors (LPDIRECT3DDEVICE9 dev, D3D9Pad* pSkp) } } -// ============================================================== -/* -void vPlanet::RenderSurfaceMicroDetails(LPDIRECT3DDEVICE9 dev) -{ - -} -*/ // ============================================================== void vPlanet::ActivateLabels(bool activate) @@ -1068,13 +1083,9 @@ void vPlanet::RenderLabels(LPDIRECT3DDEVICE9 dev, D3D9Pad *skp, oapi::Font **lab void vPlanet::RenderSphere (LPDIRECT3DDEVICE9 dev) { - float fogfactor; - D3D9Effect::FX->GetFloat(D3D9Effect::eFogDensity, &fogfactor); - + bool bUseZBuf = true; - bool bLog = false; - if (scn->GetRenderPass() == RENDERPASS_MAINSCENE && scn->GetCameraProxyVisual() == this) bLog = true; - double tot_surf = D3D9GetTime(); + double calt = abs(cdist - size); if (surfmgr2) { @@ -1084,7 +1095,7 @@ void vPlanet::RenderSphere (LPDIRECT3DDEVICE9 dev) if (scn->GetRenderPass() == RENDERPASS_MAINSCENE) { if (size < 500e3) { // Comet, Asteroid, Small Moon - if (cdist >= 100.0*size) { + if (cdist >= 1000.0*size) { surfmgr2->ElevMode = eElevMode::Spherical; bUseZBuf = false; } @@ -1117,16 +1128,15 @@ void vPlanet::RenderSphere (LPDIRECT3DDEVICE9 dev) //if (string(GetName()) == string("Earth")) sprintf_s(oapiDebugString(), 256, "UseZ=%hhu, ElevMode=%d", bUseZBuf, surfmgr2->ElevMode); surfmgr2->Render(dmWorld, bUseZBuf, prm); - - if (bLog) D3D9SetTime(D3D9Stats.Timer.Surface, tot_surf); } else { + float fogfactor; + D3D9Effect::FX->GetFloat(D3D9Effect::eFogDensity, &fogfactor); dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); if (prm.bFog) D3D9Effect::FX->SetFloat(D3D9Effect::eFogDensity, fogfactor/dist_scale); surfmgr->SetAmbientColor(prm.AmbColor); surfmgr->Render (dev, mWorld, dist_scale, patchres, 0.0, prm.bFog); // surface if (prm.bFog) D3D9Effect::FX->SetFloat(D3D9Effect::eFogDensity, fogfactor); - if (bLog) D3D9SetTime(D3D9Stats.Timer.Surface, tot_surf); } if (nbase) { @@ -1145,10 +1155,6 @@ void vPlanet::RenderSphere (LPDIRECT3DDEVICE9 dev) void vPlanet::RenderCloudLayer (LPDIRECT3DDEVICE9 dev, DWORD cullmode) { - bool bLog = false; - if (scn->GetRenderPass() == RENDERPASS_MAINSCENE && scn->GetCameraProxyVisual() == this) bLog = true; - double tot_cloud = D3D9GetTime(); - if (cullmode != D3DCULL_CCW) dev->SetRenderState (D3DRS_CULLMODE, cullmode); if (cloudmgr2) { cloudmgr2->Render(dmWorld, false, prm); @@ -1156,8 +1162,6 @@ void vPlanet::RenderCloudLayer (LPDIRECT3DDEVICE9 dev, DWORD cullmode) else clouddata->cloudmgr->Render (dev, clouddata->mWorldC, dist_scale, min(patchres,8), clouddata->viewap); // clouds if (cullmode != D3DCULL_CCW) dev->SetRenderState (D3DRS_CULLMODE, D3DCULL_CCW); - - if (bLog) D3D9SetTime(D3D9Stats.Timer.Clouds, tot_cloud); } // ============================================================== @@ -1165,8 +1169,7 @@ void vPlanet::RenderCloudLayer (LPDIRECT3DDEVICE9 dev, DWORD cullmode) void vPlanet::RenderCloudShadows (LPDIRECT3DDEVICE9 dev) { if (cloudmgr2) { - //if (prm.bCloudFlatShadows) - // cloudmgr2->RenderFlatCloudShadows (dmWorld, prm); + // Nothing to do here } else if (clouddata) { // legacy method float fogfactor; @@ -1184,9 +1187,11 @@ void vPlanet::RenderBaseSurfaces(LPDIRECT3DDEVICE9 dev) // If this planet is not a proxy body skip the rest if (hObj != oapiCameraProxyGbody()) return; - for (DWORD i=0;iRenderSurface(dev); - vbase[i]->RenderRunwayLights(dev); + if (scn->GetRenderFlags() & 0x20) { + for (DWORD i = 0; i < nbase; i++) if (vbase[i]) { + vbase[i]->RenderSurface(dev); + vbase[i]->RenderRunwayLights(dev); + } } } @@ -1197,10 +1202,12 @@ void vPlanet::RenderBaseShadows(LPDIRECT3DDEVICE9 dev, float depth) // If this planet is not a proxy body skip the rest if (hObj != oapiCameraProxyGbody()) return; - if (bObjectShadow) { - for (DWORD i=0;iRenderGroundShadow(dev, depth); - // reset device parameters - dev->SetRenderState(D3DRS_STENCILENABLE, FALSE); + if (scn->GetRenderFlags() & 0x20) { + if (bObjectShadow) { + for (DWORD i = 0; i < nbase; i++) if (vbase[i]) vbase[i]->RenderGroundShadow(dev, depth); + // reset device parameters + dev->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } } } @@ -1211,8 +1218,10 @@ void vPlanet::RenderBaseStructures (LPDIRECT3DDEVICE9 dev) // If this planet is not a proxy body skip the rest if (hObj != oapiCameraProxyGbody()) return; - for (DWORD i=0;iRenderStructures(dev); - for (DWORD i=0;iRenderBeacons(dev); + if (scn->GetRenderFlags() & 0x20) { + for (DWORD i = 0; i < nbase; i++) if (vbase[i]) vbase[i]->RenderStructures(dev); + for (DWORD i = 0; i < nbase; i++) if (vbase[i]) vbase[i]->RenderBeacons(dev); + } } // ============================================================== @@ -1242,31 +1251,6 @@ bool vPlanet::ModLighting (DWORD &ambient) return true; } -// ============================================================== - -D3DXVECTOR3 vPlanet::GetSunLightColor(VECTOR3 vPos, float fAmbient, float fGlobalAmb) -{ - double fAlt = length(vPos) - size; - if (fAlt>prm.SclHeight*20.0) return D3DXVECTOR3(1,1,1); - - float rp = -float(SPrm.rpow); - float mp = -float(SPrm.mpow); - - D3DXVECTOR3 lambda4 = D3DXVECTOR3(pow(float(SPrm.red),rp), pow(float(SPrm.green),rp), pow(float(SPrm.blue),rp)); - D3DXVECTOR3 lambda2 = D3DXVECTOR3(pow(float(SPrm.red),mp), pow(float(SPrm.green),mp), pow(float(SPrm.blue),mp)); - - D3DXVec3Normalize(&lambda4, &lambda4); - D3DXVec3Normalize(&lambda2, &lambda2); - - D3DXVECTOR3 vOutTotSun = lambda4*float(SPrm.rout) + lambda2*float(SPrm.mie); - D3DXVECTOR3 vRayInSct = lambda4*float(SPrm.rin * SPrm.rout); - - double fDPS = max(0.34, dotp(unit(vPos), sundir)); - double fDns = exp2(-fAlt * prm.InvSclHeight); - - return exp2(-vOutTotSun * float(fDns * AngleCoEff(fDPS))); -} - // ============================================================== // Get a "semi" fixed surface reference point. Update if camera // movement is greater that 2deg @@ -1280,237 +1264,6 @@ VECTOR3 vPlanet::ReferencePoint() return vRefPoint; } -// ============================================================== - -double vPlanet::AngleCoEff(double cd) -{ - cd = 1.0/max(0.0954, cd+0.2); - double val = 0.0, x = 1.0; - for (int i=0;i<8;i++) { val += prm.ScatterCoEff[i]*x; x*=cd; } - return val; -} - -// ============================================================== - -void vPlanet::UpdateAtmoConfig() -{ - prm.SclHeight = float(SPrm.height*1e3); - prm.InvSclHeight = 1.0f / float(prm.SclHeight); - double outer = size + SPrm.height * 12.0 * 1e3; -// double height = size + SPrm.height * 5.0; -// double angle = (PI-asin(size/height)) * DEG; - - SolveXScatter(prm.SclHeight, size, outer, prm.ScatterCoEff, 96.0, 8); -} - - -double GaussLobatto(double alt, double dir, double R0, double R1, double h0) -{ - double R = R0 + alt; - - double rdt = -R * cos(dir); - double Ray = rdt + sqrt(R1*R1 - (R*R - rdt*rdt)); - - double p0 = Ray * 0.0; - double p1 = Ray * 0.2765; - double p2 = Ray * 0.7235; - double p3 = Ray * 1.0; - - double a0 = sqrt(R*R + p0*p0 + 2.0*R*p0*cos(dir)) - R0; - double a1 = sqrt(R*R + p1*p1 + 2.0*R*p1*cos(dir)) - R0; - double a2 = sqrt(R*R + p2*p2 + 2.0*R*p2*cos(dir)) - R0; - double a3 = sqrt(R*R + p3*p3 + 2.0*R*p3*cos(dir)) - R0; - - double s0 = exp2(-a0/h0); - double s1 = exp2(-a1/h0); - double s2 = exp2(-a2/h0); - double s3 = exp2(-a3/h0); - - double sum = (s0*0.167 + s1*0.833 + s2*0.833 + s3*0.167) * Ray * 0.5 * 0.6931471806; - - return sum; -} - -// ============================================================== - -void vPlanet::DumpDebugFile() -{ - /* - int samples = 100; - double max_angle = 100.0; - double delta = 3.1415*max_angle/float(samples*180); - double angle = 0.0; - double outer = size + (prm.SclHeight*8.0); - - FILE *fp = NULL; - fopen_s(&fp, "OpticalDebug.txt", "w"); - if (fp==NULL) return; - - for (int i=0;i0.5) mode = 2; - if (mode==0 && alt<0.5) mode = 1; - - if (mode==1) return &SPrm; // Surface configuration - if (mode==2) return &OPrm; // Orbital configuration - - // ---------------------------------------------------- - CPrm.aux1 = lerp(SPrm.aux1, OPrm.aux1, alt); - CPrm.aux2 = lerp(SPrm.aux2, OPrm.aux2, alt); - CPrm.aux3 = lerp(SPrm.aux3, OPrm.aux3, alt); - CPrm.depth = lerp(SPrm.depth, OPrm.depth, alt); - CPrm.expo = lerp(SPrm.expo, OPrm.expo, alt); - CPrm.mie = lerp(SPrm.mie, OPrm.mie, alt); - CPrm.mphase = lerp(SPrm.mphase, OPrm.mphase, alt); - CPrm.rphase = lerp(SPrm.rphase, OPrm.rphase, alt); - CPrm.mpow = lerp(SPrm.mpow, OPrm.mpow, alt); - CPrm.rin = lerp(SPrm.rin, OPrm.rin, alt); - CPrm.rout = lerp(SPrm.rout, OPrm.rout, alt); - CPrm.rpow = lerp(SPrm.rpow, OPrm.rpow, alt); - // ---------------------------------------------------- - CPrm.red = lerp(SPrm.red, OPrm.red, alt); - CPrm.green = lerp(SPrm.green, OPrm.green, alt); - CPrm.blue = lerp(SPrm.blue, OPrm.blue, alt); - // ---------------------------------------------------- - CPrm.agamma = lerp(SPrm.agamma, OPrm.agamma, alt); - CPrm.tgamma = lerp(SPrm.tgamma, OPrm.tgamma, alt); - CPrm.hazec = lerp(SPrm.hazec, OPrm.hazec, alt); - CPrm.hazei = lerp(SPrm.hazei, OPrm.hazei, alt); - // ---------------------------------------------------- - CPrm.height = SPrm.height; - - return &CPrm; -} - - - -// ============================================================== - -bool vPlanet::LoadAtmoConfig(bool bOrbit) -{ - char name[32]; - char path[256]; - - oapiGetObjectName(hObj, name, 32); - - if (bOrbit) sprintf_s(path,"GC/%s.atmo.cfg",name); - else sprintf_s(path,"GC/%s.atms.cfg",name); - - FILEHANDLE hFile = oapiOpenFile(path, FILE_IN_ZEROONFAIL, CONFIG); - - if (!hFile) return false; - - LogAlw("Loading Atmospheric Configuration file [%s] Handle=%s", path, _PTR(hFile)); - - ScatterParams *prm; - - if (bOrbit) prm = &OPrm; - else prm = &SPrm; - - prm->orbit = bOrbit; - - oapiReadItem_float(hFile, "Red", prm->red); - oapiReadItem_float(hFile, "Green", prm->green); - oapiReadItem_float(hFile, "Blue", prm->blue); - oapiReadItem_float(hFile, "RWaveDep", prm->rpow); - oapiReadItem_float(hFile, "MWaveDep", prm->mpow); - oapiReadItem_float(hFile, "ScaleHeight", prm->height); - oapiReadItem_float(hFile, "DepthClamp", prm->depth); - // ----------------------------------------------------------------- - oapiReadItem_float(hFile, "Exposure", prm->expo); - oapiReadItem_float(hFile, "TGamma", prm->tgamma); - // ----------------------------------------------------------------- - oapiReadItem_float(hFile, "OutScatter", prm->rout); - oapiReadItem_float(hFile, "InScatter", prm->rin); - oapiReadItem_float(hFile, "RayleighPhase", prm->rphase); - // ----------------------------------------------------------------- - oapiReadItem_float(hFile, "MiePower", prm->mie); - oapiReadItem_float(hFile, "MiePhase", prm->mphase); - // ----------------------------------------------------------------- - oapiReadItem_float(hFile, "Aux1", prm->aux1); - oapiReadItem_float(hFile, "Aux2", prm->aux2); - oapiReadItem_float(hFile, "Aux3", prm->aux3); - // ----------------------------------------------------------------- - oapiReadItem_float(hFile, "AGamma", prm->agamma); - oapiReadItem_float(hFile, "HazeClr", prm->hazec); - oapiReadItem_float(hFile, "HazeIts", prm->hazei); - - oapiCloseFile(hFile, FILE_IN_ZEROONFAIL); - - if (!oapiPlanetHasAtmosphere(hObj)) return false; - - UpdateAtmoConfig(); - return true; - -} - -// ============================================================== - -void vPlanet::SaveAtmoConfig(bool bOrbit) -{ - char name[64]; - char path[256]; - - oapiGetObjectName(hObj, name, 64); - - if (bOrbit) sprintf_s(path,"GC/%s.atmo.cfg",name); - else sprintf_s(path,"GC/%s.atms.cfg",name); - - FILEHANDLE hFile = oapiOpenFile(path, FILE_OUT, CONFIG); - - ScatterParams *prm; - - if (bOrbit) prm = &OPrm; - else prm = &SPrm; - - oapiWriteItem_float(hFile, "Red", prm->red); - oapiWriteItem_float(hFile, "Green", prm->green); - oapiWriteItem_float(hFile, "Blue", prm->blue); - oapiWriteItem_float(hFile, "RWaveDep", prm->rpow); - oapiWriteItem_float(hFile, "MWaveDep", prm->mpow); - oapiWriteItem_float(hFile, "ScaleHeight", prm->height); - oapiWriteItem_float(hFile, "DepthClamp", prm->depth); - // ----------------------------------------------------------------- - oapiWriteItem_float(hFile, "Exposure", prm->expo); - oapiWriteItem_float(hFile, "TGamma", prm->tgamma); - // ----------------------------------------------------------------- - oapiWriteItem_float(hFile, "OutScatter", prm->rout); - oapiWriteItem_float(hFile, "InScatter", prm->rin); - oapiWriteItem_float(hFile, "RayleighPhase", prm->rphase); - // ----------------------------------------------------------------- - oapiWriteItem_float(hFile, "MiePower", prm->mie); - oapiWriteItem_float(hFile, "MiePhase", prm->mphase); - // ----------------------------------------------------------------- - oapiWriteItem_float(hFile, "Aux1", prm->aux1); - oapiWriteItem_float(hFile, "Aux2", prm->aux2); - oapiWriteItem_float(hFile, "Aux3", prm->aux3); - // ----------------------------------------------------------------- - oapiWriteItem_float(hFile, "AGamma", prm->agamma); - oapiWriteItem_float(hFile, "HazeClr", prm->hazec); - oapiWriteItem_float(hFile, "HazeIts", prm->hazei); - - oapiCloseFile(hFile, FILE_OUT); - - DumpDebugFile(); -} - - // =========================================================================================== // static void vPlanet::ParseMicroTexturesFile() @@ -1563,7 +1316,6 @@ void vPlanet::ParseMicroTexturesFile() } } fs.close(); - bMicroTexFileRead = true; } // =========================================================================================== @@ -1573,17 +1325,13 @@ bool vPlanet::ParseMicroTextures() if (Config->MicroMode==0) return false; // Micro textures are disabled if (surfmgr2==NULL) return false; // Only supported with tile format 2 - // Parse file (only once!) - if (!bMicroTexFileRead) { - ParseMicroTexturesFile(); - } - // Find 'our' config MicroCfgsIterator it = MicroCfgs.find(GetName()); if (it != MicroCfgs.end()) { MicroCfg = it->second; - //MicroCfgs.erase(it); Keep the table allocated for Orbiter restarts from launchpad - return true; + int cnt = 0; // Check that all three textures exists + for (auto& x : MicroCfg.Level) if (x.pTex) cnt++; + return (cnt == 3); } return false; } @@ -1591,7 +1339,7 @@ bool vPlanet::ParseMicroTextures() // =========================================================================================== // -vPlanet::sOverlay * vPlanet::IntersectOverlay(VECTOR4 q, D3DXVECTOR4 *texcoord) const +vPlanet::sOverlay * vPlanet::IntersectOverlay(VECTOR4 q, FVECTOR4 *texcoord) const { for (auto olay : overlays) { @@ -1662,37 +1410,38 @@ void vPlanet::SetMicroTexture(LPDIRECT3DTEXTURE9 pSrc, int slot) } // =========================================================================================== -// -bool vPlanet::LoadMicroTextures() +// static +void vPlanet::LoadMicroTextures(LPDIRECT3DDEVICE9 pDev) { - LogOapi("Loading Micro Textures for %s", GetName()); - char file[256]; - for (int i=0; iGetLevelDesc(0, &desc); - MicroCfg.Level[i].size = double(desc.Width) / MicroCfg.Level[i].reso; - MicroCfg.Level[i].px = double(desc.Width); - DWORD mips = MicroCfg.Level[i].pTex->GetLevelCount(); - LogOapi("Level %u, %s, %.1fpx/m, %.1fm, Mipmap count=%u", i, MicroCfg.Level[i].file, MicroCfg.Level[i].reso, MicroCfg.Level[i].size, mips); + if (Config->MicroMode == 0) return; + + for (auto &body : MicroCfgs) + { + for (auto &x : body.second.Level) + { + char file_path[MAX_PATH]; + sprintf_s(file_path, MAX_PATH, "Textures/%s", x.file); + + // If texture is not loaded, load it + if (MicroTextures.find(x.file) == MicroTextures.end()) { + if (D3DXCreateTextureFromFileA(pDev, file_path, &x.pTex) == S_OK) { + LogAlw("Microtexture [%s] loaded", x.file); + MicroTextures[x.file] = x.pTex; + } + else { + LogErr("Failed to read microtexture [%s] for [%s]", file_path, body.first.c_str()); + MicroTextures[x.file] = NULL; + } + } + + x.pTex = MicroTextures[x.file]; + + if (x.pTex) { + D3DSURFACE_DESC desc; + x.pTex->GetLevelDesc(0, &desc); + x.px = double(desc.Width); + x.size = double(desc.Width) / x.reso; } } } - MicroCfg.bLoaded = true; - for (int i=0; i class D3D9Mesh; @@ -19,6 +21,167 @@ class CloudTile; bool FilterElevationPhysics(OBJHANDLE hPlanet, int lvl, int ilat, int ilng, double elev_res, INT16* elev); + +#define SUN_COLOR 0 +#define RAY_COLOR 1 +#define MIE_COLOR 2 +#define RAY_LAND 3 +#define MIE_LAND 4 +#define ATN_LAND 5 +#define SUN_GLARE 6 +#define SKY_AMBIENT 7 + +#define PLT_CONFIG -1 +#define PLT_EARTH 0 +#define PLT_MARS 1 +#define PLT_MOON 2 +#define PLT_CLOUDS 3 +#define PLT_GIANT 4 +#define PLT_G_CLOUDS 5 + +class PlanetShader : public ShaderClass +{ +public: + PlanetShader(LPDIRECT3DDEVICE9 pDev, const char* file, const char* vs, const char* ps, const char* name, const char* options); + ~PlanetShader(); + + bool bLocals; + bool bMicrotex; + bool bShdMap; + bool bDevtools; + bool bAtmosphere; + bool bWater; + bool bRipples; + bool bCloudShd; + bool bNightlights; + + HANDLE tCloud; + HANDLE tCloud2; + HANDLE tMask; + HANDLE tDiff; + HANDLE tShadowMap; + HANDLE PrmVS; + HANDLE Prm; + HANDLE FlowVS; + HANDLE Flow; + HANDLE Lights; + HANDLE Spotlight; +}; + + +#pragma pack(push, 4) + +// Bools for Scatter.hlsl +struct sFlow { + BOOL bRay; + BOOL bCamLit; + BOOL bCamInSpace; +}; + +struct ShaderParams +{ + float4x4 mWorld; // World Matrix + float4x4 mLVP; // Light-View-Projection + float4 vSHD; // Shadow Map Parameters + float4 vMSc[3]; // Micro Texture offset-scale + float4 vTexOff; // Texture offset-scale + float4 vCloudOff; // Cloud texture offset-scale + float4 vMicroOff; // Micro texture offset-scale + float4 vOverlayOff; // Overlay texture offset-scale + float4 vOverlayCtrl[4]; + float fAlpha; + float fBeta; + float fTgtScale; +}; + +// Bools for NewPlanet.hlsl +struct FlowControlPS +{ + BOOL bInSpace; // Camera in space (not in atmosphere) + BOOL bBelowClouds; // Camera is below cloud layer + BOOL bOverlay; // Overlay on/off + BOOL bShadows; // Shadow Map on/off + BOOL bLocals; // Local Lights on/off + BOOL bMicroNormals; // Micro texture has normals + BOOL bCloudShd; // Cloud shadow textures valid and enabled + BOOL bMask; // Nightlights/water mask texture is peovided + BOOL bRipples; // Water riples texture is peovided + BOOL bMicroTex; // Micro textures exists and enabled + BOOL bPlanetShadow; // Use spherical approximation for shadow +}; + +struct FlowControlVS +{ + BOOL bInSpace; // Camera in space (not in atmosphere) + BOOL bSpherical; // Ignore elevation, render as sphere + BOOL bElevOvrl; // ElevOverlay on/off +}; + + + +struct ConstParams +{ + float4x4 mVP; // View Projection Matrix + float3 CamPos; // Geocentric Camera position + float3 toCam; // Geocentric Camera direction (unit vector) + float3 toSun; // Geocentric Sun direction (unit vector) + float3 SunAz; // Atmo scatter ref.frame (unit vector) (toCam, ZeroAz, SunAz) + float3 ZeroAz; // Atmo scatter ref.frame (unit vector) + float3 Up; // Sun/Shadow Ref Frame (Unit Vector) (Up, toSun, ZeroAz) + float3 vTangent; // Reference frame for normal mapping (Unit Vector) + float3 vBiTangent; // Reference frame for normal mapping (Unit Vector) + float3 vPolarAxis; // North Pole (unit vector) + float3 cSun; // Sun Color and intensity + float3 RayWave; // .rgb Rayleigh Wave lenghts + float3 MieWave; // .rgb Mie Wave lenghts + float4 HG; // Henyey-Greenstein Phase function params + float2 iH; // Inverse scale height for ray(.r) and mie(.g) e.g. exp(-altitude * iH) + float2 rmO; // Ray and Mie out-scatter factors + float2 rmI; // Ray and Mie in-scatter factors + float3 cAmbient; // Ambient light color at sealevel + float3 cGlare; // Sun glare color + float PlanetRad; // Planet Radius + float PlanetRad2; // Planet Radius Squared + float AtmoAlt; // Atmospehere upper altitude limit + float AtmoRad; // Atmospehere outer radius + float AtmoRad2; // Atmospehere outer radius squared + float CloudAlt; // Cloud layer altitude for color and light calculations (not for phisical rendering) + float MinAlt; // Minimum terrain altitude + float MaxAlt; // Maximum terrain altitude + float iAltRng; // 1.0 / (MaxAlt - MinAlt); + float AngMin; + float AngRng; + float iAngRng; + float AngCtr; // Cos of View cone angle from planet center that's visible from camera location + float HrzDst; // Distance to horizon (500 m) minimum if camera below sea level + float CamAlt; // Camera Altitude + float CamElev; // Camera Elevation above surface + float CamRad; // Camera geo-distance + float CamRad2; // Camera geo-distance squared + float Expo; // "HDR" exposure factor (atmosphere only) + float Time; // Simulation time / 180 + float TrGamma; // Terrain "Gamma" correction setting + float TrExpo; // "HDR" exposure factor (terrain only) + float Ambient; // Global ambient light level + float Clouds; // Cloud layer intensity (if below), and Blue light inscatter scale factor (if camera Above clouds) + float TW_Terrain; // Twilight intensity + float TW_Dst; // Twilight distance behind terminator + float CosAlpha; // Cosine of camera horizon angle i.e. PlanetRad/CamRad + float SinAlpha; // Sine of ^^ + float CamSpace; // Camera in space scale factor 0.0 = surf, 1.0 = space + float Cr2; // Camera radius on shadow plane (dot(cp.toCam, cp.Up) * cp.CamRad)^2 + float ShdDst; + float SunVis; + float dCS; + float smi; + float ecc; + float trLS; +}; + +#pragma pack(pop) + + + // ============================================================== // class vPlanet (interface) // ============================================================== @@ -56,8 +219,14 @@ class vPlanet: public vObject { bool ParseConfig(const char *fname); virtual bool GetMinMaxDistance(float *zmin, float *zmax, float *dmin); virtual void UpdateBoundingBox(); + virtual void ReOrigin(VECTOR3 global_pos); + + static void GlobalInit(oapi::D3D9Client* gc); + static void GlobalInitAtmosphere(oapi::D3D9Client* gc); static void GlobalExit(); + void TestComputations(Sketchpad *); + bool IsMesh() { return mesh != NULL; } bool Update (bool bMainScene); void CheckResolution (); @@ -68,11 +237,12 @@ class vPlanet: public vObject { bool CameraInAtmosphere() const; double CameraAltitude() const { return cdist - size; } double GetHorizonAlt() const; - double GetMinElevation() const; - double GetMaxElevation() const; + double GetMinElevation() const { return minelev; }; + double GetMaxElevation() const { return maxelev; }; VECTOR3 GetUnitSurfacePos(double lng, double lat) const; VECTOR3 GetRotationAxis() const { return axis; } VECTOR3 ToLocal(VECTOR3 &glob) const; + VECTOR3 CameraPos() const; void GetLngLat(VECTOR3 &loc, double *lng, double *lat) const; VECTOR3 ReferencePoint(); void SetMicroTexture(LPDIRECT3DTEXTURE9 pSrc, int slot); @@ -81,23 +251,53 @@ class vPlanet: public vObject { void PickSurface(D3DXVECTOR3 &vRay, TILEPICK *pPick); DWORD GetPhysicsPatchRes() const { return physics_patchres; } sOverlay * AddOverlaySurface(VECTOR4 lnglat, gcCore::OlayType type, LPDIRECT3DTEXTURE9 pSrf = NULL, sOverlay *pOld = NULL, const FVECTOR4* pB = NULL); - sOverlay * IntersectOverlay(VECTOR4 bounds, D3DXVECTOR4 *texcoord) const; + sOverlay * IntersectOverlay(VECTOR4 bounds, FVECTOR4* texcoord) const; + // Surface base interface ------------------------------------------------- DWORD GetBaseCount() const { return nbase; } vBase* GetBaseByIndex(DWORD index) const { return vbase[index]; } vBase* GetBaseByHandle(OBJHANDLE hBase) const; - // Atmospheric ------------------------------------------------------------ + + // Atmospheric physics --------------------------------------------------- ScatterParams * GetAtmoParams(int mode=-1); - double AngleCoEff(double cos_dir); - D3DXVECTOR3 GetSunLightColor(VECTOR3 vPos, float fAmbient, float fGlobalAmb); - bool LoadAtmoConfig(bool bOrbit); - void SaveAtmoConfig(bool bOrbit); - void UpdateAtmoConfig(); - void DumpDebugFile(); - bool HasAtmosphere() const { return bScatter; } + bool LoadAtmoConfig(); + void SaveAtmoConfig(); + void SaveStruct(FILEHANDLE hFile, ScatterParams* prm, int bO); + void LoadStruct(FILEHANDLE hFile, ScatterParams* prm, int bO); + char* Label(const char* x); + bool HasAtmosphere() const { return prm.bAtm; } bool HasRipples() const { return bRipple; } + LPDIRECT3DTEXTURE9 GetScatterTable(int i); + ConstParams* GetScatterConst(); + PlanetShader* GetShader(int id = PLT_CONFIG); + int GetShaderID(); + ShaderParams* GetTerrainParams() { return &sp; } + FlowControlPS* GetFlowControl() { return &fcp; } + FlowControlVS* GetFlowControlVS() { return &fcv; } + void UpdateScatter(); + int GetAtmoMode() { return atm_mode; } + FVECTOR4 SunLightColor(VECTOR3 pos, double rf = 1.0); // For a point in anywhere + FVECTOR3 SunLightColor(float ang, float alt); // For a point in atmosphere + float SunAltitude(); + FVECTOR4 ComputeCameraView(FVECTOR3 vPos); + FVECTOR4 ComputeCameraView(float a, float r, float d); + FVECTOR4 ComputeCameraView(FVECTOR3 vPos, FVECTOR3 vNrm, FVECTOR3 vRay, float r, float t_factor = 1.0f); + FVECTOR2 Gauss7(float cos_dir, float r0, float dist, FVECTOR2 ih0); + FVECTOR2 Gauss7(float alt, float cos_dir, float R0, float R1, FVECTOR2 iH0); + FVECTOR2 Gauss4(float cos_dir, float r0, float dist, FVECTOR2 ih0); + FVECTOR4 AmbientApprox(FVECTOR3 vNrm, bool bRayleigh); + void IntegrateSegment(FVECTOR3 vOrig, FVECTOR3 vRay, float len, FVECTOR4* rl = NULL, FVECTOR4* mie = NULL, FVECTOR4* tot = NULL); + float RayLength(float cos_dir, float r0, float r1); + float RayLength(float cos_dir, float r0); + float RayPhase(float cw); + float MiePhase(float cw); + D3D9Sun GetObjectAtmoParams(VECTOR3 relpos); + FVECTOR3 HDR(FVECTOR3 i); + FVECTOR3 LightFX(FVECTOR3 x); + float SunOcclusionByPlanet(); + bool SphericalShadow(); // v2 Labels interface ---------------------------------------------------- void ActivateLabels(bool activate); @@ -119,8 +319,7 @@ class vPlanet: public vObject { double horizon_excess; ///< extend horizon visibility radius double tilebb_excess; ///< extend tile visibility bounding box double horizon_minrad; ///< scale factor for lower edge of rendered horizon (account for negative elevations) (unit sphere radius) - double horizon_minelev; ///< scale factor for lower edge of rendered horizon (account for negative elevations) (elevation [m] e.g -7000 for Mars) - + // frame-by-frame options bool bAddBkg; ///< render additive to sky background (i.e. planet seen through atm.layer of another planet) int cloudvis; ///< cloud visibility: bit0=from below, bit1=from above @@ -137,9 +336,6 @@ class vPlanet: public vObject { D3DXVECTOR3 SunDir; float FogDensity; float DistScale; - float SclHeight; ///< Atmospheric scale height - float InvSclHeight; ///< Inverse of atmospheric scale height - double ScatterCoEff[8]; } prm; list overlays; @@ -148,6 +344,8 @@ class vPlanet: public vObject { TileManager2 *SurfMgr2() const { return surfmgr2; } TileManager2 *CloudMgr2() const { return cloudmgr2; } + static void ParseMicroTexturesFile(); ///< Parse MicroTex.cfg file (once) + protected: void RenderSphere (LPDIRECT3DDEVICE9 dev); void RenderCloudLayer (LPDIRECT3DDEVICE9 dev, DWORD cullmode); @@ -158,14 +356,27 @@ class vPlanet: public vObject { bool ModLighting (DWORD &ambient); bool ParseMicroTextures(); ///< Read micro-texture config for this planet - bool LoadMicroTextures(); - static void ParseMicroTexturesFile(); ///< Parse MicroTex.cfg file (once) + static void LoadMicroTextures(LPDIRECT3DDEVICE9 pDev); private: + + LPDIRECT3DTEXTURE9 pSunColor, pRaySkyView, pMieSkyView, pLandViewRay, pLandViewMie, pAmbientSky, pLandViewAtn; + + ConstParams cp; + ShaderParams sp; + FlowControlPS fcp; + FlowControlVS fcv; + + static ImageProcessing* pIP; + static PlanetShader* pRender[8]; + static LPDIRECT3DDEVICE9 pDev; + static int Qc, Wc, Nc; + float dist_scale; // planet rescaling factor double maxdist, // ??? max_centre_dist; + double minelev, maxelev; double threshold; float shadowalpha; // alpha value for surface shadows double cloudrad; // cloud layer radius [m] @@ -173,9 +384,10 @@ class vPlanet: public vObject { DWORD physics_patchres; // max surface LOD level used by physics int patchres; // surface LOD level int tilever; // Surface tile version + int iConfig; + int atm_mode; bool renderpix; // render planet as pixel block (at large distance) bool hashaze; // render atmospheric haze - bool bScatter; // Planet has scattering parameters DWORD nbase; // number of surface bases vBase **vbase; // list of base visuals SurfaceManager *surfmgr; // planet surface tile manager @@ -194,8 +406,9 @@ class vPlanet: public vObject { VECTOR3 vRefPoint; // Auxiliary reference point for normal mapped water ScatterParams SPrm; // Parameters for atmospheric configuration dialog ScatterParams OPrm; // Parameters for atmospheric configuration dialog - ScatterParams NPrm; // Parameters for atmospheric configuration dialog + ScatterParams HPrm; // Parameters for atmospheric configuration dialog ScatterParams CPrm; // Parameters for atmospheric configuration dialog + DWORD dwSctFrame; struct CloudData { // cloud render parameters (for legacy interface) CloudManager *cloudmgr; // cloud tile manager @@ -210,21 +423,42 @@ class vPlanet: public vObject { microalt1; } *clouddata; + char ShaderName[32]; + char AtmoConfigName[32]; +public: + struct _MicroTC { char file[32]; // Texture file name double reso; // Resolution px/m double size; // Texture size in meters; - double px; // pixel count + double px; // Size in pixels LPDIRECT3DTEXTURE9 pTex; }; -public: struct _MicroCfg { _MicroTC Level[3]; bool bNormals; // Normals enabled - bool bEnabled; // Micro textures enables - bool bLoaded; // Micro textures loaded + bool bEnabled; // Micro textures enabled } MicroCfg; + + struct SHDPrm { + float se; // Shadow entry + float sx; // Shadow exit + float ae; // Atmosphere entry + float ax; // Atmosphere exit + float cr; // Camera Radius in shadow frame + float hd; // Horizon distance + float h2; // Closest approach sqr-dist + float w2; + float ca; + }; + + struct TestPrm { + FVECTOR3 toCam, toSun, ZeroAz, Up, SunAz, CamPos; + float CosAlpha, SinAlpha, CamRad, CamRad2; + } TestPrm; + + SHDPrm ComputeShadow(FVECTOR3 vRay); }; #endif // !__VPLANET_H diff --git a/OVP/D3D9Client/VPlanetAtmo.cpp b/OVP/D3D9Client/VPlanetAtmo.cpp new file mode 100644 index 000000000..85a604b10 --- /dev/null +++ b/OVP/D3D9Client/VPlanetAtmo.cpp @@ -0,0 +1,1410 @@ +// ============================================================== +// VPlanet.cpp +// Part of the ORBITER VISUALISATION PROJECT (OVP) +// Dual licensed under LGPL v3 +// Copyright (C) 2006-2022 Martin Schweiger +// 2010-2022 Jarmo Nikkanen +// ============================================================== + +#define D3D_OVERLOADS + +#include +#include +#include + +#include "D3D9Client.h" +#include "D3D9Config.h" +#include "VPlanet.h" +#include "AtmoControls.h" +#include "VectorHelpers.h" +#include "IProcess.h" + +using namespace oapi; + +const float invalid_val = -1e12; + +// =========================================================================================== +// + +PlanetShader::PlanetShader(LPDIRECT3DDEVICE9 pDev, const char* file, const char* vs, const char* ps, const char* name, const char* options) + : ShaderClass(pDev, file, vs, ps, name, options) +{ + bLocals = false; + bMicrotex = false; + bShdMap = false; + bDevtools = false; + bAtmosphere = true; + bWater = false; + bRipples = false; + bCloudShd = false; + bNightlights = false; + + if (string(options).find("_LOCALLIGHTS") != string::npos) bLocals = true; + if (string(options).find("_MICROTEX") != string::npos) bMicrotex = true; + if (string(options).find("_SHDMAP") != string::npos) bShdMap = true; + if (string(options).find("_DEVTOOLS") != string::npos) bDevtools = true; + if (string(options).find("_NO_ATMOSPHERE") != string::npos) bAtmosphere = false; + if (string(options).find("_WATER") != string::npos) bWater = true; + if (string(options).find("_RIPPLES") != string::npos) bRipples = true; + if (string(options).find("_CLOUDSHD") != string::npos) bCloudShd = true; + if (string(options).find("_NIGHTLIGHTS") != string::npos) bNightlights = true; + + tCloud = GetPSHandle("tCloud"); + tCloud2 = GetPSHandle("tCloud2"); + tMask = GetPSHandle("tMask"); + tDiff = GetPSHandle("tDiff"); + tShadowMap = GetPSHandle("tShadowMap"); + PrmVS = GetVSHandle("Prm"); + Prm = GetPSHandle("Prm"); + FlowVS = GetVSHandle("FlowVS"); + Flow = GetPSHandle("Flow"); + Lights = GetPSHandle("Lights"); + Spotlight = GetPSHandle("Spotlight"); +}; + +PlanetShader::~PlanetShader() +{ + +} + + + + + + +PlanetShader* vPlanet::pRender[8] = {}; + + +// =========================================================================================== +// +void vPlanet::GlobalInitAtmosphere(oapi::D3D9Client* gc) +{ + pDev = gc->GetDevice(); + + if (Config->bAtmoQuality) pIP = new ImageProcessing(pDev, "Modules/D3D9Client/Scatter.hlsl", "SunColor"); + else pIP = new ImageProcessing(pDev, "Modules/D3D9Client/Scatter.hlsl", "SunColor", "_PERFORMANCE"); + + pIP->CompileShader("SkyView"); + pIP->CompileShader("LandView"); + pIP->CompileShader("RingView"); + pIP->CompileShader("AmbientSky"); + pIP->CompileShader("LandViewAtten"); + + if (!pIP->IsOK()) { + oapiWriteLog("InitializeScatteringEx() FAILED"); + return; + } + + // Get Texture size constants form shader file + // + //Wc = pIP->FindDefine("Wc"); + //Nc = pIP->FindDefine("Nc"); + //Qc = pIP->FindDefine("Qc"); + + if (Config->bAtmoQuality) { + Nc = 8; Wc = 128; Qc = 96; + } + else { + Nc = 6; Wc = 72; Qc = 64; + } + + bool bRiples = *(bool*)gc->GetConfigParam(CFGPRM_SURFACERIPPLE); + bool bShadows = *(bool*)gc->GetConfigParam(CFGPRM_CLOUDSHADOWS); + bool bClouds = *(bool*)gc->GetConfigParam(CFGPRM_CLOUDS); + bool bNightLights = *(bool*)gc->GetConfigParam(CFGPRM_SURFACELIGHTS); + bool bWater = *(bool*)gc->GetConfigParam(CFGPRM_SURFACEREFLECT); + bool bLocals = *(bool*)gc->GetConfigParam(CFGPRM_LOCALLIGHT); + bool bAtmosphere = *(bool*)gc->GetConfigParam(CFGPRM_ATMHAZE); + + // --------------------------------------------------- + // Compile planet shader with different configurations + // --------------------------------------------------- + + string blend = ""; + string flags = ""; + if (!Config->bAtmoQuality) flags += "_PERFORMANCE "; + + pRender[PLT_GIANT] = new PlanetShader(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "GiantVS", "GiantPS", "Giant", flags.c_str()); + pRender[PLT_G_CLOUDS] = new PlanetShader(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "CloudVS", "GiantCloudPS", "GiantCloud", flags.c_str()); + + if (Config->CloudMicro) flags += "_CLOUDMICRO "; + if (Config->bCloudNormals) flags += "_CLOUDNORMALS "; + + pRender[PLT_CLOUDS] = new PlanetShader(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "CloudVS", "CloudPS", "Clouds", flags.c_str()); + + + + flags = ""; + if (Config->BlendMode == 0) blend = "_SOFT "; + if (Config->BlendMode == 1) blend = "_MED "; + if (Config->BlendMode == 2) blend = "_HARD "; + + if (bLocals) flags += "_LOCALLIGHTS "; + if (Config->MicroMode) flags += "_MICROTEX "; + if (Config->ShadowMapMode) flags += "_SHDMAP "; + if (Config->EnableMeshDbg) flags += "_DEVTOOLS "; + if (!Config->bAtmoQuality) flags += "_PERFORMANCE "; + + pRender[PLT_MARS] = new PlanetShader(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "TerrainVS", "TerrainPS", "Mars", (flags + blend).c_str()); + + + flags += "_NO_ATMOSPHERE "; + + pRender[PLT_MOON] = new PlanetShader(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "TerrainVS", "TerrainPS", "Moon", (flags + blend).c_str()); + + + flags = ""; + blend = ""; + if (bWater) flags += "_WATER "; + if (bWater && bRiples) flags += "_RIPPLES "; + if (bShadows) flags += "_CLOUDSHD "; + if (bNightLights) flags += "_NIGHTLIGHTS "; + if (bLocals) flags += "_LOCALLIGHTS "; + + if (Config->ShadowMapMode) flags += "_SHDMAP "; + if (Config->EnableMeshDbg) flags += "_DEVTOOLS "; + if (!Config->bAtmoQuality) flags += "_PERFORMANCE "; + + pRender[PLT_EARTH] = new PlanetShader(pDev, "Modules/D3D9Client/NewPlanet.hlsl", "TerrainVS", "TerrainPS", "Earth", (flags + blend).c_str()); +} + + +// =========================================================================================== +// +FVECTOR2 vPlanet::Gauss7(float alt, float cos_dir, float R0, float R1, FVECTOR2 iH0) +{ + float dist = RayLength(cos_dir, R0 + alt, R1); + return Gauss7(cos_dir, R0 + alt, dist, iH0); +} + + +// =========================================================================================== +// +FVECTOR2 vPlanet::Gauss7(float cos_dir, float r0, float dist, FVECTOR2 ih0) +{ + static const float n[] = { -0.949107, -0.741531, -0.405845, 0.0, 0.405845,0.741531, 0.949107 }; + static const float w[] = { 0.129485, 0.279705, 0.381830, 0.417959, 0.381830, 0.279705, 0.129485 }; + + float x = 2.0 * r0 * cos_dir; + float r2 = r0 * r0; + float a[7]; + + // Compute altitudes of sample points + for (int i = 0; i < 7; i++) { + float d0 = dist * (n[i] + 1.0f) * 0.5f; + a[i] = sqrt(r2 + d0 * d0 - d0 * x) - cp.PlanetRad; + } + + float ray = 0.0f; float mie = 0.0f; + for (int i = 0; i < 7; i++) { + ray += exp(-clamp(a[i] * ih0.x, -20.0f, 20.0f)) * w[i]; + mie += exp(-clamp(a[i] * ih0.y, -20.0f, 20.0f)) * w[i]; + } + return FVECTOR2(ray, mie) * 0.5f * dist; +} + + +// =========================================================================================== +// +FVECTOR2 vPlanet::Gauss4(float cos_dir, float r0, float dist, FVECTOR2 ih0) +{ + static const float n[] = { 0.06943f, 0.33001f, 0.66999f, 0.93057f }; + static const float w[] = { 0.34786f, 0.65215f, 0.65215f, 0.34786f }; + + float x = 2.0 * r0 * cos_dir; + float r2 = r0 * r0; + float a[4]; + + // Compute altitudes of sample points + for (int i = 0; i < 4; i++) { + float d0 = dist * n[i]; + a[i] = sqrt(r2 + d0 * d0 - d0 * x) - cp.PlanetRad; + } + + float ray = 0.0f; float mie = 0.0f; + for (int i = 0; i < 4; i++) { + ray += exp(-clamp(a[i] * ih0.x, -20.0f, 20.0f)) * w[i]; + mie += exp(-clamp(a[i] * ih0.y, -20.0f, 20.0f)) * w[i]; + } + return FVECTOR2(ray, mie) * 0.5f * dist; +} + + +// =========================================================================================== +// +float vPlanet::SunAltitude() +{ + float d = dot(cp.toCam, cp.toSun); + float q = cp.CamRad * d; + + // Ray's closest approach to planet + float alt = sqrt(cp.CamRad2 - q * q) - cp.PlanetRad; + if (d < 0) return alt; + return cp.AtmoAlt; +} + + +// =========================================================================================== +// +float vPlanet::RayLength(float cos_dir, float r0, float r1) +{ + float y = r0 * cos_dir; + float z2 = r0 * r0 - y * y; + return sqrt(r1 * r1 - z2) + y; +} + + +// =========================================================================================== +// +float vPlanet::RayLength(float cos_dir, float r0) +{ + return RayLength(cos_dir, r0, cp.AtmoRad); +} + + +// =========================================================================================== +// Rayleigh phase function +// +float vPlanet::RayPhase(float cw) +{ + return 0.25f * (4.0f + cw * cw); +} + + +// =========================================================================================== +// Henyey-Greenstein Phase function +// +/*float vPlanet::MiePhase(float cw) +{ + float cw2 = cw * cw; + return cp.HG.x * (1.0f + cw2) * pow(abs(cp.HG.y - cp.HG.z * cw2 * cw), -1.5f) + cp.HG.w; +}*/ + +float vPlanet::MiePhase(float cw) +{ + return 8.0f * cp.HG.x / (1.0f - cp.HG.y * cw) + cp.HG.w; +} + + +// =========================================================================================== +// Compute optical transparency of atmosphere. color in .rgb and (ray+mie) optical depth in .a +// +FVECTOR4 vPlanet::ComputeCameraView(float angle, float rad, float distance) +{ + FVECTOR2 od = Gauss7(angle, rad, distance, cp.iH); // Ray/Mie Optical depth + FVECTOR2 rm = od * cp.rmO; + FVECTOR3 clr = cp.RayWave * rm.x + cp.MieWave * rm.y; + return FVECTOR4(exp(-clr), od.x + od.y); +} + + +// =========================================================================================== +// +FVECTOR4 vPlanet::ComputeCameraView(FVECTOR3 vPos, FVECTOR3 vNrm, FVECTOR3 vRay, float r, float t_factor) +{ + float d = 0.0f; + float a = dot(vNrm, vRay); + if (!CameraInAtmosphere()) d = RayLength(a, r); + else d = abs(dot(vPos - cp.CamPos, vRay)); + return ComputeCameraView(a, r, d); +} + + +// =========================================================================================== +// +FVECTOR4 vPlanet::ComputeCameraView(FVECTOR3 vPos) +{ + FVECTOR3 vRP = vPos - cp.CamPos; + float d = length(vRP); + float r = length(vPos); + FVECTOR3 vRay = vRP / d; + float a = dot(vPos / r, vRay); + if (!CameraInAtmosphere()) d = RayLength(a, r); // Recompute distance to atm exit + return ComputeCameraView(a, r, d); +} + + +// =========================================================================================== +// Amount of light inscattering along the ray +// +void vPlanet::IntegrateSegment(FVECTOR3 vOrig, FVECTOR3 vRay, float len, FVECTOR4* ral, FVECTOR4* mie, FVECTOR4* tot) +{ + static const int NSEG = 6; + static const float iNSEG = 1.0f / float(NSEG); + + if (ral) *ral = 0.0f; + if (mie) *mie = 0.0f; + + for (int i = 0; i < NSEG; i++) + { + float dst = len * (iNSEG * (float(i) + 0.5f)); + FVECTOR3 pos = vOrig + vRay * dst; + FVECTOR3 n = normalize(pos); + float rad = dot(n, pos); + float alt = rad - cp.PlanetRad; + float ang = dot(n, vRay); + + FVECTOR3 x = SunLightColor(-dot(n, cp.toSun), alt) * ComputeCameraView(-ang, rad, len - dst).rgb; + + if (ral) { + float f = exp(-alt * cp.iH.x) * iNSEG; + ral->rgb += x * f; ral->a += f; + } + if (mie) { + float f = exp(-alt * cp.iH.y) * iNSEG; + mie->rgb += x * f; mie->a += f; + } + } + + + if (ral) ral->rgb *= cp.RayWave * cp.cSun * cp.rmI.x * len; // Multiply with wavelength and inscatter factors + if (mie) mie->rgb *= cp.MieWave * cp.cSun * cp.rmI.y * len; + if (ral) ral->a *= len; + if (mie) mie->a *= len; + if (tot && ral && mie) { + float dRS = dot(vRay, cp.toSun); + tot->rgb = HDR(ral->rgb * RayPhase(dRS) + mie->rgb * MiePhase(dRS)); + } +} + +// =========================================================================================== +// +FVECTOR3 vPlanet::HDR(FVECTOR3 i) +{ + return -exp(-i * cp.Expo) + 1.0f; +} + +// =========================================================================================== +// +FVECTOR3 vPlanet::LightFX(FVECTOR3 x) +{ + return (x * 2.0f) / (x + 1.0f); +} + +// =========================================================================================== +// Sunlight color for pixel in atmosphere +// +FVECTOR3 vPlanet::SunLightColor(float angle, float alt) +{ + float r = alt + cp.PlanetRad; + float d = RayLength(angle, r); + FVECTOR2 rm = Gauss7(angle, r, d, cp.iH) * cp.rmO; + FVECTOR3 clr = cp.RayWave * rm.x + cp.MieWave * rm.y; + return exp(-clr); +} + +// =========================================================================================== +// +float vPlanet::SunOcclusionByPlanet() +{ + OBJHANDLE hSun = oapiGetObjectByIndex(0); + VECTOR3 up = unit(-cpos); + double r = dot(up, -cpos); + double ca = dot(up, SunDirection()); + double om = saturate(1.0 - ca * ca); + double qr = sqrt(om) * r; + double sd = SunDistance(); + double dp = r * r - size * size; + double hd = dp > 1e4 ? sqrt(dp) : 1000.0; // Distance to horizon + double sr = oapiGetSize(hSun) * abs(hd) / sd; + double svb = ca > 0.0 ? 1.0 : ilerp(size - sr * 0.33, size + sr, qr); // How much of the sun's "disc" is shadowed by planet + return svb; +} + + +// =========================================================================================== +// +FVECTOR4 vPlanet::SunLightColor(VECTOR3 relpos, double rf) +{ + static const float lim = 0.0f; + + if (!active) { + Update(true); + UpdateScatter(); + } + + FVECTOR2 rm = 0.0f; + VECTOR3 up = unit(relpos); + double r = dot(up, relpos); + double ca = dot(up, SunDirection()); + double om = saturate(1.0 - ca * ca); + double qr = sqrt(om) * r; + double ar = GetHorizonAlt() + size; + + bool bAtm = HasAtmosphere() && (surfmgr2 != NULL); + + if (!bAtm) { + if (ca > lim) return FVECTOR4(1, 1, 1, 1); // Ray doesn't intersect planet + } + else { + if (qr > ar) return FVECTOR4(1, 1, 1, 1); // Ray doesn't intersect atmosphere + if (r > ar && ca > lim) return FVECTOR4(1, 1, 1, 1); // Ray doesn't intersect atmosphere + } + + OBJHANDLE hSun = oapiGetObjectByIndex(0); + double sd = SunDistance(); + double dp = r * r - size * size; + double hd = dp > 1e4 ? sqrt(dp) : 1000.0; // Distance to horizon + double sr = oapiGetSize(hSun) * abs(hd) / sd; + double svb = ca > lim ? 1.0 : ilerp(size - sr * 0.33, size + sr, qr); // How much of the sun's "disc" is shadowed by planet + + if (!bAtm || !surfmgr2) return FVECTOR4(svb, svb, svb, svb); + + if (svb < 1e-3) return FVECTOR4(0.0, 0.0, 0.0, svb); // Ray is obscured by planet + if (r > ar) rm = Gauss7(qr - size, 0.0f, cp.PlanetRad, cp.AtmoRad, cp.iH) * 2.0f; // Ray passes through atmosphere from space to space + else rm = Gauss7(r - size, -ca, cp.PlanetRad, cp.AtmoRad, cp.iH); // Sample point 'pos' lies with-in atmosphere + + rm *= cp.rmO * rf; + return FVECTOR4(exp(-(cp.RayWave * rm.x + cp.MieWave * rm.y)) * svb, svb); +} + + +// =========================================================================================== +// +FVECTOR4 vPlanet::AmbientApprox(FVECTOR3 vNrm, bool bR) +{ + float dNS = -dot(vNrm, cp.toSun); + float fA = 1.0f - hermite(ilerp(0.0f, cp.TW_Dst, dNS)); + float3 clr = (bR ? cp.RayWave : cp.cAmbient); + return float4(clr, fA); +} + + +// =========================================================================================== +// +D3D9Sun vPlanet::GetObjectAtmoParams(VECTOR3 vRelPos) +{ + if (!active) { + Update(true); + UpdateScatter(); + } + + D3D9Sun op; + op.Transmission = 1.0f; + op.Incatter = 0.0f; + + double r = length(vRelPos); + float a = cp.AtmoAlt * 0.5f; + FVECTOR3 cSun = SunLightColor(vRelPos).rgb * cp.cSun; + DWORD ambient = *(DWORD*)gc->GetConfigParam(CFGPRM_AMBIENTLEVEL); + + if (((r - size) > a) || !HasAtmosphere() || !surfmgr2) // In space + { + op.Dir = -cp.toSun; + op.Color = (cSun.MaxRGB() > 1.0f ? cSun / cSun.MaxRGB() : cSun) * Config->GFXSunIntensity; + op.Ambient = float(ambient) * 0.0039f; + return op; + } + + VECTOR3 vNrm = unit(vRelPos); + VECTOR3 vRP = (vRelPos + cpos); // Camera relative position + double d = length(vRP); // Distance to camera + FVECTOR3 vRay = (vRP / d); // Unit viewing ray from cameta to obj_gpos + float dNR = dot(vNrm, vRay); // cosine of (Normal/vRay) angle + float dRS = dot(vRay, cp.toSun); + float dNS = dot(vNrm, cp.toSun); + float alt = r - size; + + FVECTOR4 mc = AmbientApprox(vNrm, false); + mc.a *= CPrm.tw_bld; + + + FVECTOR3 cSunAmb = SunLightColor(-dNS, alt) * cp.cSun; + cSunAmb = cSunAmb.MaxRGB() > 1.0f ? cSunAmb / cSunAmb.MaxRGB() : cSunAmb; + + op.Dir = -cp.toSun; + op.Color = (cSun.MaxRGB() > 1.0f ? cSun / cSun.MaxRGB() : cSun) * Config->GFXSunIntensity; + op.Ambient = unit(mc.rgb + cSunAmb * 2.0f) * mc.a * mc.g; + op.Ambient *= exp(-alt * cp.iH.x) * cp.rmI.x * 6e5; + op.Ambient += float(ambient) * 0.0039f; + + if (d > 1000.0f) { + FVECTOR4 rl, mi; // Incatter Color + IntegrateSegment(vRelPos, -vRay, d, &rl, &mi); // Rayleigh and Mie inscatter + op.Transmission = ComputeCameraView(dNR, r, d).rgb; + op.Incatter = HDR(rl.rgb * RayPhase(dRS) + mi.rgb * MiePhase(dRS)); + } + + return op; +} + + +// =========================================================================================== +// +bool vPlanet::SphericalShadow() +{ + if (abs(cp.MinAlt) < 1.0f && abs(cp.MaxAlt) < 1.0f) return false; // Spherical body or no data available + if (((cp.MaxAlt - cp.MinAlt) / cp.PlanetRad) < 0.05f) return true; + return false; +} + + +// =========================================================================================== +// +void vPlanet::UpdateScatter() +{ + if (scn->GetFrameId() == dwSctFrame) return; + if (scn->GetRenderPass() != RENDERPASS_MAINSCENE) return; + if (mesh) return; + + dwSctFrame = scn->GetFrameId(); + + if (HasAtmosphere()) + { + if (!pSunColor) D3DXCreateTexture(pDev, 4*Qc, Qc/2, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pSunColor); + if (!pRaySkyView) D3DXCreateTexture(pDev, Qc * 2, Qc, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pRaySkyView); + if (!pMieSkyView) D3DXCreateTexture(pDev, Qc * 2, Qc, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pMieSkyView); + if (!pLandViewRay) D3DXCreateTexture(pDev, Wc * Nc, Wc, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pLandViewRay); + if (!pLandViewMie) D3DXCreateTexture(pDev, Wc * Nc, Wc, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pLandViewMie); + if (!pLandViewAtn) D3DXCreateTexture(pDev, Wc * Nc, Wc, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pLandViewAtn); + if (!pAmbientSky) D3DXCreateTexture(pDev, Qc, Qc, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &pAmbientSky); + } + + VECTOR3 sundir, campos; OBJHANDLE hSun = oapiGetGbodyByIndex(0); + oapiGetGlobalPos(hSun, &sundir); + oapiGetGlobalPos(hObj, &gpos); + oapiCameraGlobalPos(&campos); + + sundir = unit(sundir - gpos); + FVECTOR3 cam = (campos - gpos); + + const ScatterParams* atmo = GetAtmoParams(); + + DWORD dAmbient = *(DWORD*)gc->GetConfigParam(CFGPRM_AMBIENTLEVEL); + float fAmbient = float(dAmbient) * 0.0039f; + + double pr = GetSize() + minelev; // Planet Min Radius + double cr = CamDist(); // Camera distance from a planet center + double ca = cr - pr; // Camera altitude + + float mdh = 6000.0f; // Minumum distance to horizon + float scr = 1.6e-6; + float scm = 1.0e-6; + + float ph = atmo->mphase * 200.0f; + float g = ph / sqrt(1.0f + ph * ph); + float hrz = sqrt(max(0, cr * cr - pr * pr)); + float qw = float(pr / cr); + + LPDIRECT3DSURFACE9 pTgt, pTgt2; + + // --------------------------------------------------------------------- + // Initialize camera centric tangent frame for normal mapped water + // + MATRIX3 mRot; + oapiGetRotationMatrix(hObj, &mRot); + + VECTOR3 vNrm = mul(mRot, ReferencePoint()); + VECTOR3 vRot = unit(mul(mRot, _V(0, 1, 0))); + VECTOR3 vTan = unit(crossp(vRot, vNrm)); + VECTOR3 vBiT = unit(crossp(vTan, vNrm)); + + memcpy(&cp.mVP, scn->GetProjectionViewMatrix(), sizeof(FMATRIX4)); + + cp.vPolarAxis = vRot; + cp.vTangent = vTan; // RefFrame for surface micro-tex and water + cp.vBiTangent = vBiT; // RefFrame for surface micro-tex and water + cp.cSun = FVECTOR3(1, 1, 1) * atmo->suni; + cp.PlanetRad = float(pr); + cp.PlanetRad2 = float(pr * pr); + cp.MinAlt = float(minelev); + cp.MaxAlt = float(maxelev); // Max Elevation above sea-level + cp.iAltRng = 1.0f / (cp.MaxAlt - cp.MinAlt); + cp.CamAlt = float(ca); + cp.CamElev = float(scn->GetCameraElevation()); + cp.CamRad = float(cr); + cp.CamRad2 = float(cr * cr); + cp.CamPos = cam; + cp.toCam = unit(cam); + cp.toSun = sundir; // Sun-aligned Atmo Scatter RefFrame + cp.dCS = dot(cp.toCam, cp.toSun); + cp.ZeroAz = unit(cross(cp.toCam, cp.toSun)); // Sun-aligned Atmo Scatter RefFrame + cp.SunAz = unit(cross(cp.toCam, cp.ZeroAz)); // Sun-aligned Atmo Scatter RefFrame + cp.Up = unit(cross(cp.ZeroAz, cp.toSun)); + cp.HrzDst = sqrt(max(mdh, cp.CamRad2 - cp.PlanetRad2)); + cp.Time = fmod(oapiGetSimTime(), 3600.0f); + cp.TrGamma = 1.0f / float(atmo->tgamma); + cp.TrExpo = float(atmo->trb); + cp.Ambient = fAmbient; + cp.CosAlpha = min(1.0f, cp.PlanetRad / cp.CamRad); + cp.SinAlpha = sqrt(1.0f - cp.CosAlpha * cp.CosAlpha); + cp.cAmbient = atmo->acolor; + float A = dot(cp.toCam, cp.Up) * cp.CamRad; + cp.Cr2 = A * A; + float g2 = cp.CamRad2 - cp.PlanetRad2; + cp.ShdDst = g2 > 0 ? sqrt(g2) : 0.0f; + cp.SunVis = SunOcclusionByPlanet(); + cp.trLS = float(atmo->tr3D); + + if (HasAtmosphere() == false) return; + if (surfmgr2 == NULL) return; + + + // Skip the rest if no atmosphere exists + // ------------------------------------------------------------------------------------------------------------ + float visalt = atmo->visalt; + cp.AtmoAlt = visalt; + cp.AtmoRad = visalt + cp.PlanetRad; + cp.AtmoRad2 = cp.AtmoRad * cp.AtmoRad; + cp.CloudAlt = prm.bCloud ? float(atmo->aux2 * 1e3f) : 0.0f; + cp.CamSpace = sqrt(saturate(cp.CamAlt / visalt)); + cp.AngMin = -sqrt(max(1.0f, cp.CamRad2 - cp.PlanetRad2)) / cp.CamRad; + cp.AngRng = 1.0f - cp.AngMin; + cp.iAngRng = 1.0f / cp.AngRng; + cp.AngCtr = sqrt(max(0.0f, 1.0f - qw * qw)); + cp.RayWave = unit(pow(FVECTOR3(atmo->red, atmo->green, atmo->blue), -atmo->rpow)); + cp.MieWave = unit(pow(FVECTOR3(atmo->red, atmo->green, atmo->blue), -atmo->mpow)); + + cp.rmO.x = atmo->ray * atmo->rayrat * scr * 4.0f * PI; + cp.rmO.y = atmo->mie * atmo->mierat * scm * 4.0f * PI; + cp.rmI.x = atmo->ray * scr; + cp.rmI.y = atmo->mie * scm; + + cp.iH.x = 1.0f / float(atmo->rheight * 1000.0); + cp.iH.y = 1.0f / float(atmo->mheight * 1000.0); + cp.Expo = atmo->aux3; + //cp.HG = FVECTOR4(1.5f * (1.0f - g * g) / (2.0f + g * g), 1.0f + g * g, 2.0f * g, float(atmo->mphaseb)); + cp.HG = FVECTOR4(pow(1.0f - g * g, 0.75f), g, 0.0f, float(atmo->mphaseb)); + + cp.cGlare = atmo->zcolor; + cp.Clouds = float(atmo->hazei); + cp.TW_Terrain = float(atmo->tw_bri); + cp.TW_Dst = float(atmo->tw_dst); + + if (cp.CamAlt < prm.cloudalt) { + float SMi = cp.CloudAlt; + float SMa = min(100e3, cp.HrzDst); // Semi-major axis + cp.ecc = sqrt((SMa * SMa - SMi * SMi) / (SMa * SMa)); // eccentricity + cp.smi = SMi; + } + else { + cp.ecc = 0.0f; + cp.smi = cp.HrzDst; + } + + + sFlow Flow; + Flow.bCamLit = !((cp.Cr2 < cp.PlanetRad2) && (dot(cp.toCam, cp.toSun) < 0)); + Flow.bCamInSpace = !CameraInAtmosphere(); + + + // + // ---------------------------------------------------------------------------- + // + pIP->Activate("SunColor"); + pIP->SetStruct("Const", &cp, sizeof(ConstParams)); + + pSunColor->GetSurfaceLevel(0, &pTgt); + pIP->SetOutputNative(0, pTgt); + if (!pIP->Execute(true)) LogErr("pIP Execute Failed (SunColor)"); + SAFE_RELEASE(pTgt); + + + // + // ---------------------------------------------------------------------------- + // + if (CameraInAtmosphere()) pIP->Activate("SkyView"); + else pIP->Activate("RingView"); + + // Rayleigh calculations + Flow.bRay = true; + pIP->SetStruct("Flo", &Flow, sizeof(sFlow)); + pIP->SetStruct("Const", &cp, sizeof(ConstParams)); + pIP->SetTextureNative("tSun", pSunColor, IPF_CLAMP | IPF_LINEAR); + pRaySkyView->GetSurfaceLevel(0, &pTgt); + pIP->SetOutputNative(0, pTgt); + if (!pIP->Execute(true)) LogErr("pIP Execute Failed (SkyView)"); + SAFE_RELEASE(pTgt); + + // Mie calculations + Flow.bRay = false; + pIP->SetStruct("Flo", &Flow, sizeof(sFlow)); + pIP->SetStruct("Const", &cp, sizeof(ConstParams)); + pMieSkyView->GetSurfaceLevel(0, &pTgt); + pIP->SetOutputNative(0, pTgt); + if (!pIP->Execute(true)) LogErr("pIP Execute Failed (SkyView)"); + SAFE_RELEASE(pTgt); + + + // + // ---------------------------------------------------------------------------- + // + pIP->Activate("AmbientSky"); + pIP->SetStruct("Const", &cp, sizeof(ConstParams)); + pIP->SetTextureNative("tSkyRayColor", pRaySkyView, IPF_CLAMP | IPF_LINEAR); + pIP->SetTextureNative("tSkyMieColor", pMieSkyView, IPF_CLAMP | IPF_LINEAR); + + pAmbientSky->GetSurfaceLevel(0, &pTgt); + pIP->SetOutputNative(0, pTgt); + if (!pIP->Execute(true)) LogErr("pIP Execute Failed (AmbientSky)"); + SAFE_RELEASE(pTgt); + + + // + // ---------------------------------------------------------------------------- + // + pIP->Activate("LandViewAtten"); + pIP->SetStruct("Const", &cp, sizeof(ConstParams)); + + pLandViewAtn->GetSurfaceLevel(0, &pTgt); + pIP->SetOutputNative(0, pTgt); + if (!pIP->Execute(true)) LogErr("pIP Execute Failed (AmbientSky)"); + SAFE_RELEASE(pTgt); + + + // + // ---------------------------------------------------------------------------- + // + pIP->Activate("LandView"); + + // Rayleigh calculations + Flow.bRay = true; + pIP->SetStruct("Const", &cp, sizeof(ConstParams)); + pIP->SetStruct("Flo", &Flow, sizeof(sFlow)); + pIP->SetTextureNative("tSun", pSunColor, IPF_CLAMP | IPF_LINEAR); + pLandViewRay->GetSurfaceLevel(0, &pTgt); + pIP->SetOutputNative(0, pTgt); + if (!pIP->Execute(true)) LogErr("pIP Execute Failed (SkyView)"); + SAFE_RELEASE(pTgt); + + // Mie calculations + Flow.bRay = false; + pIP->SetStruct("Const", &cp, sizeof(ConstParams)); + pIP->SetStruct("Flo", &Flow, sizeof(sFlow)); + pLandViewMie->GetSurfaceLevel(0, &pTgt); + pIP->SetOutputNative(0, pTgt); + if (!pIP->Execute(true)) LogErr("pIP Execute Failed (SkyView)"); + SAFE_RELEASE(pTgt); +} + +// ============================================================== + +PlanetShader* vPlanet::GetShader(int id) +{ + if (id == PLT_CONFIG) return pRender[GetShaderID()]; + return pRender[id]; +} + +// ============================================================== + +int vPlanet::GetShaderID() +{ + if (strcmp(ShaderName, "Moon") == 0) return PLT_MOON; + if (strcmp(ShaderName, "Earth") == 0) return PLT_EARTH; + if (strcmp(ShaderName, "Mars") == 0) return PLT_MARS; + if (strcmp(ShaderName, "Giant") == 0) return PLT_GIANT; + if (strcmp(ShaderName, "Auto") == 0) + { + bool has_atmosphere = HasAtmosphere(); + if (has_atmosphere) { + bool has_ripples = HasRipples(); + bool render_shadows = CloudMgr2() != NULL; + if (has_ripples || render_shadows) return PLT_EARTH; + if (size > 6e6) return PLT_GIANT; + return PLT_MARS; + } + } + return PLT_MOON; +} + +// ============================================================== + +ConstParams* vPlanet::GetScatterConst() +{ + if (!active) return NULL; + if (surfmgr2) return &cp; + return NULL; +} + +// ============================================================== + +LPDIRECT3DTEXTURE9 vPlanet::GetScatterTable(int i) +{ + switch (i) + { + case SUN_COLOR: return pSunColor; + case RAY_COLOR: return pRaySkyView; + case MIE_COLOR: return pMieSkyView; + case RAY_LAND: return pLandViewRay; + case MIE_LAND: return pLandViewMie; + case ATN_LAND: return pLandViewAtn; + case SKY_AMBIENT: return pAmbientSky; + default: return NULL; + } + return NULL; +} + +// ============================================================== + +ScatterParams* vPlanet::GetAtmoParams(int mode) +{ + if (!prm.bAtm || prm.atm_hzalt == 0.0) { + atm_mode = 1; + HPrm.cfg_alt = OPrm.cfg_alt = SPrm.cfg_alt = 0.0; + HPrm.cfg_halt = OPrm.cfg_halt = SPrm.cfg_halt = 0.0; + return &SPrm; // Return surface setup if a planet doesn't have atmosphere + } + + double lorb = SPrm.orbalt; + double horb = SPrm.orbalt * 10.0; + double ca = CamDist() - size; + double alt = saturate(ca / lorb); + double halt = saturate((ca - lorb) / horb); + + CPrm.cfg_alt = HPrm.cfg_alt = OPrm.cfg_alt = SPrm.cfg_alt = alt; + CPrm.cfg_halt = HPrm.cfg_halt = OPrm.cfg_halt = SPrm.cfg_halt = halt; + + if (mode == 0) { + if (ca < abs(ca - lorb)) mode = 1; + else { + if (abs(ca - lorb) < abs(ca - horb)) mode = 2; + else mode = 3; + } + } + + atm_mode = mode; + + if (mode == 1) return &SPrm; // Surface configuration + if (mode == 2) return &OPrm; // Orbital configuration + if (mode == 3) return &HPrm; // High Orbital configuration + + if (alt < 0.9999) + { + // ---------------------------------------------------- + CPrm.mierat = lerp(SPrm.mierat, OPrm.mierat, alt); + CPrm.tr3D = lerp(SPrm.tr3D, OPrm.tr3D, alt); + CPrm.aux3 = lerp(SPrm.aux3, OPrm.aux3, alt); + CPrm.mheight = lerp(SPrm.mheight, OPrm.mheight, alt); + CPrm.rheight = lerp(SPrm.rheight, OPrm.rheight, alt); + CPrm.trb = lerp(SPrm.trb, OPrm.trb, alt); + CPrm.mie = lerp(SPrm.mie, OPrm.mie, alt); + CPrm.mphase = lerp(SPrm.mphase, OPrm.mphase, alt); + //CPrm.hazei = lerp(SPrm.hazei, OPrm.hazei, alt); + CPrm.mpow = lerp(SPrm.mpow, OPrm.mpow, alt); + CPrm.rayrat = lerp(SPrm.rayrat, OPrm.rayrat, alt); + CPrm.ray = lerp(SPrm.ray, OPrm.ray, alt); + CPrm.rpow = lerp(SPrm.rpow, OPrm.rpow, alt); + // ---------------------------------------------------- + CPrm.tgamma = lerp(SPrm.tgamma, OPrm.tgamma, alt); + CPrm.mphaseb = lerp(SPrm.mphaseb, OPrm.mphaseb, alt); + CPrm.tw_bld = lerp(SPrm.tw_bld, OPrm.tw_bld, alt); + // ---------------------------------------------------- + CPrm.tw_bri = lerp(SPrm.tw_bri, OPrm.tw_bri, alt); + CPrm.green = lerp(SPrm.green, OPrm.green, alt); + CPrm.tw_dst = lerp(SPrm.tw_dst, OPrm.tw_dst, alt); + } + else { + alt = 1.0 - halt; + // ---------------------------------------------------- + CPrm.mierat = lerp(HPrm.mierat, OPrm.mierat, alt); + CPrm.tr3D = lerp(HPrm.tr3D, OPrm.tr3D, alt); + CPrm.aux3 = lerp(HPrm.aux3, OPrm.aux3, alt); + CPrm.mheight = lerp(HPrm.mheight, OPrm.mheight, alt); + CPrm.rheight = lerp(HPrm.rheight, OPrm.rheight, alt); + CPrm.trb = lerp(HPrm.trb, OPrm.trb, alt); + CPrm.mie = lerp(HPrm.mie, OPrm.mie, alt); + CPrm.mphase = lerp(HPrm.mphase, OPrm.mphase, alt); + //CPrm.hazei = lerp(HPrm.hazei, OPrm.hazei, alt); + CPrm.mpow = lerp(HPrm.mpow, OPrm.mpow, alt); + CPrm.rayrat = lerp(HPrm.rayrat, OPrm.rayrat, alt); + CPrm.ray = lerp(HPrm.ray, OPrm.ray, alt); + CPrm.rpow = lerp(HPrm.rpow, OPrm.rpow, alt); + // ---------------------------------------------------- + CPrm.tgamma = lerp(HPrm.tgamma, OPrm.tgamma, alt); + CPrm.mphaseb = lerp(HPrm.mphaseb, OPrm.mphaseb, alt); + CPrm.tw_bld = lerp(HPrm.tw_bld, OPrm.tw_bld, alt); + // ---------------------------------------------------- + CPrm.tw_bri = lerp(HPrm.tw_bri, OPrm.tw_bri, alt); + CPrm.green = lerp(HPrm.green, OPrm.green, alt); + CPrm.tw_dst = lerp(HPrm.tw_dst, OPrm.tw_dst, alt); + } + + bool bBelow = cp.CamAlt < prm.cloudalt; + CPrm.aux2 = bBelow ? SPrm.aux2 : lerp(HPrm.aux2, OPrm.aux2, saturate(1.0 - halt)); + CPrm.hazei = bBelow ? SPrm.hazei : lerp(HPrm.hazei, OPrm.hazei, saturate(1.0 - halt)); + + CPrm.red = SPrm.red; + CPrm.blue = SPrm.blue; + CPrm.suni = SPrm.suni; + CPrm.orbalt = SPrm.orbalt; + CPrm.visalt = GetHorizonAlt(); + CPrm.acolor = SPrm.acolor; + CPrm.hcolor = SPrm.hcolor; + CPrm.zcolor = SPrm.zcolor; + + return &CPrm; +} + +// ============================================================== + +bool vPlanet::LoadAtmoConfig() +{ + char name[32]; + char path[256]; + + oapiGetObjectName(hObj, name, 32); + + auto it = Config->AtmoCfg.find(name); + if (it != Config->AtmoCfg.end()) { + sprintf_s(path, 256, "GC/%s", it->second.c_str()); + } + else { + sprintf_s(path, "GC/%s.atm.cfg", name); + Config->AtmoCfg[name] = string(name) + ".atm.cfg"; + } + + FILEHANDLE hFile = oapiOpenFile(path, FILE_IN_ZEROONFAIL, CONFIG); + if (!hFile) hFile = oapiOpenFile("GC/Mercury.atm.cfg", FILE_IN_ZEROONFAIL, CONFIG); + if (!hFile) LogErr("Failed to initialize configuration for [%s]", name); + + LogAlw("Loading Atmospheric Configuration file [%s] Handle=%s", path, _PTR(hFile)); + + if (oapiReadItem_string(hFile, "Shader", ShaderName) == false) strcpy_s(ShaderName, 32, "Auto"); + if (oapiReadItem_string(hFile, "ConfigName", AtmoConfigName) == false) strcpy_s(AtmoConfigName, 32, "Custom"); + + LoadStruct(hFile, &SPrm, 0); + LoadStruct(hFile, &OPrm, 1); + LoadStruct(hFile, &HPrm, 2); + + oapiCloseFile(hFile, FILE_IN_ZEROONFAIL); + + if (!oapiPlanetHasAtmosphere(hObj)) return false; + + return true; + +} + +// ============================================================== + +char* vPlanet::Label(const char* x) +{ + static char lbl[32]; + if (iConfig == 0) sprintf_s(lbl, 32, "Srf_%s", x); + if (iConfig == 1) sprintf_s(lbl, 32, "Low_%s", x); + if (iConfig == 2) sprintf_s(lbl, 32, "Hig_%s", x); + return lbl; +} + +// ============================================================== + +void vPlanet::SaveStruct(FILEHANDLE hFile, ScatterParams* prm, int iCnf) +{ + iConfig = iCnf; + oapiWriteItem_float(hFile, Label("RPwr"), prm->rpow); + oapiWriteItem_float(hFile, Label("MPwr"), prm->mpow); + // ----------------------------------------------------------------- + oapiWriteItem_float(hFile, Label("Expo"), prm->trb); + oapiWriteItem_float(hFile, Label("TGamma"), prm->tgamma); + oapiWriteItem_float(hFile, Label("Tr3D"), prm->tr3D); + // ----------------------------------------------------------------- + oapiWriteItem_float(hFile, Label("TWDst"), prm->tw_dst); + oapiWriteItem_float(hFile, Label("Green"), prm->green); + oapiWriteItem_float(hFile, Label("TWBri"), prm->tw_bri); + // ----------------------------------------------------------------- + oapiWriteItem_float(hFile, Label("RayO"), prm->ray); + oapiWriteItem_float(hFile, Label("RayI"), prm->rayrat); + oapiWriteItem_float(hFile, Label("TWBld"), prm->tw_bld); + oapiWriteItem_float(hFile, Label("RayH"), prm->rheight); + // ----------------------------------------------------------------- + oapiWriteItem_float(hFile, Label("MieO"), prm->mie); + oapiWriteItem_float(hFile, Label("MieP"), prm->mphase); + oapiWriteItem_float(hFile, Label("MieI"), prm->mierat); + oapiWriteItem_float(hFile, Label("MieH"), prm->mheight); + // ----------------------------------------------------------------- + oapiWriteItem_float(hFile, Label("Aux2"), prm->aux2); + oapiWriteItem_float(hFile, Label("Aux3"), prm->aux3); + oapiWriteItem_float(hFile, Label("Aux4"), prm->mphaseb); + oapiWriteItem_float(hFile, Label("Aux5"), prm->hazei); +} + +// ============================================================== + +void vPlanet::LoadStruct(FILEHANDLE hFile, ScatterParams* prm, int iCnf) +{ + VECTOR3 v3; + iConfig = iCnf; + oapiReadItem_float(hFile, "OrbitAlt", prm->orbalt); + oapiReadItem_float(hFile, "AtmoVisualAlt", prm->visalt); + oapiReadItem_float(hFile, "Red", prm->red); + oapiReadItem_float(hFile, "Blue", prm->blue); + oapiReadItem_float(hFile, "SunI", prm->suni); + oapiReadItem_vec(hFile, "zcolor", v3); prm->zcolor = v3; + oapiReadItem_vec(hFile, "hcolor", v3); prm->hcolor = v3; + oapiReadItem_vec(hFile, "acolor", v3); prm->acolor = v3; + + + // ----------------------------------------------------------------- + + oapiReadItem_float(hFile, Label("RPwr"), prm->rpow); + oapiReadItem_float(hFile, Label("MPwr"), prm->mpow); + // ----------------------------------------------------------------- + oapiReadItem_float(hFile, Label("Expo"), prm->trb); + oapiReadItem_float(hFile, Label("TGamma"), prm->tgamma); + if (!oapiReadItem_float(hFile, Label("Tr3D"), prm->tr3D)) prm->tr3D = 1.0; + // ----------------------------------------------------------------- + oapiReadItem_float(hFile, Label("TWDst"), prm->tw_dst); + oapiReadItem_float(hFile, Label("Green"), prm->green); + oapiReadItem_float(hFile, Label("TWBri"), prm->tw_bri); + // ----------------------------------------------------------------- + oapiReadItem_float(hFile, Label("RayO"), prm->ray); + oapiReadItem_float(hFile, Label("RayI"), prm->rayrat); + oapiReadItem_float(hFile, Label("TWBld"), prm->tw_bld); + oapiReadItem_float(hFile, Label("RayH"), prm->rheight); + // ----------------------------------------------------------------- + oapiReadItem_float(hFile, Label("MieO"), prm->mie); + oapiReadItem_float(hFile, Label("MieP"), prm->mphase); + oapiReadItem_float(hFile, Label("MieI"), prm->mierat); + oapiReadItem_float(hFile, Label("MieH"), prm->mheight); + // ----------------------------------------------------------------- + oapiReadItem_float(hFile, Label("Aux2"), prm->aux2); + oapiReadItem_float(hFile, Label("Aux3"), prm->aux3); + oapiReadItem_float(hFile, Label("Aux4"), prm->mphaseb); + oapiReadItem_float(hFile, Label("Aux5"), prm->hazei); +} + +// ============================================================== + +void vPlanet::SaveAtmoConfig() +{ + char name[64]; + char path[256]; + + oapiGetObjectName(hObj, name, 64); + + auto it = Config->AtmoCfg.find(name); + if (it != Config->AtmoCfg.end()) { + sprintf_s(path, 256, "GC/%s", it->second.c_str()); + } + else { + sprintf_s(path, "GC/%s.atm.cfg", name); + Config->AtmoCfg[name] = string(name) + ".atm.cfg"; + } + + FILEHANDLE hFile = oapiOpenFile(path, FILE_OUT, CONFIG); + + oapiWriteItem_string(hFile, ";", "Shader(s) = [Earth, Mars, Moon, Giant, Auto]"); + oapiWriteItem_string(hFile, "Shader", ShaderName); + oapiWriteItem_string(hFile, "Planet", name); + oapiWriteItem_string(hFile, "ConfigName", AtmoConfigName); + oapiWriteItem_float(hFile, "OrbitAlt", SPrm.orbalt); + oapiWriteItem_float(hFile, "AtmoVisualAlt", SPrm.visalt); + oapiWriteItem_float(hFile, "Red", SPrm.red); + oapiWriteItem_float(hFile, "Blue", SPrm.blue); + oapiWriteItem_float(hFile, "SunI", SPrm.suni); + oapiWriteItem_vec(hFile, "zcolor", SPrm.zcolor._V()); + oapiWriteItem_vec(hFile, "hcolor", SPrm.hcolor._V()); + oapiWriteItem_vec(hFile, "acolor", SPrm.acolor._V()); + + SaveStruct(hFile, &SPrm, 0); + SaveStruct(hFile, &OPrm, 1); + SaveStruct(hFile, &HPrm, 2); + + oapiCloseFile(hFile, FILE_OUT); +} + + +// =========================================================================================== +// +vPlanet::SHDPrm vPlanet::ComputeShadow(FVECTOR3 vRay) +{ + // Compute Planet's shadow entry and exit points + vPlanet::SHDPrm sp; + + // Camera radius in "shadow" frame. + double A = dot(TestPrm.Up, TestPrm.toCam * TestPrm.CamRad); + sp.cr = abs(A); + + // Projection of viewing ray on 'shadow' axes + double u = dot(vRay, TestPrm.Up); + double t = dot(vRay, TestPrm.ZeroAz); + double z = dot(vRay, TestPrm.toSun); + + // Cosine 'a' + double a = u / sqrt(u * u + t * t); + + double k2 = A * A * a * a; + double h2 = A * A - k2; + double w2 = cp.PlanetRad2 - h2; + double w = sqrt(w2); + double k = sqrt(k2) * sign(a); + double v2 = 0; + double m = TestPrm.CamRad2 - cp.PlanetRad2; + + sp.w2 = w2; + sp.se = k - w; + sp.sx = sp.se + 2.0f * w; + + // Project distances 'es' and 'xs' back to 3D space + double f = 1.0f / sqrt(max(2.5e-5, 1.0 - z * z)); + sp.se *= f; + sp.sx *= f; + + // Compute atmosphere entry and exit points + // + a = -dot(TestPrm.toCam, vRay); + k2 = TestPrm.CamRad2 * a * a; + h2 = TestPrm.CamRad2 - k2; + v2 = cp.AtmoRad2 - h2; + w = sqrt(v2); + k = sqrt(k2) * sign(a); + + + sp.hd = m > 0.0 ? sqrt(m) : 0.0; + sp.ae = (k - w); + sp.ax = sp.ae + 2.0f * w; + sp.ca = TestPrm.CamRad * a; + + // If the ray doesn't intersect atmosphere then set both distances to zero + if (v2 < 0) sp.ae = sp.ax = invalid_val; + + // If the ray doesn't intersect shadow then set both distances to atmo exit + if (w2 < 0) { + sp.se = invalid_val; + sp.sx = invalid_val; + } + else { + FVECTOR3 vEn = TestPrm.CamPos + vRay * sp.se; + FVECTOR3 vEx = TestPrm.CamPos + vRay * sp.sx; + if (dot(vEn, TestPrm.toSun) > 0) sp.se = invalid_val; + if (dot(vEx, TestPrm.toSun) > 0) sp.sx = invalid_val; + } + + return sp; +} + + +// =========================================================================================== +// +void vPlanet::TestComputations(Sketchpad* pSkp) +{ + static int status = 0; + float size = 0.02f; + VECTOR3 campos, rpos; + VESSEL* pV = oapiGetFocusInterface(); + OBJHANDLE hV = pV->GetHandle(); + OBJHANDLE hR = pV->GetGravityRef(); + if (hR != hObj) return; + + oapiGetGlobalPos(hR, &rpos); + oapiCameraGlobalPos(&campos); + campos -= rpos; + + FVECTOR3 vCam(campos); + + static FVECTOR3 vRef = 0; + static FVECTOR3 vPos = 0; + static FVECTOR3 vRay = 0; + static float beta = 0.0f; + + if (length(GetScene()->vPickRay) > 0.8f) { + vRef = campos; + beta = dot(unit(vRef), GetScene()->vPickRay); + TestPrm.CamPos = cp.CamPos; + TestPrm.toSun = cp.toSun; + TestPrm.toCam = unit(vRef); + TestPrm.CamRad = length(vRef); + TestPrm.CamRad2 = TestPrm.CamRad * TestPrm.CamRad; + TestPrm.ZeroAz = unit(cross(TestPrm.toCam, TestPrm.toSun)); + TestPrm.SunAz = unit(cross(TestPrm.toCam, TestPrm.ZeroAz)); + TestPrm.Up = unit(cross(TestPrm.ZeroAz, TestPrm.toSun)); + TestPrm.CosAlpha = min(1.0f, cp.PlanetRad / TestPrm.CamRad); + TestPrm.SinAlpha = sqrt(1.0f - TestPrm.CosAlpha * TestPrm.CosAlpha); + } + + + // Trace picking ray -------------------------------------------- + // + float Ref2 = dot(vRef, vRef); + float Ref = sqrt(Ref2); + float ds = Ref * beta; + float he2 = Ref2 - ds * ds; + + if (length(GetScene()->vPickRay) > 0.8f) + { + if (he2 < cp.PlanetRad2 && beta < 0) { // Surface contact + float s = sqrt(cp.PlanetRad2 - he2); + vPos = vRef + GetScene()->vPickRay * (-ds - s); + status = 1; + } + else { + if (!CameraInAtmosphere()) { // Horizon ring contact + float Alpha = acos(TestPrm.CosAlpha); + float Beta = acos(-beta); + float Gamma = PI - Alpha - Beta; + float re = Ref * sin(Beta) / sin(Gamma); + float di = sqrt(re * re + Ref2 - 2.0f * re * Ref * TestPrm.CosAlpha); + vPos = vRef + GetScene()->vPickRay * di; + status = 2; + } + else { // Sky Dome contact + float ew = sqrt(cp.AtmoRad2 - he2) - ds; + vPos = vRef + GetScene()->vPickRay * ew; + status = 3; + } + } + GetScene()->vPickRay = 0; + vRay = normalize(vPos - vRef); // From vRef to vPos + } + + float cd = length(vRef - vPos); + + SHDPrm sp = ComputeShadow(vRay); + + FVECTOR4 rd = ComputeCameraView(vPos); + + D3D9DebugLog("Optical Depth=%f RGB(%f, %f, %f)", rd.a, rd.r, rd.g, rd.b); + + float sl = dot(cp.toSun, TestPrm.toCam); + float sa = dot(vRay, TestPrm.toCam); + float rl = RayLength(-sa, TestPrm.CamRad); + float rf = sqrt(cp.AtmoRad2 - cp.PlanetRad2); + float ph = dot(vRay, cp.toSun); + + FVECTOR3 cl = SunLightColor(sl, cp.CamAlt); + FVECTOR4 ral, mie; + IntegrateSegment(vPos, vRay, rl, &ral, &mie); + + FVECTOR3 is = (ral.rgb + mie.rgb);// *MiePhase(-ph)); + + D3D9DebugLog("Sunlight RGB(%f, %f, %f)", cl.x, cl.y, cl.z); + D3D9DebugLog("InScatter RGB(%f, %f, %f)", is.x, is.y, is.z); + D3D9DebugLog("RayLength = %f vs %f, sa = %f, sl = %f", rl, rf, sa, sl); + D3D9DebugLog("AtmoAlt = %f(km)", cp.AtmoAlt/1000.0f); + + double u = dot(vPos, TestPrm.Up); + double t = dot(vPos, TestPrm.ZeroAz); + bool bTgt = ((u * u + t * t) < cp.PlanetRad2 && dot(vPos, TestPrm.toSun) < 0); + bool bSrc = (sp.cr < cp.PlanetRad&& dot(vRef, TestPrm.toSun) < 0); + + float s0 = 0, s1 = 0, e0 = 0, e1 = 0, mp = 0, lf = 0; + + if (status == 1) { + s0 = sp.ae > 0 ? sp.ae : 0; + e0 = sp.se > 0 ? min(cd, sp.se) : cd; + } + else { + + if (bSrc) { // Camera in Shadow + s0 = max(sp.sx, sp.ae); + + float lf = max(0, sp.ca) / max(1.0f, abs(sp.hd)); // Lerp Factor + float mp = lerp((sp.ax + s0) * 0.5f, sp.hd, saturate(lf)); + + e0 = mp; + s1 = max(sp.sx, mp); + e1 = sp.ax; + } + else { // Camera is Lit + s0 = max(0, sp.ae); + + float lf = max(0, sp.ca) / max(1.0f, abs(sp.hd)); // Lerp Factor + float mp = lerp((sp.ax + s0) * 0.5f, sp.hd, saturate(lf)); + + bool bA = (sp.se > sp.ax || sp.se < 0); + + e0 = bA ? mp : sp.se; + s1 = bA ? mp : max(sp.sx, sp.ae); + e1 = sp.ax; + } + } + + + int sz = 250; + + // Origin Point + pSkp->QuickPen(0xFF00FF00); + pSkp->QuickBrush(0xFF00FF00); + pSkp->SetWorldBillboard(vRef - vCam, size); + pSkp->Ellipse(-sz, -sz, sz, sz); + + // Test Point 'contact point' + sz = 170; + pSkp->QuickPen(0xFF0000FF); + pSkp->QuickBrush(0xFF0000FF); + pSkp->SetWorldBillboard(vRef - vCam + vRay * cd, size); + pSkp->Ellipse(-sz, -sz, sz, sz); + + sz = 250; + // Shadow Crossing + if (sp.se != invalid_val) { + pSkp->QuickPen(0xFFDD00DD); + pSkp->QuickBrush(0xFFDD00DD); + pSkp->SetWorldBillboard(vRef - vCam + vRay * sp.se, size); + pSkp->Ellipse(-sz, -sz, sz, sz); + } + if (sp.sx != invalid_val) { + pSkp->QuickPen(0xFFFF88FF); + pSkp->QuickBrush(0xFFFF88FF); + pSkp->SetWorldBillboard(vRef - vCam + vRay * sp.sx, size); + pSkp->Ellipse(-sz, -sz, sz, sz); + } + sz = 170; + if (sp.ae != invalid_val) { + // Atmosphere entry points + pSkp->QuickPen(0xFF008080); + pSkp->QuickBrush(0xFF008080); + pSkp->SetWorldBillboard(vRef - vCam + vRay * sp.ae, size); + pSkp->Ellipse(-sz, -sz, sz, sz); + } + if (sp.ax != invalid_val) { + pSkp->QuickPen(0xFF00F0F0); + pSkp->QuickBrush(0xFF00F0F0); + pSkp->SetWorldBillboard(vRef - vCam + vRay * sp.ax, size); + pSkp->Ellipse(-sz, -sz, sz, sz); + } + sz = 120; + if (sp.hd != invalid_val) { + pSkp->QuickPen(0xFFFFFFFF); + pSkp->QuickBrush(0xFFFFFFFF); + pSkp->SetWorldBillboard(vRef - vCam + vRay * mp, size); + pSkp->Ellipse(-sz, -sz, sz, sz); + } + + + if (bSrc) D3D9DebugLog("Camera in Shadow"); + if (bTgt) D3D9DebugLog("Target in Shadow"); + + + if (status == 1) D3D9DebugLog("SURFACE"); + if (status == 2) D3D9DebugLog("HORIZON"); + if (status == 3) D3D9DebugLog("SKYDOME"); + + D3D9DebugLog("Shadow First=%f, Second=%f", sp.se, sp.sx); + D3D9DebugLog("Atmosp First=%f, Second=%f", sp.ae, sp.ax); + D3D9DebugLog("Hd=%f, Ca=%f", sp.hd, sp.ca); + D3D9DebugLog("CameraInSpace=%f", cp.CamSpace); + + D3DXMATRIX mI; D3DXMatrixIdentity(&mI); + VECTOR3 V0, V1; + IVECTOR2 pt0, pt1; + + pSkp->SetViewMode(Sketchpad::ORTHO); + pSkp->SetWorldTransform(); + + FVECTOR3 vR = vRef - vCam; + + D3D9DebugLog("s0=%f, e0=%f, s1=%f, e1=%f, mp=%f, lf=%f", s0, e0, s1, e1, mp, lf); + + if (e0 > s0) { + D3D9DebugLog("Primary Integral"); + V0 = (vR + vRay * s0)._V(); + V1 = V0 + vRay._V() * (e0 - s0); + scn->WorldToScreenSpace(V0, &pt0); + scn->WorldToScreenSpace(V1, &pt1); + pSkp->QuickPen(0xFF90FF90); + pSkp->Line(pt0.x, pt0.y, pt1.x, pt1.y); + } + + if (e1 > s1) { + D3D9DebugLog("Secondary Integral"); + V0 = (vR + vRay * s1)._V(); + V1 = V0 + vRay._V() * (e1 - s1); + scn->WorldToScreenSpace(V0, &pt0); + scn->WorldToScreenSpace(V1, &pt1); + pSkp->QuickPen(0xFF9090FF); + pSkp->Line(pt0.x, pt0.y, pt1.x, pt1.y); + } + pSkp->SetViewMode(Sketchpad::USER); +} + + diff --git a/OVP/D3D9Client/VStar.cpp b/OVP/D3D9Client/VStar.cpp index f12ecc1b8..57a705f05 100644 --- a/OVP/D3D9Client/VStar.cpp +++ b/OVP/D3D9Client/VStar.cpp @@ -49,7 +49,8 @@ bool vStar::Update (bool bMainScene) bool vStar::Render(LPDIRECT3DDEVICE9 dev) { _TRACE; - if (Config->PostProcess == PP_LENSFLARE && cdist < 150e9) return false; + + if (Config->bGlares) return true; double dist_scale; float rad_scale = float(size); @@ -91,7 +92,7 @@ bool vStar::Render(LPDIRECT3DDEVICE9 dev) mWorld._21 *= rad_scale; mWorld._22 *= rad_scale; mWorld._23 *= rad_scale; mWorld._31 *= rad_scale; mWorld._32 *= rad_scale; mWorld._33 *= rad_scale; - D3D9Effect::RenderBillboard(&mWorld, deftex); - + //D3D9Effect::RenderBillboard(&mWorld, scn->GetSunTexture(), 1.0f); + D3D9Effect::RenderBillboard(&mWorld, SURFACE(deftex)->GetTexture(), 1.0f); return true; } diff --git a/OVP/D3D9Client/VVessel.cpp b/OVP/D3D9Client/VVessel.cpp index f33e0af0a..c460b2293 100644 --- a/OVP/D3D9Client/VVessel.cpp +++ b/OVP/D3D9Client/VVessel.cpp @@ -8,6 +8,7 @@ #include #include "VVessel.h" +#include "VPlanet.h" #include "MeshMgr.h" #include "AABBUtil.h" #include "D3D9Surface.h" @@ -242,23 +243,18 @@ void vVessel::PreInitObject() else LogErr("Failed to load a custom configuration for %s",vessel->GetClassNameA()); } + // ============================================================================================ // bool vVessel::Update(bool bMainScene) { _TRACE; - if (!active) return false; - vObject::Update(bMainScene); - if (fabs(oapiGetSimTime()-tCheckLight)>0.1) { - sunLight = *scn->GetSun(); - ModLighting(&sunLight); - } + if (fabs(oapiGetSimTime()-tCheckLight)>0.1 || oapiGetPause()) ModLighting(); bBSRecompute = true; - return true; } @@ -686,6 +682,10 @@ bool vVessel::Render(LPDIRECT3DDEVICE9 dev, bool internalpass) if (scn->GetRenderPass() == RENDERPASS_SHADOWMAP) bCockpit = bVC = false; // Always render exterior view for envmaps + // if (scn->GetRenderPass() == RENDERPASS_NORMAL_DEPTH) bCockpit = bVC = false; + // Always render exterior view for envmaps + + static VCHUDSPEC hudspec_; const VCHUDSPEC *hudspec = &hudspec_; static bool gotHUDSpec(false); @@ -718,10 +718,13 @@ bool vVessel::Render(LPDIRECT3DDEVICE9 dev, bool internalpass) gotHUDSpec = !!gc->GetVCHUDSurface(&hudspec); } - // Reduce sunlight for virtual cockpit + + // Initialize MeshShader constants // - D3D9Sun sunLightVC = sunLight; - sunLightVC.Color *= 0.5f; + MeshShader::ps_const.Cam_X = *scn->GetCameraX(); + MeshShader::ps_const.Cam_Y = *scn->GetCameraY(); + MeshShader::ps_const.Cam_Z = *scn->GetCameraZ(); + // Render Exterior and Interior (VC) meshes -------------------------------------------- @@ -761,8 +764,12 @@ bool vVessel::Render(LPDIRECT3DDEVICE9 dev, bool internalpass) else pWT = &mWorld; - if (bVC && internalpass) meshlist[i].mesh->SetSunLight(&sunLightVC); - else meshlist[i].mesh->SetSunLight(&sunLight); + if (bVC && internalpass) { + D3D9Sun local = sunLight; + local.Color *= 0.5f; + meshlist[i].mesh->SetSunLight(&local); + } + else meshlist[i].mesh->SetSunLight(&sunLight); if (bVC && internalpass) { @@ -773,10 +780,16 @@ bool vVessel::Render(LPDIRECT3DDEVICE9 dev, bool internalpass) } } + const LPD3DXMATRIX pVP = scn->GetProjectionViewMatrix(); + const LPD3DXMATRIX pLVP = (const LPD3DXMATRIX)&shd->mViewProj; // Render vessel meshes -------------------------------------------------------------------------- // - if (scn->GetRenderPass() == RENDERPASS_SHADOWMAP) meshlist[i].mesh->RenderShadows(0.0f, NULL, pWT, true); + if (scn->GetRenderPass() == RENDERPASS_SHADOWMAP) meshlist[i].mesh->RenderShadowMap(pWT, pLVP, 0); + else if (scn->GetRenderPass() == RENDERPASS_NORMAL_DEPTH) + { + meshlist[i].mesh->RenderShadowMap(pWT, pVP, 1); + } else { if (internalpass) meshlist[i].mesh->Render(pWT, RENDER_VC, NULL, 0); else meshlist[i].mesh->Render(pWT, RENDER_VESSEL, pEnv, nEnv); @@ -1014,7 +1027,7 @@ void vVessel::RenderGrapplePoints (LPDIRECT3DDEVICE9 dev) // void vVessel::RenderGroundShadow(LPDIRECT3DDEVICE9 dev, OBJHANDLE hPlanet, float alpha) { - if (!bStencilShadow) return; + if (!bStencilShadow && scn->GetRenderPass() == RENDERPASS_MAINSCENE) return; if (Config->TerrainShadowing == 0) return; static const double eps = 1e-2; @@ -1096,9 +1109,9 @@ void vVessel::RenderGroundShadow(LPDIRECT3DDEVICE9 dev, OBJHANDLE hPlanet, float vessel->GetMeshOffset(i, of); nrml.w += float(dotp(of, hn)); // Sift a local groung level D3DXMatrixMultiply(&mProjWorldShift, meshlist[i].trans, &mProjWorld); - mesh->RenderShadows(alpha, &mWorld, &mProjWorldShift, false, &nrml); + mesh->RenderStencilShadows(alpha, &mWorld, &mProjWorldShift, false, &nrml); } - else mesh->RenderShadows(alpha, &mWorld, &mProjWorld, false, &nrml); + else mesh->RenderStencilShadows(alpha, &mWorld, &mProjWorld, false, &nrml); } } @@ -1261,10 +1274,7 @@ bool vVessel::ProbeIrradiance(LPDIRECT3DDEVICE9 pDev, DWORD cnt, DWORD flags) LPDIRECT3DSURFACE9 pIrDS = GetScene()->GetIrradianceDepthStencil(); - if (!pIrDS) { - LogErr("IrradianceDepthStencil doesn't exists"); - return true; - } + if (!pIrDS) return true; // Feature disabled // Create a main EnvMap with mipmap chain for blurred maps -------------------------------------------------------------------- @@ -1440,36 +1450,19 @@ LPDIRECT3DCUBETEXTURE9 vVessel::GetEnvMap(int idx) // ============================================================================================ // -bool vVessel::ModLighting(D3D9Sun *light) +bool vVessel::ModLighting() { - VECTOR3 GV; + tCheckLight = oapiGetSimTime(); // we only test the closest celestial body for shadowing OBJHANDLE hP = vessel->GetSurfaceRef(); - - if (hP==NULL) { - LogErr("Vessel's surface reference is NULL"); - return false; - } - - vessel->GetGlobalPos(GV); - - tCheckLight = oapiGetSimTime(); - - DWORD dAmbient = *(DWORD*)gc->GetConfigParam(CFGPRM_AMBIENTLEVEL); - float fAmbient = float(dAmbient)*0.0039f; - - if (DebugControls::IsActive()) { - if (*(DWORD*)gc->GetConfigParam(CFGPRM_GETDEBUGFLAGS)&DBG_FLAGS_AMBIENT) fAmbient = 0.25f; - } + if (hP==NULL) { LogErr("Vessel's surface reference is NULL"); return false; } vPlanet *vP = (vPlanet *)GetScene()->GetVisObject(hP); - - if (vP) OrbitalLighting(light, vP, GV, fAmbient); - - light->Color.r = max(0, min(1, light->Color.r)); - light->Color.g = max(0, min(1, light->Color.g)); - light->Color.b = max(0, min(1, light->Color.b)); + if (vP) { + VECTOR3 rpos = gpos - vP->GlobalPos(); + sunLight = vP->GetObjectAtmoParams(rpos); + } return true; } diff --git a/OVP/D3D9Client/VVessel.h b/OVP/D3D9Client/VVessel.h index a71b9d1e8..2ad3b2e24 100644 --- a/OVP/D3D9Client/VVessel.h +++ b/OVP/D3D9Client/VVessel.h @@ -182,7 +182,7 @@ class vVessel: public vObject { * \return \e true if lighting modifications should be applied, \e false * if global lighting conditions apply. */ - bool ModLighting (D3D9Sun *light); + bool ModLighting(); void Animate (UINT an, UINT mshidx); void AnimateComponent (ANIMATIONCOMP *comp, const D3DXMATRIX &T); diff --git a/OVP/D3D9Client/VectorHelpers.h b/OVP/D3D9Client/VectorHelpers.h index d6b0adc4e..a6a73f785 100644 --- a/OVP/D3D9Client/VectorHelpers.h +++ b/OVP/D3D9Client/VectorHelpers.h @@ -81,6 +81,27 @@ template inline _constexpr_ T saturate (T val) : val; } +template inline _constexpr_ T clamp(T x, T a, T b) +{ + return x > b ? b + : x < a ? a + : x; +} + +template inline _constexpr_ T ilerp(T a, T b, T x) +{ + return saturate((x - a) / (b - a)); +} + +template inline _constexpr_ T sqr(T a) +{ + return a * a; +} + +template inline _constexpr_ T hermite(T a) +{ + return a * a * (T(3) - T(2)*a); +} // VECTOR3 Helpers ================================================================== diff --git a/OVP/D3D9Client/VideoTab.cpp b/OVP/D3D9Client/VideoTab.cpp index 06db6991e..6a850e5af 100644 --- a/OVP/D3D9Client/VideoTab.cpp +++ b/OVP/D3D9Client/VideoTab.cpp @@ -19,6 +19,7 @@ #include "Junction.h" #include "OapiExtension.h" #include +#include #include using namespace oapi; @@ -173,6 +174,9 @@ void VideoTab::Initialise() SendDlgItemMessageA(hTab, IDC_VID_MODE, CB_RESETCONTENT, 0, 0); SendDlgItemMessage(hTab, IDC_VID_BPP, CB_RESETCONTENT, 0, 0); + + ScanAtmoCfgs(); + // Create the Direct3D9 --------------------------------------------- // IDirect3D9* d3dObject = Direct3DCreate9(D3D_SDK_VERSION); @@ -570,6 +574,7 @@ void VideoTab::InitSetupDialog(HWND hWnd) LogAlw("InitSetupDialog() Enum Device AA capability = %u",aamax); + // AA ----------------------------------------- SendDlgItemMessage(hWnd, IDC_AA, CB_RESETCONTENT, 0, 0); @@ -720,7 +725,18 @@ void VideoTab::InitSetupDialog(HWND hWnd) SendDlgItemMessageA(hWnd, IDC_GUIMODE, CB_ADDSTRING, 0, (LPARAM)"Disabled"); SendDlgItemMessageA(hWnd, IDC_GUIMODE, CB_ADDSTRING, 0, (LPARAM)"(unused)"); SendDlgItemMessageA(hWnd, IDC_GUIMODE, CB_ADDSTRING, 0, (LPARAM)"Windowed"); - + + // Earth AtmoConfig ------------------------------- + SendDlgItemMessage(hWnd, IDC_EARTHVISCFG, CB_RESETCONTENT, 0, 0); + for (auto x : AtmoCfgs["Earth"]) SendDlgItemMessageA(hWnd, IDC_EARTHVISCFG, CB_ADDSTRING, 0, (LPARAM)x.cfg.c_str()); + for (int i = 0; i < AtmoCfgs["Earth"].size(); i++) { + if (Config->AtmoCfg["Earth"] == AtmoCfgs["Earth"][i].file) { + SendDlgItemMessage(hWnd, IDC_EARTHVISCFG, CB_SETCURSEL, i, 0); + break; + } + } + + // Write values in controls ---------------- @@ -797,6 +813,11 @@ void VideoTab::InitSetupDialog(HWND hWnd) SendDlgItemMessage(hWnd, IDC_ABSANIM, BM_SETCHECK, Config->bAbsAnims == 1, 0); SendDlgItemMessage(hWnd, IDC_CLOUDNORM, BM_SETCHECK, Config->bCloudNormals == 1, 0); SendDlgItemMessage(hWnd, IDC_FLATS, BM_SETCHECK, Config->bFlats == 1, 0); + SendDlgItemMessage(hWnd, IDC_ESUNGLARE, BM_SETCHECK, Config->bGlares == 1, 0); + SendDlgItemMessage(hWnd, IDC_ELIGHTSGLARE, BM_SETCHECK, Config->bLocalGlares == 1, 0); + SendDlgItemMessage(hWnd, IDC_EIRRAD, BM_SETCHECK, Config->bIrradiance == 1, 0); + SendDlgItemMessage(hWnd, IDC_ESCACHE, BM_SETCHECK, Config->ShaderCacheUse == 1, 0); + SendDlgItemMessage(hWnd, IDC_EAQUALITY, BM_SETCHECK, Config->bAtmoQuality == 1, 0); SendDlgItemMessage(hWnd, IDC_NORMALMAPS, BM_SETCHECK, Config->UseNormalMap==1, 0); @@ -867,11 +888,16 @@ void VideoTab::SaveSetupState(HWND hWnd) Config->EnableGlass = (int)SendDlgItemMessage (hWnd, IDC_GLASSSHADE, BM_GETCHECK, 0, 0); Config->EnableMeshDbg = (int)SendDlgItemMessage (hWnd, IDC_MESH_DEBUGGER, BM_GETCHECK, 0, 0); Config->CloudMicro = (int)SendDlgItemMessage (hWnd, IDC_CLOUDMICRO, BM_GETCHECK, 0, 0); - Config->GDIOverlay = (int)(hWnd, IDC_GDIOVERLAY, BM_GETCHECK, 0, 0); + Config->GDIOverlay = (int)SendDlgItemMessage (hWnd, IDC_GDIOVERLAY, BM_GETCHECK, 0, 0); Config->bAbsAnims = (int)SendDlgItemMessage (hWnd, IDC_ABSANIM, BM_GETCHECK, 0, 0); Config->bCloudNormals = (int)SendDlgItemMessage(hWnd, IDC_CLOUDNORM, BM_GETCHECK, 0, 0); Config->bFlats = (int)SendDlgItemMessage(hWnd, IDC_FLATS, BM_GETCHECK, 0, 0); Config->DebugBreak = (int)SendDlgItemMessage(hWnd, IDC_BREAK, BM_GETCHECK, 0, 0); + Config->bGlares = (int)SendDlgItemMessage(hWnd, IDC_ESUNGLARE, BM_GETCHECK, 0, 0); + Config->bLocalGlares = (int)SendDlgItemMessage(hWnd, IDC_ELIGHTSGLARE, BM_GETCHECK, 0, 0); + Config->bIrradiance = (int)SendDlgItemMessage(hWnd, IDC_EIRRAD, BM_GETCHECK, 0, 0); + Config->ShaderCacheUse= (int)SendDlgItemMessage(hWnd, IDC_ESCACHE, BM_GETCHECK, 0, 0); + Config->bAtmoQuality = (int)SendDlgItemMessage(hWnd, IDC_EAQUALITY, BM_GETCHECK, 0, 0); // Sliders Config->Convergence = double(SendDlgItemMessage(hWnd, IDC_CONVERGENCE, TBM_GETPOS, 0, 0)) * 0.01; @@ -907,6 +933,10 @@ void VideoTab::SaveSetupState(HWND hWnd) case 2: Config->SceneAntialias = 4; break; case 3: Config->SceneAntialias = 8; break; } + + int EASel = (int)SendDlgItemMessage(hWnd, IDC_EARTHVISCFG, CB_GETCURSEL, 0, 0); + if (!AtmoCfgs["Earth"][EASel].file.empty()) Config->AtmoCfg["Earth"] = AtmoCfgs["Earth"][EASel].file; + else Config->AtmoCfg["Earth"] = "Earth.atm.cfg"; } @@ -1047,7 +1077,49 @@ void VideoTab::InitCreditsDialog(HWND hWnd) credits = NULL; CloseHandle(hFile); +} + +bool VideoTab::GetConfigName(const char* file, string& cfg, string& planet) +{ + string filename = "GC\\" + string(file); + FILEHANDLE hFile = oapiOpenFile(filename.c_str(), FILE_IN_ZEROONFAIL, CONFIG); + if (hFile) { + char ConfigName[32] = {}; char PlanetName[32] = {}; + bool bA = oapiReadItem_string(hFile, "ConfigName", ConfigName); + bool bB = oapiReadItem_string(hFile, "Planet", PlanetName); + oapiCloseFile(hFile, FILE_IN_ZEROONFAIL); + cfg = string(ConfigName); + planet = string(PlanetName); + return bA && bB; + } + return false; +} +void VideoTab::ScanAtmoCfgs() +{ + _AtmoCfg cfg = { "Default", "Earth.atm.cfg"}; + AtmoCfgs["Earth"].push_back(cfg); + + WIN32_FIND_DATA FileInformation; + string name = string(OapiExtension::GetConfigDir()) + "GC\\*_atm.cfg"; + HANDLE hFile = FindFirstFileA(name.c_str(), &FileInformation); + + if (hFile != INVALID_HANDLE_VALUE) { + do { + if (FileInformation.cFileName[0] != '.') { + if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + string cfgname, planet; + if (GetConfigName(FileInformation.cFileName, cfgname, planet)) { + _AtmoCfg cfg = { cfgname, FileInformation.cFileName }; + AtmoCfgs[planet].push_back(cfg); + } + else oapiWriteLogV("File Not Found [%s]", FileInformation.cFileName); + } + } + } + while (FindNextFileA(hFile, &FileInformation) == TRUE); + FindClose(hFile); + } } diff --git a/OVP/D3D9Client/VideoTab.h b/OVP/D3D9Client/VideoTab.h index 8305759e9..5e4a9d43c 100644 --- a/OVP/D3D9Client/VideoTab.h +++ b/OVP/D3D9Client/VideoTab.h @@ -7,10 +7,14 @@ #ifndef __VIDEOTAB_H #define __VIDEOTAB_H +#include +#include // ============================================================== class VideoTab { + + struct _AtmoCfg { string cfg, file; }; public: VideoTab(oapi::D3D9Client *gc, HINSTANCE _hInst, HINSTANCE _hOrbiterInst, HWND hVideoTab); ~VideoTab(); @@ -46,6 +50,9 @@ class VideoTab { void CreateSymbolicLinks(); void InitSetupDialog(HWND hWnd); void SaveSetupState(HWND hWnd); + void ScanAtmoCfgs(); + bool GetConfigName(const char* file, string& cfg, string& planet); + void LoadAtmoCfg(); oapi::D3D9Client *gclient; HINSTANCE hOrbiterInst; // orbiter instance handle @@ -54,8 +61,9 @@ class VideoTab { int aspect_idx; DWORD SelectedAdapterIdx; bool bHasMultiSample; + std::map> AtmoCfgs; }; //}; -#endif // !__VIDEOTAB_H \ No newline at end of file +#endif // !__VIDEOTAB_H diff --git a/OVP/D3D9Client/gcCore.h b/OVP/D3D9Client/gcCore.h index 95290a0f8..f8634acab 100644 --- a/OVP/D3D9Client/gcCore.h +++ b/OVP/D3D9Client/gcCore.h @@ -90,6 +90,7 @@ static class gcCore2 *pCoreInterface = NULL; #define IPF_PYRAMIDAL 0x0080 #define IPF_GAUSSIAN 0x0100 #define IPF_ANISOTROPIC 0x0200 +#define IPF_VERTEXTEX 0x0400 /// \defgroup dwFlags for gcSetupCustomCamera() API function ///@{ @@ -230,8 +231,7 @@ class gcIPInterface virtual void SetMesh(const MESHHANDLE hMesh, const char* tex = NULL, ipicull = ipicull::None); virtual bool Execute(bool bInScene = false); - virtual bool ExecuteTemplate(bool bInScene = false, ipitemplate = Rect); - virtual bool Execute(DWORD blendop, DWORD src, DWORD dest, bool bInScene = false, ipitemplate mde = Rect); + virtual bool Execute(DWORD blendop, bool bInScene = false, ipitemplate mde = Rect); // ---------------------------------------------------------------------------------- virtual int FindDefine(const char* key); diff --git a/OVP/D3D9Client/resource.h b/OVP/D3D9Client/resource.h index a34e564bc..349e5cad2 100644 --- a/OVP/D3D9Client/resource.h +++ b/OVP/D3D9Client/resource.h @@ -31,29 +31,17 @@ #define IDB_BITMAP1 111 #define IDC_AA 2002 #define IDC_AF 2003 -#define IDC_ATD_AUX1 2004 #define IDC_ATD_AUX2 2005 #define IDC_ATD_AUX3 2006 -#define IDC_ATD_BLUE 2009 -#define IDC_ATD_DEPTH 2010 -#define IDC_ATD_EXPO 2011 -#define IDC_ATD_GREEN 2012 #define IDC_ATD_HEIGHT 2013 #define IDC_ATD_IN 2014 #define IDC_ATD_MIE 2015 #define IDC_ATD_MPHASE 2017 #define IDC_ATD_MPOW 2018 -#define IDC_ATD_OUT 2019 -#define IDC_ATD_RED 2020 #define IDC_ATD_RPHASE 2021 #define IDC_ATD_RPOW 2022 -#define IDC_ATM_AUX1 2023 #define IDC_ATM_AUX2 2024 #define IDC_ATM_AUX3 2025 -#define IDC_ATM_BLUE 2028 -#define IDC_ATM_DEPTH 2029 -#define IDC_ATM_EXPO 2030 -#define IDC_ATM_GREEN 2031 #define IDC_ATM_HEIGHT 2032 #define IDC_ATM_IN 2033 #define IDC_ATM_LOAD 2034 @@ -61,8 +49,6 @@ #define IDC_ATM_MODE 2036 #define IDC_ATM_MPHASE 2038 #define IDC_ATM_MPOW 2039 -#define IDC_ATM_OUT 2040 -#define IDC_ATM_RED 2041 #define IDC_ATM_RPHASE 2042 #define IDC_ATM_RPOW 2043 #define IDC_ATM_SAVE 2044 @@ -152,16 +138,9 @@ #define IDC_POSTPROCESS 2140 #define IDC_ARCHIVE 2142 #define IDC_DBG_GROUPSTAT 2143 -#define IDC_ATM_GAMMATEST 2144 #define IDC_DBG_DEFINED 2145 #define IDC_ATM_TRGAMMA 2146 #define IDC_ATD_TRGAMMA 2147 -#define IDC_ATD_HAZECLR 2148 -#define IDC_ATM_HAZECLR 2149 -#define IDC_ATD_HAZEITS 2150 -#define IDC_ATM_HAZEITS 2151 -#define IDC_ATD_ATMGAMMA 2152 -#define IDC_ATM_ATMGAMMA 2153 #define IDC_DBG_DATAWND 2154 #define IDC_DBG_DATAVIEW 2155 #define IDC_LIGHTCONFIG 2156 @@ -204,3 +183,39 @@ #define IDC_DBG_CONES 2196 #define IDC_DBG_RELOADTEX 2197 #define IDC_BREAK 2198 +#define IDC_ATM_M_HEIGHT 2199 +#define IDC_ATD_M_HEIGHT 2201 +#define IDC_ATM_RAY 3002 +#define IDC_ATD_RAY 3003 +#define IDC_ATD_TRB 3004 +#define IDC_ATM_TRB 3005 +#define IDC_ATM_MIEIN 3006 +#define IDC_ATM_AUX5 3007 +#define IDC_ATM_AUX4 3008 +#define IDC_ATD_AUX4 3009 +#define IDC_ATD_AUX5 3010 +#define IDC_ATD_MIEIN 3011 +#define IDC_ATM_DISPLAY 3012 +#define IDC_ATM_TW_DST 3013 +#define IDC_ATM_TW_BRI 3015 +#define IDC_ATD_TW_DST 3016 +#define IDC_ATD_TW_BRI 3018 +#define IDC_ATM_COPYLOW 3019 +#define IDC_ATM_COPYHIGH 3020 +#define IDC_ATD_GREEN 3021 +#define IDC_ATM_GREEN 3022 +#define IDC_ATL_2 3023 +#define IDC_ATL_1 3024 +#define IDC_GFX_GLARE 3025 +#define IDC_GFX_VAL8 3026 +#define IDC_GFX_GLARE_RESET 3027 +#define IDC_GFX_RECOMPILE 3028 +#define IDC_DBG_EXPTEX 3029 +#define IDC_ESUNGLARE 3030 +#define IDC_ELIGHTSGLARE 3031 +#define IDC_EIRRAD 3032 +#define IDC_EARTHVISCFG 3033 +#define IDC_ESCACHE 3034 +#define IDC_EAQUALITY 3035 +#define IDC_ATM_TRLIGHTSHAD 3036 +#define IDC_ATD_TRLIGHTSHAD 3037 diff --git a/OVP/D3D9Client/samples/DrawOrbits/Draw.cpp b/OVP/D3D9Client/samples/DrawOrbits/Draw.cpp index a7f0c1e06..35f2db0ce 100644 --- a/OVP/D3D9Client/samples/DrawOrbits/Draw.cpp +++ b/OVP/D3D9Client/samples/DrawOrbits/Draw.cpp @@ -353,7 +353,7 @@ void Orbits::SetClipper(Sketchpad *pSkp2, OBJHANDLE hObj, DWORD idx) // FVECTOR3 Orbits::WorldDirection(VECTOR3 d) { - FVECTOR4 sc = mul(FVECTOR4(d), *pVP); + FVECTOR4 sc = mul(FVECTOR4(d, 1.0f), *pVP); float f = abs(1.0f / sc.w); sc.x *= f; sc.y *= -f; @@ -435,9 +435,9 @@ void Orbits::DrawOrbit(Sketchpad *pSkp2, COrbit *pOrb, OBJHANDLE hRef, oapi::FVE VECTOR3 _F = _P * (pOrb->SMa() * pOrb->Ecc()); // Offset the template to actual planet position FMATRIX4 mat; - mat._y = FVECTOR4(_Q * (pOrb->SMi() / smi) ); - mat._x = FVECTOR4(_P * (pOrb->SMa()) ); - mat._z = FVECTOR4(_W); + mat._y = FVECTOR4(_Q * (pOrb->SMi() / smi), 0.0f); + mat._x = FVECTOR4(_P * (pOrb->SMa()), 0.0f); + mat._z = FVECTOR4(_W, 0.0f); mat._p = FVECTOR4(Clip[0].Pos - _F, 1.0f); @@ -456,9 +456,9 @@ void Orbits::DrawOrbit(Sketchpad *pSkp2, COrbit *pOrb, OBJHANDLE hRef, oapi::FVE // Update matrix for generic drawing in 3D ---------------------- // - mat._y = FVECTOR4(_Q); - mat._x = FVECTOR4(_P); - mat._z = FVECTOR4(_W); + mat._y = FVECTOR4(_Q, 0.0f); + mat._x = FVECTOR4(_P, 0.0f); + mat._z = FVECTOR4(_W, 0.0f); mat._p = FVECTOR4(Clip[0].Pos, 1.0f); pSkp2->SetWorldTransform(&mat); diff --git a/OVP/D3D9Client/shaders/CelSphere.hlsl b/OVP/D3D9Client/shaders/CelSphere.hlsl new file mode 100644 index 000000000..93d49528b --- /dev/null +++ b/OVP/D3D9Client/shaders/CelSphere.hlsl @@ -0,0 +1,61 @@ +// ============================================================== +// Part of the ORBITER VISUALISATION PROJECT (OVP) +// Licensed under LGPL v2 +// Copyright (C) 2021 Jarmo Nikkanen +// ============================================================== + +#define BOOL bool + +struct CelDataStruct +{ + float4x4 mWorld; + float4x4 mViewProj; + float fAlpha; + float fBeta; +}; + +// Booleans go to sepatate structure. (not mixing different datatypes in a structure) +// Also bool is 32-bits in HLSL therefore must use BOOL in C++ structure +struct CelDataFlow +{ + BOOL bAlpha; + BOOL bBeta; +}; + +struct TILEVERTEX // (VERTEX_2TEX) Vertex declaration used for surface tiles and cloud layer +{ + float3 posL : POSITION0; + float3 normalL : NORMAL0; + float2 tex0 : TEXCOORD0; + float elev : TEXCOORD1; +}; + +struct CelSphereVS +{ + float4 posH : POSITION0; + float2 tex0 : TEXCOORD0; +}; + +uniform extern CelDataStruct Const; +uniform extern CelDataFlow Flow; + +sampler2D tTexA; +sampler2D tTexB; + +CelSphereVS CelVS(TILEVERTEX vrt) +{ + // Zero output. + CelSphereVS outVS = (CelSphereVS)0; + float3 posW = mul(float4(vrt.posL, 1.0f), Const.mWorld).xyz; + outVS.posH = mul(float4(posW, 1.0f), Const.mViewProj); + outVS.tex0 = vrt.tex0; + return outVS; +} + +float4 CelPS(CelSphereVS frg) : COLOR +{ + float3 vColor = 0; + if (Flow.bAlpha) vColor += tex2D(tTexA, frg.tex0).rgb * Const.fAlpha; + if (Flow.bBeta) vColor += tex2D(tTexB, frg.tex0).rgb * Const.fBeta; + return float4(vColor, 1.0); +} diff --git a/OVP/D3D9Client/shaders/D3D9Client.fx b/OVP/D3D9Client/shaders/D3D9Client.fx index ab2b319f7..471df002a 100644 --- a/OVP/D3D9Client/shaders/D3D9Client.fx +++ b/OVP/D3D9Client/shaders/D3D9Client.fx @@ -39,8 +39,10 @@ struct Mtrl struct Sun { float3 Dir; - float3 Color; float pad; - float3 Ambient; float pad2; + float3 Color; // Color and Intensity of received sunlight + float3 Ambient; // Ambient light level (Base Objects Only, Vessels are using dynamic methods) + float3 Transmission; // Visibility through atmosphere (1.0 = fully visible, 0.0 = obscured) + float3 Inscatter; // Amount of incattered light from haze }; struct Light @@ -608,7 +610,8 @@ SimpleVS BasicVS(NTVERTEX vrt) float4 SimpleTechPS(SimpleVS frg) : COLOR { - return tex2D(SimpleS, frg.tex0); + float4 c = tex2D(SimpleS, frg.tex0); + return float4(c.rgb, c.a * gMix); } float4 PanelTechPS(SimpleVS frg) : COLOR diff --git a/OVP/D3D9Client/shaders/GKernel.txt b/OVP/D3D9Client/shaders/GKernel.txt new file mode 100644 index 000000000..d607f48fe --- /dev/null +++ b/OVP/D3D9Client/shaders/GKernel.txt @@ -0,0 +1,57 @@ +-0.98021, -0.23003 +-1.01892, -0.04607 +-0.72275, -0.73153 +-0.73529, -0.49362 +-0.74056, -0.18397 +-0.78985, 0.04172 +-0.78278, 0.20061 +-0.72534, 0.44451 +-0.68829, 0.68449 +-0.52418, -0.72776 +-0.51887, -0.45061 +-0.44558, -0.18761 +-0.52242, -0.02499 +-0.53730, 0.23044 +-0.43903, 0.54231 +-0.45204, 0.77262 +-0.21119, -0.95409 +-0.25786, -0.79883 +-0.31138, -0.51868 +-0.29479, -0.27447 +-0.18909, -0.03900 +-0.25497, 0.27074 +-0.28922, 0.51331 +-0.28605, 0.78432 +-0.30000, 0.96334 +-0.03211, -0.94682 +0.01644, -0.77356 +0.00839, -0.43808 +-0.03113, -0.26783 +-0.01473, 0.04185 +0.02777, 0.26626 +-0.01912, 0.51522 +-0.05026, 0.73469 +0.01320, 0.95521 +0.22899, -0.71729 +0.25520, -0.49421 +0.29083, -0.24603 +0.18946, -0.04176 +0.29565, 0.19331 +0.30575, 0.49435 +0.21233, 0.80832 +0.24196, 0.96558 +0.54084, -0.74038 +0.50859, -0.55159 +0.55959, -0.26395 +0.54012, 0.04823 +0.51305, 0.21757 +0.49566, 0.48157 +0.53794, 0.70740 +0.79173, -0.55010 +0.73807, -0.22655 +0.79403, -0.01283 +0.80630, 0.29530 +0.69078, 0.55434 +0.71813, 0.73558 +0.93347, -0.04549 +0.94506, 0.29291 diff --git a/OVP/D3D9Client/shaders/Glare.hlsl b/OVP/D3D9Client/shaders/Glare.hlsl new file mode 100644 index 000000000..bc7e0b909 --- /dev/null +++ b/OVP/D3D9Client/shaders/Glare.hlsl @@ -0,0 +1,248 @@ +// =================================================== +// Copyright (C) 2022 Jarmo Nikkanen +// licensed under MIT +// =================================================== + + + +// ==================================================================== +// GPU based computation of local lights visibility (including the Sun) +// ==================================================================== + +float ilerp(float a, float b, float x) +{ + return saturate((x - a) / (b - a)); +} + +float3 HDRtoLDR(float3 hdr) +{ + float3 h2 = hdr * hdr; + return hdr * pow(max(0, 1.0f + h2 * h2), -0.25); +} + +sampler2D tDepth; + +#define LocalKernelSize 57 +static const float iLKS = 1.0f / LocalKernelSize; + +uniform extern struct { + float4x4 mVP; + float4x4 mSVP; + float4 vSrc; + float3 vDir; +} cbPS; + +uniform extern float2 cbKernel[LocalKernelSize]; + +struct LData +{ + float4 posH : POSITION0; // For rendering + float4 smpH : TEXCOORD0; // For sampling screen depth bufer + float3 posW : TEXCOORD1; // Camera centric location ECL + float cone : TEXCOORD3; // Attennuation by light-cone +}; + +LData VisibilityVS(float posL : POSITION0, float4 posW : TEXCOORD0) +{ + LData outVS = (LData)0; + outVS.posH = mul(float4(posL.x + 0.5f, 0.0f, 0.0f, 1.0f), cbPS.mVP); // Render projection + outVS.smpH = mul(float4(posW.xyz, 1.0f), cbPS.mSVP); // Depth sampling projection + outVS.posW = posW.xyz; + outVS.cone = posW.a; + return outVS; +} + +// Check sun/light "glare" visibility +// +float4 VisibilityPS(LData frg) : COLOR +{ + float4 smpH = frg.smpH; + smpH.xyz /= smpH.w; + float2 sp = smpH.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); // Scale and offset to 0-1 range + + if (sp.x < 0 || sp.y < 0) return 0.0f; // If a sample is outside border -> obscured + if (sp.x > 1 || sp.y > 1) return 0.0f; + + float2 vScale = 40.0f * cbPS.vSrc.zz; // Kernel scale factor (from unit kernel) + float fDepth = dot(frg.posW, cbPS.vDir) - 0.25f; // Depth to compare + float fRet = 0; + + [unroll] for (int i = 0; i < LocalKernelSize; i++) { + float2 s = sp + cbKernel[i].xy * vScale * 0.4f; + if (s.x < 0 || s.x > 1) { fRet += iLKS; continue; } + if (s.y < 0 || s.y > 1) { fRet += iLKS; continue; } + float d = tex2D(tDepth, s).a; + fRet += d > 0.1f && d < fDepth ? iLKS : 0; + } + + return 1.0f - fRet; +} + + + +// ==================================================================== +// Rendering of glares for the Sun and local lights +// ==================================================================== + +sampler2D tVis; // Pre-computed visibility factors +sampler2D tTex0; // Main Glare +sampler2D tTex1; // Atmospheric Glare + +uniform extern struct { + float4x4 mVP; + float4 Pos; + float4 Color; + float GPUId; + float Alpha; + float Blend; +} Const; + + +struct OutputVS +{ + float4 posH : POSITION0; + float3 uvi : TEXCOORD0; +}; + + +OutputVS GlareVS(float3 posL : POSITION0, float2 tex0 : TEXCOORD0) +{ + // Zero output. + OutputVS outVS = (OutputVS)0; + + float visibility = smoothstep(0.5f, 1.0f, tex2Dlod(tVis, float4(Const.GPUId, 0.5f, 0, 0)).r); + + posL.xy *= Const.Pos.zw * (0.01f + visibility); + posL.xy += Const.Pos.xy; + + outVS.posH = mul(float4(posL.xy - 0.5f, 0.0f, 1.0f), Const.mVP); + outVS.uvi = float3(tex0.xy, visibility); + + return outVS; +} + + +float4 GlarePS(OutputVS frg) : COLOR +{ + float t0 = max(0, tex2D(tTex0, frg.uvi.xy).r - 0.1f); // Texture intensity + //float t1 = max(0, tex2D(tTex1, frg.uvi.xy).r - 0.1f); // Texture intensity + //float t = lerp(t1, t0, Const.Blend); + float a = saturate(1.0f - exp(-frg.uvi.z * Const.Alpha * t0)); + return float4(HDRtoLDR(Const.Color.rgb * sqrt(t0 + 1.0f)), a); +} + + + + + + + + +// ==================================================================== +// Creation of "glare" textures +// ==================================================================== + + + +// ====================================================================== +// Render sun "Glare" (seen in space) +// +float4 CreateSunGlarePS(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + u = u * 2.0 - 1.0; v = v * 2.0 - 1.0; + + float a = atan2(u, v); + float r = sqrt(u * u + v * v); + + float q = 0.5f + 0.3f * pow(sin(3.0f * a), 4.0f); + float w = 0.5f + 0.2f * pow(sin(30.0f * a), 2.0f) * pow(sin(41.0f * a), 2.0f); + + //float I = pow(max(0, 2.0f * (1 - r / q)), 12.0f); + //float K = pow(max(0, 2.0f * (1 - r / w)), 12.0f); + //float I = exp(max(0, 10.0f * (1 - r / q))) - 1.0f; + //float K = exp(max(0, 10.0f * (1 - r / w))) - 1.0f; + + float L = pow(max(0, (1 - r / q)), 6.0f) * 3.0f; // Low frequency spikes + float H = pow(max(0, (1 - r / w)), 6.0f) * 5.0f; // High frequency spikes + float C = ilerp(0.03, 0.01, r) * 7.0f; // Core + float S = ilerp(1.7f, 0.35f, r); // Skirt + + C *= C; + C += S * S * 0.40f; + + return float4(max(L + C, H + C), 0, 0, 1); +} + + + +// ====================================================================== +// Render sun "Glare" (seen in atmosphere) +// +float4 CreateSunGlareAtmPS(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + u = u * 2.0 - 1.0; v = v * 2.0 - 1.0; + + float a = atan2(u, v); + float r = sqrt(u * u + v * v); + + float q = 0.5f + 1.0f * pow(sin(3.0f * a), 4.0f); + float w = 0.5f + 0.8f * pow(sin(30.0f * a), 2.0f) * pow(sin(41.0f * a), 2.0f); + + float I = pow(max(0, (1 - r / q)), 6.0f) * 4; + float K = pow(max(0, (1 - r / w)), 6.0f) * 8; + + float L = ilerp(0.05, 0.01, r) * 16.0f; + float T = max(0, max(I + L, K + L)) * 2.0f; + + return float4(T, 0, 0, 1); +} + + + +// ====================================================================== +// Render "Glare" for local light sources +// +float4 CreateLocalGlarePS(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + u = u * 2.0 - 1.0; v = v * 2.0 - 1.0; + + float a = atan2(u, v); + float r = sqrt(u * u + v * v); + + float q = 0.5f + 0.5f * pow(sin(3.0f * a), 4.0f); + float w = 0.5f + 0.3f * pow(sin(30.0f * a), 2.0f) * pow(sin(41.0f * a), 2.0f); + + float L = pow(max(0, (1 - r / q)), 6.0f) * 4.0f; + float H = pow(max(0, (1 - r / w)), 6.0f) * 8.0f; + float C = ilerp(0.15, 0.10, r) * 4.0f; + + return float4(max(L + C, H + C), 0, 0, 1); +} + + + + +// ====================================================================== +// Render regular Sun texture [ NOT IN USE ] +// +float4 CreateSunTexPS(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + u = u * 2.0 - 1.0; v = v * 2.0 - 1.0; + + float a = atan2(u, v); + float r = sqrt(u * u + v * v); + + float q = 0.5f + 1.0f * pow(sin(3.0f * a), 4.0f); + float w = 0.5f + 0.8f * pow(sin(30.0f * a), 2.0f) * pow(sin(41.0f * a), 2.0f); + + float I = pow(max(0, (1 - r / q)), 6.0f) * 1; + float K = pow(max(0, (1 - r / w)), 6.0f) * 3; + + float L = ilerp(0.08, 0.03, r) * 8.0f; + float T = max(0, max(I + L, K + L)); + + T = saturate(1.0f - exp(-T)); + return float4(1, 1, 1, T); +} + + diff --git a/OVP/D3D9Client/shaders/LightBlur.hlsl b/OVP/D3D9Client/shaders/LightBlur.hlsl index acb5433fa..791ca42ff 100644 --- a/OVP/D3D9Client/shaders/LightBlur.hlsl +++ b/OVP/D3D9Client/shaders/LightBlur.hlsl @@ -142,4 +142,40 @@ float4 PSMain(float x : TEXCOORD0, float y : TEXCOORD1) : COLOR } return 0; -} \ No newline at end of file +} + + +// -------------------------------------------------------------- +// Scale -2 to 3 +// +float4 HeightToColor(float a) +{ + if (a < -2) return float4(0, 0, 0, 1); + if (a > 3) return float4(0, 0, 0, 1); + if (a < -1) return saturate(float4(0, 0, 2 + a, 1.0)); + else if (a < 0) return saturate(float4(0, 1 + a, 1, 1.0)); + else if (a < 1) return saturate(float4(a, 1, 1 - a, 1.0)); + else if (a < 2) return saturate(float4(1, 2 - a, 0, 1.0)); + return saturate(float4(1, a - 2, a - 2, 1.0)); +} + + +// Visualize screen depth +// +float4 PSDepth(float x : TEXCOORD0, float y : TEXCOORD1) : COLOR +{ + float z = tex2D(tBack, float2(x,y)).a; + if (z <= 0) return float4(0, 0, 0, 1); + float q = 3 - log(1.0f + sqrt(max(0, z - 5.0))); + return float4(HeightToColor(q).rgb, 1); +} + +// Visualize screen space normals +// +float4 PSNormal(float tx : TEXCOORD0, float ty : TEXCOORD1) : COLOR +{ + float3 q = tex2D(tBack, float2(tx,ty)).xyz; + float2 xy = (q.xy + 1.0f) * 0.5f; + return float4(xy, abs(q.z), 1.0f); +} + diff --git a/OVP/D3D9Client/shaders/Metalness.fx b/OVP/D3D9Client/shaders/Metalness.fx index 250f74955..618ba0b61 100644 --- a/OVP/D3D9Client/shaders/Metalness.fx +++ b/OVP/D3D9Client/shaders/Metalness.fx @@ -161,7 +161,7 @@ float4 MetalnessPS(float4 sc : VPOS, PBRData frg) : COLOR if (gCfg.Rghn) fSmth = tex2D(RghnS, frg.tex0.xy).g; else fSmth = 1.0f; - // Fetch Roughness map + // Fetch Metalness map // if (gCfg.Metl) fMetal = tex2D(MetlS, frg.tex0.xy).g; else fMetal = gMtrl.metalness; @@ -257,6 +257,7 @@ float4 MetalnessPS(float4 sc : VPOS, PBRData frg) : COLOR SampleEnvMap(cEnv, dCN, fRgh, fMetal, rflW, nrmW); } +#if defined(_IRRADIANCE) // ====================================================================== // Sample Irradiance Map float3 cAmbient = Paraboloidal_LVLH(IrradS, nrmW).rgb; @@ -265,8 +266,10 @@ float4 MetalnessPS(float4 sc : VPOS, PBRData frg) : COLOR //cAmbient = saturate(cAmbient * (1.0f + 15.0f * gNightTime)); // Apply base ambient light cAmbient = max(cAmbient, gSun.Ambient); -#else +#endif +#endif +#if !defined(_ENVMAP) || !defined(_IRRADIANCE) // ====================================================================== // Compute Earth glow float angl = saturate((-dot(gCameraPos, nrmW) - gProxySize) * gInvProxySize); @@ -375,9 +378,16 @@ float4 MetalnessPS(float4 sc : VPOS, PBRData frg) : COLOR #endif #if defined(_LIGHTGLOW) + cDiff.rgb *= gSun.Transmission; + cDiff.rgb += gSun.Inscatter; return cDiff; #else - float3 h2 = cDiff.rgb*cDiff.rgb; - return float4(cDiff.rgb * pow(max(0, 1.0f + h2*h2), -0.25), cDiff.a); + float3 h2 = cDiff.rgb * cDiff.rgb; + cDiff.rgb *= pow(max(0, 1.0f + h2 * h2), -0.25); + + cDiff.rgb *= gSun.Transmission; + cDiff.rgb += gSun.Inscatter; + + return cDiff; #endif } diff --git a/OVP/D3D9Client/shaders/NewMesh.hlsl b/OVP/D3D9Client/shaders/NewMesh.hlsl new file mode 100644 index 000000000..ae9c89de6 --- /dev/null +++ b/OVP/D3D9Client/shaders/NewMesh.hlsl @@ -0,0 +1,172 @@ +// ============================================================== +// Part of the ORBITER VISUALISATION PROJECT (OVP) +// Dual licensed under GPL v3 and LGPL v3 +// Copyright (C) 2022 Jarmo Nikkanen +// ============================================================== + +#define BOOL bool + +// Constant Buffers -------------------------------------- +// +uniform extern struct VSConst { + float4x4 mVP; // View Projection Matrix + float4x4 mW; // World Matrix +} vs_const; + +uniform extern struct PSConst { + float3 Cam_X; + float3 Cam_Y; + float3 Cam_Z; +} ps_const; + +uniform extern struct PSBools { + BOOL bOIT; // Enable order independent transparency +} ps_bools; + + +sampler2D tDiff; + +// Vertex data input layouts ----------------------------- +// +struct MESH_VERTEX +{ + float3 posL : POSITION0; + float3 nrmL : NORMAL0; + float3 tanL : TANGENT0; + float3 tex0 : TEXCOORD0; // Handiness in .z +}; + +struct POSTEX +{ + float3 posL : POSITION0; + float2 tex0 : TEXCOORD0; +}; + +struct SHADOW_VERTEX +{ + float4 posL : POSITION0; +}; + + + +// Internal data feeds between VS and PS ------------------ +// +struct BShadowVS +{ + float4 posH : POSITION0; + float2 dstW : TEXCOORD0; +}; + +struct ShadowTexVS +{ + float4 posH : POSITION0; + float4 tex0 : TEXCOORD0; // distance in .zw +}; + +struct NormalTexVS +{ + float4 posH : POSITION0; + float3 posW : TEXCOORD0; + float3 nrmW : TEXCOORD1; + float2 tex0 : TEXCOORD2; +}; + +struct PBRData +{ + float4 posH : POSITION0; + float3 camW : TEXCOORD0; + float2 tex0 : TEXCOORD1; + float3 nrmW : TEXCOORD2; + float4 tanW : TEXCOORD3; // Handiness in .w +#if SHDMAP > 0 + float4 shdH : TEXCOORD4; +#endif +}; + +struct BasicData +{ + float4 posH : POSITION0; + float3 camW : TEXCOORD0; + float2 tex0 : TEXCOORD1; + float3 nrmW : TEXCOORD2; +#if SHDMAP > 0 + float4 shdH : TEXCOORD3; +#endif +}; + + + +// ----------------------------------------------------------------------------------- +// Shadow Map rendering with plain geometry (without texture) +// +BShadowVS ShdMapVS(SHADOW_VERTEX vrt) +{ + // Zero output. + BShadowVS outVS = (BShadowVS)0; + float3 posW = mul(float4(vrt.posL.xyz, 1.0f), vs_const.mW).xyz; + outVS.posH = mul(float4(posW, 1.0f), vs_const.mVP); + outVS.dstW = outVS.posH.zw; + return outVS; +} + +float4 ShdMapPS(BShadowVS frg) : COLOR +{ + return 1 - (frg.dstW.x / frg.dstW.y); +} + + + + +// ----------------------------------------------------------------------------------- +// Shadow Map rendering with texture alpha included +// +ShadowTexVS ShdMapOIT_VS(POSTEX vrt) +{ + // Zero output. + ShadowTexVS outVS = (ShadowTexVS)0; + float3 posW = mul(float4(vrt.posL.xyz, 1.0f), vs_const.mW).xyz; + outVS.posH = mul(float4(posW, 1.0f), vs_const.mVP); + outVS.tex0 = float4(vrt.tex0.xy, outVS.posH.zw); + return outVS; +} + +float4 ShdMapOIT_PS(ShadowTexVS frg) : COLOR +{ + if (ps_bools.bOIT) { + float alpha = tex2D(tDiff, frg.tex0.xy).a; + if (alpha < 0.75f) return 1.0f; + } + return 1 - (frg.tex0.z / frg.tex0.w); +} + + + + +// ----------------------------------------------------------------------------------- +// Render Normal and depth buffer +// +NormalTexVS NormalDepth_VS(MESH_VERTEX vrt) +{ + // Zero output. + NormalTexVS outVS = (NormalTexVS)0; + + outVS.posW = mul(float4(vrt.posL.xyz, 1.0f), vs_const.mW).xyz; + outVS.nrmW = mul(float4(vrt.nrmL, 0.0f), vs_const.mW).xyz; + outVS.posH = mul(float4(outVS.posW, 1.0f), vs_const.mVP); + outVS.tex0 = vrt.tex0.xy; + return outVS; +} + +float4 NormalDepth_PS(NormalTexVS frg) : COLOR +{ + if (ps_bools.bOIT) { + if (tex2D(tDiff, frg.tex0.xy).a < 0.75f) clip(-1); + } + //if (dot(frg.nrmW, ps_const.Cam_Z) > 0) clip(-1); + + float D = length(frg.posW); + float x = dot(frg.nrmW, ps_const.Cam_X); + float y = dot(frg.nrmW, ps_const.Cam_Y); + float z = sqrt(saturate(1.0 - (x * x + y * y))); + return float4(x, y, z, D); +} diff --git a/OVP/D3D9Client/shaders/NewPlanet.hlsl b/OVP/D3D9Client/shaders/NewPlanet.hlsl new file mode 100644 index 000000000..9a5c736f4 --- /dev/null +++ b/OVP/D3D9Client/shaders/NewPlanet.hlsl @@ -0,0 +1,911 @@ +// ============================================================================ +// Part of the ORBITER VISUALISATION PROJECT (OVP) +// licensed under LGPL v2 +// Copyright (C) 2022 Jarmo Nikkanen +// ============================================================================ + +#include "Scatter.hlsl" + +struct _Light +{ + float3 position[4]; /* position in world space */ + float3 direction[4]; /* direction in world space */ + float3 diffuse[4]; /* diffuse color of light */ + float3 attenuation[4]; /* Attenuation */ + float4 param[4]; /* range, falloff, theta, phi */ +}; + +#define Range 0 +#define Falloff 1 +#define Theta 2 +#define Phi 3 + +#define ATMNOISE 0.25 +#define GLARE_SIZE 5 // Larger value -> smaller + +// ---------------------------------------------------------------------------- +// Vertex input layouts from Vertex buffers to vertex shader +// ---------------------------------------------------------------------------- + +struct TILEVERTEX // (VERTEX_2TEX) Vertex declaration used for surface tiles and cloud layer +{ + float3 posL : POSITION0; + float3 normalL : NORMAL0; + float2 tex0 : TEXCOORD0; + float elev : TEXCOORD1; +}; + +// ---------------------------------------------------------------------------- +// Vertex Shader to Pixel Shader datafeeds +// ---------------------------------------------------------------------------- + +struct TileVS +{ + float4 posH : POSITION0; + float2 texUV : TEXCOORD0; // Texture coordinate + float4 camW : TEXCOORD1; // Radius in .w + float3 nrmW : TEXCOORD2; +#if defined(_SHDMAP) + float4 shdH : TEXCOORD3; +#endif +}; + +struct CldVS +{ + float4 posH : POSITION0; + float2 texUV : TEXCOORD0; // Texture coordinate + float3 nrmW : TEXCOORD1; + float3 posW : TEXCOORD2; +}; + +struct HazeVS +{ + float4 posH : POSITION0; + float2 texUV : TEXCOORD0; + float3 posW : TEXCOORD1; + float alpha : COLOR0; +}; + + +// Note: "bool" is 32-bits in a shaders (max count 16) +// +struct FlowControlPS +{ + BOOL bInSpace; // Camera in space (not in atmosphere) + BOOL bBelowClouds; // Camera is below cloud layer + BOOL bOverlay; // Overlay on/off + BOOL bShadows; // Shadow Map on/off + BOOL bLocals; // Local Lights on/off + BOOL bMicroNormals; // Micro texture has normals + BOOL bCloudShd; // Cloud shadow textures valid and enabled + BOOL bMask; // Nightlights/water mask texture is peovided + BOOL bRipples; // Water riples texture is peovided + BOOL bMicroTex; // Micro textures exists and enabled + BOOL bPlanetShadow; // Use spherical approximation for shadow +}; + +struct FlowControlVS +{ + BOOL bInSpace; // Camera in space (not in atmosphere) + BOOL bSpherical; // Ignore elevation, render as sphere + BOOL bElevOvrl; // ElevOverlay on/off +}; + +struct PerObjectParams +{ + float4x4 mWorld; // World Matrix + float4x4 mLVP; // Light-View-Projection + float4 vSHD; // Shadow Map Parameters + float4 vMSc[3]; // Micro Texture offset-scale + float4 vTexOff; // Texture offset-scale + float4 vCloudOff; // Cloud texture offset-scale + float4 vMicroOff; // Micro texture offset-scale + float4 vOverlayOff; // Overlay texture offset-scale + float4 vOverlayCtrl[4]; + float fAlpha; + float fBeta; + float fTgtScale; +}; + +uniform extern PerObjectParams Prm; +uniform extern FlowControlPS Flow; +uniform extern FlowControlVS FlowVS; +uniform extern _Light Lights; // Note: DX9 doesn't tolerate structure arrays outside FX framework +uniform extern bool Spotlight[4]; + + +sampler tDiff; // Diffuse texture +sampler tMask; // Nightlights / Specular mask texture +sampler tCloud; // 1st Cloud shadow texture +sampler tCloud2; // 2nd Cloud shadow texture +sampler tCloudMicro; +sampler tCloudMicroNorm; +sampler tNoise; // +sampler tOcean; // Ocean Normal Map Texture +sampler tMicroA; +sampler tMicroB; +sampler tMicroC; +sampler tGlare; +sampler tShadowMap; +sampler tOverlay; +sampler tMskOverlay; +sampler tElvOverlay; + + + + +// --------------------------------------------------------------------------------------------------- +// +float SampleShadows(float2 sp, float pd) +{ + if (sp.x < 0 || sp.y < 0) return 0.0f; // If a sample is outside border -> fully lit + if (sp.x > 1 || sp.y > 1) return 0.0f; + + if (pd < 0) pd = 0; + if (pd > 2) pd = 2; + + float2 dx = float2(Prm.vSHD[1], 0) * 1.5f; + float2 dy = float2(0, Prm.vSHD[1]) * 1.5f; + float va = 0; + + sp -= dy; + if ((tex2D(tShadowMap, sp - dx).r) > pd) va++; + if ((tex2D(tShadowMap, sp).r) > pd) va++; + if ((tex2D(tShadowMap, sp + dx).r) > pd) va++; + sp += dy; + if ((tex2D(tShadowMap, sp - dx).r) > pd) va++; + if ((tex2D(tShadowMap, sp).r) > pd) va++; + if ((tex2D(tShadowMap, sp + dx).r) > pd) va++; + sp += dy; + if ((tex2D(tShadowMap, sp - dx).r) > pd) va++; + if ((tex2D(tShadowMap, sp).r) > pd) va++; + if ((tex2D(tShadowMap, sp + dx).r) > pd) va++; + + return va * 0.1111111f; +} + +// ------------------------------------------------------------------------------------------------------------- +// Local light sources +// +void LocalLights( + out float3 diff_out, + in float3 nrmW, + in float3 posW) +{ + diff_out = 0; + + if (!Flow.bLocals) return; + int i; + + // Relative positions + float3 p[4]; + [unroll] for (i = 0; i < 4; i++) p[i] = posW - Lights.position[i]; + + // Square distances + float4 sd; + [unroll] for (i = 0; i < 4; i++) sd[i] = dot(p[i], p[i]); + + // Normalize + sd = rsqrt(sd); + [unroll] for (i = 0; i < 4; i++) p[i] *= sd[i]; + + // Distances + float4 dst = rcp(sd); + + // Attennuation factors + float4 att; + [unroll] for (i = 0; i < 4; i++) att[i] = dot(Lights.attenuation[i].xyz, float3(1.0, dst[i], dst[i] * dst[i])); + + att = rcp(att); + + // Spotlight factors + float4 spt = 1; + + [unroll] for (i = 0; i < 4; i++) { + spt[i] = (dot(p[i], Lights.direction[i]) - Lights.param[i][Phi]) * Lights.param[i][Theta]; + if (!Spotlight[i]) spt[i] = 1.0f; + } + + spt = saturate(spt); + + // Diffuse light factors + float4 dif; + [unroll] for (i = 0; i < 4; i++) dif[i] = dot(-p[i], nrmW); + + dif = saturate(dif); + dif *= (att * spt); + + [unroll] for (i = 0; i < 4; i++) diff_out += Lights.diffuse[i].rgb * dif[i]; +} + + +// ============================================================================ +// Render SkyDome and Horizon +// ============================================================================ + +HazeVS HorizonVS(float3 posL : POSITION0) +{ + // Zero output. + HazeVS outVS = (HazeVS)0; + + outVS.texUV = posL.xy*10.0; + + posL.xz *= lerp(Prm.vTexOff[0], Prm.vTexOff[1], posL.y); + posL.y = lerp(Prm.vTexOff[2], Prm.vTexOff[3], posL.y); + + outVS.posW = mul(float4(posL, 1.0f), Prm.mWorld).xyz; + outVS.posH = mul(float4(outVS.posW, 1.0f), Const.mVP); + + return outVS; +} + + +// SkyDome Shader, Renders the sky from with-in atmosphere +// +float4 HorizonPS(HazeVS frg) : COLOR +{ + float fNoise = (tex2Dlod(tNoise, float4(frg.texUV, 0, 0)).r - 0.5f) * 0.03; + + float3 uDir = normalize(frg.posW); + + SkyOut sky = GetSkyColor(uDir); + + float ph = dot(uDir, Const.toSun); + + float2 guv = float2(dot(uDir, Const.ZeroAz), dot(uDir, Const.Up)) * GLARE_SIZE + 0.5f; + float cGlr = tex2D(tGlare, guv).r * saturate(ph) * Const.SunVis; + + float3 color = HDR(sky.ray.rgb * RayPhase(ph) + (sky.mie.rgb + 0.0008f) * MiePhase(ph) * (0.75f + cGlr * Const.cGlare)); + + return float4(color + fNoise, sky.ray.a); +} + + +// Renders the horizon "ring" from space +// +float4 HorizonRingPS(HazeVS frg) : COLOR +{ + float3 uDir = normalize(frg.posW); + float3 uOrt = normalize(uDir - Const.toCam * dot(uDir, Const.toCam)); + + float d = dot(uDir, frg.posW); + float x = dot(uOrt, Const.SunAz) * 0.5 + 0.5; + float r = length(Const.CamPos + frg.posW); + float q = (r - Const.PlanetRad) / Const.AtmoAlt; + + float2 uv = float2(x, q > 0 ? sqrt(q) : 0); + + float4 cRay = tex2D(tSkyRayColor, uv).rgba; + float3 cMie = tex2D(tSkyMieColor, uv).rgb; + + float ph = dot(uDir, Const.toSun); + + float3 color = HDR(cRay.rgb * RayPhase(ph) + cMie * MiePhase(ph)); + + return float4(color, cRay.a); +} + + + +// ============================================================================ +// Planet Surface Renderer +// ============================================================================ + +#define AUX_DIST 0 // Vertex distance +#define AUX_NIGHT 1 // Night lights intensity +#define AUX_SLOPE 2 // Terrain slope factor 0.0=flat, 1.0=sloped +#define AUX_RAYDEPTH 3 // Optical depth of a ray + +TileVS TerrainVS(TILEVERTEX vrt) +{ + // Zero output. + TileVS outVS = (TileVS)0; + float4 vElev = 0; + float3 vNrmW; + + // Apply a world transformation matrix + float3 vPosW = mul(float4(vrt.posL, 1.0f), Prm.mWorld).xyz; + float3 vVrt = Const.CamPos + vPosW; + float3 vPlN = normalize(vVrt); + + if (FlowVS.bElevOvrl) + { + // ---------------------------------------------------------- + // Elevation Overlay + // + float2 vUVOvl = vrt.tex0.xy * Prm.vOverlayOff.zw + Prm.vOverlayOff.xy; + + // Sample Elevation Map + vElev = tex2Dlod(tElvOverlay, float4(vUVOvl, 0, 0)); + + // Construct world space normal + vNrmW = float3(vElev.xy, sqrt(saturate(1.0f - dot(vElev.xy, vElev.xy)))); + vNrmW = mul(float4(vNrmW, 0.0f), Prm.mWorld).xyz; + + // Reconstruct Elevation + vPosW += normalize(Const.CamPos + vPosW) * (vElev.z - vrt.elev) * vElev.w; + } + else { + vNrmW = mul(float4(vrt.normalL, 0.0f), Prm.mWorld).xyz; + } + + // Disrecard elevation and make the surface spherical + if (FlowVS.bSpherical) { + vPosW = (normalize(Const.CamPos + vPosW) * Const.PlanetRad) - Const.CamPos; + vNrmW = vPlN; + } + + outVS.posH = mul(float4(vPosW, 1.0f), Const.mVP); + +#if defined(_SHDMAP) + outVS.shdH = mul(float4(vPosW, 1.0f), Prm.mLVP); +#endif + + outVS.texUV.xy = vrt.tex0.xy; + outVS.camW = float4(-vPosW, dot(vVrt, vPlN)); + outVS.nrmW = vNrmW; + + return outVS; +} + + + +bool InRange(float2 a) +{ + return (a.x > 0.0f && a.x < 1.0f) && (a.y > 0.0f && a.y < 1.0f); +} + +float GGX_NDF(float dHN, float rgh) +{ + float r2 = rgh * rgh; + float dHN2 = dHN * dHN; + float d = (r2 * dHN2) + (1.0f - dHN2); + return r2 / (3.14f * d * d); +} + + +float4 TerrainPS(TileVS frg) : COLOR +{ + + float2 vUVSrf = frg.texUV.xy * Prm.vTexOff.zw + Prm.vTexOff.xy; + float2 vUVWtr = frg.texUV.xy * Prm.vMicroOff.zw + Prm.vMicroOff.xy; + float2 vUVCld = frg.texUV.xy * Prm.vCloudOff.zw + Prm.vCloudOff.xy; + + vUVWtr.x += Const.Time / 180.0f; + + float3 cNrm; + float fChA = 0.0f, fChB = 0.0f; + +#if defined(_RIPPLES) + cNrm = tex2D(tOcean, vUVWtr).xyz; +#endif + + // Fetch Main Textures + float4 cTex = tex2D(tDiff, vUVSrf); + float4 cMsk = float4(0, 0, 0, 1); + if (Flow.bMask) cMsk = tex2D(tMask, vUVSrf); + +#if defined(_DEVTOOLS) + if (Flow.bOverlay) { + float2 vUVOvl = frg.texUV.xy * Prm.vOverlayOff.zw + Prm.vOverlayOff.xy; + if (InRange(vUVOvl)) { + float4 cOvl = tex2D(tOverlay, vUVOvl); + float4 cWtr = tex2D(tMskOverlay, vUVOvl); + cTex.rgb = lerp(cTex.rgb, cOvl.rgb, cOvl.a * Prm.vOverlayCtrl[0].rgb); + cMsk.rgb = lerp(cMsk.rgb, cWtr.rgb, cOvl.a * Prm.vOverlayCtrl[1].rgb); + cMsk.a = lerp(cMsk.a, cWtr.a, Prm.vOverlayCtrl[1].a); + } + } +#endif + +#if defined(_CLOUDSHD) + if (Flow.bCloudShd) { + fChA = tex2D(tCloud, vUVCld).a; + fChB = tex2D(tCloud2, vUVCld - float2(1, 0)).a; + } +#endif + + float fShadow = 1.0f; + +#if defined(_SHDMAP) + if (Flow.bShadows) { + frg.shdH.xyz /= frg.shdH.w; + frg.shdH.z = 1 - frg.shdH.z; + float2 sp = frg.shdH.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); + float pd = frg.shdH.z + 0.05f * Prm.vSHD[3]; + fShadow = 1.0f - SampleShadows(sp, pd); + } +#endif + + float3 cFar, cMed, cLow; + +#if defined(_MICROTEX) + float2 UV = frg.texUV.xy; + // Create normals + if (Flow.bMicroNormals) { + // Normal in .ag luminance in .b + cFar = tex2D(tMicroC, UV * Prm.vMSc[2].zw + Prm.vMSc[2].xy).agb; // High altitude micro texture C + cMed = tex2D(tMicroB, UV * Prm.vMSc[1].zw + Prm.vMSc[1].xy).agb; // Medimum altitude micro texture B + cLow = tex2D(tMicroA, UV * Prm.vMSc[0].zw + Prm.vMSc[0].xy).agb; // Low altitude micro texture A + } + else { + // Color in .rgb no normals + cFar = tex2D(tMicroC, UV * Prm.vMSc[2].zw + Prm.vMSc[2].xy).rgb; // High altitude micro texture C + cMed = tex2D(tMicroB, UV * Prm.vMSc[1].zw + Prm.vMSc[1].xy).rgb; // Medimum altitude micro texture B + cLow = tex2D(tMicroA, UV * Prm.vMSc[0].zw + Prm.vMSc[0].xy).rgb; // Low altitude micro texture A + } +#endif + + float3 cRfl = 0; + float3 nvrW = normalize(frg.nrmW); // Per-pixel surface normal vector + float3 vRay = normalize(frg.camW.xyz); // Unit viewing ray + float3 vVrt = Const.CamPos - frg.camW.xyz; // Geo-centric pixel position + float3 vPlN = normalize(vVrt); // Planet mean normal + float3 hlvW = normalize(vRay + Const.toSun); + float dst = dot(vRay, frg.camW.xyz); // Pixel to camera distance + float rad = frg.camW.w; // Pixel geo-distance + float alt = rad - Const.PlanetRad; // Pixel altitude over mean radius + float fSrf = (1.0 - Const.CamSpace); // Camera colse to surface ? + float fMask = (1.0 - cMsk.a); // Specular Mask + float fSpe = 0; + float fAmpf = 1.0f; + float fDRS = dot(vRay, Const.toSun); + float fDPS = dot(vPlN, Const.toSun); // Mean normal dot sun + + +#if defined(_WATER) +#if defined(_RIPPLES) + + // Compute world space normal for water rendering + // + cNrm.xy = clamp((cNrm.xy - 0.5f) * fSrf * 5.0f, -1, 1); + cNrm.z = cos(cNrm.x * cNrm.y * 1.570796); + float3 wnrmW = (Const.vTangent * cNrm.r) + (Const.vBiTangent * cNrm.g) + (vPlN * cNrm.b); + wnrmW = lerp(nvrW, wnrmW, fMask); + float fDWS = dot(wnrmW, Const.toSun); // Water normal dot sun + + // Render with specular ripples and fresnel water ------------------------- + // + float fDCH = saturate(dot(vRay, hlvW)); + float fDCN = saturate(dot(vRay, wnrmW)); + float fDHN = dot(hlvW, wnrmW); + + float2 f = 1.0 - float2(fDCH, fDCN); + float2 fFresnel = f * f * f * f; + + // Compute specular reflection intensity + fSpe = GGX_NDF(fDHN, 0.1f + saturate(fDWS) * 0.1f) * (0.1f + fFresnel.x * 0.9f) * fMask; + fSpe /= (4.0f * fDCH * max(fDWS, fDCN) + 1e-3); + + // Apply fresnel water only if close enough to a surface + // + if (!Flow.bInSpace) + { + cRfl = GetAmbient(reflect(-vRay, wnrmW)) * fFresnel.y * fSrf * fMask; + // Attennuate diffuse texture for fresnel refl. + cTex.rgb *= saturate(1.0f - fFresnel.y * fSrf * fMask); + } + +#else + // Fallback to simple specular reflection + float fDHN = dot(hlvW, nvrW); + fSpe = pow(saturate(fDHN), 60.0f) * fMask * 5.0f; +#endif +#endif + + float3 nrmW = nvrW; // Micro normal defaults to vertex normal + + // Render with surface microtextures -------------------------------------- + // +#if defined(_MICROTEX) + + if (Flow.bMicroTex) + { + float step1 = smoothstep(15000, 3000, dst); + step1 *= (step1 * step1); + float3 cFnl = max(0, min(2, 1.333f * (cFar + cMed + cLow) - 1)); + + // Create normals + if (Flow.bMicroNormals) + { + cFnl = cFnl.bbb; + +#if defined(_SOFT) + float2 cMix = (cFar.rg + cMed.rg + cLow.rg) * 0.6666f; // SOFT BLEND +#endif +#if defined(_MED) + float2 cMix = (cFar.rg + 0.5f) * (cMed.rg + 0.5f) * (cLow.rg + 0.5f); // MEDIUM BLEND + fAmpf = 2.0f; +#endif +#if defined(_HARD) + float2 cMix = cFar.rg * cMed.rg * cLow.rg * 8.0f; // HARD BLEND + fAmpf = 4.0f; +#endif + + float3 cNrm = float3((cMix - 1.0f) * 2.0f, 0) * step1; + cNrm.z = cos(cNrm.x * cNrm.y * 1.57); + + // Approximate world space normal + nrmW = normalize((Const.vTangent * cNrm.x) + (Const.vBiTangent * cNrm.y) + (nvrW * cNrm.z)); + + // Bend the normal towards sun a bit + nrmW = normalize(nrmW + Const.toSun * 0.06f); + } + + // Apply luminance + cTex.rgb *= lerp(1.0f, cFnl, step1); + } +#endif + + + float3 cDiffLocal = 0; + +#if defined(_LOCALLIGHTS) + LocalLights(cDiffLocal, nrmW, -frg.camW.xyz); +#endif + +#if defined(_NO_ATMOSPHERE) + + float fDNS = saturate(dot(nvrW, Const.toSun)); + float fDCN = saturate(dot(nvrW, Const.toCam)); + float fLvl = 2.0f * fDNS / (fDNS + fDCN + 0.5f); + float fSHD = 1.0f; + + // Shadowing by planet + if (Flow.bPlanetShadow) { + float palt = sqrt(saturate(1.0f - fDPS * fDPS)) * rad - Const.PlanetRad; + fSHD = fDPS > 0 ? 1.0f : ilerp(Const.MinAlt, Const.MaxAlt, palt); + } + + // Amplify light and shadows + fLvl += dot(nvrW - vPlN, Const.toSun) * fLvl * Const.trLS; + + // Add opposition surge + fLvl += pow(saturate(fDRS), 4.0f) * 0.3f * fDNS; + +#if defined(_MICROTEX) + fLvl += dot(nrmW - nvrW, Const.toSun) * ilerp(0.0, 0.03, fLvl) * fAmpf; +#endif + + fLvl *= fSHD; // Apply planet shadow + + float3 color = cTex.rgb * LightFX(max(fLvl, 0) * fShadow + cDiffLocal); + return float4(pow(saturate(color * Const.TrExpo), Const.TrGamma), 1.0f); // Gamma corrention +#else + + float fShd = 1.0f; + +#if defined(_CLOUDSHD) + // Do we render cloud shadows ? + if (Flow.bCloudShd) { + fShd = (vUVCld.x < 1.0 ? fChA : fChB); + fShd = saturate(1.0 - fShd * Prm.fAlpha); + } +#endif + + float3 cNgt = 0; + float3 cNgt2 = 0; + float fDNS = dot(nvrW, Const.toSun); // Vertex normal dot sun + +#if defined(_NIGHTLIGHTS) + + // Night lights ? + float fNgt = saturate(-fDPS * 4.0f + 0.05f) * Prm.fBeta; // Night lights intensity and 'on' time + + cMsk.b = (cMsk.b > 0.15f ? cMsk.b : 0.0f); // Blue dirt filter + + cNgt = cMsk.rgb * (1 - Const.CamSpace) * fNgt; // Nightlights surface texture illumination term + cNgt2 = cMsk.rgb * Const.CamSpace * 4.0f * fNgt; // Nightlights orbital visibility +#endif + + float fNoise = (tex2Dlod(tNoise, float4(frg.texUV.xy * 4.0f * Prm.fTgtScale, 0, 0)).r - 0.5f) * ATMNOISE; + + // Terrain with gamma correction and attennuation + cTex.rgb = pow(saturate(cTex.rgb), Const.TrGamma) * Const.TrExpo; + + // Evaluate ambient approximation + float4 cAmb = AmbientApprox(vPlN, false); + + LandOut sct = GetLandView(rad, vPlN); + + // Get the color of sunlight and set maximum intensity to 1.0 + float3 cSun = GetSunColor(fDPS, alt); + float3 cSF = cSun * Const.cSun; + float fMx = max(max(cSF.r, cSF.g), cSF.b); + cSF = fMx > 1.0 ? cSF / fMx : cSF; + + float fL = Const.trLS * 0.3f; + float fZ = clamp(dot(nvrW - vPlN, Const.toSun) * Const.trLS, -fL, fL); + float fX = 1.0f - pow(1.0f - saturate(fDPS), 2.0f); + + fZ = fZ > 0 ? fZ * 2.0f : fZ; + +#if defined(_MICROTEX) + float fG = dot(nrmW - nvrW, Const.toSun) * fAmpf; +#else + float fG = 0.0f; +#endif + + // Diffuse "lambertian" shading term + float fD = lerp(fX + (fG + fZ) * fX, fDPS * fDPS, fMask); + + // Water masking + float fM = 0.5f - fMask * 0.25f; + + // Ambient light for terrain + // Color Distance Altitude factor Particle Density + float3 cA = normalize(cAmb.rgb + cSF * 4.0f) * cAmb.a * cAmb.g * fM * exp(-alt * Const.iH.r) * Const.rmI.r * 6e5 * Const.TW_Terrain; + + fShd = saturate(fShd + (1.0f - fX)); + + // Bake light and shadow terms + float3 cL = cSF * fD * fShadow * fShd; + + // Lit the texture with various things + cTex.rgb *= cL * 2.0f + (cA + cDiffLocal + Const.cAmbient * Const.Ambient) * saturate(1.0f + fG + fZ) + cNgt; + + cTex.rgb = max(float3(0, 0, 0), cTex.rgb); + + // Add Reflection + cTex.rgb += cRfl * 0.75f; + + // Add Specular component + cTex.rgb += cSun * fSpe * smoothstep(-0.001f, 0.03f, fDPS); + + // Amplify cloud shadows for orbital views + float fOrbShd = 1.0f - (1.0f - fShd) * Const.CamSpace * 0.5f; + + // Add Haze and night lights + cTex.rgb *= sct.atn.rgb; + cTex.rgb += (sct.ray.rgb * RayPhase(-fDRS) + sct.mie.rgb * MiePhase(-fDRS)) * fOrbShd * (1.0f + fNoise); + cTex.rgb += cNgt2; + + return float4(HDR(cTex.rgb), 1.0f); +#endif +} + + + + + + +// ============================================================================ +// Planet Cloud Renderer +// ============================================================================ + +CldVS CloudVS(TILEVERTEX vrt) +{ + // Zero output. + CldVS outVS = (CldVS)0; + + // Apply a world transformation matrix + float3 vPosW = mul(float4(vrt.posL, 1.0f), Prm.mWorld).xyz; + float3 vNrmW = mul(float4(vrt.normalL, 0.0f), Prm.mWorld).xyz; + + outVS.posH = mul(float4(vPosW, 1.0f), Const.mVP); + outVS.nrmW = vNrmW; + outVS.posW = vPosW; + outVS.texUV.xy = vrt.tex0.xy; // Note: vrt.tex0 is un-used (hardcoded in Tile::CreateMesh and varies per tile) + + return outVS; +} + + +// ============================================================================ +// +float4 CloudPS(CldVS frg) : COLOR +{ + float2 vUVTex = frg.texUV.xy; + float4 cTex = tex2D(tDiff, vUVTex); + float3 vRay; + float3 vPxl; + float dRC; + float fNrm = 1.0f; + + if (Flow.bBelowClouds) { + float rRef = Const.PlanetRad + Const.smi * 0.5f; // Reference altitude + float3 vRef = Const.toCam * rRef; + vRay = normalize(Const.toCam * (Const.CamRad - rRef) + frg.posW); // Viewing ray to the pixel + dRC = dot(vRay, Const.toCam); + float fEca2 = 1.0f - dRC * dRC; // Ray horizon angle^2 + float fD = Const.smi * rsqrt(1.0f - Const.ecc * Const.ecc * fEca2); // Distance to ellipse threshold + vPxl = vRef + vRay * fD; // Pretend the pixel being closer and lower + } + else { + vRay = normalize(frg.posW); // Viewing ray to the pixel + dRC = dot(vRay, Const.toCam); + vPxl = Const.CamPos + frg.posW; // Pixel's geocentric location + } + + float3 vPlN = normalize(vPxl); // Mean Normal at pixel's locatin + float3 nrm = vPlN; + + float dRS = dot(vRay, Const.toSun); + float dMNus = dot(vPlN, Const.toSun); + float dMN = saturate(dMNus); // Mean normal sun angle + float fPxR = dot(vPxl, vPlN); // Pixel geo distance + float fPxA = fPxR - Const.PlanetRad; // Pixel altitude + + if (!Flow.bBelowClouds) fPxA = Const.CloudAlt; + + + // ----------------------------------------------- + // Cloud layer rendering for Earth + // ----------------------------------------------- + +#if defined(_CLOUDMICRO) + float2 vUVMic = frg.texUV.xy * Prm.vMicroOff.zw + Prm.vMicroOff.xy; + float4 cMic = tex2D(tCloudMicro, vUVMic); +#endif + + +#if defined(_CLOUDNORMALS) +#if defined(_CLOUDMICRO) + + float4 cMicNorm = tex2D(tCloudMicroNorm, vUVMic); // Filename "cloud1_norm.dds" + + // Extract normal from transparency (height) data + // Filter width + float d = 2.0 / 512.0; + + float x1 = tex2D(tDiff, vUVTex + float2(-d, 0)).a; + float x2 = tex2D(tDiff, vUVTex + float2(+d, 0)).a; + nrm.x = (x1 * x1 - x2 * x2); + + float y1 = tex2D(tDiff, vUVTex + float2(0, -d)).a; + float y2 = tex2D(tDiff, vUVTex + float2(0, +d)).a; + nrm.y = (y1 * y1 - y2 * y2); + + // Blend in cloud normals only on moderately thick clouds, allowing the highest cloud tops to be smooth. + nrm.xy = (nrm.xy + saturate((cTex.a * 10.0f) - 3.0f) * saturate(((1.0f - cTex.a) * 10.0f) - 1.0f) * (cMicNorm.rg - 0.5f)); // new + + // Increase normals contrast based on sun-earth angle. + nrm.xyz = nrm.xyz * (1.0f + (0.5f * dMN)); + + nrm.z = sqrt(1.0f - saturate(nrm.x * nrm.x + nrm.y * nrm.y)); + + // Approximate world space normal from local tangent space + nrm = normalize((Const.vTangent * nrm.x) + (Const.vBiTangent * nrm.y) + (vPlN * nrm.z)); + + float dCS = dot(nrm, Const.toSun); // Cloud normal sun angle + + // Brighten the lighting model for clouds, based on sun-earth angle. Twice is better. + // Low sun angles = greater effect. No modulation leads to washed out normals at high sun angles. + dCS = saturate((1.0f - dMN) * (dCS * (1.0f - dCS)) + dCS); + dCS = saturate((1.0f - dMN) * (dCS * (1.0f - dCS)) + dCS); + + // With a high sun angle, don't let the dCS go below 0.2 to avoid unnaturally dark edges. + dCS = lerp(0.2f * dMN, 1.0f, dCS); + + // Effect of normal/sun angle to color + // Add some brightness (borrowing red channel from sunset attenuation) + // Adding it to the sun illumination factor, taking care to keep from saturating + fNrm = dCS +((1.0f - dCS) * 0.2f); +#endif +#endif + +#if defined(_CLOUDMICRO) + float f = cTex.a; + float g = lerp(1.0f, cMic.a, 1.0f - abs(dot(Const.vPolarAxis, vPlN))); + float h = (g + 4.0f) * 0.2f; + cTex.a = saturate(lerp(g, h, f) * f); +#endif + + + if (Flow.bBelowClouds) + { + // Get sunlight color + float3 cSun = GetSunColor(dMNus, fPxA); + + // Get ambient information + float4 cMlt = AmbientApprox(vPlN); + + cSun *= saturate(dRS + 1.3f); + float fPh = pow(saturate(1.0f - dRC), 32.0f) * pow(saturate(dRS), 10.0f); // Boost near horizon and close the sun + cSun *= 1.0f + fPh * 8.0f; + + cSun *= Const.cSun * fNrm; + cSun *= Const.Clouds; + cSun += cMlt.rgb * cMlt.a * 0.2f; + + LandOut sct = GetLandView(fPxA + Const.PlanetRad, vPlN); + + cTex.rgb *= cSun; + cTex.rgb *= sct.atn.rgb; + cTex.rgb += sct.ray.rgb * 2.0f; + + return float4(HDR(cTex.rgb), saturate(cTex.a)); + } + else { + + // Get sunlight color + float3 cSun = GetSunColor(dMN, fPxA); + + // Get ambient information + float4 cAmb = AmbientApprox(dMNus); + float3 cMSC = Const.RayWave * Const.RayWave * Const.Clouds; // Multiscatter color + + cSun = sqrt(cMSC * cMSC + cSun * cSun * fNrm) * cAmb.a; + + LandOut sct = GetLandView(fPxA + Const.PlanetRad, vPlN); + + cTex.rgb *= cSun; + cTex.rgb *= sct.atn.rgb; + cTex.rgb += sct.ray.rgb; + + return float4(sqr(HDR(cTex.rgb * 4.0f)), cTex.a * cAmb.a * cAmb.a); + } +} + + + + + + + + +// ============================================================================ +// Gas Giant Renderer +// ============================================================================ + +TileVS GiantVS(TILEVERTEX vrt) +{ + // Zero output. + TileVS outVS = (TileVS)0; + + // Apply a world transformation matrix + float3 vPosW = mul(float4(vrt.posL, 1.0f), Prm.mWorld).xyz; + float3 vNrmW = mul(float4(vrt.normalL, 0.0f), Prm.mWorld).xyz; + + outVS.posH = mul(float4(vPosW, 1.0f), Const.mVP); + outVS.texUV.xy = vrt.tex0.xy; + outVS.camW = float4(-vPosW, 0); + outVS.nrmW = vNrmW; + + return outVS; +} + +// ============================================================================ +// +float4 GiantPS(TileVS frg) : COLOR +{ + + float2 vUVSrf = frg.texUV.xy * Prm.vTexOff.zw + Prm.vTexOff.xy; + + // Fetch Main Textures + float4 cTex = tex2D(tDiff, vUVSrf); + + float3 nrmW = normalize(frg.nrmW); // Per-pixel surface normal vector + float3 vRay = normalize(frg.camW.xyz); // Unit viewing ray + float3 vVrt = Const.CamPos - frg.camW.xyz; // Geo-centric pixel position + float3 vPlN = normalize(vVrt); // Planet mean normal + float fDPS = dot(vPlN, Const.toSun); + float3 cSun = saturate((fDPS + 0.1) * 5.0); + + // Terrain with gamma correction and attennuation + cTex.rgb = pow(saturate(cTex.rgb), Const.TrGamma) * Const.TrExpo; + + float3 color = cTex.rgb * LightFX(cSun + float3(0.9, 0.9, 1.0) * Const.Ambient); + + return float4(HDR(color), 1.0f); +} + + +// ============================================================================ +// Gas giant cloud layer renderer +// ============================================================================ + +float4 GiantCloudPS(CldVS frg) : COLOR +{ + float4 cTex = tex2D(tDiff, frg.texUV.xy); + float3 vPlN = normalize(frg.nrmW); + float3 vRay = normalize(frg.posW); + float fDPS = dot(vPlN, Const.toSun); // Planet mean normal sun angle + + float3 cSun = saturate((fDPS + 0.1) * 5.0); + + cTex.rgb *= LightFX(cSun + float3(1.0, 1.0, 1.0) * Const.Ambient); + cTex.rgb = pow(saturate(cTex.rgb), Const.TrGamma) * Const.TrExpo; + + return float4(HDR(cTex.rgb), saturate(cTex.a)); +} diff --git a/OVP/D3D9Client/shaders/PBR.fx b/OVP/D3D9Client/shaders/PBR.fx index 0b3d59bf4..e09b23c87 100644 --- a/OVP/D3D9Client/shaders/PBR.fx +++ b/OVP/D3D9Client/shaders/PBR.fx @@ -360,6 +360,9 @@ float4 PBR_PS(float4 sc : VPOS, PBRData frg) : COLOR cDiff = cDiff * (1 - gColor*0.5f) + gColor; #endif + cDiff.rgb *= gSun.Transmission; + cDiff.rgb += gSun.Inscatter; + return cDiff; } @@ -499,6 +502,9 @@ float4 FAST_PS(float4 sc : VPOS, FASTData frg) : COLOR cDiff.a *= gMtrlAlpha; + cDiff.rgb *= gSun.Transmission; + cDiff.rgb += gSun.Inscatter; + return cDiff; } diff --git a/OVP/D3D9Client/shaders/Scatter.hlsl b/OVP/D3D9Client/shaders/Scatter.hlsl new file mode 100644 index 000000000..f3d5ea912 --- /dev/null +++ b/OVP/D3D9Client/shaders/Scatter.hlsl @@ -0,0 +1,767 @@ + +// ============================================================================ +// Part of the ORBITER VISUALISATION PROJECT (OVP) +// licensed under MIT +// Copyright (C) 2022 Jarmo Nikkanen +// ============================================================================ + +#if defined(_PERFORMANCE) // DO NOT CHANGE THESE, MUST MATCH WITH C++ CODE +#define Nc 6 //Z-dimension count in 3D texture +#define Wc 72 //3D texture size (pixels) +#define Qc 64 //2D texture size (pixels) +#else +#define Nc 8 //Z-dimension count in 3D texture +#define Wc 128 //3D texture size (pixels) +#define Qc 96 //2D texture size (pixels) +#endif + + +#define NSEG 5 +#define iNSEG 1.0f / NSEG +#define MINANGLE -0.33f // Minumum angle +#define ANGRNG (0.25f - MINANGLE) +#define iANGRNG (1.0f / ANGRNG) +#define BOOL bool +#define LastLine (0.999999f - 1.0f / Qc) + + +// Per-Frame Params +// +struct AtmoParams +{ + float4x4 mVP; // View Projection Matrix + float3 CamPos; // Geocentric Camera position + float3 toCam; // Geocentric Camera direction (unit vector) + float3 toSun; // Geocentric Sun direction (unit vector) + float3 SunAz; // Atmo scatter ref.frame (unit vector) (toCam, ZeroAz, SunAz) + float3 ZeroAz; // Atmo scatter ref.frame (unit vector) + float3 Up; // Sun/Shadow Ref Frame (Unit Vector) (Up, toSun, ZeroAz) + float3 vTangent; // Reference frame for normal mapping (Unit Vector) + float3 vBiTangent; // Reference frame for normal mapping (Unit Vector) + float3 vPolarAxis; // North Pole (unit vector) + float3 cSun; // Sun Color and intensity + float3 RayWave; // .rgb Rayleigh Wave lenghts + float3 MieWave; // .rgb Mie Wave lenghts + float4 HG; // Henyey-Greenstein Phase function params + float2 iH; // Inverse scale height for ray(.r) and mie(.g) e.g. exp(-altitude * iH) + float2 rmO; // Ray and Mie out-scatter factors + float2 rmI; // Ray and Mie in-scatter factors + float3 cAmbient; // Ambient light color at sealevel + float3 cGlare; // Sun glare color + float PlanetRad; // Planet Radius + float PlanetRad2; // Planet Radius Squared + float AtmoAlt; // Atmospehere upper altitude limit + float AtmoRad; // Atmospehere outer radius + float AtmoRad2; // Atmospehere outer radius squared + float CloudAlt; // Cloud layer altitude for color and light calculations (not for phisical rendering) + float MinAlt; // Minimum terrain altitude + float MaxAlt; // Maximum terrain altitude + float iAltRng; // 1.0 / (MaxAlt - MinAlt); + float AngMin; + float AngRng; + float iAngRng; + float AngCtr; // Cos of View cone angle from planet center that's visible from camera location + float HrzDst; // Distance to horizon (500 m) minimum if camera below sea level + float CamAlt; // Camera Altitude + float CamElev; // Camera Elevation above surface + float CamRad; // Camera geo-distance + float CamRad2; // Camera geo-distance squared + float Expo; // "HDR" exposure factor (atmosphere only) + float Time; // Simulation time / 180 + float TrGamma; // Terrain "Gamma" correction setting + float TrExpo; // "HDR" exposure factor (terrain only) + float Ambient; // Global ambient light level + float Clouds; // Cloud layer intensity (if below), and Blue light inscatter scale factor (if camera Above clouds) + float TW_Terrain; // Twilight intensity + float TW_Dst; // Twilight distance behind terminator + float CosAlpha; // Cosine of camera horizon angle i.e. PlanetRad/CamRad + float SinAlpha; // Sine of ^^ + float CamSpace; // Camera in space scale factor 0.0 = surf, 1.0 = space + float Cr2; // Camera radius on shadow plane (dot(cp.toCam, cp.Up) * cp.CamRad)^2 + float ShdDst; + float SunVis; + float dCS; + float smi; + float ecc; + float trLS; +}; + +struct sFlow { + BOOL bRay; // True for rayleigh render pass + BOOL bCamLit; // True if camera is lit by sunlight + BOOL bCamInSpace; // True if camera is in space (i.e. not in atmosphere) +}; + +uniform extern AtmoParams Const; +uniform extern sFlow Flo; + +sampler2D tSun; +sampler2D tCam; +sampler2D tLndRay; +sampler2D tLndMie; +sampler2D tLndAtn; +sampler2D tSunGlare; +sampler2D tAmbient; +sampler2D tSkyRayColor; +sampler2D tSkyMieColor; + +#if NSEG == 5 +static const float n[] = { 0.050, 0.25, 0.50, 0.75, 0.950 }; +static const float w[] = { 0.125, 0.25, 0.25, 0.25, 0.125 }; +#endif + +#if NSEG == 7 +static const float n[] = { 0.05, 0.167, 0.333, 0.500, 0.667, 0.833, 0.95 }; +static const float w[] = { 0.08, 0.167, 0.167, 0.167, 0.167, 0.167, 0.08 }; +#endif + +// Gauss7 points and weights +static const float4 n0 = float4(0.0714, 0.21428, 0.35714, 0.5 ); +static const float4 w0 = float4(0.1295, 0.27971, 0.38183, 0.41796); +static const float4 n1 = float4(0.64285, 0.78571, 0.92857, 0 ); +static const float4 w1 = float4(0.38183, 0.27971, 0.1295, 0 ); + +// Gauss4 points and weights +static const float4 n4 = float4( 0.06943, 0.33001, 0.66999, 0.93057 ); +static const float4 w4 = float4( 0.34786, 0.65215, 0.65215, 0.34786 ); + +float ilerp(float a, float b, float x) +{ + return saturate((x - a) / (b - a)); +} + +float3 sqr(float3 x) +{ + return x * x; +} + +float4 expc(float4 x) { return exp(clamp(x, -20, 20)); } +float3 expc(float3 x) { return exp(clamp(x, -20, 20)); } +float2 expc(float2 x) { return exp(clamp(x, -20, 20)); } +float expc(float x) { return exp(clamp(x, -20, 20)); } + + +float2 NrmToUV(float3 vNrm) +{ + float2 uv = float2(dot(Const.ZeroAz, vNrm), dot(Const.SunAz, vNrm)) / Const.AngCtr; + return (uv * 0.5 + 0.5); +} + + +float3 uvToLoc(float2 uv, float r) +{ + uv = (uv * 2.0 - 1.0); + float w = uv.x * uv.x + uv.y * uv.y; + if (w > 1.0f) uv *= rsqrt(w); + uv *= r; + float det = 1.0f - uv.x * uv.x - uv.y * uv.y; + float cos_ab = det > 0.0f ? sqrt(det) : 0.0f; + return float3(uv.xy, cos_ab); +} + + +float3 uvToNrm(float2 uv) +{ + float3 q = uvToLoc(uv, Const.AngCtr); + return normalize(Const.SunAz * q.y + Const.ZeroAz * q.x + Const.toCam * q.z); +} + + +float3 uvToDir(float2 uv) +{ + uv.y = uv.y * rsqrt(0.2f + uv.y * uv.y) * sqrt(1.2f); + + float x = uv.x * 2.0f - 1.0f; + float y = sqrt(1.0f - x * x); + float z = 1.0f - uv.y * Const.AngRng; + float k = sqrt(1.0f - z * z); + + return normalize(Const.SunAz * x * k + Const.ZeroAz * y * k + Const.toCam * z); +} + + +float2 DirToUV(float3 uDir) +{ + float y = dot(uDir, Const.toCam); + float3 uOrt = normalize(uDir - Const.toCam * y); + float x = dot(uOrt, Const.SunAz) * 0.5 + 0.5; + float2 uv = float2(x, 1.0f - (y - Const.AngMin) * Const.iAngRng); + uv.y = sqrt(0.2f) * uv.y * rsqrt(1.2f - uv.y * uv.y); + return uv; +} + + +float3 HDR(float3 x) +{ + return 1.0f - exp(-Const.Expo * x); +} + + +float3 LightFX(float3 x) +{ + //return x * rsqrt(1.0f + x*x) * 1.4f; + return 2.0 * x / (1.0f + x); +} + + +float RayLength(float cos_dir, float r0, float r1) +{ + float y = r0 * cos_dir; + float z2 = r0 * r0 - y * y; + return sqrt(r1 * r1 - z2) + y; +} + + +float RayLength(float cos_dir, float r0) +{ + return RayLength(cos_dir, r0, Const.AtmoRad); +} + + +// Compute UV and blend factor for smaple3D routine +// +float3 TransformUV(float3 uv, const float rc, const float prc) +{ + const float ipix = 1.0f / rc; + + uv = saturate(uv); + uv.z *= (rc - 1); + uv.x *= ipix; + uv.x += floor(uv.z) * ipix; + return uv; +} + + +// Sample a 3D texture composed from an array of 2D textures +// +float4 smaple3D(sampler2D tSamp, float3 uv, const float rc, const float pix) +{ + const float x = 1.0f / rc; + + float4 a = tex2D(tSamp, uv.xy).rgba; + float4 b = tex2D(tSamp, uv.xy + float2(x, 0)).rgba; + return lerp(a, b, frac(uv.z)); +} + + + + + + +// Optical depth integral in atmosphere for a given distance +// +float2 Gauss7(float cos_dir, float r0, float dist, float2 ih0) +{ + int i; + float x = 2.0 * r0 * cos_dir; + float r2 = r0 * r0; + + // Compute altitudes of sample points + float4 d0 = dist * n0; + float4 a0 = sqrt(r2 + d0 * (d0 - x)) - Const.PlanetRad; + float4 d1 = dist * n1; + float4 a1 = sqrt(r2 + d1 * (d1 - x)) - Const.PlanetRad; + + float2 sum = 0.0f; + for (i = 0; i < 4; i++) sum += expc(-a0[i] * ih0) * w0[i]; + for (i = 0; i < 3; i++) sum += expc(-a1[i] * ih0) * w1[i]; + return sum * dist * 0.5f; +} + + +// Optical depth integral in atmosphere for a given distance +// +float2 Gauss4(float cos_dir, float r0, float dist, float2 ih0) +{ + float4 d0 = dist * n4; + float4 a0 = sqrt(r0 * r0 + d0 * d0 - 2.0 * r0 * d0 * cos_dir) - Const.PlanetRad; + float4 ray = expc(-a0 * ih0.x); + float4 mie = expc(-a0 * ih0.y); + return float2(dot(ray, w4), dot(mie, w4)) * dist * 0.5f; +} + + +// Rayleigh phase function +// +float RayPhase(float cw) +{ + return 0.25f * (4.0f + cw * cw); +} + + +// Henyey-Greenstein Phase function +// +/*float MiePhase(float cw) +{ + float cw2 = cw * cw; + return Const.HG.x * (1.0f + cw2) * pow(abs(Const.HG.y - Const.HG.z * cw2*cw), -1.5f) + Const.HG.w; +}*/ + +float MiePhase(float cw) +{ + return 8.0f * Const.HG.x / (1.0f - Const.HG.y * cw) + Const.HG.w; +} + + +// Get a color of sunlight for a given altitude and normal-sun angle +// +float3 GetSunColor(float dir, float alt) +{ + float maxalt = max(Const.MaxAlt, Const.CloudAlt); + alt = ilerp(Const.MinAlt, maxalt, alt); + dir = saturate((dir - MINANGLE) * iANGRNG); + alt = sqrt(alt); + return tex2D(tSun, float2(dir, alt)).rgb; +} + + +float3 ComputeCameraView(float a, float r, float d) +{ + float2 rm = Gauss7(a, r, d, Const.iH) * Const.rmO; + float3 clr = Const.RayWave * rm.r + Const.MieWave * rm.g; + return exp(-clr); +} + + + +// Approximate multi-scatter effect to atmospheric color and light travel behind terminator +// +float4 AmbientApprox(float dNS, uniform const bool bR = true) +{ + float fA = 1.0f - smoothstep(0.0f, Const.TW_Dst, -dNS); + float3 clr = (bR ? Const.RayWave : Const.cAmbient); + return float4(clr, fA); +} + +float4 AmbientApprox(float3 vNrm, uniform const bool bR = true) +{ + float dNS = dot(vNrm, Const.toSun); + return AmbientApprox(dNS, bR); +} + + + +struct RayData { + float se; // Distance to 'Shadow entry' point from a camera + float sx; // Shadow exit + float ae; // Atmosphere entry + float ax; // Atmosphere exit + float hd; // Horizon distance from a camera + float ca; // Closest approach distance +}; + +struct IData { + float s0, s1, e0, e1; +}; + + +// Compute ray passage information +// vRay must point away from the camera +// +RayData ComputeRayStats(in float3 vRay, in uniform const bool bPreProcessData) +{ + RayData dat = (RayData)0; + + static const float invalid = -1e9; + + // Projection of viewing ray on 'shadow' axes + float u = dot(vRay, Const.Up); + float t = dot(vRay, Const.ZeroAz); + float z = dot(vRay, Const.toSun); + + // Shadow Entry and Exit points + // Cosine 'a' + float a = u * rsqrt(u * u + t * t); + + float k2 = Const.Cr2 * a * a; + float h2 = Const.Cr2 - k2; + float w2 = Const.PlanetRad2 - h2; + float2 b = sqrt(float2(w2, k2)); + float k = b.y * sign(a); + float v2 = 0; + float m = Const.CamRad2 - Const.PlanetRad2; + + dat.se = k - b.x; + dat.sx = dat.se + 2.0f * b.x; + + // Project distances back to 3D space + float q = rsqrt(max(2.5e-5, 1.0 - z * z)); + dat.se *= q; + dat.sx *= q; + + // Compute atmosphere entry and exit points + // + a = -dot(Const.toCam, vRay); + k2 = Const.CamRad2 * a * a; + h2 = Const.CamRad2 - k2; + v2 = Const.AtmoRad2 - h2; + float3 n = sqrt(float3(v2, k2, m)); + k = n.y * sign(a); + + dat.hd = m > 0.0 ? n.z : 0.0; + dat.ae = (k - n.x); + dat.ax = dat.ae + 2.0f * n.x; + dat.ca = Const.CamRad * a; + + // If the ray doesn't intersect atmosphere then set both distances to zero + if (v2 < 0) dat.ae = dat.ax = invalid; + + // If the ray doesn't intersect shadow then set both distances to atmo exit + if (w2 < 0) dat.se = dat.sx = invalid; + + if (bPreProcessData) + { + float3 vEn = Const.CamPos + vRay * dat.se; + float3 vEx = Const.CamPos + vRay * dat.sx; + + // If shadow entry/exit point is Lit then set it to atmo exit point + if (dot(vEn, Const.toSun) > 0) dat.se = invalid; + if (dot(vEx, Const.toSun) > 0) dat.sx = invalid; + } + + return dat; +} + + +IData PostProcessData(RayData sp) +{ + IData d; + if (!Flo.bCamLit) { // Camera in Shadow + d.s0 = max(sp.sx, sp.ae); + + float lf = max(0, sp.ca) / max(1.0f, abs(sp.hd)); // Lerp Factor + float mp = lerp((sp.ax + d.s0) * 0.5f, sp.hd, saturate(lf)); + + d.e0 = mp; + d.s1 = max(sp.sx, mp); + d.e1 = sp.ax; + } + else { // Camera is Lit + d.s0 = max(0, sp.ae); + + float lf = max(0, sp.ca) / max(1.0f, abs(sp.hd)); // Lerp Factor + float mp = lerp((sp.ax + d.s0) * 0.5f, sp.hd, saturate(lf)); + + bool bA = (sp.se > sp.ax || sp.se < 0); + + d.e0 = bA ? mp : sp.se; + d.s1 = bA ? mp : max(sp.sx, sp.ae); + d.e1 = sp.ax; + } + return d; +} + +// Compute attennuation from vPos in atmosphere to camera (or atm exit point) +// +float3 ComputeCameraView(float3 vPos, float3 vNrm, float3 vRay, float r) +{ + float d; + float a = dot(vNrm, vRay); + if (Flo.bCamInSpace) d = RayLength(a, r); + else d = dot(vPos - Const.CamPos, vRay); + float2 rm = Gauss7(a, r, d, Const.iH) * Const.rmO; + float3 clr = Const.RayWave * rm.r + Const.MieWave * rm.g; + return exp(-clr); +} + +// Integrate viewing ray for incatter color (.rgb) and optical depth (.a) +// vRay must point from camera to vOrig +// +float4 IntegrateSegmentMP(float3 vOrig, float3 vRay, float len, float iH) +{ + float4 ret = 0; + float3 vR = vRay * len; + for (int i = 0; i < NSEG; i++) + { + float3 pos = vOrig + vR * (iNSEG * (float(i) + 0.5f)); + float3 n = normalize(pos); + float rad = dot(n, pos); + float alt = rad - Const.PlanetRad; + float3 x = GetSunColor(dot(n, Const.toSun), alt); + x *= ComputeCameraView(pos, n, vRay, rad); + float f = exp(-alt * iH) * iNSEG; + ret.rgb += x * f; + ret.a += f; + } + return ret * len; +} + +float4 IntegrateSegmentNS(float3 vOrig, float3 vRay, float len, float iH) +{ + // TODO: Could try to accummulation of CamView seg. by seg. + + float4 ret = 0; + float3 vR = vRay * len; + for (int i = 0; i < NSEG; i++) + { + float3 pos = vOrig + vR * n[i]; + float3 n = normalize(pos); + float rad = dot(n, pos); + float alt = rad - Const.PlanetRad; + float3 x = GetSunColor(dot(n, Const.toSun), alt); + x *= ComputeCameraView(pos, n, vRay, rad); + float f = exp(-alt * iH) * w[i]; + ret.rgb += x * f; + ret.a += f; + } + return ret * len; +} + + + +// 2D lookup-table, for direct sunlight being filtered by atmosphere +// +float4 SunColor(float x : TEXCOORD0, float y : TEXCOORD1) : COLOR +{ + float maxalt = max(Const.MaxAlt, Const.CloudAlt); + float alt = lerp(Const.MinAlt, maxalt, y*y); + float ang = x * ANGRNG + MINANGLE; + float rad = alt + Const.PlanetRad; + float dist = RayLength(-ang, rad); + float2 rm = Gauss7(-ang, rad, dist, Const.iH) * Const.rmO; + float3 clr = Const.RayWave * rm.r + Const.MieWave * rm.g; + + return float4(exp(-clr), 1.0f); +} + + +struct SkyOut +{ + float4 ray; + float4 mie; +}; + + +// Get a precomputed rayleight and mie color values for a given direction from a camera +// +SkyOut GetSkyColor(float3 uDir) +{ + float2 uv = DirToUV(uDir); + + SkyOut o; + o.ray = tex2D(tSkyRayColor, uv).rgba; + o.mie = tex2D(tSkyMieColor, uv).rgba; + return o; +} + + + +float4 SkyView(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + // Viewing ray + float3 vRay = uvToDir(float2(u,v)); + + float rmO = Flo.bRay ? Const.rmO.r : Const.rmO.g; + float rmI = Flo.bRay ? Const.rmI.r : Const.rmI.g; + float iH = Flo.bRay ? Const.iH.r : Const.iH.g; + + RayData sp = ComputeRayStats(vRay, true); + IData id = PostProcessData(sp); + + // First segment + float4 ret = 0; + if (id.e0 > id.s0) + ret += IntegrateSegmentNS(Const.CamPos + vRay * id.s0, vRay, id.e0 - id.s0, iH); + + // Second segment + if (id.e1 > id.s1) + ret += IntegrateSegmentNS(Const.CamPos + vRay * id.s1, vRay, id.e1 - id.s1, iH); + + + ret.rgb *= rmI; + ret.rgb *= Flo.bRay ? Const.RayWave : Const.MieWave; + ret.rgb *= Const.cSun; + + if (Flo.bRay) + { + float2 vDepth = Gauss7(dot(Const.toCam, -vRay), Const.CamRad, sp.ax, Const.iH); + float2 vOut = vDepth * Const.rmO; + float4 cMlt = AmbientApprox(Const.toCam); + cMlt.rgb *= exp(-Const.CamAlt * Const.iH.r); + cMlt.rgb *= cMlt.a; + cMlt.rgb *= exp(-(Const.RayWave * vOut.r + Const.MieWave * vOut.g)); + float alpha = ilerp(10e3, 150e3, vDepth.r); + return float4(ret.rgb + cMlt.rgb, alpha); + } + + return float4(ret.rgb, 1.0f); +} + + + +// 2D lookup-table for pre-computed sky color. (pre frame), varies with camera pos and sun pos +// +float4 RingView(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + if (v >= LastLine) return float4(0, 0, 0, 0); + + v *= v; + float rmO = Flo.bRay ? Const.rmO.r : Const.rmO.g; + float rmI = Flo.bRay ? Const.rmI.r : Const.rmI.g; + float iH = Flo.bRay ? Const.iH.r : Const.iH.g; + + float x = -1.0f + u * 2.0f; + float y = sqrt(max(1e-6, 1.0f - x * x)); + float e = v * Const.AtmoAlt; + float re = Const.PlanetRad + e; + float z = re * Const.CosAlpha; + float j = re * Const.SinAlpha; + + // Sample position and viewing ray + float3 vPos = Const.SunAz * x * j + Const.ZeroAz * y * j + Const.toCam * z; + float3 vRay = normalize(vPos - Const.CamPos); + float cpd = abs(dot(vRay, Const.CamPos - vPos)); + + RayData sp = ComputeRayStats(vRay, true); + IData id = PostProcessData(sp); + + // First segment + float4 ret = 0; + if (id.e0 > id.s0) + ret += IntegrateSegmentNS(vPos - vRay * (cpd - id.s0), vRay, id.e0 - id.s0, iH); + + // Second segment + if (id.e1 > id.s1) + ret += IntegrateSegmentNS(vPos - vRay * (cpd - id.s1), vRay, id.e1 - id.s1, iH); + + ret.rgb *= rmI; + ret.rgb *= Flo.bRay ? Const.RayWave : Const.MieWave; + ret.rgb *= Const.cSun; + + if (Flo.bRay) + { + float3 vSrc = vPos - vRay * (cpd - sp.ax); + float3 vNrm = normalize(vSrc); + float2 vDepth = Gauss4(dot(vNrm, vRay), dot(vSrc, vNrm), sp.ax - sp.ae, Const.iH); + float2 vOut = vDepth * Const.rmO; + float4 cMlt = AmbientApprox(Const.toCam); + cMlt.rgb *= exp(-Const.CamAlt * Const.iH.r); + cMlt.rgb *= cMlt.a; + cMlt.rgb *= exp(-(Const.RayWave * vOut.r + Const.MieWave * vOut.g)); + float alpha = ilerp(10e3, 150e3, vDepth.r); + alpha = alpha > 0 ? sqrt(alpha) : 0; + return float4(ret.rgb + cMlt.rgb, alpha); + } + + return float4(ret.rgb, 1.0f); +} + + +// Get a precomputed total (combined) sky color for a given direction from a camera +// +float3 GetAmbient(float3 vRay) +{ + return tex2D(tAmbient, DirToUV(vRay)).rgb; +} + + +// 2D lookup-table for pre-computed total (combined) sky color. (pre frame), varies with sun/cam relation +// +float4 AmbientSky(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + // Viewing ray + float2 uv = float2(u, v); + float3 uDir = uvToDir(uv); + float ph = dot(uDir, Const.toSun); + + float3 ray = tex2D(tSkyRayColor, uv).rgb; + float3 mie = tex2D(tSkyMieColor, uv).rgb; + float3 color = ray * RayPhase(ph) + mie * MiePhase(ph); + + return float4(color, 1.0f); +} + + + +struct LandOut +{ + float4 ray; + float4 mie; + float4 atn; +}; + + +// Get a precomputed rayleight and mie haze values for a given altitude and normal +// +LandOut GetLandView(float rad, float3 vNrm) +{ + float2 uv = NrmToUV(vNrm); + + float a = rad - Const.PlanetRad; + float z = saturate((a - Const.MinAlt) * Const.iAltRng); // inverse lerp + + float3 uvb = TransformUV(float3(uv, z), Nc, Wc); + + LandOut o; + o.ray = smaple3D(tLndRay, uvb, Nc, Wc); + o.mie = smaple3D(tLndMie, uvb, Nc, Wc); + o.atn = smaple3D(tLndAtn, uvb, Nc, Wc); + return o; +} + + +// Render 3D Lookup texture for land view +// +float4 LandView(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + u *= Nc; + float a = floor(u) / Nc; + float alt = lerp(Const.MinAlt, Const.MaxAlt, a); + float r = alt + Const.PlanetRad; + + // Geo-centric Vertex location + float3 vNrm = uvToNrm(float2(frac(u), v)); + float3 vVrt = vNrm * r; + + // Viewing ray + float3 vCam = vVrt - Const.CamPos; + float3 vRay = normalize(vCam); // From camera to vertex + float cpd = abs(dot(vRay, vCam)); // Camera pixel distance + + RayData sp = ComputeRayStats(vRay, true); + + float s0 = sp.ae > 0 ? sp.ae : 0; + float e0 = sp.se > 0 ? min(cpd, sp.se) : cpd; + + //if (!Flo.bRay) dist = min(dist, 10e3); + + float rmI = Flo.bRay ? Const.rmI.r : Const.rmI.g; + float iH = Flo.bRay ? Const.iH.r : Const.iH.g; + + float4 ret = IntegrateSegmentNS(vVrt - vRay * (cpd - s0), vRay, e0 - s0, iH); + + ret.rgb *= Const.cSun; + ret.rgb *= rmI; + ret.rgb *= Flo.bRay ? Const.RayWave : Const.MieWave; + + return float4(ret.rgb, 0.0f); +} + + + +// Render 3D Lookup texture for land view attennuation +// +float4 LandViewAtten(float u : TEXCOORD0, float v : TEXCOORD1) : COLOR +{ + u *= Nc; + float a = floor(u) / Nc; + float alt = lerp(Const.MinAlt, Const.MaxAlt, a); + float r = alt + Const.PlanetRad; + + // Geo-centric Vertex location + float3 vNrm = uvToNrm(float2(frac(u), v)); + float3 vVrt = vNrm * r; + + // Viewing ray + float3 vCam = vVrt - Const.CamPos; + float3 vRay = normalize(vCam); // Towards vertex from camera + + float ang = dot(vNrm, vRay); + float len = RayLength(ang, r); + + float dist = min(len, dot(vRay, vCam)); + + float3 ret = ComputeCameraView(ang, r, dist); + + return float4(ret, 1.0); +} diff --git a/OVP/D3D9Client/shaders/Surface.fx b/OVP/D3D9Client/shaders/Surface.fx deleted file mode 100644 index 787bc9fdc..000000000 --- a/OVP/D3D9Client/shaders/Surface.fx +++ /dev/null @@ -1,1383 +0,0 @@ -// ============================================================================ -// Part of the ORBITER VISUALISATION PROJECT (OVP) -// Dual licensed under GPL v3 and LGPL v3 -// Copyright (C) 2014 - 2016 Jarmo Nikkanen -// ============================================================================ - - -// ============================================================================ -// Shader File for TileManager2 and 3D Terrain implementation -// Contains a light weight implementation -// ============================================================================ - -struct Light -{ - int type; /* Type of the light emitter 0=point, 1=spot */ - float dst2; /* Camera-Light Emitter distance squared */ - float4 diffuse; /* diffuse color of light */ - float3 position; /* position in world space */ - float3 direction; /* direction in world space */ - float3 attenuation; /* Attenuation */ - float4 param; /* range, falloff, theta, phi */ -}; - -#define Range 0 -#define Falloff 1 -#define Theta 2 -#define Phi 3 - -// ---------------------------------------------------------------------------- -// Vertex input layouts from Vertex buffers to vertex shader -// ---------------------------------------------------------------------------- - -struct TILEVERTEX // (VERTEX_2TEX) Vertex declaration used for surface tiles and cloud layer -{ - float3 posL : POSITION0; - float3 normalL : NORMAL0; - float2 tex0 : TEXCOORD0; - float elev : TEXCOORD1; -}; - - -// ---------------------------------------------------------------------------- -// Vertex Shader to Pixel Shader datafeeds -// ---------------------------------------------------------------------------- - -struct TileVS -{ - float4 posH : POSITION0; - float2 texUV : TEXCOORD0; // Texture coordinate - float4 aux : TEXCOORD1; // Night lights - float3 camW : TEXCOORD2; - float3 nrmW : TEXCOORD3; - float4 sunlight : COLOR0; // Color of the sunlight received by terrain - float3 insca : COLOR1; // "Inscatter" Added to incoming fragment color -#if defined(_SHDMAP) - float4 shdH : TEXCOORD4; -#endif -}; - -struct CloudVS -{ - float4 posH : POSITION0; - float2 texUV : TEXCOORD0; // Texture coordinate - float3 atten : COLOR0; // Attennuation - float3 insca : COLOR1; // "Inscatter" Added to incoming fragment color - float2 fade : TEXCOORD1; - float3 nrmW : TEXCOORD2; -}; - -struct HazeVS -{ - float4 posH : POSITION0; - float2 texUV : TEXCOORD0; - float3 insca : COLOR0; - float alpha : COLOR1; -}; - -struct CelSphereVS -{ - float4 posH : POSITION0; - float2 tex0 : TEXCOORD0; -}; - - - - -// ---------------------------------------------------------------------------- -// Global shader variables -// ---------------------------------------------------------------------------- - -uniform extern Light sLights[4]; // Local light sources - -uniform extern float4x4 mLVP; // Light View Projection -uniform extern float4x4 mWorld; // World matrix -uniform extern float4x4 mViewProj; // Combined View and Projection matrix -// ------------------------------------------------------------ -uniform extern float4 vMSc0; // Micro Texture A scale factors -uniform extern float4 vMSc1; // Micro Texture B scale factors -uniform extern float4 vMSc2; // Micro texture C scale factors -uniform extern float4 vTexOff; // Texture offsets used by surface manager (i.e. SubTexRange) -uniform extern float4 vCloudOff; // Texture offsets used by surface manager (i.e. SubTexRange) -uniform extern float4 vMicroOff; // Texture offsets used by surface manager (i.e. SubTexRange) -uniform extern float4 vOverlayOff; // Texture offsets used by surface manager (i.e. SubTexRange) -uniform extern float4 vOverlayCtrl[4]; -uniform extern float4 vWater; // Water material input structure (specular rgb, power) -uniform extern float3 vSunDir; // Unit Vector towards the Sun -uniform extern float3 vTangent; // Unit Vector -uniform extern float3 vBiTangent; // Unit Vector -uniform extern float3 vPolarAxis; // North Pole -uniform extern float4 vSHD; // ShadowMap Params -// ------------------------------------------------------------ -uniform extern float fDistScale; // UNUSED: Scale factor -uniform extern float fAlpha; // Cloud shodow alpha -uniform extern float fNight; // Nightlights intensity -// ------------------------------------------------------------ -uniform extern bool bCloudSh; // Enable cloud shadows -uniform extern bool bLights; // Enable night-lights -uniform extern bool bEnvEnable; // Enable environment maps -uniform extern bool bMicroNormals; // Enable micro texture normal maps -uniform extern int iTileLvl; // Surface tile level being rendered -uniform extern int iDebug; // Debug Mode identifier -uniform extern bool bDebug; // Debug Mode enabled -uniform extern bool bLocals; // Local light sources enabled for this tile -uniform extern bool bShadows; // Enable shadow projection -uniform extern bool bOverlay; // Enable shadow projection -uniform extern bool bElevOvrl; -uniform extern bool bSpherical; // Force Spherical planet (discard elevation) -uniform extern bool bCloudNorm; -uniform extern bool bEarth; -// Textures --------------------------------------------------- -uniform extern texture tDiff; // Diffuse texture -uniform extern texture tMask; // Nightlights / Specular mask texture -uniform extern texture tCloud; -uniform extern texture tCloud2; -uniform extern texture tCloudMicro; -uniform extern texture tCloudMicroNorm; -uniform extern texture tNoise; // -uniform extern texture tOcean; // Ocean Texture -uniform extern texture tEnvMap; -uniform extern texture tMicroA; -uniform extern texture tMicroB; -uniform extern texture tMicroC; -uniform extern texture tShadowMap; -uniform extern texture tOverlay; -uniform extern texture tMskOverlay; -uniform extern texture tElvOverlay; - - -// ---------------------------------------------------------------------------- -// Texture Sampler implementations -// ---------------------------------------------------------------------------- - -sampler SrfOverlayS = sampler_state -{ - Texture = ; - MinFilter = ANISOTROPIC; - MagFilter = ANISOTROPIC; - MipFilter = LINEAR; - MaxAnisotropy = ANISOTROPY_MACRO; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler MskOverlayS = sampler_state -{ - Texture = ; - MinFilter = ANISOTROPIC; - MagFilter = ANISOTROPIC; - MipFilter = LINEAR; - MaxAnisotropy = ANISOTROPY_MACRO; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler ElevationS = sampler_state -{ - Texture = ; - MinFilter = POINT; - MagFilter = POINT; - MipFilter = POINT; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler ShadowS = sampler_state -{ - Texture = ; - MinFilter = POINT; - MagFilter = POINT; - MipFilter = NONE; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler DiffTexS = sampler_state -{ - Texture = ; - MinFilter = ANISOTROPIC; - MagFilter = ANISOTROPIC; - MipFilter = LINEAR; - MaxAnisotropy = ANISOTROPY_MACRO; - MipMapLODBias = 0.0; - AddressU = CLAMP; - AddressV = CLAMP; -}; - - -sampler CloudTexS = sampler_state // Cloud shadow sampler -{ - Texture = ; - MinFilter = LINEAR; - MagFilter = LINEAR; - MipFilter = LINEAR; - MaxAnisotropy = 2; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler Cloud2TexS = sampler_state -{ - Texture = ; - MinFilter = LINEAR; - MagFilter = LINEAR; - MipFilter = LINEAR; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler MaskTexS = sampler_state -{ - Texture = ; - MinFilter = ANISOTROPIC; - MagFilter = LINEAR; - MipFilter = LINEAR; - MaxAnisotropy = ANISOTROPY_MACRO; - MipMapLODBias = 0; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler NoiseTexS = sampler_state -{ - Texture = ; - MinFilter = POINT; - MagFilter = POINT; - MipFilter = POINT; - AddressU = WRAP; - AddressV = WRAP; -}; - -sampler OceaTexS = sampler_state -{ - Texture = ; - MinFilter = LINEAR; - MagFilter = LINEAR; - MipFilter = LINEAR; - AddressU = WRAP; - AddressV = WRAP; -}; - -sampler EnvMapS = sampler_state -{ - Texture = ; - MinFilter = LINEAR; - MagFilter = LINEAR; - MipFilter = LINEAR; - AddressU = CLAMP; - AddressV = CLAMP; -}; - -sampler CloudMicroS = sampler_state -{ - Texture = ; - MinFilter = MICRO_FILTER; - MagFilter = LINEAR; - MipFilter = LINEAR; - MaxAnisotropy = MICRO_ANISOTROPY; - AddressU = WRAP; - AddressV = WRAP; -}; - -sampler CloudMicroNormS = sampler_state -{ - Texture = ; - MinFilter = MICRO_FILTER; - MagFilter = LINEAR; - MipFilter = LINEAR; - MaxAnisotropy = MICRO_ANISOTROPY; - AddressU = WRAP; - AddressV = WRAP; -}; - -sampler MicroAS = sampler_state -{ - Texture = ; - MinFilter = MICRO_FILTER; - MagFilter = LINEAR; - MipFilter = LINEAR; - MaxAnisotropy = MICRO_ANISOTROPY; - MipMapLodBias = MICRO_BIAS; - AddressU = WRAP; - AddressV = WRAP; -}; - -sampler MicroBS = sampler_state -{ - Texture = ; - MinFilter = MICRO_FILTER; - MagFilter = LINEAR; - MipFilter = LINEAR; - MaxAnisotropy = MICRO_ANISOTROPY; - MipMapLODBias = MICRO_BIAS; - AddressU = WRAP; - AddressV = WRAP; -}; - -sampler MicroCS = sampler_state -{ - Texture = ; - MinFilter = MICRO_FILTER; - MagFilter = LINEAR; - MipFilter = LINEAR; - MaxAnisotropy = MICRO_ANISOTROPY; - MipMapLODBias = MICRO_BIAS; - AddressU = WRAP; - AddressV = WRAP; -}; - -// ---------------------------------------------------------------------------- -// Atmospheric scattering model -// ---------------------------------------------------------------------------- - -uniform extern float4 vMPhase; // Pre-computed factors used in Mie phase function -uniform extern float4 vODCoEff; // Optical Depth Taylor co-efficients -uniform extern float4 vODCoEffEx; // Optical Depth Taylor co-efficients -uniform extern float3 vMieInSct; // Mie scattering factor = Mie/(lambda^m) (slider) -uniform extern float3 vRayInSct; // Rayleigh in-scattering = (ROut*RIn)/(lambda^r) (slider) -uniform extern float3 vTotOutSct; // Total out-scattering = ROut/(lambda^r) + Mie/(lambda^m) (slider) -uniform extern float3 vHazeMax; // Horizon haze limitter (slider) -uniform extern float3 vColorShift; // lerp([1,1,1], 1.0/lambda^r, Aux3) -uniform extern float3 vCameraPos; // Geo-centric camera position -uniform extern float3 vUnitCameraPos; // Geo-centric camera position (Unit vector) -uniform extern float fCloudInts; // Cloud layer intensity -uniform extern float fScaleHeight; // Atmosphere scaleheight -uniform extern float fInvScaleHeight; // Inverse Scale Height 1.0f/fScaleHeight -uniform extern float fSunAlt; // Altitude of sunlight in the horizon ring, [meters] -uniform extern float fRadius; // PlanetRad -uniform extern float fCameraAlt; // Camera Altitude -uniform extern float fHorizonAlt; // Horizon (i.e. Skydome, Atmosphere) Altitude/Height -uniform extern float fAtmRad2; // Atmosphere upper radius squared (fRadius+fHorizonAlt)^2 -uniform extern float fRPhase; // Rayleigh phase factor -uniform extern float fHorizonDst; // Camera to horizon distance sqrt(dot(vCameraPos,vCameraPos) - fRadius*fRadius) -uniform extern float fExposure; // Terrain brightness -uniform extern float fAux1; // Bound to Aux1 (slider) -uniform extern float fAux2; // Bound to Aux2 (slider) -uniform extern float fInvAux1; // Inverse of fAux1 (slider) -uniform extern float fTrGamma; // Terrain gamma control -uniform extern float fAtmGamma; // Atmosphere gamma control -uniform extern float fInvParameter; // Inverse of optical parameter 1.0/AngleCoEff(0) -uniform extern float fAmbient; // Planet specific ambient level pre-multiplied with camera altitude factor -uniform extern float fGlobalAmb; -uniform extern float fTime; // Loop from 0 to 3600 (sec) -uniform extern bool bInSpace; // Camera in the space (i.e. fCameraAlt>fHorizonAlt) -uniform extern bool bOnOff; - -// Numeric integration points and weights for Gauss-Lobatto integral -// -static const float4 vWeight4 = {0.167, 0.833, 0.833, 0.167}; -static const float4 vPoints4 = {0.0f, 0.27639f, 0.72360f, 1.0f}; -static const float3 vWeight3 = {0.33333f, 1.33333f, 0.33333f}; -static const float3 vPoints3 = {0.0f, 0.5f, 1.0f}; -static const float3 cSky = {0.7f, 0.9f, 1.2f}; -static const float3 cSun = { 1.0f, 1.0f, 1.0f }; -static const float srfoffset = -0.2; -static const float ATMNOISE = 0.02; - - - -// ------------------------------------------------------------------------------------------------------------- -// Project shadows on surface -// -float SampleShadows(float2 sp, float pd) -{ -#if defined(_SHDMAP) - - if (sp.x < 0 || sp.y < 0) return 0.0f; // If a sample is outside border -> fully lit - if (sp.x > 1 || sp.y > 1) return 0.0f; - - if (pd < 0) pd = 0; - if (pd > 2) pd = 2; - - float2 dx = float2(vSHD[1], 0) * 1.5f; - float2 dy = float2(0, vSHD[1]) * 1.5f; - float va = 0; - - sp -= dy; - if ((tex2D(ShadowS, sp - dx).r) > pd) va++; - if ((tex2D(ShadowS, sp).r) > pd) va++; - if ((tex2D(ShadowS, sp + dx).r) > pd) va++; - sp += dy; - if ((tex2D(ShadowS, sp - dx).r) > pd) va++; - if ((tex2D(ShadowS, sp).r) > pd) va++; - if ((tex2D(ShadowS, sp + dx).r) > pd) va++; - sp += dy; - if ((tex2D(ShadowS, sp - dx).r) > pd) va++; - if ((tex2D(ShadowS, sp).r) > pd) va++; - if ((tex2D(ShadowS, sp + dx).r) > pd) va++; - - return va * 0.1111111f; -#else - return 0.0f; -#endif -} - -// ------------------------------------------------------------------------------------------------------------- -// Local light sources -// -void LocalLights( - out float3 diff_out, - in float3 nrmW, - in float3 posW) -{ - -#if LMODE == 0 - diff_out = 0; - return; -#else - - if (!bLocals) return; - - float3 posWN = normalize(-posW); - float3 p[4]; - int i; - - // Relative positions - [unroll] for (i = 0; i < 4; i++) p[i] = posW - sLights[i].position; - - // Square distances - float4 sd; - [unroll] for (i = 0; i < 4; i++) sd[i] = dot(p[i], p[i]); - - // Normalize - sd = rsqrt(sd); - [unroll] for (i = 0; i < 4; i++) p[i] *= sd[i]; - - // Distances - float4 dst = rcp(sd); - - // Attennuation factors - float4 att; - [unroll] for (i = 0; i < 4; i++) att[i] = dot(sLights[i].attenuation.xyz, float3(1.0, dst[i], dst[i] * dst[i])); - - att = rcp(att); - - // Spotlight factors - float4 spt; - [unroll] for (i = 0; i < 4; i++) { - spt[i] = (dot(p[i], sLights[i].direction) - sLights[i].param[Phi]) * sLights[i].param[Theta]; - if (sLights[i].type == 0) spt[i] = 1.0f; - } - - spt = saturate(spt); - - // Diffuse light factors - float4 dif; - [unroll] for (i = 0; i < 4; i++) dif[i] = dot(-p[i], nrmW); - - dif = saturate(dif); - dif *= (att*spt); - - diff_out = 0; - - [unroll] for (i = 0; i < 4; i++) diff_out += sLights[i].diffuse.rgb * dif[i]; -#endif -} - - -// ------------------------------------------------------------------------------------------------------------- -// "HDR" -// -float3 Light_fx2(float3 x) -{ - //return saturate(x); - //return x * rsqrt(1.0f + x*x) * 1.4f; - return 2.0*x / (1.0f + x); -} - - -// ------------------------------------------------------------------------------------------------------------- -// Henyey-Greenstein Phase function -// x = (1-g^2)/(4pi), y = 1+g^2, w = -2*g -// -float MPhase(float cw) -{ - return max(1, vMPhase.x * pow(abs(vMPhase.y-vMPhase.w*cw), -1.5f)); -} - -// ---------------------------------------------------------------------------- -// Rayleigh Phase function -// -float RPhase(float cw) -{ - - //return (1.0 + cw*fRPhase) * (0.75 + cw*cw*0.5f); - //return (1.0 + cw*cw*fRPhase); - return (1.0 + cw*fRPhase); -} - -// ---------------------------------------------------------------------------- -// Optical depth angle co-efficiency factor. (Accurate and valid for angles 0 to 96deg) -// c = cosine of the ray direction (1.0 is up) -// -float AngleCoEff(float c) -{ - float c1 = rcp(max(0.0954, c+0.2)); - float c2 = c1*c1; - float4 v1 = float4(1.0f, c1, c2, c2*c1); - return dot(v1, vODCoEff) + dot(v1*(c2*c2), vODCoEffEx); -} - -float Shadow(float c, float f) -{ - float fC = saturate((c+fAux1+f)*fInvAux1); - return (3.0 - 2.0 * fC) * (fC*fC); -} - -float4 DebugProg(in float3 nrmW, in float3 color, in float fRad) -{ - float a = (fRad - fRadius) / 7000.0f; - - if (iDebug==1) return float4((nrmW + 1.0) * 0.5, 1.0); - - if (iDebug==2) { - float x = dot(nrmW, vTangent) + 1; - float y = dot(nrmW, vBiTangent) + 1; - float z = dot(nrmW, vUnitCameraPos) + 1; - return float4(x, y, z, 2.0) * 0.5; - } - - if (iDebug==3) { - if (a<-1) return saturate(float4(0, 0, 2+a, 1.0)); - else if (a<0) return saturate(float4(0, 1+a, 1, 1.0)); - else if (a<1) return saturate(float4(a, 1, 1-a, 1.0)); - else if (a<2) return saturate(float4(1, 2-a, 0, 1.0)); - else return saturate(float4(1, a-2, a-2, 1.0)); - } - - if (iDebug==4) { - a = saturate(a*0.5 + 0.5); - return float4(a, a, a, 1.0); - } - - if (iDebug==5) { - return float4(color, 1); - } - - return float4(0,0,0,1); -} - - -// ============================================================================ -// Atmospheric scattering implementation. (Will render horizon and sky-color) -// ---------------------------------------------------------------------------- -// vIns = Light in scattering -// vUnitRay = Unit Vector pointing in ray direction. (away from the camera) -// ============================================================================ - -void SkyColor(out float3 vIns, in float3 vUnitRay) -{ - float fDRC = dot(vUnitRay, vUnitCameraPos); - float fCam = fCameraAlt + fRadius; - float fCm2 = fCam * fCam; - float fPrm = fCam * fDRC; - float fRd2 = fCm2 - fPrm*fPrm; - float fRay = sqrt(fAtmRad2 - fRd2); - - if (fRd2>fAtmRad2) { - vIns = 0; - return; - } - - float3 vRay; - - if (fCm2 < fAtmRad2) { - fRay -= fPrm; - vRay = vUnitRay * (fRay * 0.5f); - } - else { - fRay *= 2.0f; - vRay = vUnitRay * abs(fPrm); - } - - - float fDRS = -dot(vUnitRay, vSunDir); - float3 vPos = vCameraPos + vRay; - float3 vNr1 = normalize(vPos); - float fAlt = dot(vNr1, vPos)-fRadius; - float fDNS = dot(vNr1, vSunDir); - float fDNR = dot(vNr1, vUnitRay); - - // Setup altitudes for all sample points - float3 vAlt; - - if (fCm2 < fAtmRad2) vAlt = float3(fCameraAlt, fAlt, fHorizonAlt); - else vAlt = float3(fHorizonAlt, fAlt, fHorizonAlt); - - // Atmospheric densities for sample points - float3 vDns = exp2(-vAlt*fInvScaleHeight); - - // Mean atmospheric density for a viewing ray - float fMnD = dot(vDns, vWeight3); - - // Evaluate a Gauss-Lobatto integral (from camera to skydome). Will give optical depth for the ray - float fDep = fMnD * (fRay * fInvScaleHeight) * 0.3465735903f; - - fDep *= 0.5f; - - float fASn = AngleCoEff(fDNS); - - // Color of inscattered sunlight - float3 vSun = cSun * exp2(-vTotOutSct * fAux2*((vDns[0]+vDns[1]) * 0.5f * fASn)) * fDep * Shadow(fDNS, srfoffset); - //float3 vSun = cSun * exp2(-vTotOutSct * fAux2*(vDns[1] * fASn)) * fDep * Shadow(fDNS, srfoffset); - - // Compute in-scattering - vIns = (vRayInSct*RPhase(fDRS) + vMieInSct*MPhase(fDRS)) * vSun; - - float fNgt = saturate(fDNS*2.924f+0.657f); - - // Compute ambient light level for the sky - float3 vAmb = (vRayInSct + 0.5f) * (3.0*fAmbient * fNgt); - - vIns = 1.0f - exp2(-(vAmb + vIns) * vColorShift); - //vIns = 1.0f - exp2(-(vIns) * vColorShift); - - vIns = pow(abs(vIns*vHazeMax), fAtmGamma); -} - - - - - -// ============================================================================ -// Planet Surface Renderer -// ============================================================================ - -#define AUX_DIST 0 // Vertex distance -#define AUX_NIGHT 1 // Night lights intensity -#define AUX_SLOPE 2 // Terrain slope factor 0.0=flat, 1.0=sloped -#define AUX_RAYDEPTH 3 // Optical depth of a ray - - -TileVS SurfaceTechVS(TILEVERTEX vrt, - uniform bool sbRipples, - uniform bool sbNoAtmo) -{ - // Zero output. - TileVS outVS = (TileVS)0; - float4 vElev = 0; - float3 vNrmW; - float3 vVrt; - float3 vPlN; - - // Apply a world transformation matrix - float3 vPosW = mul(float4(vrt.posL, 1.0f), mWorld).xyz; - - if (bElevOvrl) - { - // ---------------------------------------------------------- - // Elevation Overlay - // - float2 vUVOvl = vrt.tex0.xy * vOverlayOff.zw + vOverlayOff.xy; - - // Sample Elevation Map - vElev = tex2Dlod(ElevationS, float4(vUVOvl, 0, 0)); - - // Construct world space normal - vNrmW = float3(vElev.xy, sqrt(saturate(1.0f - dot(vElev.xy, vElev.xy)))); - vNrmW = mul(float4(vNrmW, 0.0f), mWorld).xyz; - - // Reconstruct Elevation - vPosW += normalize(vCameraPos + vPosW) * (vElev.z - vrt.elev) * vElev.w; - - vVrt = vCameraPos + vPosW; - vPlN = normalize(vVrt); - } - else { - vNrmW = mul(float4(vrt.normalL, 0.0f), mWorld).xyz; - vVrt = vCameraPos + vPosW; - vPlN = normalize(vVrt); - } - - // Disrecard elevation and make the surface spherical - if (bSpherical) vPosW = (normalize(vCameraPos + vPosW) * fRadius) - vCameraPos; - - outVS.posH = mul(float4(vPosW, 1.0f), mViewProj); - -#if defined(_SHDMAP) - outVS.shdH = mul(float4(vPosW, 1.0f), mLVP); -#endif - - outVS.texUV.xy = vrt.tex0.xy; // Note: vrt.tex0 is un-used (hardcoded in Tile::CreateMesh and varies per tile) - - float3 vRay = normalize(-vPosW); // Unit viewing ray - float fDPS = dot(vPlN, vSunDir); // Dot mean normal, sun direction - float fRay = abs(dot(vPosW, vRay)); // Vertex camera distance - float fNgt = fDPS * 4.0f - 0.05f; - float fTrA = saturate(fDPS*2.924f + 0.657f); - outVS.camW = -vPosW; - outVS.nrmW = vNrmW; - - outVS.aux[AUX_NIGHT] = -fNgt; - outVS.aux[AUX_DIST] = fRay; - - - - // If no atmosphere skip the rest - if (sbNoAtmo) return outVS; - - - // Camara altitude dependency multiplier for ambient color of atmosphere - //float fAmb = max(saturate(fNgt+0.9f)*fAmbient, fGlobalAmb) * 0.08f; - - float fAmb = max(saturate(fTrA*fAmbient), fGlobalAmb); - - float fDPR = dot(vPlN, vRay); // Dot mean normal, viewing ray - float fDNR = dot(vNrmW, vRay); - float fDNS = dot(vNrmW, vSunDir); // Dot vertex normal, sun direction - float fDRS = dot(vRay, vSunDir); // Dot viewing ray, sun direction - float fDst = dot(vVrt, vPlN); // Vertex geo-distance - float fAlt = fDst - fRadius; // Vertex altitude - - float fCamAlt = fCameraAlt; - - if (bInSpace) { - float fCm2 = fDst * fDst; - float fPrm = fDst * fDPR; - fCamAlt = fHorizonAlt; - fRay = sqrt(fAtmRad2 - (fCm2 - fPrm*fPrm)) - fPrm; // Length of the ray inside atmosphere - } - - - // Altitude vector for sample points - float3 vAlt = float3(fAlt, (fAlt + fCamAlt)*0.5, fCamAlt); - - // Compute atmospheric density for all sample points - float3 vDns = exp2(-vAlt*fInvScaleHeight); // Compute atmospheric density for all sample points - - // Evaluate a Gauss-Lobatto integral to give an optical depth for a viewing ray - float fDRay = dot(vDns, vWeight3) * (fRay * fInvScaleHeight) * 0.3465735903f; - - fDRay *= 0.5; - - float3 vSunLight = exp2(-vTotOutSct * (vDns[0] * 0.12f * AngleCoEff(fDPS))) * Shadow(fDPS, srfoffset); - - outVS.aux[AUX_RAYDEPTH] = clamp(fDRay, 0, 10); - - // Multiply in-coming light with phase and light scattering factors - outVS.insca = ((vRayInSct * RPhase(fDRS)) + (vMieInSct * MPhase(fDRS))) * vSunLight * fDRay; - outVS.insca = (1.0f - exp2(-outVS.insca)); - - outVS.sunlight = float4(vSunLight, fAmb); - - return outVS; -} - - - -bool InRange(float2 a) -{ - return (a.x > 0.0f && a.x < 1.0f) && (a.y > 0.0f && a.y < 1.0f); -} - - -float4 SurfaceTechPS(TileVS frg, - uniform bool sbSpecular, - uniform bool sbRipples, - uniform bool sbMicro, - uniform bool sbNoAtmos, - uniform bool sbShadows) : COLOR -{ - - float2 vUVSrf = frg.texUV.xy * vTexOff.zw + vTexOff.xy; - float2 vUVWtr = frg.texUV.xy * vMicroOff.zw + vMicroOff.xy; - float2 vUVCld = frg.texUV.xy * vCloudOff.zw + vCloudOff.xy; - - vUVWtr.x += fTime/180.0f; - - float3 cNrm; - float fChA, fChB; - - if (sbRipples) cNrm = tex2D(OceaTexS, vUVWtr).xyz; - - float4 cMsk = tex2D(MaskTexS, vUVSrf); - float4 cTex = tex2D(DiffTexS, vUVSrf); - - if (bOverlay) { - float2 vUVOvl = frg.texUV.xy * vOverlayOff.zw + vOverlayOff.xy; - if (InRange(vUVOvl)) { - float4 cOvl = tex2D(SrfOverlayS, vUVOvl); - float4 cWtr = tex2D(MskOverlayS, vUVOvl); - cTex.rgb = lerp(cTex.rgb, cOvl.rgb, cOvl.a * vOverlayCtrl[0].rgb); - cMsk.rgb = lerp(cMsk.rgb, cWtr.rgb, cOvl.a * vOverlayCtrl[1].rgb); - cMsk.a = lerp(cMsk.a, cWtr.a, vOverlayCtrl[1].a); - } - } - - if (sbShadows) { - if (bCloudSh) { - fChA = tex2D(CloudTexS, vUVCld).a; - fChB = tex2D(Cloud2TexS, vUVCld - float2(1, 0)).a; - } - } - - float fShadow = 1.0f; - -#if defined(_SHDMAP) - if (bShadows) { - frg.shdH.xyz /= frg.shdH.w; - frg.shdH.z = 1 - frg.shdH.z; - float2 sp = frg.shdH.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); - float pd = frg.shdH.z + 0.05f * vSHD[3]; - fShadow = 1.0f - SampleShadows(sp, pd); - } -#endif - - float3 cFar, cMed, cLow; - - if (sbMicro) { - float2 UV = frg.texUV.xy; - // Create normals - if (bMicroNormals) { - // Normal in .ag luminance in .b - cFar = tex2D(MicroCS, UV*vMSc2.zw + vMSc2.xy).agb; // High altitude micro texture C - cMed = tex2D(MicroBS, UV*vMSc1.zw + vMSc1.xy).agb; // Medimum altitude micro texture B - cLow = tex2D(MicroAS, UV*vMSc0.zw + vMSc0.xy).agb; // Low altitude micro texture A - } - else { - // Color in .rgb no normals - cFar = tex2D(MicroCS, UV*vMSc2.zw + vMSc2.xy).rgb; // High altitude micro texture C - cMed = tex2D(MicroBS, UV*vMSc1.zw + vMSc1.xy).rgb; // Medimum altitude micro texture B - cLow = tex2D(MicroAS, UV*vMSc0.zw + vMSc0.xy).rgb; // Low altitude micro texture A - } - } - - - float3 cSpe = 0; - float3 nrmW = normalize(frg.nrmW); // Per-pixel surface normal vector - float3 nvrW = nrmW; // Per-pixel surface normal vector - float3 camW = normalize(frg.camW); // Unit viewing ray - float3 vVrt = vCameraPos - frg.camW; // Geo-centric pixel position - //float3 vPlN = normalize(vVrt); // Planet mean normal - //float fRad = dot(vVrt, vPlN); // Pixel Geo-distance - float3 cNgt = saturate(frg.aux[AUX_NIGHT]) * fNight; - - - // Render with specular ripples and fresnel water ------------------------- - // - if (sbSpecular) { - - // Specular Mask - float m = (1.0 - cMsk.a) * saturate(0.2f - frg.aux[AUX_NIGHT] * 4.0f); - float f4 = 0; - - // Specular intensity - float fInts = saturate(1.0 - fCameraAlt * 0.2e-4); - - if (sbRipples) { - - float3 vPlN = normalize(vVrt); // Planet mean normal - - cNrm.xy = clamp((cNrm.xy - 0.5f) * fInts * 5.0f, -1, 1); - - cNrm.z = cos(cNrm.x * cNrm.y * 1.570796); - - // Compute world space normal - nrmW = (vTangent * cNrm.r) + (vBiTangent * cNrm.g) + (vPlN * cNrm.b); - nrmW = lerp(nvrW, nrmW, m); - } - - // Compute Fresnel term - float f = 1.0 - saturate(dot(camW, nrmW)); - float f2 = f*f; - f4 = f2*f2; - - // Compute specular reflection intensity - float s = dot(reflect(-vSunDir, nrmW), camW); - - cSpe = m * float3(1.2f, 1.1f, 1.0f) * pow(saturate(s), 35.0f) * max(0.7, fInts*1.5) * fShadow; - - // Apply fresnel reflection - cTex.rgb = lerp(cTex.rgb, cSky, m * f4); - } - - - // Render with surface microtextures -------------------------------------- - // - if (sbMicro) { - - float dist = frg.aux[AUX_DIST]; - float step1 = smoothstep(15000, 3000, dist); - step1 *= (step1*step1); - float3 cFnl = max(0, min(2, 1.333f*(cFar+cMed+cLow)-1)); - - // Create normals - if (bMicroNormals) { - - cFnl = cFnl.bbb; - - #if BLEND==0 - float2 cMix = (cFar.rg + cMed.rg + cLow.rg) * 0.6666f; // SOFT BLEND - #elif BLEND==1 - float2 cMix = (cFar.rg+0.5f) * (cMed.rg+0.5f) * (cLow.rg+0.5f); // MEDIUM BLEND - #else - float2 cMix = cFar.rg * cMed.rg * cLow.rg * 8.0f; // HARD BLEND - #endif - - float3 cNrm = float3((cMix - 1.0f) * 2.0f, 0) * step1; - cNrm.z = cos(cNrm.x * cNrm.y * 1.57); - // Approximate world space normal - nrmW = normalize((vTangent * cNrm.x) + (vBiTangent * cNrm.y) + (nvrW * cNrm.z)); - - // Bend the normal towards sun a bit - nrmW = normalize(nrmW + vSunDir * 0.06f); - } - // Apply luminance - cTex.rgb *= lerp(1.0f, cFnl, step1); - } - - - - // Is Debug mode enabled - /* - // ---------------------------------------------------------------------- - if (bDebug) { - float3 vPlN = normalize(vVrt); - float fRad = dot(vVrt, vPlN); - return DebugProg(nrmW, cTex.rgb, fRad); - } - // ---------------------------------------------------------------------- - */ - float3 cDiffLocal = 0; - - LocalLights(cDiffLocal, nrmW, -frg.camW); - - // Do we have an atmosphere or not ? - // - if (sbNoAtmos) { - - float3 vPlN = normalize(vVrt); // Planet mean normal - float fTrS = saturate(dot(nvrW, vSunDir)*10.0f); // Shadowing by terrain - float fPlS = saturate(dot(vPlN, vSunDir)*10.0f); // Shadowing by planet - - float fDNS = dot(nrmW, vSunDir); - float fDRS = dot(camW, vSunDir); - - float fX = pow(saturate(fDNS), 0.33f); // Lambertian - float fZ = pow(abs(fDRS), 5.0f) * 0.5f; // Shadow compensation - float fLvl = fX * (fZ + 1.0f) * fExposure; // Bake all together - - fLvl *= (fTrS * fPlS); // Apply shadows - - float3 color = cTex.rgb * Light_fx2(cSun*max(fLvl, 0) * fShadow + cDiffLocal); - - return float4(pow(saturate(color), fTrGamma), 1.0f); // Gamma corrention - } - else { - - float a = (tex2Dlod(NoiseTexS, float4(frg.texUV.xy, 0, 0)).r - 0.5f) * ATMNOISE; - float fShd = 1.0f; - - // Do we render cloud shadows ? - // - if (sbShadows) { - if (bCloudSh) { - fShd = (vUVCld.x < 1.0 ? fChA : fChB); - fShd *= fShd; - fShd = saturate(1.0 - fShd*fAlpha); - } - } - - // Night lights ? - if (bLights) { - cMsk.b = (cMsk.b > 0.15f ? cMsk.b : 0.0f); // Blue dirt filter - cNgt *= cMsk.rgb; - } - - float q = saturate(fCameraAlt * 1e-5); - - - // Terrain, Specular and Night lights - float3 sun = max(frg.sunlight.rgb * fShadow, float3(0.9, 0.9, 1.0) * frg.sunlight.w); - float3 color = cTex.rgb * Light_fx2(sun*fShd + cDiffLocal + cNgt*(1-q)) + (cNgt*q*3.0f); - float3 atten = exp2(-vTotOutSct * frg.aux[AUX_RAYDEPTH]); - - // Terrain with gamma correction and attennuation - color = pow(abs(color * fExposure), fTrGamma) * atten; - - // Add atmosphere with gamma correction - color += pow(abs(frg.insca.rgb * vHazeMax), fAtmGamma); - - // Add Specular component - color += cSpe * atten * fShd; - - return float4(color+a, 1.0f); - } -} - - - -// ============================================================================ -// Cloud Layer Renderer -// ============================================================================ - -CloudVS CloudTechVS(TILEVERTEX vrt) -{ - // Zero output. - CloudVS outVS = (CloudVS)0; - - // Apply a world transformation matrix - float3 vPosW = mul(float4(vrt.posL, 1.0f), mWorld).xyz; - float3 vNrmW = mul(float4(vrt.normalL, 0.0f), mWorld).xyz; - outVS.posH = mul(float4(vPosW, 1.0f), mViewProj); - outVS.nrmW = vNrmW; - outVS.texUV.xy = vrt.tex0.xy; // Note: vrt.tex0 is un-used (hardcoded in Tile::CreateMesh and varies per tile) - - float3 vVrt = vCameraPos + vPosW; // Geo-centric vertex position - float3 vPlN = normalize(vVrt); - float3 vRay = normalize(-vPosW); // Unit viewing ray - float fDPS = dot(vPlN, vSunDir); // Dot mean normal, sun direction - float fRay = abs(dot(vPosW, vRay)); // Vertex camera distance - float fTrA = saturate(fDPS*2.924f + 0.657f); - - // Camara altitude dependency multiplier for ambient color of atmosphere - - float fAmb = max(saturate(fTrA*8.0*fAmbient), fGlobalAmb) * 0.25f; - - float fDPR = dot(vPlN, vRay); // Dot mean normal, viewing ray - float fDNR = dot(vNrmW, vRay); - float fDNS = dot(vNrmW, vSunDir); // Dot vertex normal, sun direction - float fDRS = dot(vRay, vSunDir); // Dot viewing ray, sun direction - float fDst = dot(vVrt, vPlN); // Vertex geo-distance - float fAlt = fDst - fRadius; // Vertex altitude - - float fCamAlt = fCameraAlt; - - if (bInSpace) { - float fCm2 = fDst * fDst; - float fPrm = fDst * fDPR; - fCamAlt = fHorizonAlt; - fRay = sqrt(fAtmRad2 - (fCm2 - fPrm*fPrm)) - fPrm; // Length of the ray inside atmosphere - } - - - // Altitude vector for sample points - float3 vAlt = float3(fAlt, (fAlt + fCamAlt)*0.5, fCamAlt); - - // Compute atmospheric density for all sample points - float3 vDns = exp2(-vAlt*fInvScaleHeight); // Compute atmospheric density for all sample points - - // Evaluate a Gauss-Lobatto integral to give an optical depth for a viewing ray - float fDRay = dot(vDns, vWeight3) * (fRay * fInvScaleHeight) * 0.3465735903f; - - fDRay *= 0.5; - - float3 vSunLight = exp2(-vTotOutSct * (vDns[0] * 0.25f * AngleCoEff(fDPS))) * Shadow(fDPS, srfoffset); - - // Compute surface texture color attennuation (i.e. extinction term) - outVS.atten = exp2(-vTotOutSct * fDRay); - outVS.fade.x = exp2(-fDRay * 0.5f) * 2.0f; - outVS.fade.y = 1.0f - abs(dot(vPolarAxis, vPlN)); - - // Multiply in-coming light with phase and light scattering factors - outVS.insca = ((vRayInSct * RPhase(fDRS)) + (vMieInSct * MPhase(fDRS))) * vSunLight * fDRay; - - outVS.insca = (1.0f - exp2(-outVS.insca)); - outVS.atten *= max(vSunLight, (vRayInSct + 1.0f) * fAmb*0.75f) * 1.3f; - - return outVS; -} - - -float4 CloudTechPS(CloudVS frg) : COLOR -{ - float2 vUVMic = frg.texUV.xy * vMicroOff.zw + vMicroOff.xy; - float2 vUVTex = frg.texUV.xy; - - float a = (tex2Dlod(NoiseTexS, float4(vUVTex,0,0)).r - 0.5f) * ATMNOISE; - - float4 cTex = tex2D(DiffTexS, vUVTex); - - if (!bEarth) { - // This is not the Earth - float3 color = cTex.rgb*frg.atten.rgb*fCloudInts + frg.insca.rgb*vHazeMax; - return float4(saturate(color + a), cTex.a*saturate(frg.fade.x*fCloudInts*fCloudInts)); - } - - // ----------------------------------------------- - // Cloud layer rendering for Earth - // ----------------------------------------------- - - float4 cMic = tex2D(CloudMicroS, vUVMic); - -#if defined(_CLOUDNORMALS) - - if (bCloudNorm) { - -#if defined(_CLOUDMICRO) - float4 cMicNorm = tex2D(CloudMicroNormS, vUVMic); // Filename "cloud1_norm.dds" -#endif - - // Filter width - float d = 2.0 / 512.0; - float3 nrm = 0; - - float x1 = tex2D(DiffTexS, vUVTex + float2(-d, 0)).a; - float x2 = tex2D(DiffTexS, vUVTex + float2(+d, 0)).a; - nrm.x = (x1*x1 - x2*x2); - - float y1 = tex2D(DiffTexS, vUVTex + float2(0, -d)).a; - float y2 = tex2D(DiffTexS, vUVTex + float2(0, +d)).a; - nrm.y = (y1*y1 - y2*y2); - - float dMN = dot(frg.nrmW, vSunDir); // Planet mean normal sun angle - -#if defined(_CLOUDMICRO) - // Blend in cloud normals only on moderately thick clouds, allowing the highest cloud tops to be smooth. - nrm.xy = (nrm.xy + saturate((cTex.a * 10.0f) - 3.0f) * saturate(((1.0f - cTex.a) * 10.0f) - 1.0f) * (cMicNorm.rg - 0.5f)); // new -#endif - // Increase normals contrast based on sun-earth angle. - nrm.xyz = nrm.xyz * (1.0f + (0.5f * dMN)); - - nrm.z = sqrt(1.0f - saturate(nrm.x*nrm.x + nrm.y*nrm.y)); - - // Approximate world space normal from local tangent space - nrm = normalize((vTangent * nrm.x) + (vBiTangent * nrm.y) + (frg.nrmW * nrm.z)); - - float dCS = dot(nrm, vSunDir); // Cloud normal sun angle - - // Brighten the lighting model for clouds, based on sun-earth angle. Twice is better. - // Low sun angles = greater effect. No modulation leads to washed out normals at high sun angles. - dCS = saturate((1.0f - dMN) * (dCS * (1.0f - dCS)) + dCS); - dCS = saturate((1.0f - dMN) * (dCS * (1.0f - dCS)) + dCS); - - // With a high sun angle, don't let the dCS go below 0.2 to avoid unnaturally dark edges. - dCS = lerp(0.2f*dMN, 1.0f, dCS); - - // Effect of normal/sun angle to color - // Add some brightness (borrowing red channel from sunset attenuation) - // Adding it to the sun illumination factor, taking care to keep from saturating - cTex.rgb *= dCS + ((1.0f - dCS) * 0.2f); - } -#endif - -#if defined(_CLOUDMICRO) - float f = cTex.a; - float g = lerp(1.0f, cMic.a, frg.fade.y); - float h = (g + 4.0f)*0.2f; - cTex.a = saturate(lerp(g, h, f) * f); -#endif - - // Reduce attenuation near terminator (multiply by 3) - // Change attenuation to be grayscale, not colored (.r not .rgb) - // Ensure illumination goes as far as possible by borrowing red channel (.r) - //float3 color = cTex.rgb*saturate(frg.atten.r * 3)*fCloudInts; - float3 color = cTex.rgb*saturate(frg.atten.r * 3)*fCloudInts; - - // Blend haze without saturating - color = lerp(color, 1.0f, frg.insca.rgb*vHazeMax); - - return float4(saturate(color + a), cTex.a*saturate(fCloudInts*fCloudInts)); -} - - -technique CloudTech -{ - pass P0 - { - vertexShader = compile vs_3_0 CloudTechVS(); - pixelShader = compile ps_3_0 CloudTechPS(); - - AlphaBlendEnable = true; - BlendOp = Add; - SrcBlend = SrcAlpha; - DestBlend = InvSrcAlpha; - ZEnable = false; - ZWriteEnable = false; - } -} - - -#if defined(_CLOUDSHADOWS) -#define _CLDSHD true -#else -#define _CLDSHD false -#endif - - -// This is used for high resolution base tiles -------------------------------- -// -technique TileTech -{ - - pass P0 // Earth - { - //Spec, Rippl, Mic, NoAtm, Shadows - pixelShader = compile ps_3_0 SurfaceTechPS(true, true, false, false, _CLDSHD); - vertexShader = compile vs_3_0 SurfaceTechVS(true, false); - AlphaBlendEnable = false; //Rippl, NoAtm - } - - pass P1 // Earth, NoRipples - { - //Spec, Rippl, Mic, NoAtm, Shadows - pixelShader = compile ps_3_0 SurfaceTechPS(true, false, false, false, _CLDSHD); - vertexShader = compile vs_3_0 SurfaceTechVS(false, false); - AlphaBlendEnable = false; //Rippl, NoAtm - } - - pass P2 // Mars - { - //Spec, Rippl, Mic, NoAtm, Shadows - pixelShader = compile ps_3_0 SurfaceTechPS(false, false, true, false, false); - vertexShader = compile vs_3_0 SurfaceTechVS(false, false); - AlphaBlendEnable = false; //Rippl, NoAtm - } - - pass P3 // Mars, no micro - { - //Spec, Rippl, Mic, NoAtm, Shadows - pixelShader = compile ps_3_0 SurfaceTechPS(false, false, false, false, false); - vertexShader = compile vs_3_0 SurfaceTechVS(false, false); - AlphaBlendEnable = false; //Rippl, NoAtm - } - - pass P4 // Luna - { - //Spec, Rippl, Mic, NoAtm, Shadows - pixelShader = compile ps_3_0 SurfaceTechPS(false, false, true, true, false); - vertexShader = compile vs_3_0 SurfaceTechVS(false, true); - AlphaBlendEnable = false; //Rippl, NoAtm - } - - pass P5 // Luna, no micro - { - //Spec, Rippl, Mic, NoAtm, Shadows - pixelShader = compile ps_3_0 SurfaceTechPS(false, false, false, true, false); - vertexShader = compile vs_3_0 SurfaceTechVS(false, true); - AlphaBlendEnable = false; //Rippl, NoAtm - } -} - - - -// ============================================================================ -// Render Horizon "Ring" from the space -// ============================================================================ - -HazeVS RingTechVS(float3 posL : POSITION0) -{ - // Zero output. - HazeVS outVS = (HazeVS)0; - - posL.xz *= lerp(vTexOff[0], vTexOff[1], posL.y); - posL.y = lerp(vTexOff[2], vTexOff[3], posL.y); - - float3 posW = mul(float4(posL, 1.0f), mWorld).xyz; - outVS.posH = mul(float4(posW, 1.0f), mViewProj); - - if (bOnOff) SkyColor(outVS.insca, normalize(posW)); // HorizonColor(outVS.insca, normalize(posW)); - else outVS.insca = float3(0, 0, 0); - - return outVS; -} - -float4 RingTechPS(HazeVS frg) : COLOR -{ - float a = (tex2Dlod(NoiseTexS, float4(frg.texUV,0,0)).r - 0.5f) * ATMNOISE; - return float4(frg.insca.rgb+a, 1.0f); -} - -technique RingTech -{ - pass P0 - { - vertexShader = compile vs_3_0 RingTechVS(); - pixelShader = compile ps_3_0 RingTechPS(); - - AlphaBlendEnable = true; - BlendOp = Add; - SrcBlend = One; - DestBlend = One; - ZEnable = false; - ZWriteEnable = false; - } -} - - - - - - -// ============================================================================ -// Render SkyDome and Horizon -// ============================================================================ - -HazeVS HorizonTechVS(float3 posL : POSITION0) -{ - // Zero output. - HazeVS outVS = (HazeVS)0; - - outVS.texUV = posL.xy*10.0; - - posL.xz *= lerp(vTexOff[0], vTexOff[1], posL.y); - posL.y = lerp(vTexOff[2], vTexOff[3], posL.y); - - float3 posW = mul(float4(posL, 1.0f), mWorld).xyz; - outVS.posH = mul(float4(posW, 1.0f), mViewProj); - - if (bOnOff) SkyColor(outVS.insca, normalize(posW)); - else outVS.insca = float3(0, 0, 0); - - return outVS; -} - - -float4 HorizonTechPS(HazeVS frg) : COLOR -{ - float a = (tex2Dlod(NoiseTexS, float4(frg.texUV,0,0)).r - 0.5f) * 0.008; - return float4(frg.insca.rgb+a, 1.0f); -} - -technique HorizonTech -{ - pass P0 - { - vertexShader = compile vs_3_0 HorizonTechVS(); - pixelShader = compile ps_3_0 HorizonTechPS(); - - AlphaBlendEnable = true; - BlendOp = Add; - SrcBlend = One; - DestBlend = One; - ZEnable = false; - ZWriteEnable = false; - } -} - - - -// ============================================================================ -// Render Skydome (i.e. Celestial Sphere Background Image Manager) from Space -// ============================================================================ - -CelSphereVS SpaceTechVS(TILEVERTEX vrt) -{ - // Zero output. - CelSphereVS outVS = (CelSphereVS)0; - float3 posW = mul(float4(vrt.posL, 1.0f), mWorld).xyz; - outVS.posH = mul(float4(posW, 1.0f), mViewProj); - outVS.tex0 = vrt.tex0; - return outVS; -} - -float4 SpaceTechPS(CelSphereVS frg) : COLOR -{ - float3 vColor = 0; - if (bLights) vColor += tex2D(DiffTexS, frg.tex0).rgb * fAlpha; - if (bLocals) vColor += tex2D(MaskTexS, frg.tex0).rgb * fNight; - return float4(vColor, 1.0); -} - -technique SkyDomeTech -{ - pass P0 - { - vertexShader = compile vs_3_0 SpaceTechVS(); - pixelShader = compile ps_3_0 SpaceTechPS(); - - AlphaBlendEnable = false; - ZEnable = false; - ZWriteEnable = false; - } -} diff --git a/OVP/D3D9Client/shaders/Vessel.fx b/OVP/D3D9Client/shaders/Vessel.fx index 1a85fbdef..ea4691f5b 100644 --- a/OVP/D3D9Client/shaders/Vessel.fx +++ b/OVP/D3D9Client/shaders/Vessel.fx @@ -249,6 +249,9 @@ float4 AdvancedPS(float4 sc : VPOS, PBRData frg) : COLOR cTex = cTex * (1 - gColor*0.5f) + gColor; #endif + cTex.rgb *= gSun.Transmission; + cTex.rgb += gSun.Inscatter; + return cTex; } diff --git a/Orbitersdk/include/DrawAPI.h b/Orbitersdk/include/DrawAPI.h index 2324f98d8..e8f73a9ff 100644 --- a/Orbitersdk/include/DrawAPI.h +++ b/Orbitersdk/include/DrawAPI.h @@ -21,6 +21,7 @@ #include "OrbiterAPI.h" #include +#include #ifdef D3D9CLIENT_EXPORTS #include "d3dx9.h" @@ -67,12 +68,24 @@ namespace oapi { y = _y; } + FVECTOR2(double _x, double _y) + { + x = float(_x); + y = float(_y); + } + FVECTOR2(long _x, long _y) { x = float(_x); y = float(_y); } + FVECTOR2(DWORD _x, DWORD _y) + { + x = float(_x); + y = float(_y); + } + FVECTOR2(int _x, int _y) { x = float(_x); @@ -102,6 +115,35 @@ namespace oapi { return FVECTOR2(x * f, y * f); } + inline FVECTOR2 operator* (FVECTOR2 f) const + { + return FVECTOR2(x * f.x, y * f.y); + } + + inline FVECTOR2& operator*= (FVECTOR2& f) + { + x *= f.x; y *= f.y; + return *this; + } + + inline FVECTOR2& operator+= (FVECTOR2& f) + { + x += f.x; y += f.y; + return *this; + } + + inline FVECTOR2& operator-= (FVECTOR2& f) + { + x -= f.x; y -= f.y; + return *this; + } + + inline FVECTOR2& operator/= (FVECTOR2& f) + { + x /= f.x; y /= f.y; + return *this; + } + inline FVECTOR2 operator/ (float f) const { f = 1.0f / f; @@ -113,6 +155,11 @@ namespace oapi { return FVECTOR2(x + f, y + f); } + inline FVECTOR2 operator+ (FVECTOR2& f) const + { + return FVECTOR2(x + f.x, y + f.y); + } + inline FVECTOR2 operator- (float f) const { return FVECTOR2(x - f, y - f); @@ -137,7 +184,7 @@ namespace oapi { * \brief 32-bit floating point 3D vector type. * \note This structure is compatible with the D3DXVECTOR3 type. */ - typedef struct FVECTOR3 + typedef union FVECTOR3 { FVECTOR3() { @@ -170,7 +217,33 @@ namespace oapi { y = float(v.y); z = float(v.z); } + FVECTOR3(const D3DXCOLOR& v) + { + x = float(v.r); + y = float(v.g); + z = float(v.b); + } #endif + float MaxRGB() const + { + return max(max(r, g), b); + } + + float MinRGB() const + { + return min(min(r, g), b); + } + + float sql() const + { + return x * x + y * y + z * z; + } + + inline VECTOR3 _V() const + { + VECTOR3 v = { x,y,z }; + return v; + } inline FVECTOR3& operator*= (float f) { @@ -178,6 +251,12 @@ namespace oapi { return *this; } + inline FVECTOR3& operator*= (const FVECTOR3 &f) + { + x *= f.x; y *= f.y; z *= f.z; + return *this; + } + inline FVECTOR3& operator/= (float f) { // return *this *= (1.0f / f); // nicer? @@ -192,23 +271,45 @@ namespace oapi { return *this; } + inline FVECTOR3& operator+= (const FVECTOR3& f) + { + x += f.x; y += f.y; z += f.z; + return *this; + } + inline FVECTOR3& operator-= (float f) { x -= f; y -= f; z -= f; return *this; } + inline FVECTOR3& operator-= (const FVECTOR3 &f) + { + x -= f.x; y -= f.y; z -= f.z; + return *this; + } + inline FVECTOR3 operator* (float f) const { return FVECTOR3(x * f, y * f, z * f); } + inline FVECTOR3 operator* (const FVECTOR3 &f) const + { + return FVECTOR3(x * f.x, y * f.y, z * f.z); + } + inline FVECTOR3 operator/ (float f) const { f = 1.0f / f; return FVECTOR3(x * f, y * f, z * f); } + inline FVECTOR3 operator/ (const FVECTOR3 &f) const + { + return FVECTOR3(x / f.x, y / f.y, z / f.z); + } + inline FVECTOR3 operator+ (float f) const { return FVECTOR3(x + f, y + f, z + f); @@ -235,12 +336,18 @@ namespace oapi { } #ifdef D3D9CLIENT_EXPORTS - inline operator D3DXVECTOR3() + inline operator D3DXVECTOR3() const { return D3DXVECTOR3(x, y, z); } + inline operator D3DXCOLOR() const + { + return D3DXCOLOR(x, y, z, 1); + } #endif - float x, y, z; + struct { float x, y, z; }; + struct { float r, g, b; }; + FVECTOR2 xy; } FVECTOR3; @@ -248,8 +355,7 @@ namespace oapi { * \brief 32-bit floating point 4D vector type. * \note This structure is compatible with the D3DXVECTOR4 type. */ -#pragma pack(push, 1) - typedef union FVECTOR4 + typedef union __declspec(align(16)) FVECTOR4 { DWORD dword_abgr() const { @@ -283,6 +389,11 @@ namespace oapi { return clr; } + float MaxRGB() const + { + return max(max(r, g), b); + } + FVECTOR4() { r = g = b = a = 0.0f; @@ -323,7 +434,7 @@ namespace oapi { w = float(v.w); } - FVECTOR4(const VECTOR3& v, float _w = 0.0f) + FVECTOR4(const VECTOR3& v, float _w) { x = float(v.x); y = float(v.y); @@ -331,7 +442,7 @@ namespace oapi { w = _w; } - FVECTOR4(const FVECTOR3& v, float _w = 0.0f) + FVECTOR4(const FVECTOR3& v, float _w) { rgb = v; w = _w; @@ -369,6 +480,13 @@ namespace oapi { z = float(v.z); w = float(v.w); } + FVECTOR4(const D3DXCOLOR& v) + { + x = float(v.r); + y = float(v.g); + z = float(v.b); + w = float(v.a); + } #endif @@ -435,19 +553,18 @@ namespace oapi { } #ifdef D3D9CLIENT_EXPORTS - inline operator D3DXVECTOR4() + inline operator D3DXVECTOR4() const { return D3DXVECTOR4(x, y, z, w); } #endif - + __m128 xm; float data[4]; struct { float x, y, z, w; }; struct { float r, g, b, a; }; FVECTOR3 xyz; // , w; }; FVECTOR3 rgb; // , a; }; } FVECTOR4; -#pragma pack(pop) typedef union DRECT @@ -487,7 +604,7 @@ namespace oapi { * \brief Float-valued 4x4 matrix. * \note This structure is compatible with the D3DXMATRIX. */ - typedef union FMATRIX4 + typedef union __declspec(align(16)) FMATRIX4 { FMATRIX4() { m11 = m12 = m13, m14 = m21 = m22 = m23 = m24 = m31 = m32 = m33 = m34 = m41 = m42 = m43 = m44 = 0; @@ -513,6 +630,14 @@ namespace oapi { { memcpy_s(data, sizeof(FMATRIX4), &m, sizeof(m)); } + FMATRIX4(const LPD3DXMATRIX m) + { + memcpy_s(data, sizeof(FMATRIX4), m, sizeof(FMATRIX4)); + } + inline operator LPD3DXMATRIX() + { + return (LPD3DXMATRIX)this; + } #endif void Zero() @@ -526,6 +651,15 @@ namespace oapi { m11 = m22 = m33 = m44 = 1.0f; } + void _swap(float& a, float& b) { float c = a; a = b; b = c; } + + void Transpose() + { + _swap(m12, m21); _swap(m13, m31); + _swap(m14, m41); _swap(m23, m32); + _swap(m24, m42); _swap(m34, m43); + } + float data[16]; struct { FVECTOR4 _x, _y, _z, _p; }; struct { float m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44; }; @@ -545,6 +679,16 @@ namespace oapi { } + inline FVECTOR4 tmul(const FVECTOR4& V, const FMATRIX4& M) + { + float x = V.x * M.m11 + V.y * M.m12 + V.z * M.m13 + V.w * M.m14; + float y = V.x * M.m21 + V.y * M.m22 + V.z * M.m23 + V.w * M.m24; + float z = V.x * M.m31 + V.y * M.m32 + V.z * M.m33 + V.w * M.m34; + float w = V.x * M.m41 + V.y * M.m42 + V.z * M.m43 + V.w * M.m44; + return FVECTOR4(x, y, z, w); + } + + /** * \brief Transform a position by matrix */ @@ -573,14 +717,20 @@ namespace oapi { inline FVECTOR2 unit(const FVECTOR2& v) { - float f = 1.0f / sqrt(v.x * v.x + v.y * v.y); + float f = 1.0f / ::sqrt(v.x * v.x + v.y * v.y); return FVECTOR2(v.x * f, v.y * f); } inline FVECTOR3 unit(const FVECTOR3& v) { - float f = 1.0f / sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - return FVECTOR3(v.x * f, v.y * f, v.z * f); + float d = v.x * v.x + v.y * v.y + v.z * v.z; + return d > 0 ? FVECTOR3(v.x, v.y, v.z) / ::sqrt(d) : 0.0f; + } + + inline FVECTOR3 normalize(const FVECTOR3& v) + { + float d = v.x * v.x + v.y * v.y + v.z * v.z; + return d > 0 ? FVECTOR3(v.x, v.y, v.z) / ::sqrt(d) : 0.0f; } inline float dot(const FVECTOR2& v, const FVECTOR2& w) @@ -600,12 +750,12 @@ namespace oapi { inline float length(const FVECTOR2& v) { - return sqrt(v.x * v.x + v.y * v.y); + return ::sqrt(v.x * v.x + v.y * v.y); } inline float length(const FVECTOR3& v) { - return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + return ::sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } inline FVECTOR3 cross(const FVECTOR3& a, const FVECTOR3& b) @@ -673,6 +823,16 @@ namespace oapi { return FVECTOR4(::exp(x.x), ::exp(x.y), ::exp(x.z), ::exp(x.w)); } + inline FVECTOR3 sqrt(const FVECTOR3& x) + { + return FVECTOR3(::sqrt(x.x), ::sqrt(x.y), ::sqrt(x.z)); + } + + inline FVECTOR4 sqrt(const FVECTOR4& x) + { + return FVECTOR4(::sqrt(x.x), ::sqrt(x.y), ::sqrt(x.z), ::sqrt(x.w)); + } + // ====================================================================== @@ -1518,6 +1678,15 @@ class OAPIFUNC Sketchpad */ virtual void SetClipDistance(float _near, float _far) { assert(false); } + /** + * \brief [DX9] Set a world matrix for drawing into a specified 3D location and the drawing will be facing the camera. + * \param wpos Camera centric location in ECL frame. + * \param scl Drawing scale factor. + * \param bFixed If 'true' drawing will retain a constant size recardless of camera distance. (One drawing unit is aprox. one pixel) + * \param index Direction of drawing stace x-axis in ecliptic frame. If 'NULL' drawing is orientated with screen (i.e. display) + * \Note Only works in perspective projection + */ + virtual void SetWorldBillboard(const FVECTOR3& wpos, float scl = 1.0f, bool bFixed = true, const FVECTOR3 *index = NULL) { assert(false); } private: SURFHANDLE surf; }; diff --git a/Src/Celbody/Moon/Config/Moon.cfg b/Src/Celbody/Moon/Config/Moon.cfg index ba1117224..7ab2773aa 100644 --- a/Src/Celbody/Moon/Config/Moon.cfg +++ b/Src/Celbody/Moon/Config/Moon.cfg @@ -33,6 +33,8 @@ LabelFormat = 2 MaxPatchResolution = 16 ; highest sphere patch level ElevationResolution = 0.5 ; target resolution of elevation data [m] HorizonExcess = 0.015 ; prevent mountain tops beyond sphere horizon from disappearing +MaxElevation = 10800 +MinElevation = -9200 ; === Fixed surface observation points === BEGIN_OBSERVER diff --git a/Src/Celbody/Vsop87/Earth/Config/Earth.cfg b/Src/Celbody/Vsop87/Earth/Config/Earth.cfg index dd01ecbc1..9c5ce2904 100644 --- a/Src/Celbody/Vsop87/Earth/Config/Earth.cfg +++ b/Src/Celbody/Vsop87/Earth/Config/Earth.cfg @@ -61,6 +61,8 @@ MinCloudResolution = 1 ; cloud layer from this resolution MaxCloudResolution = 9 ; highest cloud resolution level ElevationResolution = 0.5 ; target resolution of elevation data [m] SpecularRipple = TRUE ; enable specular water microtexture +MaxElevation = 9000 +MinElevation = -420 ; === Surface Bases === ; place additional bases or diff --git a/Src/Celbody/Vsop87/Mars/Config/Mars.cfg b/Src/Celbody/Vsop87/Mars/Config/Mars.cfg index ab5c43107..d6b68efd9 100644 --- a/Src/Celbody/Vsop87/Mars/Config/Mars.cfg +++ b/Src/Celbody/Vsop87/Mars/Config/Mars.cfg @@ -50,4 +50,5 @@ AlbedoRGB = 0.52 0.36 0.16 MaxPatchResolution = 16 ; highest sphere patch level ElevationResolution = 1 HorizonExcess = 0.035 ; prevent mountain tops beyond sphere horizon from disappearing -MinElevation = -22000 ; min surface elevation relative to mean radius \ No newline at end of file +MinElevation = -8300 ; min surface elevation relative to mean radius +MaxElevation = 21300 \ No newline at end of file diff --git a/Src/Vessel/DeltaGlider/Meshes/deltaglider_vc.msh b/Src/Vessel/DeltaGlider/Meshes/deltaglider_vc.msh index e099122c5..f7fed26e6 100644 --- a/Src/Vessel/DeltaGlider/Meshes/deltaglider_vc.msh +++ b/Src/Vessel/DeltaGlider/Meshes/deltaglider_vc.msh @@ -19913,6 +19913,7 @@ GEOM 1319 1121 MATERIAL 24 TEXTURE 0 LABEL ILOCK_GLASS +FLAG 1 GEOM 6 4 -0.090357 0.045438 8.109951 -0.000006 0.420735 -0.907183 -0.069649 0.068852 8.120810 -0.000005 0.420729 -0.907187 @@ -19926,6 +19927,7 @@ GEOM 6 4 4 2 3 MATERIAL 24 TEXTURE 0 +FLAG 1 GEOM 120 108 ; cockpitglass 128 1.217259 1.510586 4.404531 -0.591781 -0.777958 -0.211134 1.242981 1.457264 4.528909 -0.591780 -0.777958 -0.211135 diff --git a/Src/Vessel/DeltaGlider/Meshes/deltaglidercockpit.msh b/Src/Vessel/DeltaGlider/Meshes/deltaglidercockpit.msh index b5e5f37a2..1375c3cfb 100644 --- a/Src/Vessel/DeltaGlider/Meshes/deltaglidercockpit.msh +++ b/Src/Vessel/DeltaGlider/Meshes/deltaglidercockpit.msh @@ -23251,6 +23251,7 @@ GEOM 1319 1121 ; psngr4 126 3 26 598 MATERIAL 24 TEXTURE 0 +FLAG 1 GEOM 6 4 ; cockpitglass 127 -0.090357 0.045438 8.109951 -0.000006 0.420735 -0.907183 -0.069649 0.068852 8.120810 -0.000005 0.420729 -0.907187 @@ -23264,6 +23265,7 @@ GEOM 6 4 ; cockpitglass 127 4 2 3 MATERIAL 24 TEXTURE 0 +FLAG 1 GEOM 120 108 ; cockpitglass 128 1.217259 1.510586 4.404531 -0.591781 -0.777958 -0.211134 1.242981 1.457264 4.528909 -0.591780 -0.777958 -0.211135