OpenGl-實驗-設計程式實現點光源的移動觀察效果

唐傘皮發表於2020-12-23

程式碼比較亂,還請見諒,如果有幫助到您,請給俺點個贊(畢竟花了好久除錯出來的,滿眼都是淚)

一:實現效果

在這裡插入圖片描述

二:程式碼實現

通過小鍵盤控制光源的移動

#include <windows.h>
#include <GL/glut.h>
#include <math.h>
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#define PI 3.1416
float r[17]={0,0.1,0.2,0.3,0.4,1,0.7,1,0.4,0.6,0,1};
float g[17]={1,0,0.5,1,0.5,0.6,0.7,0.3,1,0.6,0.2,0,1,0};
float b[17]={0.3,0.8,0.9,1,0,0,0,1,0.4,0.6,1,0.2,1,0.5,1};
GLint color[9]={1,2,3,0,2,3,1,2,3};
float n=30.0;
float n2=-30.0;
GLfloat xRot = -5.0f;
GLfloat yRot = 5.0f;
GLfloat zRot = -5.0f;
static GLfloat vertex_list[][3] = {
    -0.5f, -0.5f, -0.5f,
     0.5f, -0.5f, -0.5f,
    -0.5f,  0.5f, -0.5f,
     0.5f,  0.5f, -0.5f,
    -0.5f, -0.5f,  0.5f,
     0.5f, -0.5f,  0.5f,
    -0.5f,  0.5f,  0.5f,
     0.5f,  0.5f,  0.5f,
};
static const GLint index_list[][4] = {
    0, 2, 3, 1,
    0, 4, 6, 2,
    0, 1, 5, 4,
    4, 5, 7, 6,
    1, 3, 7, 5,
    2, 6, 7, 3,
};
GLfloat light_position1 [] = {xRot,yRot,zRot,1.0}; //點光源位置
void Init(void)
{
 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 glColor3f(1.0f, 1.0f, 0.0f);
        // 儲存座標和角度
 GLfloat x, y, z, angle,x1,y1;
//光照引數初始化全位於此處
    GLfloat mat_specular [] = {1.0,1.0,1.0,1.0}; //鏡面反射引數
    GLfloat mat_shininess [] = {100.0}; //高光指數
  //  GLfloat light_position [] = {5.0,5.0,5.0,1.0}; //點光源位置
//GLfloat light_position [] = {0.0,0.0,50.0,0.0}; //無限遠模擬平行光
   // GLfloat white_light [] = {1.0,1.0,1.0,1.0}; //設定光源顏色
      GLfloat light_1 [] = {1.0,0.5,0.3,1.0}; //設定光源顏色
    //GLfloat light_2 [] = {0,0.5,0.3,1.0}; //設定光源顏色
    //   GLfloat light_position1 [] = {xRot,yRot,zRot,1.0}; //點光源位置
     //      GLfloat light_position2 [] = {5.0,-5.0,5.0,1.0}; //點光源位置
    GLfloat model_ambient [] = {0.1,0.1,0.1,1.0}; //環境光引數
    glClearColor(0.0,0.0,0.0,0.0); //背景色
    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); //定義鏡面光為白色

    glLightfv(GL_LIGHT1,GL_POSITION,light_position1); //定義光源的位置
    glLightfv(GL_LIGHT1,GL_DIFFUSE,light_1); //定義散射光為白色
    glLightfv(GL_LIGHT1,GL_SPECULAR,light_1); //定義鏡面光為白色

 //    glLightfv(GL_LIGHT2,GL_POSITION,light_position2); //定義光源的位置
  //  glLightfv(GL_LIGHT2,GL_DIFFUSE,light_2); //定義散射光為白色
  //  glLightfv(GL_LIGHT2,GL_SPECULAR,light_2); //定義鏡面光為白色

    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,model_ambient); //光照模型引數:全域性環境光
    glEnable(GL_LIGHTING); //開啟光源
   // glEnable(GL_LIGHT0); //啟動 0 號光源
      glEnable(GL_LIGHT1); //啟動 0 號光源
         // glEnable(GL_LIGHT2); //啟動 0 號光源
    glEnable(GL_DEPTH_TEST); //開啟深度測試


 // 把著色模式設定為單調著色
