OpenGL 回顾——简化版的窗体(包含鼠标控制,普通键位控制,以及镜面反射)

// OpenGLBook.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

//变量声明
static GLfloat spin =0.0;
GLfloat zoom=-10.0f;
GLfloat angel=20.0f;
BOOL    light;                                    // 光源的开/关
BOOL    lp;                                    // L键按下了么?
BOOL    fp;                                    // F键按下了么?
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess[] = {50.0};
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
//函数声明
void init(void);
void display(void);
void spinDisplay(void);
void reshape(int w,int h);
void mouse(int button,int state,int x,int y);
void processNormalKeys(unsigned char key,int x,int y);
void processKeyUpDowm(int key,int x,int y);

/************************************************************************/
/*         函数实现                                                     */
/************************************************************************/

//初始化
void init(void){
    glClearColor(0.0f,0.0f,0.0f,0.0f);
     glShadeModel(GL_SMOOTH);
 

    glShadeModel(GL_SMOOTH);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
    glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

    //glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);    
    ///////////////////////
    glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
    glClearColor(0.1f,0.1f, 0.1f, 0.9f);                // Black Background
    glClearDepth(1.0f);                                    // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                                // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    // Really Nice Perspective Calculations
}

//图形绘画
void display(void){
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 清除屏幕及深度缓存
     // 重置模型观察矩阵
 
     glPushMatrix();
     //glLoadIdentity(); //等同于glPushMatrix();和glPopMatrix();配对重绘
     glTranslatef(0.0f,0.0f,zoom);
    glRotatef(spin,0.0f,1.0f,0.0f);
    glutSolidSphere(1.0, 20, 16);
    glPopMatrix();
    glutSwapBuffers(); //交换屏幕缓冲区与后台缓冲区
        angel+=5.0f;
    glutPostRedisplay(); //重绘
//     glPushMatrix();
}

void reshape(int w,int h){
    if (h==0)                                        // Prevent A Divide By Zero By
    {
        h=1;                                        // Making Height Equal One
    }

    glViewport(0,0,(GLsizei)w,(GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f);//透视

    //glOrtho(-50.0,50.0,-50.0,50.0,-1.0,100.0); //平行修剪空间(离观察者远时,不会缩小)
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

//鼠标响应
void mouse(int button,int state,int x,int y)
{

    switch(state){
    case GLUT_DOWN:
        if (button==GLUT_LEFT_BUTTON)  //左键
        {
            
            break;
        }
        if (button==GLUT_RIGHT_BUTTON) //右键
        {
            
            break;
        }
    case GLUT_UP:
        if (button==GLUT_WHEEL_UP)
        {
            zoom-=1.0f;
            glutPostRedisplay();
            break;
        }
        else if (button==GLUT_WHEEL_DOWN)
        {
            zoom+=1.0f;
            glutPostRedisplay();
            break;
        }
    default:
        break;
    }
    
}
//按键响应
void processNormalKeys(unsigned char key,int x,int y)
{
    switch(key){
    case 27:
        exit(0);
        break;
    case 'l':
        if (!lp)
        {
            lp=TRUE;                // lp 设为 TRUE
            light=!light;                // 切换光源的 TRUE/FALSE
        }
        else{
            lp=FALSE;
            light=!light;    
        }
        if (!light)                // 如果没有光源
        {
            glDisable(GL_LIGHTING);        // 禁用光源
        }
        else                    // 否则
        {
            glEnable(GL_LIGHTING);        // 启用光源
        }
        break;
    case 'r':
        spin+=2.0f;
        if (spin>360.0f)
        {
            spin-=360.0f;
        }
        glutPostRedisplay();
        break;
    }
    
}

void processKeyUpDowm(int key,int x,int y){
    switch(key){
    case GLUT_KEY_UP:
            lp=TRUE;        
            break;
    case GLUT_KEY_DOWN:
        lp=false;
        break;
    default:
        break;
    }
}
//主函数
int _tmain(int argc, char**argv)
{
    glutInit(&argc,argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); 
    glutInitWindowSize(640,480);
    glutInitWindowPosition(350,150);
    glutCreateWindow("this is my window");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutKeyboardFunc(processNormalKeys);
    glutMainLoop();
    return 0;
}

ps:

  镜面反射步骤:光源要设置镜面反射的属性、之后相应的物体要设置镜面反射的材质。还有自发光的属性emission,看起来就行物体在自己发光一样。

  尽量用glPushMatrix()和  glPopMatrix()进行绘图,而glLoadIdentity()在初始化和重绘的时候用。

  暂时还没发现回调函数中有捕获普通按键按下的函数,不过影响不是很大。长按相当于连续按多次。

原文地址:https://www.cnblogs.com/ForRickHuan/p/5716363.html