📄 main.c
字号:
/* Copyright (C) Jason Shankel, 2001.
* All rights reserved worldwide.
*
* This software is provided "as is" without express or implied
* warranties. You may freely copy and compile this source into
* applications you distribute provided that the copyright text
* below is included in the resulting source code, for example:
* "Portions Copyright (C) Jason Shankel, 2001"
*/
/*
Game Gems II Skybox Demo
by
Jason Shankel
*/
#include <GL/glut.h>
#include <GL/glaux.h>
#include "GL/glext.h"
#include <stdio.h>
#include <stdlib.h>
/*
Camera controls
*/
static GLfloat cameraTheta=0,cameraPhi=0;
static GLint mouseX=0,mouseY=0,mouseDownX=0,mouseDownY=0;
/*
Skybox rendering mode
*/
#define kSkyboxMode2d 0
#define kSkyboxModeCubeEnvironment 1
static int skyboxMode = kSkyboxMode2d;
static int cubeMapAvailable = 0;
static int hudMode = 1;
/*
Texture objects
*/
static GLuint textureObjectCubeMap;
static GLuint textureObjects2d[6];
/*
Shiny object parameters
*/
static int rotateObject = 1;
static GLint objectAngle=0;
#define kTorus 0
#define kSphere 1
#define kTeapot 2
#define kCube 3
#define kNoObject 4
#define kObjectTypeCount 5
static int objectType = kTorus;
/*
Rendering functions
*/
static void drawSkybox2d(void);
static void drawSkyboxCubeEnvironment(void);
static void hudEnd(void);
static void hudBegin(void);
static void hudDisplayString(int x,int y,void *font,const char *str);
/*
Init/Shutdown
*/
static GLboolean initSkybox(void);
static void shutdownSkybox(void);
/*
Image loading
SWAP_BYTES is used to flip inverted *.bmp files
*/
GLboolean loadImage(GLenum target,const char *fileName);
#define SWAP_BYTES(b1,b2) (b1)=(b1)^(b2);(b2)=(b1)^(b2);(b1)=(b1)^(b2);
/*
GLUT callbacks
*/
static void onTimer(int value);
static void onDisplay(void);
static void onMouseMoveButtonDown(int x,int y);
static void onMouseDown(int b,int s,int x,int y);
static void onSpecialKey(int key,int x,int y);
static void onKey(unsigned char key,int x,int y);
/*
Draw skybox using cube environment mapping. The skybox cube is drawn as two triangle fans, centered around opposite corners of the cube
*/
void
drawSkyboxCubeEnvironment(void)
{
/*
Setup cube environment mapping
*/
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_CUBE_MAP_ARB);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB,textureObjectCubeMap);
/*
Disable the depth buffer when rendering the skybox
*/
glDisable(GL_DEPTH_TEST);
glDepthMask(0);
/*
Draw a fan around 10,10,10
*/
glBegin(GL_TRIANGLE_FAN);
glTexCoord3f(1,1,1);
glVertex3f(10,10,10);
glTexCoord3f(1,1,-1);
glVertex3f(10,10,-10);
glTexCoord3f(-1,1,-1);
glVertex3f(-10,10,-10);
glTexCoord3f(-1,1,1);
glVertex3f(-10,10,10);
glTexCoord3f(-1,-1,1);
glVertex3f(-10,-10,10);
glTexCoord3f(1,-1,1);
glVertex3f(10,-10,10);
glTexCoord3f(1,-1,-1);
glVertex3f(10,-10,-10);
glTexCoord3f(1,1,-1);
glVertex3f(10,10,-10);
glEnd();
/*
Draw a fan around -10,-10,-10
*/
glBegin(GL_TRIANGLE_FAN);
glTexCoord3f(-1,-1,-1);
glVertex3f(-10,-10,-10);
glTexCoord3f(-1,-1,1);
glVertex3f(-10,-10,10);
glTexCoord3f(1,-1,1);
glVertex3f(10,-10,10);
glTexCoord3f(1,-1,-1);
glVertex3f(10,-10,-10);
glTexCoord3f(1,1,-1);
glVertex3f(10,10,-10);
glTexCoord3f(-1,1,-1);
glVertex3f(-10,10,-10);
glTexCoord3f(-1,1,1);
glVertex3f(-10,10,10);
glTexCoord3f(-1,-1,1);
glVertex3f(-10,-10,10);
glEnd();
/*
Reactivate depth buffer
*/
glEnable(GL_DEPTH_TEST);
glDepthMask(1);
/*
Now draw shiny object
*/
/*
Set up reflection mapping coordinate generation
*/
glTexGenf(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP_ARB);
glTexGenf(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP_ARB);
glTexGenf(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP_ARB);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
/*
Set up object matrix
*/
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(0,0,-8);
glRotatef(cameraPhi,1,0,0);
glRotatef(cameraTheta,0,1,0);
/*
Rotating about two axes with different angles gives a nice tumbling effect
*/
glRotatef((GLfloat)objectAngle,1,0,0);
glRotatef((GLfloat)2*objectAngle,0,1,0);
/*
Rotate texture matrix to match camera matrix
*/
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glRotatef(-cameraTheta,0,1,0);
glRotatef(-cameraPhi,1,0,0);
/*
Some glut objects require matrix-mode to be set to GL_MODELVIEW
*/
glMatrixMode(GL_MODELVIEW);
/*
Draw Object
*/
if(objectType != kNoObject)
{
switch(objectType)
{
case kTorus:
glutSolidTorus(1,2,16,16);
break;
case kSphere:
glutSolidSphere(3,16,16);
break;
case kTeapot:
glutSolidTeapot(3);
break;
case kCube:
glutSolidCube(3);
break;
};
}
/*
Restore texture and modelview matrices
*/
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
/*
Disable reflection mapping
*/
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
}
/*
Draw skybox using six faces and six 2d textures
*/
void
drawSkybox2d(void)
{
/*
Enable 2d texture mapping
*/
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
glEnable(GL_TEXTURE_2D);
/*
Disable the depth buffer when rendering the skybox
*/
glDisable(GL_DEPTH_TEST);
glDepthMask(0);
/*
Rear Face
*/
glBindTexture(GL_TEXTURE_2D,textureObjects2d[0]);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(1,0);
glVertex3f(10,10,10);
glTexCoord2f(1,1);
glVertex3f(10,-10,10);
glTexCoord2f(0,1);
glVertex3f(-10,-10,10);
glTexCoord2f(0,0);
glVertex3f(-10,10,10);
glEnd();
/*
Front Face
*/
glBindTexture(GL_TEXTURE_2D,textureObjects2d[1]);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(1,0);
glVertex3f(-10,10,-10);
glTexCoord2f(1,1);
glVertex3f(-10,-10,-10);
glTexCoord2f(0,1);
glVertex3f(10,-10,-10);
glTexCoord2f(0,0);
glVertex3f(10,10,-10);
glEnd();
/*
Right Face
*/
glBindTexture(GL_TEXTURE_2D,textureObjects2d[2]);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(1,0);
glVertex3f(10,10,-10);
glTexCoord2f(1,1);
glVertex3f(10,-10,-10);
glTexCoord2f(0,1);
glVertex3f(10,-10,10);
glTexCoord2f(0,0);
glVertex3f(10,10,10);
glEnd();
/*
Left Face
*/
glBindTexture(GL_TEXTURE_2D,textureObjects2d[3]);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(1,0);
glVertex3f(-10,10,10);
glTexCoord2f(1,1);
glVertex3f(-10,-10,10);
glTexCoord2f(0,1);
glVertex3f(-10,-10,-10);
glTexCoord2f(0,0);
glVertex3f(-10,10,-10);
glEnd();
/*
Top Face
*/
glBindTexture(GL_TEXTURE_2D,textureObjects2d[4]);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0,1);
glVertex3f(-10,10,10);
glTexCoord2f(0,0);
glVertex3f(-10,10,-10);
glTexCoord2f(1,0);
glVertex3f(10,10,-10);
glTexCoord2f(1,1);
glVertex3f(10,10,10);
glEnd();
/*
Bottom Face
*/
glBindTexture(GL_TEXTURE_2D,textureObjects2d[5]);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0,1);
glVertex3f(-10,-10,-10);
glTexCoord2f(0,0);
glVertex3f(-10,-10,10);
glTexCoord2f(1,0);
glVertex3f(10,-10,10);
glTexCoord2f(1,1);
glVertex3f(10,-10,-10);
glEnd();
/*
Reactive depth buffer
*/
glEnable(GL_DEPTH_TEST);
glDepthMask(1);
}
/*
Main Display Function
*/
void
onDisplay(void)
{
int hudY;
/*
Set projection matrix for 100 degree FOV
*/
GLfloat w = (GLfloat)glutGet(GLUT_WINDOW_WIDTH),h = (GLfloat)glutGet(GLUT_WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(100.0,w/h,1,100);
/*
Set modelview matrix for camera
*/
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(cameraPhi,1,0,0);
glRotatef(cameraTheta,0,1,0);
/*
No need to clear the color buffer, the skybox fills the whole screen
Shiny objects in cube environment mode use depth buffer, so we do need to clear that one
*/
glClear(GL_DEPTH_BUFFER_BIT);
/*
Draw skybox
*/
if(skyboxMode == kSkyboxMode2d)
{
drawSkybox2d();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -