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

本文介绍OpenGL的基础知识,包括工程建立、使用光照、纹理映射等,并通过一个旋转玉石的实例演示如何实现3D图形的绘制及旋转效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近交期末作业,学了一下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图,效果不是很好)

   

用来贴图的图片这样:


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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值