openGL程序示例代码——旋转的玉石

时间:2022-08-05 20:49:05

最近交期末作业,学了一下openGL,作为初学者感觉会有用的在这列一下。

1、工程的建立:

      VS中,新建工程/win32/win32控制台应用程序。

2、在新建的控制台应用程序中添加 glut库的方法:

      <1>将下载的gult32库文件放在项目目录下。

      <2>VS中,项目/属性/连接器/输入/附加依赖项,在附加依赖项中输入glut32.lib

一、绘图

如果我们要绘制一个3D物体只需要绘制它的各个面即可, 只不过这里的顶点坐标是3维的,因此我们可以事先计算好各个顶点的坐标。

注意,在opengl中绘制每个面时,所有面给出的顶点的顺序都要按照逆时针或者顺时针(我这里采用的是逆时针),这样才能保证所绘制出来的图像时正确的。

二、光照

Opengl中使用光照时,首先定义了3个跟光滑有关的数组:前两个参数为{R,G,B,a}

  GLfloat lightAmbient[4] = { 0.5, 0.5, 0.5, 1.0 };//环境光——比较均匀,四面八方都有
  GLfloat lightDiffuse[4] = { 1.0, 1.0, 1.0, 1.0 };//漫射光—特定位置发出的光
GLfloat lightPosition[4] = {0.0, 0.0, 2.0, 1.0 };//参数(x,y,z,a)

三、纹理映射

注意:所要加纹理的3D图的某个面上的顶点要 和 纹理图上的点对应起来。

代码举例:

//将2D的纹理坐标映射到3D的空间物体表面上
glTexCoord2f(0.0,1.0); //纹理坐标,需要计算的……
glVertex3f(-0.3f,0.3f, -0.3f);//物体顶点


四、旋转用一个函数就行,如:glRotatef(yrot, 0, 1, 0);//沿y轴旋转 yrot度  ,然后每运行一次yrot加一个值



五、代码贴一下


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 本程序效果:旋转的棱形玉石
// 交互:按“l”开启光照,按“L”关闭光照
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include<iostream>
#include <Windows.h>
#include "glut.h"
#include "GLAUX.H"

using namespace std;
static float xrot = 0.0;
static float yrot = 0.0;
static float zrot = 0.0;

GLuint texture[1]; // 存储一个纹理

//3个与光照有关的数组
GLfloat light_ambient[4]={1.0, 1.0, 1.0, 1.0};//环境光。参数为{R,G,B,A}。环境光一般比较均匀,四面八方都有
GLfloat light_diffuse[4]={1.0, 1.0, 1.0, 1.0};//漫射光——特定位置发出的光
GLfloat light_position[4]={0.5,0.5, 0.5, 0.0};//光源位置


AUX_RGBImageRec *LoadBMP(char *Filename) // 载入位图图象
{
FILE *File=NULL;
if (!Filename) // 确保文件名已提供
{
MessageBox(NULL,"纹理文件不存在!","警告!",MB_ICONWARNING);
return NULL; // 如果没提供,返回 NULL
}
File=fopen(Filename,"r"); // 尝试打开文件
if (File) // 文件存在么?
{
fclose(File); // 关闭句柄
return auxDIBImageLoad(Filename); // 载入位图并返回指针
}
return NULL; // 如果载入失败,返回 NULL
}
int LoadGLTextures() // 载入位图(调用上面的代码)并转换成纹理
{
int Status=FALSE; // 状态指示器
AUX_RGBImageRec *TextureImage[1]; // 创建纹理的存储空间
memset(TextureImage,0,sizeof(void *)*1); // 将指针设为 NULL

if (TextureImage[0]=LoadBMP("yu.bmp"))// 载入位图,检查有无错误,如果位图没找到则退出
{
Status=TRUE; // 将 Status 设为 TRUE
glGenTextures(1, &texture[0]); // 创建纹理

// 使用来自位图数据生成 的典型纹理
glBindTexture(GL_TEXTURE_2D, texture[0]);
// 生成纹理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//当所显示的纹理比加载进来的纹理小时,采用GL_LINEAR的方法来处理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//当所显示的纹理比加载进来的纹理大时,采用GL_LINEAR的方法来处理
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
}
if (TextureImage[0]) // 纹理是否存在
{
if (TextureImage[0]->data) // 纹理图像是否存在
{
free(TextureImage[0]->data); // 释放纹理图像占用的内存
}

free(TextureImage[0]); // 释放图像结构
}
return Status; // 返回 Status
}

void cube()
{
glBindTexture(GL_TEXTURE_2D, texture[0]); // 选择纹理

glBegin(GL_TRIANGLES); // 开始画图
//glColor4f(1.0f,1.0f,1.0f,1.0f); // 白色
glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, 2.0f, 0.0f); // 顶点 a
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f,1.0f, 1.0f); // 左 b
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f,1.0f, 1.0f); // 右 c

glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, 2.0f, 0.0f); // Top Of Triangle (Right) a
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f,1.0f, 1.0f); // Left Of Triangle (Right) c
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f,1.0f, -1.0f); // Right Of Triangle (Right) d

glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, 2.0f, 0.0f); // Top Of Triangle (Back) a
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f,1.0f, -1.0f); // Left Of Triangle (Back) d
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f,1.0f, -1.0f); // Right Of Triangle (Back) e

glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, 2.0f, 0.0f); // Top Of Triangle (Left) a
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f,1.0f,-1.0f); // Left Of Triangle (Left) e
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f,1.0f, 1.0f); // Right Of Triangle (Left) b
glEnd();

glBegin(GL_TRIANGLES); // Start Drawing A Triangle
//glColor4f(0.0f,0.66f,0.91f,0.6f); // 白
glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, -1.0f, 0.0f); // Top Of Triangle (Front) f
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f,1.0f, 1.0f); // Left Of Triangle (Front) b
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f,1.0f, 1.0f); // Right Of Triangle (Front) c

glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, -1.0f, 0.0f); // Top Of Triangle (Right) f
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f,1.0f, 1.0f); // Left Of Triangle (Right) c
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 1.0f,1.0f, -1.0f); // Right Of Triangle (Right) d

glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, -1.0f, 0.0f); // Top Of Triangle (Back) a
glTexCoord2f(0.0f, 0.0f);
glVertex3f( 1.0f,1.0f, -1.0f); // Left Of Triangle (Back) d
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f,1.0f, -1.0f); // Right Of Triangle (Back) e

glTexCoord2f(0.5f, 1.0f);
glVertex3f( 0.0f, -1.0f, 0.0f); // Top Of Triangle (Left) a
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f,1.0f,-1.0f); // Left Of Triangle (Left) e
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f,1.0f, 1.0f); // Right Of Triangle (Left) b
glEnd();
}

void display(void)
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0, -5); //平移函数,将屏幕位置沿z轴移-10
glRotatef(yrot, 0, 1, 0);//沿y轴旋转 yrot度
//glPolygonMode(GL_FRONT, GL_LINE);
cube();
//xrot = xrot + 1;
yrot = yrot + 1;
//zrot = zrot + 1;
Sleep(8);
glutSwapBuffers();
}

void reshape(int w, int h)
{
if(h==0) h = 1;

glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);//切换到投影矩阵,(要使用透视(3D).那么先要设置透视投影)
glLoadIdentity(); //然后把矩阵设为单位矩阵
gluPerspective(45.0, (GLfloat)w/(GLfloat)h, 1, 100.0);//然后调用glFrustum()或gluPerspective(),它们生成的矩阵会与当前的矩阵相乘,生成透视的效果;
//参数解释(视角,实际窗口的纵横比,眼睛到物体最近处的距离,眼睛到物体最远处的距离)

glMatrixMode(GL_MODELVIEW);//设置完成后开始画图,需要切换到 模型视图矩阵 才能正确画图
// 画一个物体A (看起来是3D的),
// 如这时候需画一个 2D效果 的 物体A,那么又需要透视投影

}
void init(int width, int height )
{
if(height == 0) height = 1;

if (!LoadGLTextures()) // 调用纹理载入子例程
{
MessageBox(NULL,"纹理载入失败","警告!",MB_ICONWARNING);
return; // 如果未能载入,返回
}

glEnable(GL_TEXTURE_2D); // 启用纹理映射

glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);//进行透视校正

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat)width/(GLfloat)height, 1, 100.0);
glMatrixMode(GL_MODELVIEW);

//*opengl中支持8个光源,即GL_LIGHT0~GL_LIGHT7*/
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);//指定光源1的环境光参数
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);//指定光源1的漫射光参数
glLightfv(GL_LIGHT1, GL_POSITION, light_position);//指定光源1的位置
glEnable(GL_LIGHT1);//允许光源1的使用
//glEnable(GL_LIGHTING);//我们还需要启动总光源开关,默认的时候不开,后面的L键来控制开启和关闭

}

void keyboard(unsigned char key, int w, int h)
{
if(key == 'l') // 开启光源
glEnable(GL_LIGHTING);
if(key == 'L') // 关闭光源
{
glDisable(GL_LIGHTING);
}
if(key == 27) // ESC退出程序
exit(0);
}


int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(400, 100);
glutInitWindowSize(640, 480);
glutCreateWindow("旋转的玉石");

glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

glutDisplayFunc(display);
glutIdleFunc(display);

if(yrot > 6.0)
{
yrot = 0;
}

glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
init(640, 480);
glutMainLoop();
return 0;
}



效果图:(自己做的gif图,效果不是很好)

 openGL程序示例代码——旋转的玉石  

用来贴图的图片这样:

openGL程序示例代码——旋转的玉石


用到的库函数到这里下载:http://download.csdn.net/detail/u013394782/7543095