Quake II RTX doxygen  1.0 dev
sird.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "sw.h"
20 
21 /*
22 ** Start Added by Lewey
23 **
24 ** This is where the real SIRDS code is
25 */
26 
27 //width of the repeating pattern. Increasing this will
28 //increase the quality of the SIRD by giving it more
29 //height levels.
30 //
31 //Make sure: ((R_SIRDw % 3) == 0)
32 // && (((R_SIRDw / 3) % R_SIRDExponents) == 0)
33 #define R_SIRDw 144
34 
35 //height of the repeating pattern (not really important)
36 #define R_SIRDh 50
37 
38 //maximum offset. This is the max number of pixels
39 //an item can be moved due to it's height, this is
40 //is also obviously then the number of different
41 //height layers you can have. A large R_SIRDw will
42 //make it harder and harder to see the image, a larger
43 //ratio of R_SIRDw (i.e. less than 3) will eventually
44 //cause your eyes to be unable to see the pattern.
45 #define R_SIRDmaxDiff (R_SIRDw / 3)
46 
47 //the number of lower powers to ignore
48 #define R_SIRDIgnoreExponents 5
49 
50 //the number of exponents (after ignored ones) to have different
51 //height values (ones after it are rounded to the max difference)
52 #define R_SIRDExponents 6
53 
54 //the number of height levels each exponent is given
55 #define R_SIRDstepsPerExponent (R_SIRDmaxDiff / R_SIRDExponents)
56 
57 //this is the z value of the sky, which logically should be 0, but
58 //for implimentation reasons is made very high. Not my doing by the
59 //way. If you move to a different platform, you may need to change this
60 #define R_SIRD_ZofSky 0x8ccc
61 
62 //this is the number of random numbers
63 //defined in "rand1k.h"
64 #define R_SIRDnumRand 103
65 
66 //this hold the background pattern
68 
69 //these are the actual random numbers
70 static const byte r_SIRDrandValues[] = {
71 #include "rand1k.h"
72 };
73 
74 
75 //Only used if id386 is false, this acts as a
76 // reverse bit-scanner, and uses a sort of binary
77 // search to find the index of the highest set bit.
78 //You could also expand the loop 4 times to remove
79 // the 'while'
80 #if !id386 || !(defined _MSC_VER)
81 static int UShortLog(int val)
82 {
83  int mask = 0xff00;
84  int p = 0;
85  int b = 8;
86  while (b) {
87  if (val & mask) {
88  p += b;
89  b >>= 1;
90  mask &= (mask << b);
91  } else {
92  mask &= (mask << (b >> 1));
93  mask >>= b;
94  b >>= 1;
95  }
96  }
97  return p;
98 }
99 #endif
100 
101 static int R_SIRDZFunc(int sub)
102 {
103  int e;
104 
105  //special case the sky.
106  if (sub == R_SIRD_ZofSky)
107  return 0;
108 
109 #if id386 && (defined _MSC_VER)
110  e = sub;
111  //calculate the log (base 2) of the number. In other
112  //words the index of the highest set bit. bsr is undefined
113  //if it's input is 0, so special case that.
114  if (e != 0) {
115  __asm {
116  mov ebx, e
117  bsr eax, ebx
118  mov e, eax
119  }
120  }
121 #else
122  e = UShortLog(sub);
123 #endif
124 
125  //clip the exponent
126  if (e < R_SIRDIgnoreExponents)
127  return 0;
128 
129  // based on the power, shift the z so that
130  // it's as high as it can get while still staying
131  // under 0x100
132  if (e > 8) {
133  sub >>= (e - 8);
134  } else {
135  if (e < 8) {
136  sub <<= (8 - e);
137  }
138  }
139 
140  // Lower the power of the number, this helps scaling and removes
141  // small z values.
143 
144  // contruct the height value. The power is used as the primary calculator,
145  // and then the extra bits are used to offset. In this way you
146  // get more detail than just the log of the z value, and it works
147  // as a pretty good approximation of it.
149  e += ((sub * R_SIRDstepsPerExponent) >> 8);
150 
151  //make sure we stay under maximum height.
152  return ((e <= R_SIRDmaxDiff) ? e : R_SIRDmaxDiff);
153 }
154 
156 {
157  short* curz, *oldz;
158  short cz = 0, lastz = 0;
159  byte* curp;
160  byte* curbp, j = 0;
161  int x, y, i, zinc, k;
162  int mode = sw_drawsird->integer;
163 
164  //note of interest: I've made this static so that
165  //if you like you could make it not static and see
166  //what would happen if you didn't change the background
167  static int ji = 0;
168 
169  //create the background image to tile
170  //basically done by shifting the values around
171  //each time and xoring them with a randomly
172  //selected pixel
173  for (i = 0; i < R_SIRDw * R_SIRDh * VID_BYTES; i++) {
174  if ((i % R_SIRDnumRand) == 0) {
175  ji++;
176  ji %= R_SIRDnumRand;
178  }
180  }
181 
182  //if we are under water:
183  if ((r_dowarp) && (vid.width != WARP_WIDTH)) {
184  //the rendering is only in the top left
185  //WARP_WIDTH by WARP_HEIGHT area, so scale the z-values
186  //to span over the whole screen
187 
188 
189  //why are we going backwards? so that we don't write over the
190  //values before we read from them
191 
192  zinc = ((WARP_WIDTH * 0x10000) / vid.width);
193  for (y = vid.height - 1; y >= 0; y--) {
194  curz = (d_pzbuffer + (vid.width * y));
195  oldz = (d_pzbuffer + (vid.width * ((y * WARP_HEIGHT) / vid.height)));
196  k = (zinc * (vid.width - 1));
197 
198  for (x = vid.width - 1; x >= 0; x--) {
199  curz[x] = oldz[k >> 16];
200  k -= zinc;
201  }
202  }
203  }
204 
205 
206  //SIRDify each line
207  for (y = 0; y < vid.height; y++) {
208  curp = (vid.buffer + (vid.rowbytes * y));
209  curz = (d_pzbuffer + (vid.width * y));
210 
211  if (mode != 3) {
212  // draw the SIRD
213 
214  // copy the background into the left most column
215  curbp = &(r_SIRDBackground[ R_SIRDw * (y % R_SIRDh) ]);
216  for (x = 0; x < R_SIRDw; x++) {
217  curp[0] = curbp[0];
218  curp[1] = curbp[1];
219  curp[2] = curbp[2];
220 
221  curp += VID_BYTES;
222  curbp += VID_BYTES;
223  }
224 
225  lastz = 0;
226  cz = 0;
227  curz += R_SIRDw;
228  curbp = curp - R_SIRDw * VID_BYTES;
229 
230  // now calculate the SIRD
231  for (x = R_SIRDw; x < vid.width; x++) {
232  //only call the z-function with a new
233  //value, it is slow so this saves quite
234  //some time.
235  if (lastz != *curz) {
236  lastz = *curz;
237 
238  //convert from z to height offset
239  cz = (mode == 2) ? R_SIRDmaxDiff - R_SIRDZFunc(lastz) : R_SIRDZFunc(lastz);
240 
241  //the "height offset" used in making SIRDS
242  //can be considered an adjustment of the
243  //frequency of repetition in the pattern.
244  //so here we are copying from bp to p, and so
245  //it simply increases or decreases the distance
246  //between the two.
247  curbp = (curp - R_SIRDw * VID_BYTES + cz * VID_BYTES);
248  }
249 
250  curp[0] = curbp[0];
251  curp[1] = curbp[1];
252  curp[2] = curbp[2];
253 
254  curp += VID_BYTES;
255  curbp += VID_BYTES;
256  curz++;
257  }
258  } else {
259  //if we are just drawing the height map
260  //this lets you see which layers are used to
261  //create the SIRD
262  //
263  //NOTE: even though it may sort of look like
264  //a grey-scale height map, that is merely a
265  //coincidence because of how the colours are
266  //organized in the pallette.
267 
268  for (x = 0; x < vid.width; x++) {
269  if (lastz != *curz) {
270  lastz = *curz;
271  cz = R_SIRDZFunc(*curz);
272  }
273 
274  curp[0] = cz;
275  curp[1] = cz;
276  curp[2] = cz;
277 
278  curp += VID_BYTES;
279  curz++;
280  }
281  }
282  }
283 }
284 
285 /*
286 ** End Added by Lewey
287 */
viddef_t::buffer
pixel_t * buffer
Definition: sw.h:124
r_SIRDBackground
static byte r_SIRDBackground[R_SIRDw *R_SIRDh *VID_BYTES]
Definition: sird.c:67
viddef_t::width
int width
Definition: sw.h:127
viddef_t::height
int height
Definition: sw.h:128
UShortLog
static int UShortLog(int val)
Definition: sird.c:81
r_dowarp
qboolean r_dowarp
Definition: main.c:40
R_SIRDIgnoreExponents
#define R_SIRDIgnoreExponents
Definition: sird.c:48
r_SIRDrandValues
static const byte r_SIRDrandValues[]
Definition: sird.c:70
WARP_WIDTH
#define WARP_WIDTH
Definition: sw.h:64
viddef_t::rowbytes
int rowbytes
Definition: sw.h:125
sw.h
R_SIRDstepsPerExponent
#define R_SIRDstepsPerExponent
Definition: sird.c:55
R_ApplySIRDAlgorithum
void R_ApplySIRDAlgorithum(void)
Definition: sird.c:155
R_SIRD_ZofSky
#define R_SIRD_ZofSky
Definition: sird.c:60
R_SIRDh
#define R_SIRDh
Definition: sird.c:36
R_SIRDmaxDiff
#define R_SIRDmaxDiff
Definition: sird.c:45
VID_BYTES
#define VID_BYTES
Definition: sw.h:49
R_SIRDZFunc
static int R_SIRDZFunc(int sub)
Definition: sird.c:101
rand1k.h
R_SIRDw
#define R_SIRDw
Definition: sird.c:33
d_pzbuffer
short * d_pzbuffer
Definition: main.c:127
WARP_HEIGHT
#define WARP_HEIGHT
Definition: sw.h:65
R_SIRDnumRand
#define R_SIRDnumRand
Definition: sird.c:64
sw_drawsird
cvar_t * sw_drawsird
Definition: main.c:93
vid
viddef_t vid
Definition: main.c:22