PBO
快速向显卡传输 读取数据
读取数据
声明 pbo
创建一个 pbo对象 glGenBuffers(1,&_pbo);
绑定
glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo); //从显卡读取数据
glBufferData(GL_PIXEL_PACK_BUFFER,_width*_height*4,0,GL_STREAM_READ);
glBindBuffer(GL_PIXEL_PACK_BUFFER,0); //回复状态
绘制完主窗口读取数据
//DMA控制器
glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo); //开始使用pbo
glReadPixels //读取显存数据到pbo
//数据映射到内存
void* data = glMapBuffer(GL_PIXEL_PACK_BUFFER,GL_READ_ONLY);
if (data)
{
save(_width,_height,(char*)data,_width * _height * 4);
}
glUnmapBuffer(GL_PIXEL_PACK_BUFFER); //取消映射
双pbo技术 乒乓球技术
glReadBuffer(GL_FRONT)//指定读取前后缓冲区
创建两个pbo 防止读取 映射之间等待 两个pbo进行交替操作
//! DMA
glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo[_DMA]);
glReadPixels(0,0,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,0);
glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo[_READ]);
void* data = glMapBuffer(GL_PIXEL_PACK_BUFFER,GL_READ_ONLY);
if (data)
{
//save(_width,_height,(char*)data,_width * _height * 4);
}
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
std::swap(_DMA,_READ);
内存写到显卡 Unpack
纹理的加载更新 上传不消耗cpu时间 消耗的是DMA
动态更新buffer
void updateBuffer(int w,int h,unsigned char* data)
{
int* iData = (int*)data;
for (int i = 0 ;i < w * h; ++ i)
{
iData[i] = rand();
}
}
创建两个pbo
glGenBuffers(2,_pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[0]);
glBufferData(GL_PIXEL_UNPACK_BUFFER,_width * _height * 4,0,GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[1]);
glBufferData(GL_PIXEL_UNPACK_BUFFER,_width * _height * 4,0,GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0);
_dynamicTex = createTexture(_width,_height,0,GL_RGBA);
更新纹理
纹理数据从pbo通过DMA传送到纹理
glBindTexture(GL_TEXTURE_2D,_dynamicTex);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[_DMA]);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[_WRITE]);
void* data = glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY);
if (data)
{
updateBuffer(_width,_height,(unsigned char*)data);
}
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0);
renderCube(_dynamicTex,true);
std::swap(_DMA,_WRITE);
优化手段总结:
FBO 离屏渲染画中画 opengl版本高
PBO 视频播放
双PBO 视频录制
低版本高效画中画
virtual void render(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
renderCube(_texture,true);
glBindTexture(GL_TEXTURE_2D,_dynamicTex);
glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,_width,_height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清掉显存
renderCube(_dynamicTex,false);
}
摄像机
opengl中只有模型矩阵 跟投影矩阵 相机变换通过glLookAt中传入对应的参数构建相机矩阵变换
对相机操作 可以实现物体旋转等操作
对lookAt参数进行修改
static float angle = 0;
float r=10;
_eye.x = cos(angle*M_PI/180)*r;
_eye.z = sin(angle*M_PI/180)*r;
angle +=0.1f;
gluLookAt(_eye.x,_eye.y,_eye.z,_lookAt.x,_lookAt.y,_lookAt.z,0,1,0);
键盘输入对相机位置进行修改
virtual LRESULT events(HWND hWnd,UINT msgId, WPARAM wParam, LPARAM lParam)
{
switch (msgId)
{
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_LEFT:
_eye.x += 1.0f;
break;
case VK_RIGHT:
_eye.x -= 1.0f;
break;
case VK_UP:
_eye.z -= 0.1f;
break;
case VK_DOWN:
_eye.z += 0.1f;
break;
}
}
break;
}
return __super::events(hWnd,msgId,wParam,lParam);
}
创建一个地平面
增加一个纹理id 创建绘制
glBindTexture(GL_TEXTURE_2D,_texGround);
glLoadIdentity();
glDrawArrays(GL_QUADS,24,4);
#include <windows.h>
#include <tchar.h>
#include <math.h>
#include "FreeImage.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;
struct Vertex
{
float x, y, z;
float u, v;
};
class SamplerTexture :public OpenGLWindow
{
GLuint _texture;
GLuint _texGround;
float3 _eye;
float3 _lookAt;
public:
SamplerTexture()
{
_eye = float3(0,0,10);
_lookAt = float3(0,0,0);
}
unsigned createTextureFromImage(const char* fileName)
{
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
if (fifmt == FIF_UNKNOWN)
{
return 0;
}
FIBITMAP *dib = FreeImage_Load(fifmt, fileName,0);
FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);
FIBITMAP* temp = dib;
dib = FreeImage_ConvertTo32Bits(dib);
FreeImage_Unload(temp);
BYTE* pixels = (BYTE*)FreeImage_GetBits(dib);
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
for (int i = 0 ;i < width * height * 4 ; i+=4 )
{
BYTE temp = pixels[i];
pixels[i] = pixels[i + 2];
pixels[i + 2] = temp;
}
unsigned res = createTexture(width,height,pixels);
FreeImage_Unload(dib);
return res;
}
unsigned createTexture(int w,int h,const void* data)
{
unsigned texId;
glGenTextures(1,&texId);
glBindTexture(GL_TEXTURE_2D,texId);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);
return texId;
}
virtual void onInitGL()
{
_texture = createTextureFromImage("2.jpg");
_texGround = createTextureFromImage("1.jpg");
}
virtual void render()
{
#define M_PI (3.14159265358979323846)
glMatrixMode(GL_PROJECTION);