只使用了2d的纹理,纹理贴图就是将一张图片贴到物体的表面
相关函数:
glEnable(GL_TEXTURE_2D);//开启2D纹理
glBindTexture(GL_TEXTURE_2D, textures[0]);//绑定纹理,将绘制的纹理
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexCoord2f(0, 0);
所有代码: 上键调整纹理模式 T键是否打开纹理
#include <Windows.h>
#include <iostream>
#include <gl\GL.h>
#include <gl\GLU.h>
#pragma comment(lib,"opengl32.lib")//opengl相关库
#pragma comment(lib,"glu32.lib")
/全局句柄
HGLRC hRC;
HDC hDC;
HWND hWnd;
/全局句柄
//全局变量
long width;//纹理宽度和高度
long height;
unsigned char *bmp;//纹理数据
GLuint textures[2];
int flag_tex = 0;//纹理模式
bool b_tex = true;//是否打开纹理
const int NUM = 100;//圆等分程度
int n = 50;//圆的顶点数
GLfloat Circle_vex[NUM];//存放圆顶点
void GetBmpByFilePath(char *filepath)//读取bmp位图
{
FILE *file = NULL;
fopen_s(&file,filepath, "rb");
if (file == NULL) { MessageBox(NULL,"文件读取失败!","错误",MB_OK); return; }
//读取bmp头
BITMAPFILEHEADER bmpFileHead;
fread(&bmpFileHead, sizeof(BITMAPFILEHEADER), 1, file);
if (bmpFileHead.bfType != 0x4d42) { MessageBox(NULL,"图像不是bmp格式!", "错误", MB_OK); return; }
DWORD sumNum = bmpFileHead.bfSize;//这个长度是数据长度
DWORD offNum = bmpFileHead.bfOffBits;//数据偏移头部长度
BITMAPINFOHEADER bmpInfoHead;
fread(&bmpInfoHead, sizeof(BITMAPINFOHEADER), 1, file);
if (bmpInfoHead.biCompression != 0){ MessageBox(NULL,"无法处理的bmp压缩格式!", "错误", MB_OK); return; }
if (bmpInfoHead.biBitCount != 24)
{
MessageBox(NULL, "无法处理的bmp格式!", "错误", MB_OK); return;
}
width = bmpInfoHead.biWidth;//宽度必须是4B的倍数
height = bmpInfoHead.biHeight;
width = (width*3 + 3) / 4 * 4;
height = abs(height);
bmp = new unsigned char[height*width];
fread(bmp, 1, height*width, file);
for (int j = 0; j < height; j++)//更换BGR循序为RGB
for (int i = 0; i < width; i++)
{
unsigned char b = bmp[j*width + i];
unsigned char r = bmp[j*width + i + 2];
bmp[j*width + i] = r;
bmp[j*width + i + 2] = b;
i += 2;
}
width /= 3;
fclose(file);
}
void MakeCircle()//计算圆的坐标并移动位置到左下角
{
float ang = 6.18 / n;
int j = 0;
for (int i = 0; i < n;i++)
{
Circle_vex[j++] = sin(i*ang)/2-0.5;
Circle_vex[j++] = cos(i*ang)/2-0.5;
}
}
void InitGL()//初始化opengl参数
{
glClearColor(0.5, 0.5, 0.5, 1);//设置颜色缓存颜色
glEnable(GL_TEXTURE_2D);//开启2D纹理
GetBmpByFilePath("opengl.bmp");//读取纹理
glGenTextures(2, textures);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//线性滤波
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//线性滤波
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//线性滤波
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//线性滤波
if (bmp) free(bmp);//释放bmp内存
MakeCircle();
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, Circle_vex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, Circle_vex);
}
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT ); // 每次刷新屏幕颜色缓存
glBindTexture(GL_TEXTURE_2D, textures[flag_tex]);//选择纹理类型
//是否使用纹理
if (b_tex) glEnable(GL_TEXTURE_2D);
else glDisable(GL_TEXTURE_2D);
//矩形
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(0, 0);
glTexCoord2f(1, 0); glVertex2f(1, 0);
glTexCoord2f(1, 1); glVertex2f(1, 1);
glTexCoord2f(0, 1); glVertex2f(0, 1);
glEnd();
//圆形
glDrawArrays(GL_POLYGON, 0, n);
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)// 消息处理回调函数
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
return 0; // Return To The Message Loop
}
case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}
case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}
case WM_KEYDOWN: // 按键按下 由wParam决定
{
switch (wParam)
{
case 'T':
b_tex = !b_tex;
break;
case VK_UP:
flag_tex++;
if (flag_tex == 2) flag_tex = 0;
break;
}
return 0; // Jump Back
}
case WM_KEYUP: // 按键松开
{
//z = 0;
return 0; // Jump Back
}
case WM_SIZE: // Resize The OpenGL Window
{
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));//改变GL窗口大小
return 0; // Jump Back
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hwnd, uMsg, wParam, lParam);//默认消息回调处理函数
}
void KillGLWindow()
{
if (hRC) // 删除着色描述表
{
if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
hRC = NULL; // Set RC To NULL
}
if (hDC && !ReleaseDC(hWnd, hDC)) // 释放DC
{
MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
hDC = NULL; // Set DC To NULL
}
if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
hWnd = NULL; // Set hWnd To NULL
}
}
int WINAPI WinMain(HINSTANCE h,HINSTANCE,LPSTR lpCmdLine,int nCmdShow)
{
WNDCLASS wc;
wc.hInstance = h;
wc.hbrBackground = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC)WndProc;
RegisterClass(&wc);
hWnd = CreateWindow("OpenGL", "test", WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_BORDER | WS_MAXIMIZEBOX, 0, 0, 300, 300, NULL, NULL, h, NULL);
//opengl设定
hDC = GetDC(hWnd);
static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
24, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
int PixelFormat;
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) // 按照给定像素格式规范匹配与设备上下文合适的像素格式
{
KillGLWindow(); // 重置显示区
MessageBox(NULL, "不能设置像素格式", "错误", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回 FALSE
}
if (!SetPixelFormat(hDC, PixelFormat, &pfd)) // 设置像素格式
{
KillGLWindow(); // 重置显示区
MessageBox(NULL, "不能设置像素格式", "错误", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回 FALSE
}
if (!(hRC = wglCreateContext(hDC))) // 设置合适设备的OpenGL渲染上下文
{
KillGLWindow(); // 重置显示区
MessageBox(NULL, "不能创建OpenGL渲染描述表", "错误", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回 FALSE
}
if (!wglMakeCurrent(hDC, hRC)) // 尝试激活着色描述表
{
KillGLWindow(); // 重置显示区
MessageBox(NULL, "不能激活当前的OpenGL渲然描述表", "错误", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回 FALSE
}
//opengl着色表设定结束
ShowWindow(hWnd, SW_SHOW);
InitGL();//opengl相关初始化
//消息处理
bool done = false;
MSG msg;
while (!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // 如果有消息就处理消息
{
if (msg.message == WM_QUIT) // Have We Received A Quit Message?
{
done = TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // 没消息就处理界面
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
return TRUE;
}