1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: d3d_poly.cpp 4349 2010-12-17 15:07:11Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include "d3d_local.h"
29 
30 // MACROS ------------------------------------------------------------------
31 
32 // TYPES -------------------------------------------------------------------
33 
34 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
35 
36 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
37 
38 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
39 
40 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
41 
42 // PUBLIC DATA DEFINITIONS -------------------------------------------------
43 
44 // PRIVATE DATA DEFINITIONS ------------------------------------------------
45 
46 static byte ptex[8][8] =
47 {
48 	{ 0, 0, 0, 0, 0, 0, 0, 0 },
49 	{ 0, 0, 0, 0, 0, 0, 0, 0 },
50 	{ 0, 0, 0, 1, 1, 0, 0, 0 },
51 	{ 0, 0, 1, 1, 1, 1, 0, 0 },
52 	{ 0, 0, 1, 1, 1, 1, 0, 0 },
53 	{ 0, 0, 0, 1, 1, 0, 0, 0 },
54 	{ 0, 0, 0, 0, 0, 0, 0, 0 },
55 	{ 0, 0, 0, 0, 0, 0, 0, 0 },
56 };
57 
58 // CODE --------------------------------------------------------------------
59 
60 //==========================================================================
61 //
62 //	MatrixMultiply
63 //
64 //==========================================================================
65 
MatrixMultiply(MyD3DMatrix & out,const MyD3DMatrix & a,const MyD3DMatrix & b)66 void MatrixMultiply(MyD3DMatrix &out, const MyD3DMatrix& a, const MyD3DMatrix& b)
67 {
68 	MyD3DMatrix ret;
69 	for (int i = 0; i < 4; i++)
70 	{
71 		for (int j = 0; j < 4; j++)
72 		{
73 			ret(i, j) = 0.0f;
74 			for (int k = 0; k < 4; k++)
75 			{
76 				ret(i, j) += a(i, k) * b(k, j);
77 			}
78 		}
79 	}
80 	out = ret;
81 }
82 
83 //==========================================================================
84 //
85 //	VDirect3DDrawer::WorldDrawing
86 //
87 //==========================================================================
88 
WorldDrawing()89 void VDirect3DDrawer::WorldDrawing()
90 {
91 	guard(VDirect3DDrawer::WorldDrawing);
92 	MyD3DVertex		out[256];
93 	int				lb, i;
94 	surfcache_t		*cache;
95 	float			s, t, lights, lightt;
96 	surface_t		*surf;
97 	texinfo_t		*tex;
98 	vuint32			light;
99 
100 	//	First draw horizons.
101 	if (RendLev->HorizonPortalsHead)
102 	{
103 		for (surf = RendLev->HorizonPortalsHead; surf; surf = surf->DrawNext)
104 		{
105 			DoHorizonPolygon(surf);
106 		}
107 	}
108 
109 	//	For sky areas we just write to the depth buffer to prevent drawing
110 	// polygons behind the sky.
111 	if (RendLev->SkyPortalsHead)
112 	{
113 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
114 		RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
115 		for (surf = RendLev->SkyPortalsHead; surf; surf = surf->DrawNext)
116 		{
117 			for (i = 0; i < surf->count; i++)
118 			{
119 				out[i] = MyD3DVertex(surf->verts[i], 0, 0, 0);
120 			}
121 			RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
122 		}
123         RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0f);
124 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
125 	}
126 
127 	//	Draw surfaces.
128 	if (RendLev->SimpleSurfsHead)
129 	{
130 		for (surf = RendLev->SimpleSurfsHead; surf; surf = surf->DrawNext)
131 		{
132 			texinfo_t *tex = surf->texinfo;
133 			SetTexture(tex->Tex, tex->ColourMap);
134 
135 			if (surf->lightmap != NULL ||
136 				surf->dlightframe == r_dlightframecount)
137 			{
138 				light = 0xffffffff;
139 			}
140 			else
141 			{
142 				int lev = surf->Light >> 24;
143 				int lR = ((surf->Light >> 16) & 255) * lev / 255;
144 				int lG = ((surf->Light >> 8) & 255) * lev / 255;
145 				int lB = (surf->Light & 255) * lev / 255;
146 				light = 0xff000000 | (lR << 16) | (lG << 8) | lB;
147 			}
148 			SetFade(surf->Fade);
149 
150 			for (i = 0; i < surf->count; i++)
151 			{
152 				out[i] = MyD3DVertex(surf->verts[i], light,
153 					(DotProduct(surf->verts[i], tex->saxis) + tex->soffs) * tex_iw,
154 					(DotProduct(surf->verts[i], tex->taxis) + tex->toffs) * tex_ih);
155 			}
156 
157 			RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
158 		}
159 	}
160 
161 	if (HaveMultiTexture)
162 	{
163 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
164 		RenderDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
165 		RenderDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
166 		RenderDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
167 		RenderDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
168 		RenderDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
169 		RenderDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
170 
171 		for (lb = 0; lb < NUM_BLOCK_SURFS; lb++)
172 		{
173 			if (!RendLev->light_chain[lb])
174 			{
175 				continue;
176 			}
177 
178 			if (!light_surf[lb])
179 			{
180 				light_surf[lb] = CreateSurface(BLOCK_WIDTH, BLOCK_HEIGHT, 16, false);
181 				RendLev->block_changed[lb] = true;
182 			}
183 			if (RendLev->block_changed[lb])
184 			{
185 				RendLev->block_changed[lb] = false;
186 				UploadTextureImage(light_surf[lb], 0, BLOCK_WIDTH, BLOCK_HEIGHT, RendLev->light_block[lb]);
187 			}
188 
189 			RenderDevice->SetTexture(1, light_surf[lb]);
190 
191 			for (cache = RendLev->light_chain[lb]; cache; cache = cache->chain)
192 			{
193 				surf = cache->surf;
194 				tex = surf->texinfo;
195 				SetTexture(tex->Tex, tex->ColourMap);
196 				SetFade(surf->Fade);
197 				for (i = 0; i < surf->count; i++)
198 				{
199 					s = DotProduct(surf->verts[i], tex->saxis) + tex->soffs;
200 					t = DotProduct(surf->verts[i], tex->taxis) + tex->toffs;
201 					lights = (s - surf->texturemins[0]) / 16 + cache->s + 0.5;
202 					lightt = (t - surf->texturemins[1]) / 16 + cache->t + 0.5;
203 					out[i] = MyD3DVertex(surf->verts[i], 0xffffffff,
204 						s * tex_iw, t * tex_ih,
205 						lights / BLOCK_WIDTH, lightt / BLOCK_HEIGHT);
206 				}
207 				RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
208 			}
209 		}
210 
211 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
212 		RenderDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
213 	}
214 	else
215 	{
216 		RenderDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
217 		RenderDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
218 		RenderDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
219 		RenderDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
220 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
221 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
222 		RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);	// don't bother writing Z
223 
224 		for (lb = 0; lb < NUM_BLOCK_SURFS; lb++)
225 		{
226 			if (!RendLev->light_chain[lb])
227 			{
228 				continue;
229 			}
230 
231 			if (!light_surf[lb])
232 			{
233 				light_surf[lb] = CreateSurface(BLOCK_WIDTH, BLOCK_HEIGHT, 16, false);
234 				RendLev->block_changed[lb] = true;
235 			}
236 			if (RendLev->block_changed[lb])
237 			{
238 				RendLev->block_changed[lb] = false;
239 				UploadTextureImage(light_surf[lb], 0, BLOCK_WIDTH, BLOCK_HEIGHT, RendLev->light_block[lb]);
240 			}
241 
242 			RenderDevice->SetTexture(0, light_surf[lb]);
243 
244 			for (cache = RendLev->light_chain[lb]; cache; cache = cache->chain)
245 			{
246 				surf = cache->surf;
247 				tex = surf->texinfo;
248 				SetFade(surf->Fade);
249 				for (i = 0; i < surf->count; i++)
250 				{
251 					s = DotProduct(surf->verts[i], tex->saxis) + tex->soffs;
252 					t = DotProduct(surf->verts[i], tex->taxis) + tex->toffs;
253 					lights = (s - surf->texturemins[0]) / 16 + cache->s + 0.5;
254 					lightt = (t - surf->texturemins[1]) / 16 + cache->t + 0.5;
255 					out[i] = MyD3DVertex(surf->verts[i], 0xffffffff,
256 						lights / BLOCK_WIDTH, lightt / BLOCK_HEIGHT);
257 				}
258 				RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
259 			}
260 		}
261 
262 		RenderDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, magfilter);
263 		RenderDevice->SetSamplerState(0, D3DSAMP_MINFILTER, minfilter);
264 		RenderDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, mipfilter);
265 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
266 		RenderDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
267 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
268 		RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);		// back to normal Z buffering
269 	}
270 
271 	//
272 	//  Add specular hightlights
273 	//
274 	if (specular_highlights)
275 	{
276 		RenderDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
277 		RenderDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
278 		RenderDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
279 		RenderDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
280 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
281 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
282 		RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);	// don't bother writing Z
283 		SetFade(0);
284 
285 		for (lb = 0; lb < NUM_BLOCK_SURFS; lb++)
286 		{
287 			if (!RendLev->add_chain[lb])
288 			{
289 				continue;
290 			}
291 
292 			if (!add_surf[lb])
293 			{
294 				add_surf[lb] = CreateSurface(BLOCK_WIDTH, BLOCK_HEIGHT, 16, false);
295 				RendLev->add_changed[lb] = true;
296 			}
297 			if (RendLev->add_changed[lb])
298 			{
299 				RendLev->add_changed[lb] = false;
300 				UploadTextureImage(add_surf[lb], 0, BLOCK_WIDTH, BLOCK_HEIGHT, RendLev->add_block[lb]);
301 			}
302 
303 			RenderDevice->SetTexture(0, add_surf[lb]);
304 
305 			for (cache = RendLev->add_chain[lb]; cache; cache = cache->addchain)
306 			{
307 				surf = cache->surf;
308 				tex = surf->texinfo;
309 				for (i = 0; i < surf->count; i++)
310 				{
311 					s = DotProduct(surf->verts[i], tex->saxis) + tex->soffs;
312 					t = DotProduct(surf->verts[i], tex->taxis) + tex->toffs;
313 					lights = (s - surf->texturemins[0]) / 16 + cache->s + 0.5;
314 					lightt = (t - surf->texturemins[1]) / 16 + cache->t + 0.5;
315 					out[i] = MyD3DVertex(surf->verts[i], 0xffffffff,
316 						lights / BLOCK_WIDTH, lightt / BLOCK_HEIGHT);
317 				}
318 				RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
319 			}
320 		}
321 
322 		RenderDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, magfilter);
323 		RenderDevice->SetSamplerState(0, D3DSAMP_MINFILTER, minfilter);
324 		RenderDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, mipfilter);
325 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
326 		RenderDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
327 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
328 		RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);		// back to normal Z buffering
329 	}
330 	unguard;
331 }
332 
333 //==========================================================================
334 //
335 //	VDirect3DDrawer::DoHorizonPolygon
336 //
337 //==========================================================================
338 
DoHorizonPolygon(surface_t * Surf)339 void VDirect3DDrawer::DoHorizonPolygon(surface_t* Surf)
340 {
341 	guard(VDirect3DDrawer::DoHorizonPolygon);
342 	float Dist = 4096.0;
343 	TVec v[4];
344 	if (Surf->HorizonPlane->normal.z > 0.0)
345 	{
346 		v[0] = Surf->verts[0];
347 		v[3] = Surf->verts[3];
348 		TVec HDir = -Surf->plane->normal;
349 
350 		TVec Dir1 = Normalise(vieworg - Surf->verts[1]);
351 		TVec Dir2 = Normalise(vieworg - Surf->verts[2]);
352 		float Mul1 = 1.0 / DotProduct(HDir, Dir1);
353 		v[1] = Surf->verts[1] + Dir1 * Mul1 * Dist;
354 		float Mul2 = 1.0 / DotProduct(HDir, Dir2);
355 		v[2] = Surf->verts[2] + Dir2 * Mul2 * Dist;
356 		if (v[1].z < v[0].z)
357 		{
358 			v[1] = Surf->verts[1] + Dir1 * Mul1 * Dist * (Surf->verts[1].z -
359 				Surf->verts[0].z) / (Surf->verts[1].z - v[1].z);
360 			v[2] = Surf->verts[2] + Dir2 * Mul2 * Dist * (Surf->verts[2].z -
361 				Surf->verts[3].z) / (Surf->verts[2].z - v[2].z);
362 		}
363 	}
364 	else
365 	{
366 		v[1] = Surf->verts[1];
367 		v[2] = Surf->verts[2];
368 		TVec HDir = -Surf->plane->normal;
369 
370 		TVec Dir1 = Normalise(vieworg - Surf->verts[0]);
371 		TVec Dir2 = Normalise(vieworg - Surf->verts[3]);
372 		float Mul1 = 1.0 / DotProduct(HDir, Dir1);
373 		v[0] = Surf->verts[0] + Dir1 * Mul1 * Dist;
374 		float Mul2 = 1.0 / DotProduct(HDir, Dir2);
375 		v[3] = Surf->verts[3] + Dir2 * Mul2 * Dist;
376 		if (v[1].z < v[0].z)
377 		{
378 			v[0] = Surf->verts[0] + Dir1 * Mul1 * Dist * (Surf->verts[1].z -
379 				Surf->verts[0].z) / (v[0].z - Surf->verts[0].z);
380 			v[3] = Surf->verts[3] + Dir2 * Mul2 * Dist * (Surf->verts[2].z -
381 				Surf->verts[3].z) / (v[3].z - Surf->verts[3].z);
382 		}
383 	}
384 
385 	texinfo_t* Tex = Surf->texinfo;
386 	SetTexture(Tex->Tex, Tex->ColourMap);
387 
388 	int lev = Surf->Light >> 24;
389 	int lR = ((Surf->Light >> 16) & 255) * lev / 255;
390 	int lG = ((Surf->Light >> 8) & 255) * lev / 255;
391 	int lB = (Surf->Light & 255) * lev / 255;
392 	vuint32 light = 0xff000000 | (lR << 16) | (lG << 8) | lB;
393 	SetFade(Surf->Fade);
394 
395 	//	Draw it
396 	MyD3DVertex	out[4];
397 	RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
398 	for (int i = 0; i < 4; i++)
399 	{
400 		out[i] = MyD3DVertex(v[i], light,
401 			(DotProduct(v[i], Tex->saxis) + Tex->soffs) * tex_iw,
402 			(DotProduct(v[i], Tex->taxis) + Tex->toffs) * tex_ih);
403 	}
404 	RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, out, sizeof(MyD3DVertex));
405 	RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
406 
407 	//	Write to the depth buffer.
408 	RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
409 	RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
410 	for (int i = 0; i < Surf->count; i++)
411 	{
412 		out[i] = MyD3DVertex(Surf->verts[i], 0, 0, 0);
413 	}
414 	RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, out, sizeof(MyD3DVertex));
415 	RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0f);
416 	RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
417 	unguard;
418 }
419 
420 //==========================================================================
421 //
422 //	VDirect3DDrawer::DrawSkyPolygon
423 //
424 //==========================================================================
425 
DrawSkyPolygon(surface_t * surf,bool bIsSkyBox,VTexture * Texture1,float offs1,VTexture * Texture2,float offs2,int CMap)426 void VDirect3DDrawer::DrawSkyPolygon(surface_t* surf, bool bIsSkyBox,
427 	VTexture* Texture1, float offs1, VTexture* Texture2, float offs2,
428 	int CMap)
429 {
430 	guard(VDirect3DDrawer::DrawSkyPolygon);
431 	MyD3DVertex		out[256];
432 	int				i;
433 	int				sidx[4];
434 
435 	SetFade(surf->Fade);
436 	sidx[0] = 0;
437 	sidx[1] = 1;
438 	sidx[2] = 2;
439 	sidx[3] = 3;
440 	if (!bIsSkyBox)
441 	{
442 		if (surf->verts[1].z > 0)
443 		{
444 			sidx[1] = 0;
445 			sidx[2] = 3;
446 		}
447 		else
448 		{
449 			sidx[0] = 1;
450 			sidx[3] = 2;
451 		}
452 	}
453 	texinfo_t *tex = surf->texinfo;
454 	if (HaveMultiTexture && Texture2->Type != TEXTYPE_Null)
455 	{
456 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
457 		RenderDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
458 		RenderDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
459 		RenderDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
460 		RenderDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
461 
462 		SetTexture(Texture1, CMap);
463 		TexStage = 1;
464 		SetTexture(Texture2, CMap);
465 		TexStage = 0;
466 		for (i = 0; i < surf->count; i++)
467 		{
468 			out[i] = MyD3DVertex(surf->verts[i] + vieworg, 0xff000000 | (int(r_sky_bright_factor * 255) << 16) & 0x00ff0000 |
469 					(int(r_sky_bright_factor * 255) << 8) & 0x0000ff00 | int(r_sky_bright_factor * 255) & 0x000000ff,
470 				(DotProduct(surf->verts[sidx[i]], tex->saxis) + tex->soffs - offs1) * tex_iw,
471 				(DotProduct(surf->verts[i], tex->taxis) + tex->toffs) * tex_ih,
472 				(DotProduct(surf->verts[sidx[i]], tex->saxis) + tex->soffs - offs2) * tex_iw,
473 				(DotProduct(surf->verts[i], tex->taxis) + tex->toffs) * tex_ih);
474 		}
475 		RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
476 
477 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
478 		RenderDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
479 	}
480 	else
481 	{
482 		SetTexture(Texture1, CMap);
483 		for (i = 0; i < surf->count; i++)
484 		{
485 			out[i] = MyD3DVertex(surf->verts[i] + vieworg, 0xff000000 | (int(r_sky_bright_factor * 255) << 16) & 0x00ff0000 |
486 					(int(r_sky_bright_factor * 255) << 8) & 0x0000ff00 | int(r_sky_bright_factor * 255) & 0x000000ff,
487 				(DotProduct(surf->verts[sidx[i]], tex->saxis) + tex->soffs - offs1) * tex_iw,
488 				(DotProduct(surf->verts[i], tex->taxis) + tex->toffs) * tex_ih);
489 		}
490 		RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
491 
492 		if (Texture2->Type != TEXTYPE_Null)
493 		{
494 			SetTexture(Texture2, CMap);
495 			for (i = 0; i < surf->count; i++)
496 			{
497 				out[i] = MyD3DVertex(surf->verts[i] + vieworg, 0xff000000 | (int(r_sky_bright_factor * 255) << 16) & 0x00ff0000 |
498 					(int(r_sky_bright_factor * 255) << 8) & 0x0000ff00 | int(r_sky_bright_factor * 255) & 0x000000ff,
499 					(DotProduct(surf->verts[sidx[i]], tex->saxis) + tex->soffs - offs2) * tex_iw,
500 					(DotProduct(surf->verts[i], tex->taxis) + tex->toffs) * tex_ih);
501 			}
502 			RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
503 			RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
504 			RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
505 		}
506 	}
507 	unguard;
508 }
509 
510 //==========================================================================
511 //
512 //	VDirect3DDrawer::DrawMaskedPolygon
513 //
514 //==========================================================================
515 
DrawMaskedPolygon(surface_t * surf,float Alpha,bool Additive)516 void VDirect3DDrawer::DrawMaskedPolygon(surface_t* surf, float Alpha,
517 	bool Additive)
518 {
519 	guard(VDirect3DDrawer::DrawMaskedPolygon);
520 	MyD3DVertex	out[256];
521 	int			l;
522 
523 	texinfo_t* tex = surf->texinfo;
524 	SetTexture(tex->Tex, tex->ColourMap);
525 
526 	if (surf->lightmap != NULL ||
527 		surf->dlightframe == r_dlightframecount)
528 	{
529 		RendLev->BuildLightMap(surf, 0);
530 		int w = (surf->extents[0] >> 4) + 1;
531 		int h = (surf->extents[1] >> 4) + 1;
532 		int size = w * h;
533 		int r = 0;
534 		int g = 0;
535 		int b = 0;
536 		for (int i = 0; i < size; i++)
537 		{
538 			r += 255 * 256 - blocklightsr[i];
539 			g += 255 * 256 - blocklightsg[i];
540 			b += 255 * 256 - blocklightsb[i];
541 		}
542 		r = r / (size * 256);
543 		g = g / (size * 256);
544 		b = b / (size * 256);
545 		int alpha = (int)(Alpha * 255);
546 		l = (alpha << 24) | (r << 16) | (g << 8) | b;
547 	}
548 	else
549 	{
550 		int lev = surf->Light >> 24;
551 		int lR = ((surf->Light >> 16) & 255) * lev / 255;
552 		int lG = ((surf->Light >> 8) & 255) * lev / 255;
553 		int lB = (surf->Light & 255) * lev / 255;
554 		int alpha = (int)(Alpha * 255);
555 		l = (alpha << 24) | (lR << 16) | (lG << 8) | lB;
556 	}
557 	SetFade(surf->Fade);
558 
559 	for (int i = 0; i < surf->count; i++)
560 	{
561 		out[i] = MyD3DVertex(surf->verts[i], l,
562 			(DotProduct(surf->verts[i], tex->saxis) + tex->soffs) * tex_iw,
563 			(DotProduct(surf->verts[i], tex->taxis) + tex->toffs) * tex_ih);
564 	}
565 
566 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
567 	if (blend_sprites || Additive || Alpha < 1.0)
568 	{
569 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
570 		RenderDevice->SetRenderState(D3DRS_ALPHAREF, 0);
571 	}
572 	if (Additive)
573 	{
574 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
575 	}
576 
577 	RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, surf->count - 2, out, sizeof(MyD3DVertex));
578 
579 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
580 	if (blend_sprites || Additive || Alpha < 1.0)
581 	{
582 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
583 		RenderDevice->SetRenderState(D3DRS_ALPHAREF, 170);
584 	}
585 	if (Additive)
586 	{
587 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
588 	}
589 	unguard;
590 }
591 
592 //==========================================================================
593 //
594 //	VDirect3DDrawer::DrawSpritePolygon
595 //
596 //==========================================================================
597 
DrawSpritePolygon(TVec * cv,VTexture * Tex,float Alpha,bool Additive,VTextureTranslation * Translation,int CMap,vuint32 light,vuint32 Fade,const TVec &,float,const TVec & saxis,const TVec & taxis,const TVec & texorg)598 void VDirect3DDrawer::DrawSpritePolygon(TVec *cv, VTexture* Tex, float Alpha,
599 	bool Additive, VTextureTranslation* Translation, int CMap, vuint32 light,
600 	vuint32 Fade, const TVec&, float, const TVec& saxis, const TVec& taxis,
601 	const TVec& texorg)
602 {
603 	guard(VDirect3DDrawer::DrawSpritePolygon);
604 	MyD3DVertex		out[4];
605 
606 	SetSpriteLump(Tex, Translation, CMap);
607 
608 	int l = ((int)(Alpha * 255) << 24) | (light & 0x00ffffff);
609 	for (int i = 0; i < 4; i++)
610 	{
611 		TVec texpt = cv[i] - texorg;
612 		out[i] = MyD3DVertex(cv[i], l,
613 			DotProduct(texpt, saxis) * tex_iw,
614 			DotProduct(texpt, taxis) * tex_ih);
615 	}
616 	SetFade(Fade);
617 
618 	if (blend_sprites || Additive || Alpha < 1.0)
619 	{
620 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
621 		RenderDevice->SetRenderState(D3DRS_ALPHAREF, 0);
622 	}
623 	if (Additive)
624 	{
625 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
626 	}
627 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
628 
629 	RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, out, sizeof(MyD3DVertex));
630 
631 	if (blend_sprites || Additive || Alpha < 1.0)
632 	{
633 		RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
634 		RenderDevice->SetRenderState(D3DRS_ALPHAREF, 170);
635 	}
636 	if (Additive)
637 	{
638 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
639 	}
640 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
641 	unguard;
642 }
643 
644 //==========================================================================
645 //
646 //	VDirect3DDrawer::DrawAliasModel
647 //
648 //==========================================================================
649 
DrawAliasModel(const TVec & origin,const TAVec & angles,const TVec & Offset,const TVec & Scale,VMeshModel * Mdl,int frame,int nextframe,VTexture * Skin,VTextureTranslation * Trans,int CMap,vuint32 light,vuint32 Fade,float Alpha,bool Additive,bool is_view_model,float Inter,bool Interpolate)650 void VDirect3DDrawer::DrawAliasModel(const TVec &origin, const TAVec &angles,
651 	const TVec& Offset, const TVec& Scale, VMeshModel* Mdl, int frame,
652 	int nextframe, VTexture* Skin, VTextureTranslation* Trans, int CMap,
653 	vuint32 light, vuint32 Fade, float Alpha, bool Additive,
654 	bool is_view_model, float Inter, bool Interpolate)
655 {
656 	guard(VDirect3DDrawer::DrawAliasModel);
657 	mframe_t			*pframedesc;
658 	mframe_t			*pnextframedesc;
659 	float 				l;
660 	int					index;
661 	trivertx_t			*verts;
662 	trivertx_t			*verts2;
663 	int					*order;
664 	int					count;
665 	float				shadelightr;
666 	float				shadelightg;
667 	float				shadelightb;
668 	float				*shadedots;
669 	MyD3DVertex			out[256];//FIXME
670 	D3DPRIMITIVETYPE	primtype;
671 	int					i;
672 	MyD3DMatrix			matWorld;
673 	MyD3DMatrix			matTmp;
674 	TVec				alias_forward;
675 	TVec				alias_right;
676 	TVec				alias_up;
677 	vuint32				alpha;
678 
679 	if (is_view_model)
680 	{
681 		// hack the depth range to prevent view model from poking into walls
682 		viewData.MaxZ = 0.3;
683 		RenderDevice->SetViewport(&viewData);
684 	}
685 
686 	//
687 	// get lighting information
688 	//
689 	shadelightr = ((light >> 16) & 0xff) / 512.0;
690 	shadelightg = ((light >> 8) & 0xff) / 512.0;
691 	shadelightb = (light & 0xff) / 512.0;
692 	shadedots = r_avertexnormal_dots[((int)(angles.yaw * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
693 	light &= 0x00ffffff;
694 	alpha = int(Alpha * 255) << 24;
695 
696 	//
697 	// draw all the triangles
698 	//
699 	mmdl_t* pmdl = Mdl->Data;
700 	pframedesc = (mframe_t*)((byte *)pmdl + pmdl->ofsframes + frame * pmdl->framesize);
701 	pnextframedesc = (mframe_t*)((byte *)pmdl + pmdl->ofsframes + nextframe * pmdl->framesize);
702 
703 	AngleVectors(angles, alias_forward, alias_right, alias_up);
704 
705 	matWorld = IdentityMatrix;
706 	for (i = 0; i < 3; i++)
707 	{
708 		matWorld(0, i) = alias_forward[i];
709 		matWorld(1, i) = -alias_right[i];
710 		matWorld(2, i) = alias_up[i];
711 	}
712 	matWorld(3, 0) = origin.x;
713 	matWorld(3, 1) = origin.y;
714 	matWorld(3, 2) = origin.z;
715 
716 	matTmp = IdentityMatrix;
717 	matTmp(0, 0) = Scale.x;
718 	matTmp(1, 1) = Scale.y;
719 	matTmp(2, 2) = Scale.z;
720 	matTmp(3, 0) = Offset.x * Scale.x;
721 	matTmp(3, 1) = Offset.y * Scale.y;
722 	matTmp(3, 2) = Offset.z * Scale.z;
723 	matWorld = matTmp * matWorld;
724 
725 	TVec scale;
726 	TVec scale_origin;
727 	if (Interpolate)
728 	{
729 		scale[0] = pframedesc->scale[0] + Inter * (pnextframedesc->scale[0] - pframedesc->scale[0]);
730 		scale[1] = pframedesc->scale[1] + Inter * (pnextframedesc->scale[1] - pframedesc->scale[1]);
731 		scale[2] = pframedesc->scale[2] + Inter * (pnextframedesc->scale[2] - pframedesc->scale[2]);
732 		scale_origin[0] = ((1 - Inter) * pframedesc->scale_origin[0] + Inter * pnextframedesc->scale_origin[0]);
733 		scale_origin[1] = ((1 - Inter) * pframedesc->scale_origin[1] + Inter * pnextframedesc->scale_origin[1]);
734 		scale_origin[2] = ((1 - Inter) * pframedesc->scale_origin[2] + Inter * pnextframedesc->scale_origin[2]);
735 	}
736 	else
737 	{
738 		scale[0] = pframedesc->scale[0];
739 		scale[1] = pframedesc->scale[1];
740 		scale[2] = pframedesc->scale[2];
741 		scale_origin[0] = pframedesc->scale_origin[0];
742 		scale_origin[1] = pframedesc->scale_origin[1];
743 		scale_origin[2] = pframedesc->scale_origin[2];
744 	}
745 
746 	matTmp = IdentityMatrix;
747 	matTmp(0, 0) = scale[0];
748 	matTmp(1, 1) = scale[1];
749 	matTmp(2, 2) = scale[2];
750 	matTmp(3, 0) = scale_origin[0];
751 	matTmp(3, 1) = scale_origin[1];
752 	matTmp(3, 2) = scale_origin[2];
753 	matWorld = matTmp * matWorld;
754 
755 	RenderDevice->SetTransform(D3DTS_WORLD, &matWorld);
756 
757 	SetPic(Skin, Trans, CMap);
758 
759 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
760 	RenderDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
761 	RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
762 	if (Additive)
763 	{
764 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
765 	}
766 	RenderDevice->SetRenderState(D3DRS_ALPHAREF, 0);
767 
768 	SetFade(Fade);
769 
770 	verts = (trivertx_t *)(pframedesc + 1);
771 	order = (int *)((byte *)pmdl + pmdl->ofscmds);
772 	if (Interpolate)
773 	{
774 		verts2 = (trivertx_t *)(pnextframedesc + 1);
775 	}
776 
777 	while (*order)
778 	{
779 		// get the vertex count and primitive type
780 		count = *order++;
781 		if (count < 0)
782 		{
783 			count = -count;
784 			primtype = D3DPT_TRIANGLEFAN;
785 		}
786 		else
787 		{
788 			primtype = D3DPT_TRIANGLESTRIP;
789 		}
790 
791 		if (count > 256)
792 		{
793 			Sys_Error("Too many command verts");
794 		}
795 
796 		for (i = 0; i < count; i++)
797 		{
798 			// texture coordinates come from the draw list
799 			out[i].texs = ((float *)order)[0];
800 			out[i].text = ((float *)order)[1];
801 			order += 2;
802 
803 			// normals and vertexes come from the frame list
804 			index = *order++;
805 			if (model_lighting)
806 			{
807 				l = shadedots[verts[index].lightnormalindex];
808 				out[i].colour = alpha |
809 					(((int)(l * shadelightr * 0xff) << 16) & 0x00ff0000) |
810 					(((int)(l * shadelightg * 0xff) <<  8) & 0x0000ff00) |
811 					(((int)(l * shadelightb * 0xff)      ) & 0x000000ff);
812 			}
813 			else
814 			{
815 				out[i].colour = alpha | light;
816 			}
817 			if (Interpolate)
818 			{
819 				out[i].x = ((1 - Inter) * verts[index].v[0] + (Inter) * verts2[index].v[0]);
820 				out[i].y = ((1 - Inter) * verts[index].v[1] + (Inter) * verts2[index].v[1]);
821 				out[i].z = ((1 - Inter) * verts[index].v[2] + (Inter) * verts2[index].v[2]);
822 			}
823 			else
824 			{
825 				out[i].x = verts[index].v[0];
826 				out[i].y = verts[index].v[1];
827 				out[i].z = verts[index].v[2];
828 			}
829 		}
830 
831 		RenderDevice->DrawPrimitiveUP(primtype, count - 2, out, sizeof(MyD3DVertex));
832 	}
833 
834 	RenderDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
835 	RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
836 	if (Additive)
837 	{
838 		RenderDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
839 	}
840 	RenderDevice->SetRenderState(D3DRS_ALPHAREF, 170);
841 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
842 
843 	RenderDevice->SetTransform(D3DTS_WORLD, &IdentityMatrix);
844 	if (is_view_model)
845 	{
846 		viewData.MaxZ = 1.0;
847 		RenderDevice->SetViewport(&viewData);
848 	}
849 	unguard;
850 }
851 
852 //==========================================================================
853 //
854 //	VDirect3DDrawer::StartParticles
855 //
856 //==========================================================================
857 
StartParticles()858 void VDirect3DDrawer::StartParticles()
859 {
860 	guard(VDirect3DDrawer::StartParticles);
861 	if (!particle_texture)
862 	{
863 		rgba_t		pbuf[8][8];
864 
865 		for (int j = 0; j < 8; j++)
866 		{
867 			for (int i = 0; i < 8; i++)
868 			{
869 				pbuf[j][i].r = 255;
870 				pbuf[j][i].g = 255;
871 				pbuf[j][i].b = 255;
872 				pbuf[j][i].a = byte(ptex[j][i] * 255);
873 			}
874 		}
875 		particle_texture = CreateSurface(8, 8, 16, false);
876 		UploadTextureImage(particle_texture, 0, 8, 8, &pbuf[0][0]);
877 	}
878 	RenderDevice->SetTexture(0, particle_texture);
879 	RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
880 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
881 	RenderDevice->SetRenderState(D3DRS_ALPHAREF, 0);
882 	unguard;
883 }
884 
885 //==========================================================================
886 //
887 //	VDirect3DDrawer::DrawParticle
888 //
889 //==========================================================================
890 
DrawParticle(particle_t * p)891 void VDirect3DDrawer::DrawParticle(particle_t *p)
892 {
893 	guard(VDirect3DDrawer::DrawParticle);
894 	MyD3DVertex out[4];
895 	out[0] = MyD3DVertex(p->org - viewright * p->Size + viewup * p->Size, p->colour, 0, 0);
896 	out[1] = MyD3DVertex(p->org + viewright * p->Size + viewup * p->Size, p->colour, 1, 0);
897 	out[2] = MyD3DVertex(p->org + viewright * p->Size - viewup * p->Size, p->colour, 1, 1);
898 	out[3] = MyD3DVertex(p->org - viewright * p->Size - viewup * p->Size, p->colour, 0, 1);
899 	RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, out, sizeof(MyD3DVertex));
900 	unguard;
901 }
902 
903 //==========================================================================
904 //
905 //	VDirect3DDrawer::EndParticles
906 //
907 //==========================================================================
908 
EndParticles()909 void VDirect3DDrawer::EndParticles()
910 {
911 	guard(VDirect3DDrawer::EndParticles);
912 	RenderDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
913 	RenderDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
914 	RenderDevice->SetRenderState(D3DRS_ALPHAREF, 170);
915 	unguard;
916 }
917 
918 //==========================================================================
919 //
920 //	VDirect3DDrawer::StartPortal
921 //
922 //==========================================================================
923 
StartPortal(VPortal * Portal,bool UseStencil)924 bool VDirect3DDrawer::StartPortal(VPortal* Portal, bool UseStencil)
925 {
926 	guard(VDirect3DDrawer::StartPortal);
927 	if (UseStencil)
928 	{
929 		//	Disable drawing
930 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
931 		RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
932 		RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
933 
934 		//	Set up stencil test.
935 		if (!RendLev->PortalDepth)
936 		{
937 			RenderDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
938 		}
939 		RenderDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
940 		RenderDevice->SetRenderState(D3DRS_STENCILREF, RendLev->PortalDepth);
941 		RenderDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR);
942 
943 		//	Mark the portal area.
944 		DrawPortalArea(Portal);
945 
946 		//	Set up stencil test for portal
947 		RenderDevice->SetRenderState(D3DRS_STENCILREF, RendLev->PortalDepth + 1);
948 		RenderDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
949 
950 		if (Portal->NeedsDepthBuffer())
951 		{
952 			RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
953 			//	Clear depth buffer
954 			viewData.MinZ = 1.0;
955 			RenderDevice->SetViewport(&viewData);
956 			RenderDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
957 			DrawPortalArea(Portal);
958 			RenderDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
959 			viewData.MinZ = 0.0;
960 			RenderDevice->SetViewport(&viewData);
961 		}
962 		else
963 		{
964 			RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
965 			RenderDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
966 		}
967 
968 		//	Enable drawing.
969 		RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0f);
970 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
971 
972 		RendLev->PortalDepth++;
973 	}
974 	else
975 	{
976 		if (!Portal->NeedsDepthBuffer())
977 		{
978 			RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
979 			RenderDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
980 		}
981 	}
982 	return true;
983 	unguard;
984 }
985 
986 //==========================================================================
987 //
988 //	VDirect3DDrawer::DrawPortalArea
989 //
990 //==========================================================================
991 
DrawPortalArea(VPortal * Portal)992 void VDirect3DDrawer::DrawPortalArea(VPortal* Portal)
993 {
994 	guard(VDirect3DDrawer::DrawPortalArea);
995 	MyD3DVertex	out[256];
996 	for (int i = 0; i < Portal->Surfs.Num(); i++)
997 	{
998 		const surface_t* Surf = Portal->Surfs[i];
999 		for (int i = 0; i < Surf->count; i++)
1000 		{
1001 			out[i] = MyD3DVertex(Surf->verts[i], 0, 0, 0);
1002 		}
1003 	    RenderDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, Surf->count - 2,
1004             out, sizeof(MyD3DVertex));
1005 	}
1006 	unguard;
1007 }
1008 
1009 //==========================================================================
1010 //
1011 //	VDirect3DDrawer::EndPortal
1012 //
1013 //==========================================================================
1014 
EndPortal(VPortal * Portal,bool UseStencil)1015 void VDirect3DDrawer::EndPortal(VPortal* Portal, bool UseStencil)
1016 {
1017 	guard(VDirect3DDrawer::EndPortal);
1018 	if (UseStencil)
1019 	{
1020 		if (Portal->NeedsDepthBuffer())
1021 		{
1022 			//	Clear depth buffer
1023 			viewData.MinZ = 1.0;
1024 			RenderDevice->SetViewport(&viewData);
1025 			RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
1026 			RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1027 			RenderDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1028 			DrawPortalArea(Portal);
1029 			RenderDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1030 			RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0f);
1031 			RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
1032 			viewData.MinZ = 0.0;
1033 			RenderDevice->SetViewport(&viewData);
1034 		}
1035 		else
1036 		{
1037 			RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1038 			RenderDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1039 		}
1040 
1041 	    RenderDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR);
1042 
1043 		//	Draw proper z-buffer for the portal area.
1044 		RenderDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
1045 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
1046 		RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1047 		DrawPortalArea(Portal);
1048 		RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0f);
1049 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
1050 		RenderDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1051 
1052 		RenderDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
1053 
1054 		RendLev->PortalDepth--;
1055 		RenderDevice->SetRenderState(D3DRS_STENCILREF, RendLev->PortalDepth);
1056 		if (!RendLev->PortalDepth)
1057 		{
1058 			RenderDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1059 		}
1060 	}
1061 	else
1062 	{
1063 		if (Portal->NeedsDepthBuffer())
1064 		{
1065 			//	Clear depth buffer
1066 			RenderDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, 0);
1067 		}
1068 		else
1069 		{
1070 			RenderDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
1071 			RenderDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1072 		}
1073 
1074 		//	Draw proper z-buffer for the portal area.
1075 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
1076 		RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
1077 		DrawPortalArea(Portal);
1078 		RenderDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0f);
1079 		RenderDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
1080 	}
1081 	unguard;
1082 }
1083