Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / surface_light_grid.cpp
blobd8542286909d98b0f960cdd39c7dda64a444dc0c
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include "nel/3d/surface_light_grid.h"
23 #include "nel/misc/common.h"
24 #include "nel/3d/ig_surface_light.h"
25 #include "nel/misc/fast_floor.h"
26 #include "nel/3d/light_influence_interpolator.h"
27 #include "nel/3d/point_light_named.h"
28 #include "nel/3d/scene_group.h"
31 using namespace NLMISC;
33 #ifdef DEBUG_NEW
34 #define new DEBUG_NEW
35 #endif
37 namespace NL3D {
40 // ***************************************************************************
41 CSurfaceLightGrid::CSurfaceLightGrid()
43 /* ***********************************************
44 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
45 * It can be loaded/called through CAsyncFileManager for instance
46 * ***********************************************/
48 Width= 0;
49 Height= 0;
53 // ***************************************************************************
54 void CSurfaceLightGrid::serial(NLMISC::IStream &f)
56 /* ***********************************************
57 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
58 * It can be loaded/called through CAsyncFileManager for instance
59 * ***********************************************/
61 (void)f.serialVersion(0);
62 f.serial(Origin);
63 f.serial(Width);
64 f.serial(Height);
65 f.serial(Cells);
69 // ***************************************************************************
70 void CSurfaceLightGrid::getStaticLightSetup(NLMISC::CRGBA sunAmbient, const CVector &localPos, std::vector<CPointLightInfluence> &pointLightList, uint8 &sunContribution,
71 CIGSurfaceLight &igsl, NLMISC::CRGBA &localAmbient) const
73 // Get local coordinate to the grid.
74 float xfloat= (localPos.x - Origin.x) * igsl.getOOCellSize();
75 float yfloat= (localPos.y - Origin.y) * igsl.getOOCellSize();
76 sint wCell= Width-1;
77 sint hCell= Height-1;
78 // fastFloor: use a precision of 256 to avoid doing OptFastFloorBegin.
79 sint wfixed= wCell<<8;
80 sint hfixed= hCell<<8;
81 sint xfixed= NLMISC::OptFastFloor(xfloat * 256);
82 sint yfixed= NLMISC::OptFastFloor(yfloat * 256);
83 clamp(xfixed, 0, wfixed);
84 clamp(yfixed, 0, hfixed);
85 // compute the cell coord, and the subCoord for bilinear.
86 sint xCell, yCell, xSub, ySub;
87 xCell= xfixed>>8;
88 yCell= yfixed>>8;
89 clamp(xCell, 0, wCell-1);
90 clamp(yCell, 0, hCell-1);
91 // Hence, xSub and ySub range is [0, 256].
92 xSub= xfixed - (xCell<<8);
93 ySub= yfixed - (yCell<<8);
96 // Use a CLightInfluenceInterpolator to biLinear light influence
97 CLightInfluenceInterpolator interp;
98 // Must support only 2 light per cell corner.
99 nlassert(CSurfaceLightGrid::NumLightPerCorner==2);
100 nlassert(CLightInfluenceInterpolator::NumLightPerCorner==2);
101 // Get ref on array of PointLightNamed.
102 CPointLightNamed *igPointLights= NULL;;
103 if( igsl._Owner->getPointLightList().size() >0 )
105 // const_cast, because will only change _IdInfluence, and
106 // also because CLightingManager will call appendLightedModel()
107 igPointLights= const_cast<CPointLightNamed*>(&(igsl._Owner->getPointLightList()[0]));
109 // For 4 corners.
110 uint x,y;
111 uint sunContribFixed= 0;
112 uint rLocalAmbientFixed= 0;
113 uint gLocalAmbientFixed= 0;
114 uint bLocalAmbientFixed= 0;
115 uint wLocalAmbientFixed= 0;
116 for(y=0;y<2;y++)
118 for(x=0;x<2;x++)
120 // Prepare compute for PointLights.
121 //-------------
122 // get ref on TLI, and on corner.
123 const CCellCorner &cellCorner= Cells[ (yCell+y)*Width + xCell+x ];
124 CLightInfluenceInterpolator::CCorner &corner= interp.Corners[y*2 + x];
125 // For all lights
126 uint lid;
127 if (igPointLights)
129 for (lid = 0; lid < CSurfaceLightGrid::NumLightPerCorner; lid++)
131 // get the id of the light in the ig
132 uint igLightId = cellCorner.Light[lid];
133 // If empty id, stop
134 if (igLightId == 0xFF)
135 break;
136 else
138 // Set pointer of the light in the corner
139 corner.Lights[lid] = igPointLights + igLightId;
143 // Reset Empty slots.
144 for(; lid<CSurfaceLightGrid::NumLightPerCorner; lid++)
146 // set to NULL
147 corner.Lights[lid]= NULL;
150 // BiLinear SunContribution.
151 //-------------
152 uint xBi= (x==0)?256-xSub : xSub;
153 uint yBi= (y==0)?256-ySub : ySub;
154 uint mulBi= xBi * yBi;
155 sunContribFixed+= cellCorner.SunContribution * mulBi;
158 // BiLinear Ambient Contribution.
159 //-------------
160 // If FF, then take Sun Ambient => leave color and alpha To 0.
161 if(igPointLights && cellCorner.LocalAmbientId!=0xFF)
163 CPointLight &pl= igPointLights[cellCorner.LocalAmbientId];
164 // take current ambient from pointLight
165 CRGBA ambCorner= pl.getAmbient();
166 // Add with sun this one?
167 if(pl.getAddAmbientWithSun())
168 ambCorner.addRGBOnly(ambCorner, sunAmbient);
169 // bilinear
170 rLocalAmbientFixed+= ambCorner.R * mulBi;
171 gLocalAmbientFixed+= ambCorner.G * mulBi;
172 bLocalAmbientFixed+= ambCorner.B * mulBi;
173 // increase the weight influence of igPointLights
174 wLocalAmbientFixed+= 256 * mulBi;
178 // interpolate PointLights.
179 interp.interpolate(pointLightList, xSub/256.f, ySub/256.f);
181 // Final SunContribution
182 sunContribution= sunContribFixed>>16;
184 // Final Ambient Contribution of Ambient Lights
185 CRGBA tempAmbient;
186 tempAmbient.R= rLocalAmbientFixed>>16;
187 tempAmbient.G= gLocalAmbientFixed>>16;
188 tempAmbient.B= bLocalAmbientFixed>>16;
189 // must interpolate between SunAmbient and tempAmbient
190 uint uAmbFactor= wLocalAmbientFixed>>16;
191 // Blend, but tempAmbient.r/g/b is already multiplied by weight.
192 localAmbient.modulateFromuiRGBOnly(sunAmbient, 256 - uAmbFactor);
193 localAmbient.addRGBOnly(localAmbient, tempAmbient);
199 } // NL3D