opengles中使用vbo(顶点缓冲区)
来源:互联网 发布:java 今天星期几 编辑:程序博客网 时间:2024/05/22 04:40
为什么要使用VBO:
如果不使用vbo,要绘制物体的顶点信息需要从内存传递到显存,当绘制的模型比较复杂时,频繁的在内存和显存中做数据传递会降低效率。因此使用VBO,可以先把一部分顶点数据缓存起来,绘制的时候直接从缓存中获取,大大降低内存和显存之间数据拷贝的开销,总而言之是为了提高绘制效率。
如何使用vbo:
//申明顶点数据结构struct Vertex{float x, y, z;float u, v;float r, g, b, a;};Vertex vertexs[] ={{ -1.0f, -1.0f, -8.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, -1.0f, -8.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, -8.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, -1.0f, -8.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, -8.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, -8.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },};/*为什么要使用vbo (顶点缓冲区):如果不使用vbo,要绘制物体的顶点信息需要从内存传递到显存,当绘制的模型比较复杂时,频繁的在内存和显存中做数据传递会降低效率。因此使用VBO,可以先把一部分顶点数据缓存起来,绘制的时候直接从缓存中获取,大大降低内存和显存之间数据拷贝的开销。*/glGenBuffers(1,&_vbo);//声明一个vboglBindBuffer(GL_ARRAY_BUFFER,_vbo);//指定buffer类型为顶点bufferglBufferData(GL_ARRAY_BUFFER,sizeof(vertexs),vertexs,GL_STATIC_DRAW);//将顶点数据拷贝到显存glBindBuffer(GL_ARRAY_BUFFER, 0);//禁用缓存//使用vbo绘制glBindTexture(GL_TEXTURE_2D, _texGrass);glBindBuffer(GL_ARRAY_BUFFER, _vbo);glUniformMatrix4fv(_shader._MVP, 1, false, MVP1.data());glVertexAttribPointer(_shader._positionAttr, 3, GL_FLOAT, false, sizeof(Vertex), (void*)0);//sizeof(Vertex) 偏移量:(void*)0 起始地址glVertexAttribPointer(_shader._uvAttr, 2, GL_FLOAT, false, sizeof(Vertex), (void*)12);// (void*)12 起始地址 每个float4个字节 每个顶点有3个float(x,y,z)glVertexAttribPointer(_shader._colorAttr, 4, GL_FLOAT, false, sizeof(Vertex), (void*)20);//12+8 三个位置坐标占12byte 两个纹理坐标占8byte 故颜色坐标的偏移量是20glDrawArrays(GL_TRIANGLES, 0, 6);//这步是必须的glBindBuffer(GL_ARRAY_BUFFER, 0);//禁用缓存
shader实现类:
#pragma once#include <assert.h>class ShaderId{public:ShaderId(){_shaderId = -1;}int _shaderId;};/*** 程序*/class ProgramId{public:int _programId;ShaderId _vertex;ShaderId _fragment;public:ProgramId(){_programId = -1;}public:/*** 加载函数*/bool createProgram(const char* vertex, const char* fragment){bool error = false;do{if (vertex){_vertex._shaderId = glCreateShader(GL_VERTEX_SHADER);glShaderSource(_vertex._shaderId, 1, &vertex, 0);glCompileShader(_vertex._shaderId);GLint compileStatus;glGetShaderiv(_vertex._shaderId, GL_COMPILE_STATUS, &compileStatus);error = compileStatus == GL_FALSE;if (error){GLchar messages[256];glGetShaderInfoLog(_vertex._shaderId, sizeof(messages), 0, messages);assert(messages && 0 != 0);break;}}if (fragment){_fragment._shaderId = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(_fragment._shaderId, 1, &fragment, 0);glCompileShader(_fragment._shaderId);GLint compileStatus;glGetShaderiv(_fragment._shaderId, GL_COMPILE_STATUS, &compileStatus);error = compileStatus == GL_FALSE;if (error){GLchar messages[256];glGetShaderInfoLog(_fragment._shaderId, sizeof(messages), 0, messages);assert(messages && 0 != 0);break;}}_programId = glCreateProgram();if (_vertex._shaderId){glAttachShader(_programId, _vertex._shaderId);}if (_fragment._shaderId){glAttachShader(_programId, _fragment._shaderId);}glLinkProgram(_programId);GLint linkStatus;glGetProgramiv(_programId, GL_LINK_STATUS, &linkStatus);if (linkStatus == GL_FALSE){GLchar messages[256];glGetProgramInfoLog(_programId, sizeof(messages), 0, messages);break;}glUseProgram(_programId);} while (false);if (error){if (_fragment._shaderId){glDeleteShader(_fragment._shaderId);_fragment._shaderId = 0;}if (_vertex._shaderId){glDeleteShader(_vertex._shaderId);_vertex._shaderId = 0;}if (_programId){glDeleteProgram(_programId);_programId = 0;}}return true;}/*** 使用程序*/virtual void begin(){glUseProgram(_programId);}/*** 使用完成*/virtual void end(){glUseProgram(0);}};class PROGRAM_P2_C4 :public ProgramId{public:typedef int attribute;typedef int uniform;public:attribute _position;uniform _color;uniform _MVP;public:PROGRAM_P2_C4(){_position = -1;_color = -1;_MVP = -1;}~PROGRAM_P2_C4(){}/// 初始化函数virtual bool initialize(){const char* vs ={"precision lowp float; ""uniform mat4 _MVP;""attribute vec2 _position;""void main()""{"" vec4 pos = vec4(_position,0,1);"" gl_Position = _MVP * pos;""}"};const char* ps ={"precision lowp float; ""uniform vec4 _color;""void main()""{"" gl_FragColor = _color;""}"};bool res = createProgram(vs, ps);if (res){_position = glGetAttribLocation(_programId, "_position");_color = glGetUniformLocation(_programId, "_color");_MVP = glGetUniformLocation(_programId, "_MVP");}return res;}/*** 使用程序*/virtual void begin(){glUseProgram(_programId);glEnableVertexAttribArray(_position);}/*** 使用完成*/virtual void end(){glDisableVertexAttribArray(_position);glUseProgram(0);}};class PROGRAM_P2_AC4 :public ProgramId{public:typedef int attribute;typedef int uniform;public:attribute _position;attribute _color;uniform _MVP;public:PROGRAM_P2_AC4(){_position = -1;_color = -1;_MVP = -1;}~PROGRAM_P2_AC4(){}/// 初始化函数virtual bool initialize(){const char* vs ={"precision lowp float; ""uniform mat4 _MVP;""attribute vec2 _position;""attribute vec4 _color;""varying vec4 _outColor;""void main()""{"" vec4 pos = vec4(_position,0,1);"" _outColor = _color;"" gl_Position = _MVP * pos;""}"};const char* ps ={"precision lowp float; ""varying vec4 _outColor;""void main()""{"" gl_FragColor = _outColor;""}"};bool res = createProgram(vs, ps);if (res){_position = glGetAttribLocation(_programId, "_position");_color = glGetAttribLocation(_programId, "_color");_MVP = glGetUniformLocation(_programId, "_MVP");}return res;}/*** 使用程序*/virtual void begin(){glUseProgram(_programId);glEnableVertexAttribArray(_position);glEnableVertexAttribArray(_color);}/*** 使用完成*/virtual void end(){glDisableVertexAttribArray(_position);glDisableVertexAttribArray(_color);glUseProgram(0);}};class PROGRAM_P2_UV_AC4 :public ProgramId{public:typedef int attribute;typedef int uniform;public:attribute _position;attribute _color;attribute _uv;uniform _MVP;uniform _texture;//! 第二阶段文理uniform _texture1;uniform _uvAnim;public:PROGRAM_P2_UV_AC4(){_position = -1;_color = -1;_uv = -1;_texture = -1;_texture1 = -1;_uvAnim = -1;_MVP = -1;}~PROGRAM_P2_UV_AC4(){}/// 初始化函数virtual bool initialize(){const char* vs ={"precision lowp float; ""uniform mat4 _MVP;""attribute vec2 _position;""attribute vec2 _uv;""attribute vec4 _color;""varying vec4 _outColor;""varying vec2 _outUV;""void main()""{"" vec4 pos = vec4(_position,0,1);"" _outColor = _color;"" _outUV = _uv;"" gl_Position = _MVP * pos;""}"};const char* ps ={"precision lowp float; ""uniform sampler2D _texture;\n""uniform sampler2D _texture1;\n""uniform float _uvAnim;\n""varying vec4 _outColor;\n""varying vec2 _outUV;\n""void main()""{"" vec4 tColor0 = texture2D(_texture,_outUV);\n"" vec2 newUV = vec2(_uvAnim + _outUV.x,_outUV.y);"" vec4 tColor1 = texture2D(_texture1,newUV);\n"" gl_FragColor = tColor0 * tColor1;\n""}"};bool res = createProgram(vs, ps);if (res){_position = glGetAttribLocation(_programId, "_position");_color = glGetAttribLocation(_programId, "_color");_uv = glGetAttribLocation(_programId, "_uv");_texture = glGetUniformLocation(_programId, "_texture");_texture1 = glGetUniformLocation(_programId, "_texture1");_MVP = glGetUniformLocation(_programId, "_MVP");_uvAnim = glGetUniformLocation(_programId, "_uvAnim");}return res;}/*** 使用程序*/virtual void begin(){glUseProgram(_programId);glEnableVertexAttribArray(_position);glEnableVertexAttribArray(_uv);glEnableVertexAttribArray(_color);}/*** 使用完成*/virtual void end(){glDisableVertexAttribArray(_position);glDisableVertexAttribArray(_uv);glDisableVertexAttribArray(_color);glUseProgram(0);}};class PROGRAM_P3_UV :public ProgramId{public:typedef int attribute;typedef int uniform;public:attribute _position;attribute _uv;uniform _MVP;uniform _texture;public:PROGRAM_P3_UV(){_position = -1;_uv = -1;_texture = -1;_MVP = -1;}~PROGRAM_P3_UV(){}/// 初始化函数virtual bool initialize(){const char* vs ={"precision lowp float; ""uniform mat4 _MVP;""attribute vec2 _position;""attribute vec2 _uv;""varying vec2 _outUV;""void main()""{"" vec4 pos = vec4(_position,0,1);"" _outUV = _uv;"" gl_Position = _MVP * pos;""}"};const char* ps ={"precision lowp float; ""uniform sampler2D _texture;\n""varying vec2 _outUV;\n""void main()""{"" vec4 tColor0 = texture2D(_texture,_outUV);\n"" gl_FragColor = tColor0;\n""}"};bool res = createProgram(vs, ps);if (res){_position = glGetAttribLocation(_programId, "_position");_uv = glGetAttribLocation(_programId, "_uv");_texture = glGetUniformLocation(_programId, "_texture");_MVP = glGetUniformLocation(_programId, "_MVP");}return res;}/*** 使用程序*/virtual void begin(){glUseProgram(_programId);glEnableVertexAttribArray(_position);glEnableVertexAttribArray(_uv);}/*** 使用完成*/virtual void end(){glDisableVertexAttribArray(_position);glDisableVertexAttribArray(_uv);glUseProgram(0);}};class PROGRAM_P2_T2_C3 :public ProgramId{public:typedef int location;public:location _positionAttr;location _colorAttr;location _uvAttr;location _MVP;location _texture;public:PROGRAM_P2_T2_C3(){_positionAttr = -1;_colorAttr = -1;_uvAttr = -1;_MVP = -1;}~PROGRAM_P2_T2_C3(){}/// 初始化函数virtual bool initialize(){const char* vs ={"uniform mat4 _MVP;""attribute vec3 _position;""attribute vec4 _color;""attribute vec2 _uv;""varying vec4 _outColor;""varying vec2 _outUV;""void main()""{"" vec4 pos = vec4(_position.x,_position.y,_position.z,1);"" gl_Position = _MVP * pos;"" _outColor = _color;"" _outUV = _uv;""}"};const char* ps ={"precision lowp float; ""uniform sampler2D _texture;\n""varying vec4 _outColor;\n""varying vec2 _outUV;""void main()""{"" vec4 color = texture2D(_texture,_outUV);"" if(color.a < 0.2)"" discard;"" gl_FragColor = color * _outColor;""}"};bool res = createProgram(vs, ps);if (res){_positionAttr = glGetAttribLocation(_programId, "_position");_colorAttr = glGetAttribLocation(_programId, "_color");_uvAttr = glGetAttribLocation(_programId, "_uv");_MVP = glGetUniformLocation(_programId, "_MVP");_texture = glGetUniformLocation(_programId, "_texture");}return res;}/*** 使用程序*/virtual void begin(){glUseProgram(_programId);glEnableVertexAttribArray(_positionAttr);glEnableVertexAttribArray(_uvAttr);glEnableVertexAttribArray(_colorAttr);}/*** 使用完成*/virtual void end(){glDisableVertexAttribArray(_positionAttr);glDisableVertexAttribArray(_uvAttr);glDisableVertexAttribArray(_colorAttr);glUseProgram(0);}};
窗口实现类:
#pragma once#include <Windows.h>#include <tchar.h>#include <math.h>#include <EGL/egl.h>#include <gles2/gl2.h>#include "freeImage/FreeImage.h"#include "CELLMath.hpp"#include "CELLShader.hpp"namespace CELL{class FirstCameraInfor{public:FirstCameraInfor(){_moveSpeed = 5;_eye = CELL::float3(0.0f, 10.0f, 0.0f);_look = CELL::float3(0.5f, -0.4f, -0.5f);_up = CELL::float3(0, 1, 0);_right = CELL::float3(1, 0, 0);}CELL::float3 _eye;CELL::float3 _look;CELL::float3 _up;CELL::float3 _right;float _moveSpeed;public:void updateCamera(float fElapsed){CELL::float3 tmpLook = _look;CELL::float3 dir = _look - _eye;dir = normalize(dir);//! 这里调用windows函数获取键盘的状态unsigned char keys[256];GetKeyboardState(keys);if (keys[VK_UP] & 0x80){_eye -= dir*-_moveSpeed * fElapsed;_look -= dir*-_moveSpeed * fElapsed;}if (keys[VK_DOWN] & 0x80){_eye += (dir*-_moveSpeed) * fElapsed;_look += (dir*-_moveSpeed) * fElapsed;}if (keys[VK_LEFT] & 0x80){_eye -= (_right*_moveSpeed) * fElapsed;_look -= (_right*_moveSpeed) * fElapsed;}if (keys[VK_RIGHT] & 0x80){_eye += (_right*_moveSpeed) * fElapsed;_look += (_right*_moveSpeed) * fElapsed;}}};class CELLWinApp{public://申明顶点数据结构struct Vertex{float x, y, z;float u, v;float r, g, b, a;};public://! 实例句柄HINSTANCE _hInstance;//! 窗口句柄HWND _hWnd;//! 窗口的高度int _width;//! 窗口的宽度int _height;/// for gles2.0EGLConfig _config;EGLSurface _surface;EGLContext _context;EGLDisplay _display;//! 增加shaderPROGRAM_P2_T2_C3 _shader;unsigned _textureId;unsigned _texDynamic;unsigned _texGrass;FirstCameraInfor _camera;unsigned _vbo;public:CELLWinApp(HINSTANCE hInstance):_hInstance(hInstance){WNDCLASSEX winClass;winClass.lpszClassName = _T("CELLWinApp");winClass.cbSize = sizeof(winClass);winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;winClass.lpfnWndProc = wndProc;winClass.hInstance = hInstance;winClass.hIcon = 0;winClass.hIconSm = 0;winClass.hCursor = LoadCursor(hInstance, IDC_ARROW);winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);winClass.lpszMenuName = NULL;winClass.cbClsExtra = 0;winClass.cbWndExtra = 0;RegisterClassEx(&winClass);_textureId = 0;}virtual ~CELLWinApp(){UnregisterClass(_T("CELLWinApp"), _hInstance);}/*** 初始化 OpenGLES2.0*/bool initOpenGLES20(){const EGLint attribs[] ={EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_BLUE_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_RED_SIZE, 8,EGL_DEPTH_SIZE, 24,EGL_NONE};EGLint format(0);EGLintnumConfigs(0);EGLint major;EGLint minor;//! 1_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);//! 2initeglInitialize(_display, &major, &minor);//! 3eglChooseConfig(_display, attribs, &_config, 1, &numConfigs);eglGetConfigAttrib(_display, _config, EGL_NATIVE_VISUAL_ID, &format);//! 4 _surface = eglCreateWindowSurface(_display, _config, _hWnd, NULL);//! 5EGLint attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };_context = eglCreateContext(_display, _config, 0, attr);//! 6if (eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE){return false;}eglQuerySurface(_display, _surface, EGL_WIDTH, &_width);eglQuerySurface(_display, _surface, EGL_HEIGHT, &_height);return true;}/*** 销毁OpenGLES2.0*/void destroyOpenGLES20(){if (_display != EGL_NO_DISPLAY){eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);if (_context != EGL_NO_CONTEXT){eglDestroyContext(_display, _context);}if (_surface != EGL_NO_SURFACE){eglDestroySurface(_display, _surface);}eglTerminate(_display);}_display = EGL_NO_DISPLAY;_context = EGL_NO_CONTEXT;_surface = EGL_NO_SURFACE;}virtual unsigned createTexture(int width, int height){unsigned textureId;glGenTextures(1, &textureId);glBindTexture(GL_TEXTURE_2D, textureId);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);return textureId;}virtual unsigned buildMipMap(char* fileNames[], int size){unsigned textureId = 0;/*** 产生一个纹理Id,可以认为是纹理句柄,后面的操作将书用这个纹理id*/glGenTextures(1, &textureId);/*** 使用这个纹理id,或者叫绑定(关联)*/glBindTexture(GL_TEXTURE_2D, textureId);/*** 指定纹理的放大,缩小滤波,使用线性方式,即当图片放大的时候插值方式*/glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);for (int i = 0; i < size; ++i){//1 获取图片格式FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileNames[i], 0);//2 加载图片FIBITMAP *dib = FreeImage_Load(fifmt, fileNames[i], 0);//3 转化为rgb 24色dib = FreeImage_ConvertTo24Bits(dib);//4 获取数据指针BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);int width = FreeImage_GetWidth(dib);int height = FreeImage_GetHeight(dib);for (int x = 0; x < width * height * 3; x += 3){BYTE temp = pixels[x];pixels[x] = pixels[x + 2];pixels[x + 2] = temp;}/*** 将图片的rgb数据上传给opengl.*/glTexImage2D(GL_TEXTURE_2D, //! 指定是二维图片i, //! 指定为第一级别,纹理可以做mipmap,即lod,离近的就采用级别大的,远则使用较小的纹理GL_RGB, //! 纹理的使用的存储格式width, //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。height, //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。0, //! 是否的边GL_RGB, //! 数据的格式,bmp中,windows,操作系统中存储的数据是bgr格式GL_UNSIGNED_BYTE, //! 数据是8bit数据pixels);FreeImage_Unload(dib);}return textureId;}virtual unsigned loadTexture(const char* fileName){unsigned textureId = 0;//1 获取图片格式FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);//2 加载图片FIBITMAP *dib = FreeImage_Load(fifmt, fileName, 0);int fmt = GL_RGB;//4 获取数据指针BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);int width = FreeImage_GetWidth(dib);int height = FreeImage_GetHeight(dib);if (fifmt == FIF_PNG){dib = FreeImage_ConvertTo32Bits(dib);fmt = GL_RGBA;for (int i = 0; i < width * height * 4; i += 4){BYTE temp = pixels[i];pixels[i] = pixels[i + 2];pixels[i + 2] = temp;}}else{//3 转化为rgb 24色dib = FreeImage_ConvertTo24Bits(dib);for (int i = 0; i < width * height * 3; i += 3){BYTE temp = pixels[i];pixels[i] = pixels[i + 2];pixels[i + 2] = temp;}}/*** 产生一个纹理Id,可以认为是纹理句柄,后面的操作将书用这个纹理id*/glGenTextures(1, &textureId);/*** 使用这个纹理id,或者叫绑定(关联)*/glBindTexture(GL_TEXTURE_2D, textureId);/*** 指定纹理的放大,缩小滤波,使用线性方式,即当图片放大的时候插值方式*/glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);/*** 将图片的rgb数据上传给opengl.*/glTexImage2D(GL_TEXTURE_2D, //! 指定是二维图片0, //! 指定为第一级别,纹理可以做mipmap,即lod,离近的就采用级别大的,远则使用较小的纹理fmt, //! 纹理的使用的存储格式width, //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。height, //! 宽度,老一点的显卡,不支持不规则的纹理,即宽度和高度不是2^n。0, //! 是否的边fmt, //! 数据的格式,bmp中,windows,操作系统中存储的数据是bgr格式GL_UNSIGNED_BYTE, //! 数据是8bit数据pixels);/*** 释放内存*/FreeImage_Unload(dib);return textureId;}protected:static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){CELLWinApp* pThis = (CELLWinApp*)GetWindowLong(hWnd, GWL_USERDATA);if (pThis){return pThis->onEvent(hWnd, msg, wParam, lParam);}if (WM_CREATE == msg){CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;SetWindowLong(hWnd, GWL_USERDATA, (DWORD_PTR)pCreate->lpCreateParams);}return DefWindowProc(hWnd, msg, wParam, lParam);}public:/*** 事件函数*/virtual LRESULT onEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){case WM_CLOSE:case WM_DESTROY:{::PostQuitMessage(0);}break;case WM_MOUSEMOVE:break;default:return DefWindowProc(hWnd, msg, wParam, lParam);}return S_OK;}virtual void render(){glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);glViewport(0, 0, _width, _width);_camera.updateCamera(0.016f);CELL::matrix4 matView = CELL::lookAt(_camera._eye, _camera._look, _camera._up);float x = 0;float y = 0;float w = 200;float h = 200;Vertex vertex[] ={{ x, y, 0, 0, 1, 1.0f, 1.0f, 1.0f, 1.0f },{ x + w, y, 0, 1, 1, 1.0f, 1.0f, 1.0f, 1.0f },{ x, y + h, 0, 0, 0, 1.0f, 1.0f, 1.0f, 1.0f },{ x + w, y + h, 0, 1, 0, 1.0f, 1.0f, 1.0f, 1.0f },};float gSize = 100;float gPos = -5;float rept = 100;Vertex grounds[] ={{ -gSize, gPos, -gSize, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ gSize, gPos, -gSize, rept, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ gSize, gPos, gSize, rept, rept, 1.0f, 1.0f, 1.0f, 1.0f },{ -gSize, gPos, -gSize, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ gSize, gPos, gSize, rept, rept, 1.0f, 1.0f, 1.0f, 1.0f },{ -gSize, gPos, gSize, 0.0f, rept, 1.0f, 1.0f, 1.0f, 1.0f },};_shader.begin();{CELL::matrix4 matWorld(1);CELL::matrix4 matProj = CELL::perspective(45.0f, (GLfloat)_width / (GLfloat)_height, 0.1f, 100.0f);CELL::matrix4 MVP = matProj * matView * matWorld;glUniform1i(_shader._texture, 0);//! 绘制地面glBindTexture(GL_TEXTURE_2D, _textureId);glUniformMatrix4fv(_shader._MVP, 1, false, MVP.data());glVertexAttribPointer(_shader._positionAttr, 3, GL_FLOAT, false, sizeof(Vertex), &grounds[0].x);glVertexAttribPointer(_shader._uvAttr, 2, GL_FLOAT, false, sizeof(Vertex), &grounds[0].u);glVertexAttribPointer(_shader._colorAttr, 4, GL_FLOAT, false, sizeof(Vertex), &grounds[0].r);glDrawArrays(GL_TRIANGLES, 0, sizeof(grounds) / sizeof(grounds[0]));CELL::matrix4 matRot;static float angle = 0;matRot.translate(0, 0, -1);angle += 1;CELL::matrix4 MVP1 = matProj * matView * matRot;//使用vbo绘制glBindTexture(GL_TEXTURE_2D, _texGrass);glBindBuffer(GL_ARRAY_BUFFER, _vbo);glUniformMatrix4fv(_shader._MVP, 1, false, MVP1.data());glVertexAttribPointer(_shader._positionAttr, 3, GL_FLOAT, false, sizeof(Vertex), (void*)0);//sizeof(Vertex) 偏移量:(void*)0 起始地址glVertexAttribPointer(_shader._uvAttr, 2, GL_FLOAT, false, sizeof(Vertex), (void*)12);// (void*)12 起始地址 每个float4个字节 每个顶点有3个float(x,y,z)glVertexAttribPointer(_shader._colorAttr, 4, GL_FLOAT, false, sizeof(Vertex), (void*)20);//12+8 三个位置坐标占12byte 两个纹理坐标占8byte 故颜色坐标的偏移量是20glDrawArrays(GL_TRIANGLES, 0, 6);//这步是必须的glBindBuffer(GL_ARRAY_BUFFER, 0);glBindTexture(GL_TEXTURE_2D, _texDynamic);glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, _width, _height);CELL::matrix4 screenProj = CELL::ortho<float>(0, float(_width), float(_height), 0, -100.0f, 100);glUniformMatrix4fv(_shader._MVP, 1, false, screenProj.data());glVertexAttribPointer(_shader._positionAttr, 3, GL_FLOAT, false, sizeof(Vertex), &vertex[0].x);glVertexAttribPointer(_shader._uvAttr, 2, GL_FLOAT, false, sizeof(Vertex), &vertex[0].u);glVertexAttribPointer(_shader._colorAttr, 4, GL_FLOAT, false, sizeof(Vertex), &vertex[0].r);glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(vertex) / sizeof(vertex[0]));}_shader.end();}/*** 主函数*/int main(int width, int height){_hWnd = CreateWindowEx(NULL,_T("CELLWinApp"),_T("CELLWinApp"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,width,height,NULL,NULL,_hInstance,this);if (_hWnd == 0){return -1;}UpdateWindow(_hWnd);ShowWindow(_hWnd, SW_SHOW);if (!initOpenGLES20()){return false;}glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_DEPTH_TEST);//Vertex vertexs[] =//{//{ -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },//{ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },//{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },//{ -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },//{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },//{ -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },//};Vertex vertexs[] ={{ -1.0f, -1.0f, -8.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, -1.0f, -8.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, -8.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, -1.0f, -8.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f, -8.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },{ -1.0f, 1.0f, -8.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },};/*为什么要使用vbo (顶点缓冲区):如果不使用vbo,要绘制物体的顶点信息需要从内存传递到显存,当绘制的模型比较复杂时,频繁的在内存和显存中做数据传递会降低效率。因此使用VBO,可以先把一部分顶点数据缓存起来,绘制的时候直接从缓存中获取,大大降低内存和显存之间数据拷贝的开销。*/glGenBuffers(1,&_vbo);//声明一个vboglBindBuffer(GL_ARRAY_BUFFER,_vbo);//指定buffer类型为顶点bufferglBufferData(GL_ARRAY_BUFFER,sizeof(vertexs),vertexs,GL_STATIC_DRAW);//将顶点数据拷贝到显存glBindBuffer(GL_ARRAY_BUFFER, 0);_shader.initialize();char* szName[] ={"Debug/data/image/tex33X32.bmp","Debug/data/image/tex16X16.bmp","Debug/data/image/tex8x8.bmp","Debug/data/image/tex4x4.bmp","Debug/data/image/tex2X2.bmp","Debug/data/image/tex1x1.bmp",};_textureId = buildMipMap(szName, 6);_texGrass = loadTexture("Debug/data/image/grass.png");_texDynamic = createTexture(_width, _height);_camera._eye = CELL::float3(1, 1, 5);_camera._look = CELL::float3(0.5f, -0.4f, -5.5f);_camera._up = CELL::float3(0.0f, 1.0f, 0.0f);_camera._right = CELL::float3(1.0f, 0.0f, 0.0f);MSG msg = { 0 };while (msg.message != WM_QUIT){if (msg.message == WM_DESTROY ||msg.message == WM_CLOSE){break;}/*** 有消息,处理消息,无消息,则进行渲染绘制*/if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}else{render();eglSwapBuffers(_display, _surface);}}/*** 销毁OpenGLES20*/destroyOpenGLES20();return 0;}};}
程序入口:
#include "CELLWinApp.hpp"int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow){UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(hInstance);UNREFERENCED_PARAMETER(lpCmdLine);UNREFERENCED_PARAMETER(nCmdShow);CELL::CELLWinApp app(hInstance);app.main(800, 600);return 0;}
完整代码下载地址:http://download.csdn.net/detail/hb707934728/9843449
阅读全文
0 0
- opengles中使用vbo(顶点缓冲区)
- opengles 使用VBO:顶点缓存
- OpenGL ES 3.0 顶点缓冲区VBO使用
- 顶点缓冲区VBO和索引缓冲区IBO的结合使用
- opengles中VBO和IBO结合使用
- OpenGL顶点缓冲区对象(VBO)
- GLES 顶点缓冲区对象(VBO)
- OpenGL顶点缓冲区对象(VBO)
- iOS --- OpenGLES之顶点缓存对象VBO
- 使用VBO:顶点缓存
- OpenGL ES 学习教程(五) 极速绘制,使用 VBO (顶点缓冲区对象)!
- OpenGL--顶点数组与缓冲区中使用顶点数组
- 4.OpenGL--顶点数组与缓冲区中使用顶点数组
- OpenGL系列教程之八:OpenGL顶点缓冲区对象(VBO)
- OpenGL系列教程之八:OpenGL顶点缓冲区对象(VBO)
- OpenGL VBO顶点缓冲的使用
- OpenGL VBO顶点缓冲的使用
- OpenGL VBO顶点缓冲的使用
- MySQL创建索引方法:ALTER TABLE和CREATE INDEX的区别
- android通知栏屏蔽访客模式
- (chrome)Adobe Flash 无法正常使用
- ijkPlayer编译流程记录
- python基础之map/reduce/filter/sorted
- opengles中使用vbo(顶点缓冲区)
- 设计模式之状态模式
- awk/sed-Exercise
- (42)触发器Actor
- 数据库中树结构数据,转换为Java对象树结构( 多叉树结构 )
- 单调,凹凸,极最拐,渐近线,曲率以及不等式的证明方法
- linux wc
- 查看mysql 占用空间
- python基础之面向对象02