main.cpp
#include "qtvideorender.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtVideoRender w;
w.show();
return a.exec();
}
/*
二:opengl 渲染管线
3D图标转换成 平面 有色2D像素输出
贴图纹理信息 法线信息
(1)顶点数据 ---》(2)顶点着色器-GLSL---》(3)形状图元----》
(4)几何着色器 加点架线--》》(5)光栅化-----矢量图转位图》(6)片段着色器---》(7)测试与混合
开始 不要深扣 邓学到一定程度 再回来看看 就会有更多的理解和体会
VBO:显存缓存区
VAO:
第一步:编译着色器
第二步:对源码编译 然后 链接成程序 工作只做一次 就可以了 以后就可以复制粘贴了
*/
QtRender.h:
#pragma once
#include <QtWidgets/QWidget>
#include "ui_qtvideorender.h"
#include"GL\eglew.h"
#include"Windows.h"
//#include<windows.h>
#include <QResizeEvent>
class QtVideoRender : public QWidget
{
Q_OBJECT
public:
QtVideoRender(QWidget *parent = nullptr);
~QtVideoRender();
virtual QPaintEngine* paintEngine() const { return NULL; }
virtual void resizeEvent(QResizeEvent* event);
//更新界面绘制
void GLUpdate();
private:
bool createGLContext();
void render();
bool event(QEvent* event);
void initializeGL();
//编译着色器
GLuint CompileShader(GLenum shaderType, const char* url);
//链接着色器
GLuint CreateGPUProgram(const char* vs, const char* fs);
private:
Ui::QtVideoRenderClass ui;
private:
HDC dc;
//设备上下文
HGLRC rc;//opengl上下文 也是渲染上下文
HWND hwnd;//windows窗口句柄
float vertices[9] = {
0.0f,0.5f,0.0f,
-0.5f,-0.5f,0.0f,
0.5f,-0.5f,0.0f
};
GLuint VBO, VAO;
float vertices2[9] = {
0.9f,0.9f,0.0f,
0.7f,0.7f,0.0f,
0.9f,0.7f,0.0f
};
GLuint VBO2, VAO2;
};
qtrender.cpp:
#include "qtvideorender.h"
#include <assert.h>
//
#pragma comment(lib,"glew32.lib")
#pragma comment(lib,"opengl32.lib")
#include"QtEvent.h"
#include "GLTool.h"
QtVideoRender::QtVideoRender(QWidget *parent)
: QWidget(parent,Qt::MSWindowsOwnDC)
//Qt::MSWindowsOwnDC 使用自己的pc
{
//1.
setAttribute(Qt::WA_PaintOnScreen);
//绘制到屏幕 就不能使用qt默认的了 的绘制就不能用了 ;已经手动实现paintEngine() 这个函数
setAttribute(Qt::WA_NoSystemBackground);//无系统背景
setAutoFillBackground(true);//自动填充
ui.setupUi(this);
//2.
hwnd = (HWND)winId();
bool sucess=createGLContext();
//
wglMakeCurrent(dc, rc);
assert(glewInit() == GLEW_OK);
QApplication::postEvent(this, new QtEvent(QtEvent::GL_Renderer));
//这里怎么初始化的??
initializeGL();
}
QtVideoRender::~QtVideoRender()
{
wglMakeCurrent(NULL, NULL);
if (rc)
{
wglDeleteContext(rc);
}
if (dc)
{
ReleaseDC(hwnd, dc);
}
}
//2.
void QtVideoRender::resizeEvent(QResizeEvent* event)
{
glViewport(0, 0, event->size().width(), event->size().height());
GLUpdate();
}
void QtVideoRender::GLUpdate()
{
QApplication::postEvent(this, new QtEvent(QtEvent::GL_Renderer));
}
bool QtVideoRender::createGLContext()
{
//获取设备上下文
dc = GetDC(hwnd);
//概念:深度缓冲 模板缓冲区位深
PIXELFORMATDESCRIPTOR pfd;//???结构体
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
//指定结构体版本号,设置为1
pfd.nVersion = 1;
//rgba 4个字节
pfd.cColorBits = 32;
//设置深度缓冲 空间物体 对于眼睛有距离 记录这些点的层次
pfd.cDepthBits = 24;
//设置模板缓冲区位深 :屏幕上的像素点保留一个无符号的整形
pfd.cStencilBits = 8;
//设置像素类型
pfd.iPixelType = PFD_TYPE_RGBA;
//可以绘制到窗口
// 第三个参数设置双缓冲 机制 有两张图 一个前一个后 前面显示,后面绘画 绘画完了 放在前面 显示放在后面 开始绘画 绘画完了 放在前面 两者交替循环
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
int format = 0;
format = ChoosePixelFormat(dc, &pfd);
if (!format)
{
throw;//实际开发不是这么做
//return false;
}
SetPixelFormat(dc, format, &pfd);
//opengl上下文
rc = wglCreateContext(dc);
return true;
}
bool QtVideoRender::event(QEvent* event)
{
if (event->type() == QtEvent::GL_Renderer)
{
//进行渲染
render();
}
return QWidget::event(event);
}
#include <QDebug>
void QtVideoRender::initializeGL()
{
//CompileShader(GL_VERTEX_SHADER, "assets/vertextShader.glsl");
//CompileShader(GL_FRAGMENT_SHADER, "assets/fragmentShader.glsl");
qDebug() << 111;
GLuint program = CreateGPUProgram("F:/Work2025/Two/VideoRender/bin/assets/vertextShader.glsl",
"F:/Work2025/Two/VideoRender/bin/assets/fragmentShader.glsl");
//测试加的
glUseProgram(program);
GLint posLocation = glGetAttribLocation(program, "pos");
//把内存转到显存
glGenBuffers(
1,//创建VBO的个数
&VBO
);
//绑定
glBindBuffer(GL_ARRAY_BUFFER, VBO);
int size = sizeof(vertices);
//把数据丢给显存
glBufferData(
GL_ARRAY_BUFFER,//缓冲类型
size,//数据的大小
vertices,//顶点数据
GL_STATIC_DRAW
);
//GL_STATIC_DRAW //数据几乎不会改变
//GL_DYNAMIC_DRAW 数据可能会改变
//GL_STREAM_DRAW 每次绘制数据都会发生改变
//启用顶点属性
glEnableVertexAttribArray(posLocation);
glVertexAttribPointer(
posLocation,//顶点属性ID
3,//几个数据构成一组
GL_FLOAT,//数据类型
GL_FALSE,//是否标准化处理
sizeof(float) * 3,//步长 第一组数据和第二组数据差多少
(void*)(sizeof(float) * 0)//偏移量 第一组数据的起始位置
);
//解绑
glBindBuffer(GL_ARRAY_BUFFER, 0);
assert(!glGetError());
/*
//GLuint program = CreateGPUProgram("assets/vertexShader.glsl", "assets/fragmentShader.glsl");
*/
}
GLuint QtVideoRender::CompileShader(GLenum shaderType, const char* url)
{
char* shaderCode = LoadFileContext(url);
//为了方彪找出哪个着色器出错的
const char* shaderTypeStr= "Vertex Shader";
//创建着色器
GLuint shader = glCreateShader(shaderType);
qDebug() << 222;//这块 着色器 创建有问题 是和机器电脑有关系吗 可以当个有通用的 opengl
if (shaderType == GL_FRAGMENT_SHADER)
{
shaderTypeStr = "Fragment Shader";
}
if (!shader)
{
throw;
}
//源码和shader关联
glShaderSource(shader, 1, &shaderCode, NULL);
glCompileShader(shader);
GLint success = GL_TRUE;
//获取编译的状态
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
char infolog[1024];
GLsizei logLen = 0;
glGetShaderInfoLog(shader, sizeof(infolog), &logLen, infolog);
printf("error compile %s shader error: %s",shaderTypeStr,infolog);
glDeleteShader(shader);
throw;
}
printf("compile success");
delete shaderCode;
return shader;
}
GLuint QtVideoRender::CreateGPUProgram(const char* vs, const char* fs)
{
GLuint vsShader=CompileShader(GL_VERTEX_SHADER, vs);
GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER, fs);
//创建
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vsShader);
glAttachShader(shaderProgram, fsShader);
glLinkProgram(shaderProgram);
GLint success = GL_TRUE;
glGetProgramiv(shaderProgram, GL_COMPILE_STATUS, &success);
if (!success)
{
char infolog[1024];
GLsizei logLen = 0;
glGetShaderInfoLog(shaderProgram, sizeof(infolog), &logLen, infolog);
printf("error Link shader error: %s", infolog);
glDeleteShader(shaderProgram);
throw;
}
printf("Line shader program success\n");
glDetachShader(shaderProgram, vsShader);
glDetachShader(shaderProgram, fsShader);
glDeleteShader(vsShader);
glDeleteShader(fsShader);
return shaderProgram;
}
void QtVideoRender::render()
{
//glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*
static float redv = 0;
redv += 0.01;
if (redv > 1)redv = 0;
glClearColor(redv, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(dc);
*/
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//绘制模式 0 号顶点 绘制三个顶点
glDrawArrays(GL_TRIANGLES, 0, 3);
SwapBuffers(dc);
}
/*
Qt::MSWindowsOwnDC:
一:
实验 :
(1)显示窗口 是白色的
1.注意 平台的字节设置 是unicode 还是多字节的 根据平台选择 不然 导致错误
rc = wglCreateContext(dc);这一步会中断掉 这个问题不是错误 而是忽视 ,有时候忽视细节 会导致问题无法解决
从而花一大把时间去 查找不是问题的问题 ,最后这种经验算不算一种收获 也是值得深思的
(2)在窗口绘制颜色
(3)改变窗口大小 发现 渲染区域不改变
就实现 resize事件 去更新界面 渲染颜色随窗口变动而改变
*/