第一个OpenGLES小程序

  虽然几年前就注册了CSDN,但一直都是来这儿看文章下资料,现在要慢慢养成写BLOG的习惯。星期天在家看了一会OpenGLES编程方面的资料,模仿写了一个简单的小程序,生成一个沿Y轴不停旋转的三角形,我尽量把注释写的详细写。程序运行在WM5.0上。

 程序截图

#include "stdafx.h"
#include "OpenGLES_First.h"

#include "GLES/gl.h"
#include "GLES/egl.h"

#define PRECISION 16 
#define ONE (1 << PRECISION)
#define ZERO 0

// 转换成定点数
GLfixed FixedFromInt(int value) {return value << PRECISION;};
GLfixed FixedFromFloat(float value) {return static_cast<GLfixed>(value * static_cast<float>(ONE));};
GLfixed MultiplyFixed(GLfixed op1, GLfixed op2) {return (op1 * op2) >> PRECISION;};

// 程序人口函数
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine,int nCmdShow);
// 窗口回调函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// opelgles初始化函数
BOOL InitOGLES();
// 渲染函数
void Render();
// 资源释放函数
void Clean();
// 设置透视投影模式函数
void Perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear,  GLfloat zFar);


// 当前实例的句柄
HINSTANCE hInst;
//窗口的句柄
HWND hWnd;
// 上下文设备
HDC hDC;

// 此参数代表程序输出的显示器
EGLDisplay glesDisplay; 
// 此参数实际上就是一个FrameBuffer
EGLSurface glesSurface; 
/**此参数代表状态机,存储当前的颜色、纹理坐标、变换矩阵、绚染模式等一大堆状态。
这些状态作用于程序提交的顶点 坐标等图元从而形成帧缓冲内的像素*/
EGLContext glesContext; 

//窗口标题
TCHAR szAppName[] = L"First OpenGLES ";


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
 //系统信息
 MSG msg;
 //窗口类
 WNDCLASS wc;
 //赋值实例句柄
 hInst = hInstance;
 //程序退出标志
 bool done = FALSE;

 //确保此程序同时只有一个实例运行
 if(hWnd = FindWindow(szAppName, szAppName))
 {
  //如果已有实例在运行,把其设置为最前端窗口
  SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
  return 0;
 }

 //设置窗口类属性
 wc.style          = CS_HREDRAW | CS_VREDRAW;        
 wc.lpfnWndProc    = (WNDPROC) WndProc;
 wc.cbClsExtra     = 0;
 wc.cbWndExtra     = 0;
 wc.hInstance      = hInstance;
 wc.hIcon          = LoadIcon(hInstance, NULL);
 wc.hCursor       = 0;
 wc.hbrBackground  = 0;
 wc.lpszMenuName   = NULL;
 wc.lpszClassName  = szAppName;

 //注册窗口类
 if(!RegisterClass(&wc))
  return FALSE;

 //创建窗口
 hWnd=CreateWindow(szAppName,
  szAppName,
  WS_VISIBLE,
  CW_USEDEFAULT,CW_USEDEFAULT,
  CW_USEDEFAULT, CW_USEDEFAULT,
  NULL, NULL,
  hInst, NULL);

 if(!hWnd) return FALSE;

 //初始化OpenGLES
 if(!InitOGLES()) return FALSE;

 //显示窗口
 ShowWindow(hWnd, nCmdShow);
 UpdateWindow(hWnd);

 //消息循环
 while(!done)
 {
  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   if(msg.message==WM_QUIT)
    done=TRUE;
   else
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
  }
  else
  {
   //渲染
   Render();
  }
   


 }

 //资源释放
 Clean();
 return 0;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 
 switch (message)
 {  
 case WM_PAINT: 
  //重绘区域
  ValidateRect(hWnd,NULL);
  return 0;

 case WM_DESTROY:
  PostQuitMessage(0);
  return 0; 
 };
 return DefWindowProc(hWnd, message, wParam, lParam);  
}

/**
初始化OpenGLES分四步:
 调用eglInitialize()初始化egl库
 用eglChooseConfig()选择合适的FrameBuffer
 调用eglCreateWindowSurface创建EGLSurface
 用eglCreateContext创建RenderContext
*/
BOOL InitOGLES()

 //所为Config实际指的是FrameBuffer的参数
 EGLConfig configs[10];
 //机器配置
 EGLint matchingConfigs; 

 //设置配置属性,这些属性决定FrameBuffer的格式和能力
 const EGLint configAttribs[] =
 {
  EGL_RED_SIZE,       8,
  EGL_GREEN_SIZE,     8,
  EGL_BLUE_SIZE,      8,
  EGL_ALPHA_SIZE,     EGL_DONT_CARE,
  EGL_DEPTH_SIZE,     16,
  EGL_STENCIL_SIZE,   EGL_DONT_CARE,
  EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
  EGL_NONE,           EGL_NONE
 };

 // 获取display
 hDC = GetWindowDC(hWnd);
 glesDisplay = eglGetDisplay(hDC);  //Ask for an available display

 // 初始化egl库
 if(!eglInitialize(glesDisplay, NULL, NULL))
  return FALSE;

 // 选择合适的FrameBuffer
 if(!eglChooseConfig(glesDisplay, configAttribs, &configs[0], 10,  &matchingConfigs))
  return FALSE;

 // 如果没有合适的配置跳出程序
 if (matchingConfigs < 1)  return FALSE;  

 // 创建EGLSurface
 glesSurface = eglCreateWindowSurface(glesDisplay, configs[0], hWnd, configAttribs); 
 if(!glesSurface) return FALSE;

 // 创建EGLContext
 glesContext = eglCreateContext(glesDisplay,configs[0],0,configAttribs);
 if(!glesContext) return FALSE;

 // 绑定上面设置的属性到当前的渲染中 
 eglMakeCurrent(glesDisplay, glesSurface, glesSurface, glesContext);

 // 设置屏幕背景色
 glClearColorx(0, 0, 0, 0);

 // 启用阴影平滑
 glShadeModel(GL_SMOOTH); 

 // 设置视口的尺寸
 RECT rect;
 GetWindowRect(hWnd, &rect); 
 glViewport(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 

 // 设置投影模式 (OpenGL ES提供了2种投影模式。1.平行映射模式 2.透视投影模式。 同时只能选择一种)
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();  

 //1.平行映射模式: 设置该模式下的左右下上近远六个面。物体只要出于之中,就会进行投影计算,向屏幕进行投影。
//  glOrthox(FixedFromInt(-50), FixedFromInt(50),
//   FixedFromInt(-50), FixedFromInt(50),
//   FixedFromInt(-50), FixedFromInt(50));

 /**
 2.透视投影模式:
  第一个参数是视角,一般我们设置45度,必将接近人的视角。你也可以设置的大一些,类似照相机的广角镜头。
  第二个参数是屏幕的宽、高比,很简单,把屏幕的宽除以高就行了。
  最后两个参数是设置近面和远面,和设置平行模式的参数意义相同
 */
 
 GLfloat ratio = (GLfloat)(rect.right - rect.left)/(rect.bottom - rect.top);
 //glMatrixMode(GL_PROJECTION);
 //glLoadIdentity();       
 Perspective(45.0f,ratio, 1.0f, 40.0f);
 //glMatrixMode(GL_MODELVIEW);

 //设置模型视景矩阵
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 return TRUE;
}

// 设置图形的顶点颜色并渲染
void Render()
{
 //旋转角度
 static int rotation = 0;
 
 // 顶点坐标和颜色数组
 GLshort vertexArray[9] = {-5,-5,0,   5,-5,0,     0,5,0 };
 GLubyte colorArray[12] = {255,0,0,0,   0,255,0,0,    0,0,255,0};

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
 glLoadIdentity(); 
 glTranslatex(0, 0, FixedFromInt(-30));
 glRotatex(FixedFromInt(rotation++), 0, ONE, 0); 

 // 启动顶点坐标
 glEnableClientState(GL_VERTEX_ARRAY);
 glVertexPointer(3, GL_SHORT, 0, vertexArray);
 
 // 启动顶点颜色
 glEnableClientState(GL_COLOR_ARRAY);
 glColorPointer(4,GL_UNSIGNED_BYTE, 0, colorArray);

 // 绘制三角形
 glDrawArrays(GL_TRIANGLES, 0, 3); 

 // 关闭顶点坐标和颜色
 glDisableClientState(GL_VERTEX_ARRAY);
 glDisableClientState(GL_COLOR_ARRAY);


 eglSwapBuffers(glesDisplay, glesSurface);

 
}
//----------------------------------------------------------------------------
void Clean()
{
 //销毁opengles相关资源
 if(glesDisplay)
 {
  eglMakeCurrent(glesDisplay, NULL, NULL, NULL); 
  if(glesContext) eglDestroyContext(glesDisplay, glesContext);
  if(glesSurface) eglDestroySurface(glesDisplay, glesSurface);
  eglTerminate(glesDisplay);
 }
 //销毁窗口
 DestroyWindow(hWnd);
 UnregisterClass(szAppName, hInst); 
}

void Perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear,  GLfloat zFar)
{
 GLfixed xmin, xmax, ymin, ymax, aspectFixed, znearFixed;    

 aspectFixed = FixedFromFloat(aspect);
 znearFixed = FixedFromFloat(zNear);

 ymax = MultiplyFixed(znearFixed, FixedFromFloat((GLfloat)tan(fovy * 3.1415962f / 360.0f))); 
 ymin = -ymax;

 xmin = MultiplyFixed(ymin, aspectFixed);
 xmax = MultiplyFixed(ymax, aspectFixed); 
 glFrustumx(xmin, xmax, ymin, ymax, znearFixed, FixedFromFloat(zFar));
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值