📄 sphereworld32.c
字号:
// SphereWorld32.c
// OpenGL SuperBible
// Program by Richard S. Wright Jr.
// This program demonstrates a full featured robust Win32
// OpenGL framework
///////////////////////////////////////////////////////////////////////////////
// Include Files
#include <windows.h> // Win32 Framework (No MFC)
#include <gl\gl.h> // OpenGL
#include <gl\glu.h> // GLU Library
#include <stdio.h> // Standard IO (sprintf)
#include "..\..\common\wglext.h" // WGL Extension Header
#include "..\..\common\glext.h" // OpenGL Extension Header
#include "..\..\common\gltools.h" // GLTools library
#include "resource.h" // Dialog resources
// Initial rendering options specified by the user.
struct STARTUPOPTIONS {
DEVMODE devMode; // Display mode to use
int nPixelFormat; // Pixel format to use
int nPixelFormatMS; // Multisampled pixel format
BOOL bFullScreen; // Full screen?
BOOL bFSAA;
BOOL bVerticalSync;
};
///////////////////////////////////////////////////////////////////////////////
// Module globals
static HPALETTE hPalette = NULL; // Palette Handle
static HINSTANCE ghInstance = NULL; // Module Instance Handle
static LPCTSTR lpszAppName = "SphereWorld32"; // Name of App
static GLint nFontList; // Base display list for font
static struct STARTUPOPTIONS startupOptions; // Startup options info
static LARGE_INTEGER CounterFrequency;
static LARGE_INTEGER FPSCount;
static LARGE_INTEGER CameraTimer;
#define NUM_SPHERES 30 // Number of Spheres
GLTFrame spheres[NUM_SPHERES]; // Location of spheres
GLTFrame frameCamera; // Location and orientation of camera
// Light and material Data
GLfloat fLightPos[4] = { -100.0f, 100.0f, 50.0f, 1.0f }; // Point source
GLfloat fNoLight[] = { 0.0f, 0.0f, 0.0f, 0.0f };
GLfloat fLowLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
GLfloat fBrightLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
// Shadow matrix
GLTMatrix mShadowMatrix;
// Textures identifiers
#define GROUND_TEXTURE 0
#define TORUS_TEXTURE 1
#define SPHERE_TEXTURE 2
#define NUM_TEXTURES 3
GLuint textureObjects[NUM_TEXTURES];
const char *szTextureFiles[] = {"grass.tga", "wood.tga", "orb.tga"};
// Sphere and torus display lists
GLuint lTorusList, lSphereList;
///////////////////////////////////////////////////////////////////////////////
// Forward Declarations
// Declaration for Window procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
// Startup Dialog Procedure
BOOL APIENTRY StartupDlgProc (HWND hDlg, UINT message,
UINT wParam, LONG lParam);
// Find the best available pixelformat, including if Multisample is available
void FindBestPF(HDC hDC, int *nRegularFormat, int *nMSFormat);
BOOL ShowStartupOptions(void); // Initial startup dialog
void ChangeSize(GLsizei w, GLsizei h); // Change projection and viewport
void RenderScene(void); // Draw everything
void SetupRC(HDC hDC); // Set up the rendering context
void ShutdownRC(void); // Shutdown the rendering context
HPALETTE GetOpenGLPalette(HDC hDC); // Create a 3-3-2 palette
void DrawInhabitants(GLint nShadow); // Draw inhabitants of the world
void DrawGround(void); // Draw the ground
///////////////////////////////////////////////////////////////////////////////
// Extension function pointers
PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = NULL;
PFNGLWINDOWPOS2IPROC glWindowPos2i = NULL;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
//////////////////////////////////////////////////////////////
// Window has changed size. Reset to match window coordiantes
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat fAspect;
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
fAspect = (GLfloat)w / (GLfloat)h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the clipping volume
gluPerspective(35.0f, fAspect, 1.0f, 50.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
///////////////////////////////////////////////////////////
// Draw the ground as a series of triangle strips
void DrawGround(void)
{
GLfloat fExtent = 20.0f;
GLfloat fStep = 1.0f;
GLfloat y = -0.4f;
GLfloat iStrip, iRun;
GLfloat s = 0.0f;
GLfloat t = 0.0f;
GLfloat texStep = 1.0f / (fExtent * .075f);
// Ground is a tiling texture
glBindTexture(GL_TEXTURE_2D, textureObjects[GROUND_TEXTURE]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Lay out strips and repeat textures coordinates
for(iStrip = -fExtent; iStrip <= fExtent; iStrip += fStep)
{
t = 0.0f;
glBegin(GL_TRIANGLE_STRIP);
for(iRun = fExtent; iRun >= -fExtent; iRun -= fStep)
{
glTexCoord2f(s, t);
glNormal3f(0.0f, 1.0f, 0.0f); // All Point up
glVertex3f(iStrip, y, iRun);
glTexCoord2f(s + texStep, t);
glNormal3f(0.0f, 1.0f, 0.0f); // All Point up
glVertex3f(iStrip + fStep, y, iRun);
t += texStep;
}
glEnd();
s += texStep;
}
}
///////////////////////////////////////////////////////////////////////
// Draw random inhabitants and the rotating torus/sphere duo
void DrawInhabitants(GLint nShadow)
{
static GLfloat yRot = 0.0f; // Rotation angle for animation
GLint i;
if(nShadow == 0)
{
yRot += 0.5f;
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
else
glColor4f(0.0f, 0.0f, .0f, .75f); // Shadow color
// Draw the randomly located spheres
glBindTexture(GL_TEXTURE_2D, textureObjects[SPHERE_TEXTURE]);
for(i = 0; i < NUM_SPHERES; i++)
{
glPushMatrix();
gltApplyActorTransform(&spheres[i]);
glCallList(lSphereList);
glPopMatrix();
}
glPushMatrix();
glTranslatef(0.0f, 0.1f, -2.5f);
glPushMatrix();
glRotatef(-yRot * 2.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(1.0f, 0.0f, 0.0f);
glCallList(lSphereList);
glPopMatrix();
if(nShadow == 0)
{
// Torus alone will be specular
glMaterialfv(GL_FRONT, GL_SPECULAR, fBrightLight);
}
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, textureObjects[TORUS_TEXTURE]);
glCallList(lTorusList);
glMaterialfv(GL_FRONT, GL_SPECULAR, fNoLight);
glPopMatrix();
}
//////////////////////////////////////////////////
// Draw everything
void RenderScene(void)
{
static int iFrames = 0; // Count frames to calculate fps ever 100 frames
static float fps = 0.0f; // Calculated fps
// Clear the window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glPushMatrix();
gltApplyCameraTransform(&frameCamera); // Move camera/world
// Position light before any other transformations
glLightfv(GL_LIGHT0, GL_POSITION, fLightPos);
// Draw the ground
glColor3f(1.0f, 1.0f, 1.0f);
DrawGround();
// Draw shadows first
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_STENCIL_TEST);
glPushMatrix();
glMultMatrixf(mShadowMatrix);
DrawInhabitants(1);
glPopMatrix();
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
// Draw inhabitants normally
DrawInhabitants(0);
glPopMatrix();
// Calculate Frame Rate, once every 100 frames
iFrames++;
if(iFrames == 100)
{
float fTime;
// Get the current count
LARGE_INTEGER lCurrent;
QueryPerformanceCounter(&lCurrent);
fTime = (float)(lCurrent.QuadPart - FPSCount.QuadPart) /
(float)CounterFrequency.QuadPart;
fps = (float)iFrames / fTime;
// Reset frame count and timer
iFrames = 0;
QueryPerformanceCounter(&FPSCount);
}
// If we have the window position extension, display
// the frame rate, and tell if multisampling was enabled
// and if the VSync is turned on.
if(glWindowPos2i != NULL)
{
int iRow = 10;
char cBuffer[64];
// Turn off depth test, lighting, and texture mapping
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glColor3f(1.0f, 1.0f, 1.0f);
// Set position and display message
glWindowPos2i(0, iRow);
glListBase(nFontList);
glCallLists (13, GL_UNSIGNED_BYTE, "OpenGL Rocks!");
iRow+= 20;
// Display the frame rate
sprintf(cBuffer,"FPS: %.1f", fps);
glWindowPos2i(0, iRow);
glCallLists(strlen(cBuffer), GL_UNSIGNED_BYTE, cBuffer);
iRow += 20;
// MultiSampled?
if(startupOptions.bFSAA == TRUE && startupOptions.nPixelFormatMS != 0)
{
glWindowPos2i(0, iRow);
glCallLists(25 ,GL_UNSIGNED_BYTE,"Multisampled Frame Buffer");
iRow += 20;
}
// VSync?
if(wglSwapIntervalEXT != NULL && startupOptions.bVerticalSync == TRUE)
{
glWindowPos2i(0, iRow);
glCallLists(9 ,GL_UNSIGNED_BYTE, "VSync On");
iRow += 20;
}
// Put everything back
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
}
}
///////////////////////////////////////////////////////////////////////////////
// Setup. Create font/bitmaps, load textures, create display lists
void SetupRC(HDC hDC)
{
GLTVector3 vPoints[3] = {{ 0.0f, -0.4f, 0.0f },
{ 10.0f, -0.4f, 0.0f },
{ 5.0f, -0.4f, -5.0f }};
int iSphere;
int i;
// Setup the Font characteristics
HFONT hFont;
LOGFONT logfont;
logfont.lfHeight = -20;
logfont.lfWidth = 0;
logfont.lfEscapement = 0;
logfont.lfOrientation = 0;
logfont.lfWeight = FW_BOLD;
logfont.lfItalic = FALSE;
logfont.lfUnderline = FALSE;
logfont.lfStrikeOut = FALSE;
logfont.lfCharSet = ANSI_CHARSET;
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logfont.lfQuality = DEFAULT_QUALITY;
logfont.lfPitchAndFamily = DEFAULT_PITCH;
strcpy(logfont.lfFaceName,"Arial");
// Create the font and display list
hFont = CreateFontIndirect(&logfont);
SelectObject (hDC, hFont);
//Create display lists for glyphs 0 through 128
nFontList = glGenLists(128);
wglUseFontBitmaps(hDC, 0, 128, nFontList);
DeleteObject(hFont); // Don't need original font anymore
// Grayish background
glClearColor(fLowLight[0], fLowLight[1], fLowLight[2], fLowLight[3]);
// Clear stencil buffer with zero, increment by one whenever anybody
// draws into it. When stencil function is enabled, only write where
// stencil value is zero. This prevents the transparent shadow from drawing
// over itself
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -