(四)opengl绘制三角形

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事件 去更新界面 渲染颜色随窗口变动而改变 
	 
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值