2 //**************************************************************************
6 //**************************************************************************
8 // HEADER FILES ------------------------------------------------------------
17 // MACROS ------------------------------------------------------------------
19 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
21 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
23 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
25 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
27 extern float texw, texh;
29 extern float vx, vy, vz;
31 extern byte topLineRGB[3];
34 // PUBLIC DATA DEFINITIONS -------------------------------------------------
37 fadeout_t fadeOut[2]; // For both skies.
39 // PRIVATE DATA DEFINITIONS ------------------------------------------------
41 // CODE --------------------------------------------------------------------
43 // The texture offset to be applied to the texture coordinates in SkyVertex().
44 static float maxSideAngle = (float) PI/3;
46 static int rows, columns;
47 static float scale = 32; // Fogging affects, thus close-by.
49 static fadeout_t *currentFO;
51 // Calculate the vertex and texture coordinates.
52 static void SkyVertex(int r, int c)
54 // The direction must be clockwise.
55 float topAngle = c/(float)columns * 2*PI;
56 float sideAngle = maxSideAngle * (rows-r)/(float)rows;
57 float height = sin(sideAngle);
58 float realRadius = scale*cos(sideAngle);
59 float x = vx + realRadius*cos(topAngle),
60 z = vz + realRadius*sin(topAngle),
61 y = vy + ((!yflip)? scale*height : -scale*height);
63 // And the texture coordinates.
64 if(!yflip) // Flipped Y is for the lower hemisphere.
65 glTexCoord2f(4*c/(float)columns + texoff/texw, r/(float)rows*200.0/256.0);
67 glTexCoord2f(4*c/(float)columns + texoff/texw, (rows-r)/(float)rows*200.0/256.0);
71 if(r==0) glColor4f(1,1,1,0); else glColor3f(1,1,1);
75 if(r==0) glColor3f(0,0,0); else glColor3f(1,1,1);
77 // And finally the vertex.
81 static void CapSideVertex(int r, int c)
83 // The direction must be clockwise.
84 float topAngle = c/(float)columns * 2*PI;
85 float sideAngle = maxSideAngle * (rows-r)/(float)rows;
86 float height = sin(sideAngle);
87 float realRadius = scale*cos(sideAngle);
89 glVertex3f(vx + realRadius*cos(topAngle),
90 vy + ((!yflip)? scale*height : -scale*height),
91 vz + realRadius*sin(topAngle));
94 // Hemi is Upper or Lower. Zero is not acceptable.
95 // The current texture is used. SKYHEMI_NO_TOPCAP can be used.
96 void OGL_RenderSkyHemisphere(int hemi)
100 if(hemi & SKYHEMI_LOWER) yflip = true; else yflip = false;
102 // The top row (row 0) is the one that's faded out.
103 // There must be at least 4 columns. The preferable number
104 // is 4n, where n is 1, 2, 3... There should be at least
105 // two rows because the first one is always faded.
107 columns = 4*skyDetail; // 4n
108 if(hemi & SKYHEMI_JUST_CAP)
110 //glBindTexture(GL_TEXTURE_2D, 0);
111 glDisable( GL_TEXTURE_2D );
113 // Use the appropriate color.
115 glColor3fv(currentFO->rgb);
118 glBegin(GL_TRIANGLE_FAN);
119 for(c=0; c<columns; c++) CapSideVertex(0, c);
122 // If we are doing a colored fadeout...
125 // We must fill the background for the top row since it'll
126 // be partially translucent.
127 glBegin(GL_TRIANGLE_STRIP);
129 for(c=0; c<columns; c++)
131 CapSideVertex(1, c); // One step down.
132 CapSideVertex(0, c+1); // And one step right.
138 glEnable( GL_TEXTURE_2D );
142 // The total number of triangles per hemisphere can be calculated
143 // as follows: rows * columns * 2 + 2 (for the top cap).
144 for(r=0; r<rows; r++)
146 glBegin(GL_TRIANGLE_STRIP);
147 // Add the start vertex.
149 for(c=0; c<columns; c++)
151 SkyVertex(r+1, c); // One step down.
152 SkyVertex(r, c+1); // And one step right.
154 // Add the end vertex for this row. This vertex is also
155 // the start vertex for the next row.
159 for(c=0; c<columns; c++)
170 void OGL_HandleColoredFadeOut(int skynum)
174 currentFO = fadeOut + skynum-1;
175 // We have to remember the top line average RGB.
178 currentFO->set = 1; // Now it is.
179 for(i=0; i<3; i++) currentFO->rgb[i] = topLineRGB[i]/255.0;
180 // Determine if it should be used.
181 for(currentFO->use=false, i=0; i<3; i++)
182 if(currentFO->rgb[i] > .3)
184 // Colored fadeout is needed.
185 currentFO->use = true;
191 static void OGL_DrawSkyhemi(int whichHemi)
195 skyname = OGL_PrepareSky(skytexture, false);
197 OGL_HandleColoredFadeOut(1);
199 // First the top cap.
200 OGL_RenderSkyHemisphere(whichHemi | SKYHEMI_JUST_CAP);
201 glBindTexture(GL_TEXTURE_2D, skyname);
203 // Render the front sky (sky1).
204 OGL_RenderSkyHemisphere(whichHemi);
207 void R_RenderSkyHemispheres(int hemis)
209 // IS there a sky to be rendered?
212 // We don't want anything written in the depth buffer, not yet.
213 glDepthMask(GL_FALSE);
214 glPushAttrib(GL_ENABLE_BIT);
215 // Disable culling, all triangles face the viewer.
216 glDisable(GL_CULL_FACE);
218 // Draw the possibly visible hemispheres.
219 if(hemis & SKYHEMI_UPPER) OGL_DrawSkyhemi(SKYHEMI_UPPER);
220 if(hemis & SKYHEMI_LOWER) OGL_DrawSkyhemi(SKYHEMI_LOWER);
221 // Enable the disabled things.
223 glDepthMask(GL_TRUE);