@@ -56,8 +56,8 @@ fixed_t skyheight;
56
56
fixed_t skyiscale;
57
57
58
58
int sky1shift, sky2shift;
59
- fixed_t sky1pos= 0 , sky1speed= 0 ;
60
- fixed_t sky2pos= 0 , sky2speed= 0 ;
59
+ fixed_t sky1scrolldelta, sky2scrolldelta ;
60
+ fixed_t sky1columnoffset, sky2columnoffset ;
61
61
62
62
// The xtoviewangleangle[] table maps a screen pixel
63
63
// to the lowest viewangle that maps back to x ranges
@@ -73,6 +73,7 @@ char SKYFLATNAME[8] = "F_SKY1";
73
73
74
74
75
75
static tallpost_t * skyposts[MAXWIDTH];
76
+ static byte compositeskybuffer[MAXWIDTH][512 ]; // holds doublesky composite sky to blit to the screen
76
77
77
78
78
79
//
@@ -198,33 +199,58 @@ inline void SkyColumnBlaster()
198
199
R_BlastSkyColumn (colfunc);
199
200
}
200
201
202
+ inline bool R_PostDataIsTransparent (byte* data)
203
+ {
204
+ if (*data == ' \0 ' )
205
+ {
206
+ return true ;
207
+ }
208
+ return false ;
209
+ }
210
+
211
+
212
+
201
213
//
202
214
// R_RenderSkyRange
203
215
//
204
216
// [RH] Can handle parallax skies. Note that the front sky is *not* masked in
205
217
// in the normal convention for patches, but uses color 0 as a transparent
206
218
// color.
207
219
// [ML] 5/11/06 - Removed sky2
220
+ // [BC] 7/5/24 - Brought back for real this time
208
221
//
209
222
void R_RenderSkyRange (visplane_t * pl)
210
223
{
211
224
if (pl->minx > pl->maxx )
212
225
return ;
213
226
214
227
int columnmethod = 2 ;
215
- int skytex ;
228
+ int frontskytex, backskytex ;
216
229
fixed_t front_offset = 0 ;
230
+ fixed_t back_offset = 0 ;
217
231
angle_t skyflip = 0 ;
218
232
219
- if (pl->picnum == skyflatnum)
233
+ if (pl->picnum == skyflatnum )
220
234
{
221
235
// use sky1
222
- skytex = sky1texture;
236
+ frontskytex = texturetranslation[sky1texture];
237
+ if (level.flags & LEVEL_DOUBLESKY)
238
+ {
239
+ backskytex = texturetranslation[sky2texture];
240
+ }
241
+ else
242
+ {
243
+ backskytex = -1 ;
244
+ }
245
+ front_offset = sky1columnoffset;
246
+ back_offset = sky2columnoffset;
223
247
}
224
248
else if (pl->picnum == int (PL_SKYFLAT))
225
249
{
226
250
// use sky2
227
- skytex = sky2texture;
251
+ frontskytex = texturetranslation[sky2texture];
252
+ backskytex = -1 ;
253
+ front_offset = sky2columnoffset;
228
254
}
229
255
else
230
256
{
@@ -236,7 +262,8 @@ void R_RenderSkyRange(visplane_t* pl)
236
262
const side_t * side = *line->sidenum + sides;
237
263
238
264
// Texture comes from upper texture of reference sidedef
239
- skytex = texturetranslation[side->toptexture ];
265
+ frontskytex = texturetranslation[side->toptexture ];
266
+ backskytex = -1 ;
240
267
241
268
// Horizontal offset is turned into an angle offset,
242
269
// to allow sky rotation as well as careful positioning.
@@ -261,7 +288,8 @@ void R_RenderSkyRange(visplane_t* pl)
261
288
262
289
dcol.iscale = skyiscale >> skystretch;
263
290
dcol.texturemid = skytexturemid;
264
- dcol.textureheight = textureheight[skytex];
291
+ dcol.textureheight = textureheight[frontskytex]; // both skies are forced to be the same height anyway
292
+ dcol.texturefrac = dcol.texturemid + (dcol.yl - centery) * dcol.iscale ;
265
293
skyplane = pl;
266
294
267
295
// set up the appropriate colormap for the sky
@@ -284,13 +312,97 @@ void R_RenderSkyRange(visplane_t* pl)
284
312
// column in this range.
285
313
for (int x = pl->minx ; x <= pl->maxx ; x++)
286
314
{
287
- int colnum = ((((viewangle + xtoviewangle[x]) ^ skyflip) >> sky1shift) + front_offset) >> FRACBITS;
288
- skyposts[x] = R_GetTextureColumn (skytex, colnum);
315
+ int sky1colnum = ((((viewangle + xtoviewangle[x]) ^ skyflip) >> sky1shift) + front_offset) >> FRACBITS;
316
+ tallpost_t * skypost = R_GetTextureColumn (frontskytex, sky1colnum);
317
+ if (backskytex == -1 )
318
+ {
319
+ skyposts[x] = skypost;
320
+ }
321
+ else
322
+ {
323
+ // create composite of both skies
324
+ int sky2colnum = ((((viewangle + xtoviewangle[x]) ^ skyflip) >> sky2shift) + back_offset) >> FRACBITS;
325
+ tallpost_t * skypost2 = R_GetTextureColumn (backskytex, sky2colnum);
326
+
327
+ int count = MIN<int > (512 , MIN (textureheight[backskytex], textureheight[frontskytex]) >> FRACBITS);
328
+ int destpostlen = 0 ;
329
+
330
+ BYTE* composite = compositeskybuffer[x];
331
+ tallpost_t * destpost = (tallpost_t *)composite;
332
+
333
+ tallpost_t * orig = destpost; // need a pointer to the og element to return!
334
+
335
+ // here's the skinny...
336
+
337
+ // we need to grab sky1 as long as it has a valid topdelta and length
338
+ // in a lot of cases there's gaps in length and topdelta because of transparency
339
+ // its up to us to find these gaps and put in sky2 when needed
340
+
341
+ // but when we grab from sky1, we ALSO have to check every byte if it's index 0.
342
+ // if it is, we need to grab the same byte from sky2 instead.
343
+ // this allows non-converted sky patches, like those in hexen.wad or tlsxctf1.wad
344
+ // to work
345
+
346
+ // the finished tallpost should be the same length as count, and 0 topdelta, with a endpost after.
347
+
348
+ destpost->topdelta = 0 ;
349
+
350
+ while (destpostlen < count)
351
+ {
352
+ int remaining = count - destpostlen; // pixels remaining to be replenished
353
+
354
+ if (skypost->topdelta == destpostlen)
355
+ {
356
+ // valid first sky, grab its data and advance the pixel
357
+ memcpy (destpost->data () + destpostlen, skypost->data (), skypost->length );
358
+ // before advancing, check the data we just inserted, and input sky2 if its index 0
359
+ for (int i = 0 ; i < skypost->length ; i++)
360
+ {
361
+ if (R_PostDataIsTransparent (destpost->data () + destpostlen + i))
362
+ {
363
+ // use sky2 for this pixel
364
+
365
+ memcpy (destpost->data () + destpostlen + i,
366
+ skypost2->data () + destpostlen + i, 1 );
367
+ }
368
+ }
369
+ destpostlen += skypost->length ;
370
+ }
371
+ else
372
+ {
373
+ // sky1 top delta is less than current pixel, lets get sky2 up to the pixel
374
+ int cursky1delta = abs ((skypost->end () ? remaining : skypost->topdelta ) - destpostlen);
375
+ int sky2len = cursky1delta > remaining ? remaining : cursky1delta;
376
+ memcpy (destpost->data () + destpostlen, skypost2->data () + destpostlen,
377
+ sky2len);
378
+ destpostlen += sky2len;
379
+ }
380
+
381
+ if (!skypost->next ()->end () && destpostlen >= skypost->topdelta + skypost->length )
382
+ {
383
+ skypost = skypost->next ();
384
+ }
385
+
386
+ if (!skypost2->next ()->end () && destpostlen >= skypost2->topdelta + skypost2->length )
387
+ {
388
+ skypost2 = skypost2->next ();
389
+ }
390
+
391
+ destpost->length = destpostlen;
392
+ }
393
+
394
+ // finish the post up.
395
+ destpost = destpost->next ();
396
+ destpost->length = 0 ;
397
+ destpost->writeend ();
398
+
399
+ skyposts[x] = orig;
400
+ }
289
401
}
290
402
291
403
R_RenderColumnRange (pl->minx , pl->maxx , (int *)pl->top , (int *)pl->bottom ,
292
404
skyposts, SkyColumnBlaster, false , columnmethod);
293
-
405
+
294
406
R_ResetDrawFuncs ();
295
407
}
296
408
0 commit comments