PBO 摄像机类的实现 第一人称第三人称的效果

这篇博客探讨了OpenGL中的Pixel Buffer Objects (PBO)技术,用于快速数据传输和读取,以及如何利用双PBO(乒乓技术)进行视频播放和录制的优化。同时,文章还介绍了摄像机类的实现,包括第一人称和第三人称视角的转换,以及通过键盘输入和滚轮控制的相机操作。
摘要由CSDN通过智能技术生成

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);
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值