2 * Star field screensaver
4 * Copyright 2011 Carlo Bramini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #define WIN32_LEAN_AND_MEAN
36 #define FAR_PLANE -80.0f
37 #define NEAR_PLANE 3.0f
39 #define FIELD_WIDTH 50.f
40 #define FIELD_HEIGHT 45.f
41 #define FIELD_DEPTH (NEAR_PLANE - FAR_PLANE + GAP)
44 #define STAR_GREEN 0.f
45 #define STAR_BLUE 0.10f
46 #define STAR_TAIL 0.9f
56 static VERTEX Vertex
[MAX_STARS
];
57 static HGLRC hRC
; // Permanent Rendering Context
58 static HDC hDC
; // Private GDI Device Context
60 static GLuint glStarTex
;
63 static GLfloat g_light_position
[4] = {
64 0.0f
, 0.0f
, 3.0f
, 1.0f
67 static PIXELFORMATDESCRIPTOR pfd
= // Pixel Format Descriptor
69 sizeof(PIXELFORMATDESCRIPTOR
), // Size Of This Pixel Format Descriptor
70 1, // Version Number (?)
71 PFD_DRAW_TO_WINDOW
| // Format Must Support Window
72 PFD_SUPPORT_OPENGL
| // Format Must Support OpenGL
73 PFD_DOUBLEBUFFER
, // Must Support Double Buffering
74 PFD_TYPE_RGBA
, // Request An RGBA Format
75 16, // Select A 16Bit Color Depth
76 0, 0, 0, 0, 0, 0, // Color Bits Ignored (?)
78 0, // Shift Bit Ignored (?)
79 0, // No Accumulation Buffer
80 0, 0, 0, 0, // Accumulation Bits Ignored (?)
81 16, // 16Bit Z-Buffer (Depth Buffer)
82 0, // No Stencil Buffer
83 0, // No Auxiliary Buffer (?)
84 PFD_MAIN_PLANE
, // Main Drawing Layer
86 0, 0, 0 // Layer Masks Ignored (?)
89 static HBITMAP
CreateStarBitmap(HWND hWnd
, HDC hDC
)
94 HBITMAP hTextBmp
, hFileBmp
;
96 HGDIOBJ hOldText
, hOldFile
;
102 // Get instance for loading the texture
103 hInstance
= (HINSTANCE
)GetWindowLong(hWnd
, GWL_HINSTANCE
);
109 MAKEINTRESOURCE(IDB_STAR
),
112 LR_CREATEDIBSECTION
| LR_DEFAULTSIZE
116 GetObject(hFileBmp
, sizeof(BITMAP
), &bm
);
118 // Allocate new 32 bit texture
119 ZeroMemory(&bi
, sizeof(bi
));
121 bi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
122 bi
.bmiHeader
.biWidth
= bm
.bmWidth
;
123 bi
.bmiHeader
.biHeight
= -bm
.bmHeight
;
124 bi
.bmiHeader
.biPlanes
= 1;
125 bi
.bmiHeader
.biBitCount
= 32;
126 bi
.bmiHeader
.biCompression
= BI_RGB
;
128 // Makes GCC happy ;-|
131 hTextBmp
= CreateDIBSection(hDC
,
138 // Save new texture specs
139 // GetObject(hTextBmp, sizeof(BITMAP), &bmStarTex);
140 // bmStarTex.bmBits = lpBits;
142 // Copy 24 bit texture in 32 texture
143 hTextDC
= CreateCompatibleDC(hDC
);
144 hFileDC
= CreateCompatibleDC(hDC
);
146 hOldText
= SelectObject(hTextDC
, hTextBmp
);
147 hOldFile
= SelectObject(hFileDC
, hFileBmp
);
149 BitBlt(hTextDC
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, hFileDC
, 0, 0, SRCCOPY
);
151 SelectObject(hTextDC
, hOldText
);
152 SelectObject(hFileDC
, hOldFile
);
157 // Delete 24 bit texture
158 DeleteObject(hFileBmp
);
160 GetObject(hTextBmp
, sizeof(BITMAP
), &bm
);
162 // Apply ALPHA channel to new texture
163 for (Ptr32
=(DWORD
*)lpBits
, i
=0; i
< (UINT
)(bm
.bmWidth
* bm
.bmHeight
); i
++)
165 DWORD Color
= Ptr32
[i
] & 0x00FFFFFF;
166 DWORD Alpha
= Color
& 0xFF;
168 Color
|= Alpha
<< 24;
176 static void InitGL(HBITMAP hStarTex
)
182 // set the GL clear color - use when the color buffer is cleared
183 glClearColor(STAR_RED
, STAR_GREEN
, STAR_BLUE
, STAR_TAIL
);
185 if (Settings
.bSmoothShading
)
186 // set the shading model to 'smooth'
187 glShadeModel( GL_SMOOTH
);
189 // set the shading model to 'flat'
190 glShadeModel( GL_FLAT
);
192 // set GL to render front of polygons
193 glPolygonMode( GL_FRONT_AND_BACK
, GL_FILL
);
195 glDisable( GL_DEPTH_TEST
);
198 glEnable( GL_LIGHTING
);
199 // enable lighting for front
200 glLightModeli( GL_FRONT
, GL_TRUE
);
201 // material have diffuse and ambient lighting
202 glColorMaterial( GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
);
204 glEnable( GL_COLOR_MATERIAL
);
206 glEnable( GL_LIGHT0
);
208 // set light attenuation
209 glLightf( GL_LIGHT0
, GL_CONSTANT_ATTENUATION
, 0.01f
); //0.01f );
210 glLightf( GL_LIGHT0
, GL_LINEAR_ATTENUATION
, 0.01f
); //0.2f );
211 glLightf( GL_LIGHT0
, GL_QUADRATIC_ATTENUATION
, 0.005f
); //0.001f );
213 // clear the color buffer once
214 glClear( GL_COLOR_BUFFER_BIT
);
217 srand( time( NULL
) );
219 // Initialize *ALL* stars vertexes (not just programmed ones).
220 for (i
= 0; i
< MAX_STARS
; i
++)
222 xp
= ( (float) rand() / RAND_MAX
- .5f
) * FIELD_WIDTH
;
223 yp
= ( (float) rand() / RAND_MAX
- .5f
) * FIELD_HEIGHT
;
224 zp
= ( (float) rand() / RAND_MAX
) * FIELD_DEPTH
+ FAR_PLANE
;
226 Vertex
[i
].x1
= -1.f
+ xp
;
227 Vertex
[i
].y1
= -1.f
+ yp
;
228 Vertex
[i
].x2
= 1.f
+ xp
;
229 Vertex
[i
].y2
= 1.f
+ yp
;
233 glGenTextures(1, &glStarTex
); // Create One Texture
235 // Create Linear Filtered Texture
236 glBindTexture(GL_TEXTURE_2D
, glStarTex
);
238 if (Settings
.bEnableFiltering
)
240 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
241 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR
);
243 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_NEAREST
);
244 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_NEAREST
);
247 // Get Texture properties
248 GetObject(hStarTex
, sizeof(BITMAP
), &bm
);
250 // Create texture as a mipmap
252 glTexImage2D(GL_TEXTURE_2D
, 0, 4, bm
.bmWidth
, bm
.bmHeight
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, bm
.bmBits
);
254 gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, bm
.bmWidth
, bm
.bmHeight
, GL_RGBA
, GL_UNSIGNED_BYTE
, bm
.bmBits
);
257 // Disable Texture Mapping (background smoothing)
258 glDisable(GL_TEXTURE_2D
);
260 if (Settings
.bFinePerspective
)
261 // Really Fast Perspective Calculations
262 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_FASTEST
);
264 // Really Nice Perspective Calculations
265 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_NICEST
);
268 glEnable( GL_BLEND
);
279 // Initialize current speed
280 fSpeed
= (float)Settings
.uiSpeed
/ 100.f
;
282 glEnable(GL_TEXTURE_2D
); // Enable Texture Mapping
284 glBlendFunc(GL_SRC_ALPHA
,GL_ONE
); // Set The Blending Function For Translucency
286 switch (Settings
.uiRotation
) {
287 case ROTATION_LINEAR
:
289 glRotatef( fAngle
, 0.0f
, 0.0f
, 1.0f
);
292 case ROTATION_PERIODIC
:
293 fAngle
+= fSpeed
/ 75.f
;
294 fSpin
= (float)(50. * cos(fAngle
));
295 glRotatef( fSpin
, 0.0f
, 0.0f
, 1.0f
);
299 glColor3ub(255, 255, 255);
301 glBegin(GL_QUADS
); // Begin Drawing The Textured Quad
304 for (i
= 0; i
< Settings
.uiNumStars
; i
++)
306 glTexCoord2f(0.0f
, 0.0f
); glVertex3f(Vertex
[i
].x1
, Vertex
[i
].y1
, Vertex
[i
].z
);
307 glTexCoord2f(1.0f
, 0.0f
); glVertex3f(Vertex
[i
].x2
, Vertex
[i
].y1
, Vertex
[i
].z
);
308 glTexCoord2f(1.0f
, 1.0f
); glVertex3f(Vertex
[i
].x2
, Vertex
[i
].y2
, Vertex
[i
].z
);
309 glTexCoord2f(0.0f
, 1.0f
); glVertex3f(Vertex
[i
].x1
, Vertex
[i
].y2
, Vertex
[i
].z
);
312 Vertex
[i
].z
+= fSpeed
;
314 // check to see if passed view
315 if( Vertex
[i
].z
> NEAR_PLANE
+ GAP
||
316 Vertex
[i
].z
< FAR_PLANE
)
318 xp
= ( (float) rand() / RAND_MAX
- .5f
) * FIELD_WIDTH
;
319 yp
= ( (float) rand() / RAND_MAX
- .5f
) * FIELD_HEIGHT
;
321 Vertex
[i
].x1
= -1.f
+ xp
;
322 Vertex
[i
].y1
= -1.f
+ yp
;
323 Vertex
[i
].x2
= 1.f
+ xp
;
324 Vertex
[i
].y2
= 1.f
+ yp
;
325 Vertex
[i
].z
= FAR_PLANE
;
329 glEnd(); // Done Drawing The Textured Quad
331 glDisable(GL_TEXTURE_2D
); // Enable Texture Mapping
334 static LRESULT CALLBACK
335 OnCreate(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
342 // Gets A Device Context For The Window
345 // Finds The Closest Match To The Pixel Format We Set Above
346 PixelFormat
= ChoosePixelFormat(hDC
, &pfd
);
348 // No Matching Pixel Format?
351 MessageBox(0, _T("Can't Find A Suitable PixelFormat."), _T("Error"),MB_OK
| MB_ICONERROR
);
353 // This Sends A 'Message' Telling The Program To Quit
358 // Can We Set The Pixel Mode?
359 if (!SetPixelFormat(hDC
, PixelFormat
, &pfd
))
361 MessageBox(0, _TEXT("Can't Set The PixelFormat."), _T("Error"), MB_OK
| MB_ICONERROR
);
363 // This Sends A 'Message' Telling The Program To Quit
368 // Grab A Rendering Context
369 hRC
= wglCreateContext(hDC
);
374 MessageBox(0, _T("Can't Create A GL Rendering Context."), _T("Error"), MB_OK
| MB_ICONERROR
);
376 // This Sends A 'Message' Telling The Program To Quit
381 // Can We Make The RC Active?
382 if (!wglMakeCurrent(hDC
, hRC
))
384 MessageBox(0, _T("Can't Activate GLRC."), _TEXT("Error"), MB_OK
| MB_ICONERROR
);
386 // This Sends A 'Message' Telling The Program To Quit
392 hStarTex
= CreateStarBitmap(hWnd
, hDC
);
394 // Initialize The GL Screen Using Screen Info
397 // Delete GDI object for texture
398 DeleteObject(hStarTex
);
400 // Update screen every 10ms
401 SetTimer(hWnd
, 1, 10, NULL
);
403 // Initialize spinning angle
409 static LRESULT CALLBACK
410 OnDestroy(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
412 // Delete update timer
415 // Disable Fullscreen Mode
416 ChangeDisplaySettings(NULL
, 0);
418 // Make The DC Current
419 wglMakeCurrent(hDC
, NULL
);
422 wglDeleteContext(hRC
);
425 ReleaseDC(hWnd
, hDC
);
434 static LRESULT CALLBACK
435 OnPaint(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
437 if (Settings
.bDoBlending
)
439 glBlendFunc( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
442 glDisable( GL_LIGHTING
);
444 // blend in a polygon
445 glColor4f(STAR_RED
, STAR_GREEN
, STAR_BLUE
, STAR_TAIL
);
447 // Restore both model view and projection to identity
448 glMatrixMode(GL_MODELVIEW
);
452 glMatrixMode(GL_PROJECTION
);
456 // Blur the background
458 glVertex3f( -1.0f
, -1.0f
, -1.0f
);
459 glVertex3f( -1.0f
, 1.0f
, -1.0f
);
460 glVertex3f( 1.0f
, 1.0f
, -1.0f
);
461 glVertex3f( 1.0f
, -1.0f
, -1.0f
);
464 // Recover previous matrix
466 glMatrixMode(GL_MODELVIEW
);
470 glEnable( GL_LIGHTING
);
472 glClear(GL_COLOR_BUFFER_BIT
);
475 // save the current matrix state, so transformation will
476 // not persist across displayFunc calls, since we
477 // will do a glPopMatrix() at the end of this function
483 // restore the matrix state
489 // swap the double buffer
492 // Clear redraw event
493 ValidateRect(hWnd
, NULL
);
498 static LRESULT CALLBACK
499 OnSize(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
501 GLsizei w
= LOWORD(lParam
);
502 GLsizei h
= HIWORD(lParam
);
504 // map the view port to the entire client area
505 glViewport(0, 0, w
, h
);
507 // set the matrix mode to projection matrix
508 glMatrixMode(GL_PROJECTION
);
510 // load the identity matrix
513 // set the perspective matrix
514 gluPerspective( 64.0, (GLdouble
) w
/ (GLdouble
)h
, .1, 300.0 );
516 // set the matrix mode to the modelview matrix
517 glMatrixMode(GL_MODELVIEW
);
519 // load the identity matrix into the modelview matrix
523 gluLookAt( 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 2.0, 3.0 );
525 // set the position of the light
526 glLightfv( GL_LIGHT0
, GL_POSITION
, g_light_position
);
532 ScreenSaverProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
536 return OnCreate(hWnd
, wParam
, lParam
);
539 InvalidateRect(hWnd
, NULL
, FALSE
);
543 return OnDestroy(hWnd
, wParam
, lParam
);
546 return OnPaint(hWnd
, wParam
, lParam
);
548 case WM_SIZE
: // Resizing The Screen
549 return OnSize(hWnd
, wParam
, lParam
);
553 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
555 return DefScreenSaverProc(hWnd
, uMsg
, wParam
, lParam
);
561 ATOM
InitApp(HINSTANCE hInstance
, LPCTSTR szClassName
)
565 ZeroMemory(&wc
, sizeof(wc
));
567 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
568 wc
.lpfnWndProc
= ScreenSaverProc
;
571 wc
.hInstance
= hInstance
;
572 wc
.hIcon
= LoadIcon(NULL
, IDI_APPLICATION
);
573 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
574 wc
.hbrBackground
= (HBRUSH
)GetStockObject(WHITE_BRUSH
);
575 wc
.lpszMenuName
= NULL
;
576 wc
.lpszClassName
= szClassName
;
578 return RegisterClass(&wc
);
581 HWND
InitInstance(HINSTANCE hInstance
, int nCmdShow
)
584 TCHAR szClass
[] = _T("CLASS");
585 TCHAR szTitle
[] = _T("TITLE");
587 InitApp(hInstance
, szClass
);
595 192*3, //CW_USEDEFAULT,
596 108*3, //CW_USEDEFAULT,
604 ShowWindow(hWnd
, nCmdShow
);
611 int WINAPI
WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPSTR lpCmdLine
, int nShowCmd
)
617 RegisterDialogClasses(hInstance
);
619 hWnd
= InitInstance(hInstance
, nShowCmd
);
621 hDlg
= CreateDialog(hInstance
, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE
), NULL
, ScreenSaverConfigureDialog
);
622 ShowWindow(hDlg
, SW_SHOW
);
627 if (GetMessage(&msg
, NULL
, 0, 0) <= 0)
630 TranslateMessage(&msg
);
631 DispatchMessage(&msg
);