1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
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
;
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 * ***********************************************/
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);
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();
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
;
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]));
111 uint sunContribFixed
= 0;
112 uint rLocalAmbientFixed
= 0;
113 uint gLocalAmbientFixed
= 0;
114 uint bLocalAmbientFixed
= 0;
115 uint wLocalAmbientFixed
= 0;
120 // Prepare compute for PointLights.
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
];
129 for (lid
= 0; lid
< CSurfaceLightGrid::NumLightPerCorner
; lid
++)
131 // get the id of the light in the ig
132 uint igLightId
= cellCorner
.Light
[lid
];
134 if (igLightId
== 0xFF)
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
++)
147 corner
.Lights
[lid
]= NULL
;
150 // BiLinear SunContribution.
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.
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
);
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
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
);