//glShadeModel(GL_FLAT); //glShadeModel(GL_SMOOTH);
 // 把順時針環繞的多邊形設為正面,這與預設是相反的,因為我們使用的是三角形扇
 glFrontFace(GL_CW);
 glOrtho(-1.0f,1.0f,-1.0f,1.0f,-1.0f,1.0f);
}
void SpecialKeys(int key, int x, int y)
{
 if (key == GLUT_KEY_UP)
 xRot -= 5.0f;
 if (key == GLUT_KEY_DOWN)
 xRot += 5.0f;
 if (key == GLUT_KEY_LEFT)
 yRot -= 5.0f;
 if (key == GLUT_KEY_RIGHT)
 yRot += 5.0f;
 if (key> 356.0f)
 xRot = 0.0f;
 if (key< -1.0f)
 xRot = 355.0f;
 if (key> 356.0f)
 yRot = 0.0f;
 if (key< -1.0f)
 yRot = 355.0f;
 if (key==GLUT_KEY_F1) //繞著 z 軸旋轉
 zRot+= 5.0f;
 // 使用新的座標重新繪製場景

 glutPostRedisplay();
}
void RenderScene()
{
 // 儲存座標和角度
 GLfloat x, y, z, angle,x1,y1;
 // 用於三角形顏色的交替設定
 int iPivot = 1;
 // 用預設顏色設定背景色,並清除深度緩衝區(必須的,因為 3D 空間有視景深度)
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 //開啟剔除功能(背面剔除,它用於消除一個表面的背面)
 //glEnable(GL_CULL_FACE);
 // 開啟深度測試,如果不開啟深度測試,3D 錐體的顯示就會與現實情況不符合
 glEnable(GL_DEPTH_TEST);
 // 儲存矩陣狀態並旋轉
 glPushMatrix();
GLfloat light_position1 [] = {xRot,yRot,zRot,1.0}; //點光源位置
glLightfv(GL_LIGHT1,GL_POSITION,light_position1); //定義光源的位置

 /*
 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
 glRotatef(zRot, 0.0f, 0.0f, 1.0f);
 */
// glBegin(GL_TRIANGLE_FAN);


glBegin(GL_QUADS);

 for(int i=0; i<6; ++i)  // 有六個面,迴圈六次
 {
     glColor3d(r[i],g[i],b[i]);//顏色設定為青色


         for(int j=0; j<4; ++j)     // 每個面有四個頂點,迴圈四次
 {
          glNormal3f(vertex_list[index_list[i][j]][0],vertex_list[index_list[i][j]][1],vertex_list[index_list[i][j]][2]); //設定法向量
      glVertex3fv(vertex_list[index_list[i][j]]);
 }

 }

 glEnd();
    // ...
 //glEnd();
 glPopMatrix();
 glutSwapBuffers();
}
int main(int argv,char *argc[]){
 glutInit(&argv,argc);
 glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
 glutInitWindowSize(400,400);
 glutInitWindowPosition(400,300);
 glutCreateWindow("3D 空間繪製圓錐面");
 glutDisplayFunc(RenderScene);
 glutSpecialFunc(SpecialKeys);
 Init();
 glutMainLoop();
}



三:補充

法向量的設定
一個面一個法向量。三個頂點決定一個面。法向量可以通過 3 個頂點得到的兩個向量叉乘求出。
函式:glNormal3f (GLfloat x, GLfloat y, GLfloat z):x, y, z 表示法向量指向的位置。
作用:用來設定當前的法向量,這個法向量將被應用到緊接下來的 glVertex() 所定義的頂點上。但是通常各個頂
點的法向是各不相同的,所以我們通常在定義每個頂點之前都為它確定一次法向量。
用法示例:

glBegin();
glNormal3f(x,y,z); //設定法向量
glVertex3f(x,y,z); //設定點座標
glNormal3f(x,y,z); //設定法向量
glVertex3f(x,y,z); //設定點座標
glEnd();

相關文章