source: trunk/Packages/bgrabitmap/phongdraw.inc

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 8.3 KB
Line 
1{$ifdef PARAM_PHONGSSE}
2 {$asmmode intel}
3 //SSE rotate singles
4 const Shift231 = 1 + 8;
5 Shift312 = 2 + 16;
6{$endif}
7
8var
9 //Light source normal.
10 vL: TPoint3D_128; {xmm0}
11 //Light source position.
12 vLS: TPoint3D_128; {xmm1}
13 //Vector H is the unit normal to the hypothetical surface oriented
14 //halfway between the light direction vector (L) and the viewing vector (V).
15 vH: TPoint3D_128; {xmm2}
16
17 vN: TPoint3D_128; {xmm3} // surface normal
18 vP: TPoint3D_128; {xmm4} // position of lighted pixel
19 vV: TPoint3D_128; // viewer direction
20{$ifdef PARAM_PHONGSSE}
21 LightDestFactor4: TPoint3D_128; // for multiplication
22{$endif}
23
24 //Calculate LdotN and NnH
25 NH: Single;
26{$ifndef PARAM_PHONGSSE}
27 vD: TPoint3D_128;
28{$endif}
29
30 Iw, Ic: integer; // Iw: specular intensity, Ic: ambient+diffuse intensity
31 sIw: single; // floating point value for Iw
32
33 z, LdotN, NnH,
34 dist, distfactor, diffuseterm, specularterm: single;
35 eLight: TExpandedPixel;
36 mc,mcLeft,mcRight,mcTop,mcBottom: TBGRAPixel; ///map values
37
38{$ifdef PARAM_SIMPLECOLOR}
39 eColor: TExpandedPixel;
40{$else}
41 {$ifndef PARAM_SCANNER}
42 pcolormap: PBGRAPixel;
43 {$endif}
44{$endif}
45
46 {$hints off}
47 function ComputePixel(x,y: integer; DiffuseLight, SpecularLight: Word; Alpha: Byte): TBGRAPixel; inline;
48 var ec: TExpandedPixel;
49 {$ifndef PARAM_SIMPLECOLOR}
50 eColor: TExpandedPixel;
51 {$endif}
52 begin
53 {$ifndef PARAM_SIMPLECOLOR}
54 {$ifdef PARAM_SCANNER}
55 eColor := GammaExpansion(ColorScan.ScanNextPixel);
56 {$else}
57 eColor := GammaExpansion(pcolormap^);
58 {$endif}
59 {$endif}
60 Alpha := ApplyOpacity(Alpha, eColor.alpha shr 8);
61 ec.red := (eColor.Red*DiffuseLight+eLight.Red*SpecularLight+PhongLightPrecisionDiv2) shr PhongLightPrecisionSh;
62 ec.green := (eColor.Green*DiffuseLight+eLight.Green*SpecularLight+PhongLightPrecisionDiv2) shr PhongLightPrecisionSh;
63 ec.blue := (eColor.Blue*DiffuseLight+eLight.Blue*SpecularLight+PhongLightPrecisionDiv2) shr PhongLightPrecisionSh;
64 ec.alpha := Alpha shl 8+Alpha;
65 result := GammaCompression(ec);
66 end;
67 {$hints on}
68
69var
70 minx,miny,maxx,maxy: integer;
71 pmap: PBGRAPixel;
72 pdest: PBGRAPixel;
73 x,y : integer; // Coordinates of point in height map.
74 vS1,vS2: TPoint3D_128; // surface vectors (plane)
75 deltaDown: Int32or64;
76 IsLineUp,IsLineDown: boolean;
77
78begin
79 if map = nil then exit;
80 {$ifndef PARAM_SIMPLECOLOR}
81 {$ifndef PARAM_SCANNER}
82 if (colorMap.Width < map.width) or (colorMap.Height < map.height) then
83 raise Exception.Create('Dimension mismatch');
84 {$endif}
85 {$endif}
86
87 if (map.width = 0) or (map.Height = 0) then exit;
88 if ofsX >= dest.ClipRect.Right then exit;
89 if ofsY >= dest.ClipRect.Bottom then exit;
90 if ofsX <= dest.ClipRect.Left-map.Width then exit;
91 if ofsY <= dest.ClipRect.Top-map.Height then exit;
92
93 minx := 0;
94 miny := 0;
95 maxx := map.Width-1;
96 maxy := map.Height-1;
97 if ofsX < dest.clipRect.Left then minx := dest.clipRect.Left-ofsX;
98 if ofsY < dest.clipRect.Top then miny := dest.clipRect.Top-ofsY;
99 if OfsX+maxx > dest.ClipRect.Right-1 then maxx := dest.ClipRect.Right-1-ofsX;
100 if OfsY+maxy > dest.ClipRect.Bottom-1 then maxy := dest.ClipRect.Bottom-1-ofsY;
101
102 eLight := GammaExpansion(LightColor);
103 {$ifdef PARAM_SIMPLECOLOR}
104 eColor := GammaExpansion(color);
105 {$endif}
106
107 //light origin
108 vLS := Point3D_128(LightPosition.X-ofsX,
109 LightPosition.Y-ofsY,
110 LightPositionZ);
111
112 //surface vectors
113 vS1 := Point3D_128(1,0,0);
114 vS2 := Point3D_128(0,1,0);
115
116 vV := Point3D_128(0,0,1);
117
118 dist := 0;
119 LdotN := 0;
120 NnH := 0;
121
122 {$ifdef PARAM_PHONGSSE}
123 LightDestFactor4 := Point3D_128(LightDestFactor,LightDestFactor,LightDestFactor,LightDestFactor);
124 {$endif}
125
126 if map.LineOrder = riloTopToBottom then
127 deltaDown := map.Width*sizeof(TBGRAPixel)
128 else
129 deltaDown := -map.Width*sizeof(TBGRAPixel);
130 for y := miny to maxy do
131 begin
132 //read map values
133 pmap := map.ScanLine[y]+minx;
134 mc := BGRAPixelTransparent;
135 mcRight := pmap^;
136 pdest := dest.ScanLine[y+ofsY]+ofsX+minx;
137 {$ifndef PARAM_SIMPLECOLOR}
138 {$ifdef PARAM_SCANNER}
139 ColorScan.ScanMoveTo(OfsX+minx,OfsY+Y);
140 {$else}
141 pcolormap := ColorMap.ScanLine[y];
142 {$endif}
143 {$endif}
144 IsLineUp := y > 0;
145 IsLineDown := y < map.Height-1;
146 mcTop := BGRAPixelTransparent;
147 mcBottom := BGRAPixelTransparent;
148 for x := minx to maxx do
149 begin
150 mcLeft := mc;
151 mc := mcRight;
152 if x < map.width-1 then
153 mcRight := (pmap+1)^ else
154 mcRight := BGRAPixelTransparent;
155 if mc.alpha = 0 then
156 begin
157 {$ifndef PARAM_SIMPLECOLOR}
158 {$ifdef PARAM_SCANNER}
159 ColorScan.ScanNextPixel;
160 {$else}
161 inc(pcolormap);
162 {$endif}
163 {$endif}
164 inc(pdest);
165 inc(pmap);
166 continue;
167 end;
168
169 //compute surface vectors
170 if IsLineUp then mcTop := pbgrapixel(pbyte(pmap)-deltaDown)^;
171 if IsLineDown then mcBottom := pbgrapixel(pbyte(pmap)+deltaDown)^;
172 inc(pmap);
173
174 z := MapHeight(mc)*mapAltitude;
175 if mcLeft.alpha = 0 then
176 begin
177 if mcRight.alpha = 0 then
178 vS1.z := 0
179 else
180 vS1.z := (MapHeight(mcRight)-MapHeight(mc))*mapAltitude*2;
181 end else
182 begin
183 if mcRight.alpha = 0 then
184 vS1.z := (MapHeight(mc)-MapHeight(mcLeft))*mapAltitude*2
185 else
186 vS1.z := (MapHeight(mcRight)-MapHeight(mcLeft))*mapAltitude;
187 end;
188 if mcTop.alpha = 0 then
189 begin
190 if mcBottom.alpha = 0 then
191 vS2.z := 0
192 else
193 vS2.z := (MapHeight(mcBottom)-MapHeight(mc))*mapAltitude*2;
194 end else
195 begin
196 if mcBottom.alpha = 0 then
197 vS2.z := (MapHeight(mc)-MapHeight(mcTop))*mapAltitude*2
198 else
199 vS2.z := (MapHeight(mcBottom)-MapHeight(mcTop))*mapAltitude;
200 end;
201
202 //position vector
203 vP := Point3D_128(x, y, z);
204 {$ifdef PARAM_PHONGSSE}
205 if UseSSE3 then
206 begin
207 {$DEFINE PARAM_USESSE3}
208 asm
209 movups xmm1, vLS
210 end;
211 {$i phongdrawsse.inc}
212 {$UNDEF PARAM_USESSE3}
213 end else
214 begin
215 asm
216 movups xmm1, vLS
217 end;
218 {$i phongdrawsse.inc}
219 end;
220 {$else}
221 vP := Point3D_128(x, y, z);
222 vL := vLS- vP*LightDestFactor;
223 Normalize3D_128(vL);
224
225 //compute bisector of angle between light and observer
226 vH := vL + vV;
227 Normalize3D_128(vH);
228
229 // compute normal vector to the surface
230 VectProduct3D_128(vS1,vS2,vN);
231 Normalize3D_128(vN);
232
233 //Calculate LdotN and NnH
234 LdotN := DotProduct3D_128(vN,vL);
235 vD := vLS-vP;
236 dist := sqrt(DotProduct3D_128(vD,vD));
237
238 NH := DotProduct3D_128(vH,vN);
239 {$endif}
240
241 if NH <= 0 then
242 NnH := 0
243 else
244 NnH := exp(SpecularIndex*ln(NH)); //to be optimized
245
246 distfactor := LightSourceIntensity / (dist*LightSourceDistanceFactor + LightSourceDistanceTerm);
247
248 if (LdotN <= 0) then //Point is not illuminated by light source.
249 //Use negative diffuse for contrast
250 diffuseterm := distfactor * NegativeDiffusionFactor * LdotN
251 else
252 diffuseterm := distfactor * DiffusionFactor * LdotN;
253 Ic := round((AmbientFactor + diffuseterm)*PhongLightPrecision);
254
255 //specular (reflection)
256 specularterm := distfactor * SpecularFactor * NnH;
257 sIw := specularterm*PhongLightPrecision;
258 if sIw > PhongLightPrecision then Iw := PhongLightPrecision else
259 Iw := round(sIw);
260
261 //intensity bounds (0..PhongLightPrecision)
262 If Ic < 0 then Ic := 0;
263 If Ic > PhongLightPrecision then
264 begin
265 If DiffuseSaturation then
266 begin
267 Iw := Iw+(Ic-PhongLightPrecision);
268 if Iw > PhongLightPrecision then Iw := PhongLightPrecision;
269 end;
270 Ic := PhongLightPrecision;
271 end;
272 Ic := Ic*(PhongLightPrecision-Iw) shr PhongLightPrecisionSh;
273
274 DrawPixelInlineWithAlphaCheck(pdest, ComputePixel(x,y,Ic,Iw,mc.alpha));
275 {$ifndef PARAM_SIMPLECOLOR}
276 {$ifndef PARAM_SCANNER}
277 inc(pcolormap);
278 {$endif}
279 {$endif}
280 inc(pdest); //go to next pixel
281 end;
282 end;
283end;
284
285{$undef PARAM_PHONGSSE}
286{$undef PARAM_SIMPLECOLOR}
287{$undef PARAM_SCANNER}
288
Note: See TracBrowser for help on using the repository browser.