qt opengl 64位配置

首先说明利用qt内置qopenglwidget窗口在64位下会出现显卡的一个dll报错,换成32位就没事,因此探索出下面的这种配置方式。
显卡DLL报错可以解决,在自己电脑上将opengl渲染改成独显,总之支持就行。
采用Qwindow类以及qt封装好的opengl上下文,渲染到窗口上,然后将这个窗口作为子窗口显示到mainwindow上。
渲染类://来自于网上一个OpenGL框架,但是其中的qt自带的shader类需要使用Qt的矩阵结构没法用glm了,我这里就自己写了个。

 //  "myrenderer.h"
   #pragma once
class IconRender : public QObject
{
	Q_OBJECT
public:
	IconRender(QSurfaceFormat & format, IconRender * share = 0, QScreen  * screen = 0);
	QSurfaceFormat format() const { return m_format; }

	void changequad( QUADS x);
	//缓存对象

	QOpenGLFunctions_3_3_Compatibility                                 * m_fun;
public slots:
	void Render(QSurface * surface, const QColor & color, const QSize & size);
private:
	unsigned int VBO2, VAO2;
	void Initialize();
	void Init_QUAD_VBO();
	void Draw_QUAD();
	void CompileShader(unsigned int *id, const char* vertexPath, const char* fragmentPath, const char* geometryPath = NULL);
private:
	//着色器程序ID
	unsigned int ID;
	bool                                                           m_bInitialized;
	QSurfaceFormat                                         m_format;
	QOpenGLContext                                     * m_context;
	QVector<QVector3D>                                m_quad_vertices;
	GLuint                                                        m_quad_vbo;

	GLuint                                                        m_MODEL_MATRIX_LOC;
	GLuint                                                        m_VIEW_MATRIX_LOC;
	GLuint                                                        m_PROJECTION_MATRIX_LOC;

	QMatrix4x4                                                 m_model_matrix;
	QMatrix4x4                                                 m_view_matrix;
	QMatrix4x4                                                 m_projection_matrix;
	QSize                                                          m_viewSize;
};

myRenderer.cpp//vbo绑定记得改

#include<IconRender.h>
#define W  180
#define H 150
IconRender::IconRender(QSurfaceFormat &format, IconRender *share, QScreen *screen)
	:m_bInitialized(false)
	, m_format(format)
	, m_context(0)
	, m_fun(0)

{
	m_context = new QOpenGLContext(this);
	if (screen)
	{
		m_context->setScreen(screen);
	}
	m_context->setFormat(format);
	if (share)
	{
		m_context->setShareContext(share->m_context);
	}
	m_context->create();
}

void IconRender::Render(QSurface * surface, const QColor & color, const QSize & viewSize)
{

	m_viewSize = surface->size();
	if (m_context == NULL)
	{
		return;
	}
	if (m_context->makeCurrent(surface) != true)
	{
		return;
	}
	if (m_bInitialized == false)
	{
		m_bInitialized = true;
		Initialize();
	}
	//resizeopengl
	_matProj = glm::perspective(glm::radians(45.0f), float(W) / float(H), 0.1f, 1000.0f);//使用glm数学库 根据公式计算得到投影矩阵  这公式可以推倒出来
	m_fun->glViewport(0, 0, surface->size().width(), surface->size().height());

	Draw_QUAD();
	m_context->swapBuffers(surface);
}
void IconRender::changequad( QUADS x)
{
	m_fun->glBindBuffer(GL_ARRAY_BUFFER, VBO2);
	m_fun->glBufferData(GL_ARRAY_BUFFER, x.g_cubeVertices.size() * sizeof(float) * 6, &(x.g_cubeVertices[0].x), GL_DYNAMIC_DRAW);
}
void IconRender::Initialize()
{
	m_fun = m_context->versionFunctions<QOpenGLFunctions_3_3_Compatibility>();
	m_fun->initializeOpenGLFunctions();//初始化函数
	Init_QUAD_VBO();


}

void IconRender::Init_QUAD_VBO()
{
	    m_fun->glEnable(GL_DEPTH_TEST);
		CompileShader(&ID, "texture.vs", "texture.fs");
		m_fun->glGenVertexArrays(1, &VAO2);
		m_fun->glGenBuffers(1, &VBO2);
		m_fun->glBindVertexArray(VAO2);
		m_fun->glBindBuffer(GL_ARRAY_BUFFER, VBO2);
		m_fun->glBufferData(GL_ARRAY_BUFFER, icon.g_cubeVertices.size() * sizeof(float) * 6, &(icon.g_cubeVertices[0].x), GL_DYNAMIC_DRAW);
		// 位置属性
		m_fun->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
		m_fun->glEnableVertexAttribArray(0);
		// 颜色属性
		m_fun->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
		m_fun->glEnableVertexAttribArray(1);
		//解除绑定VBO2
		m_fun->glBindBuffer(GL_ARRAY_BUFFER, 0);

		//解除绑定VAO2
		m_fun->glBindVertexArray(0);

}

void IconRender::Draw_QUAD()
{
	m_fun->glEnable(GL_DEPTH_TEST);
	m_fun->glEnableClientState(GL_VERTEX_ARRAY);
	m_fun->glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	m_fun->glClearColor(1, 1, 1, 1.0f);
	m_fun->glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	//激活着色器
	m_fun->glUseProgram(ID);
	glm::vec3 _iconeye(60, 60, 60);
	glm::vec3 _iconlookAt(-1, -1, -1);
	targetPo = _iconeye + _iconlookAt;
	_matView = glm::lookAt(_iconeye, targetPo, _up); //使用glm数学库 根据公式计算得到视图矩阵  这公式可以推倒出来
	glm::mat4 model = glm::mat4(1.0);
	glm::mat4 trans = glm::mat4(1.0f);//创建单位矩阵
	trans = glm::translate(trans, glm::vec3(-50.0, -50.0, -50.0));//先平移后旋转再缩放

	trans = _matView * trans;
	GLuint Uniform1 = m_fun->glGetUniformLocation(ID, "model");
	GLuint Uniform2 = m_fun->glGetUniformLocation(ID, "view");
	GLuint Uniform3 = m_fun->glGetUniformLocation(ID, "project");
	m_fun->glUniformMatrix4fv(Uniform1, 1, GL_FALSE, glm::value_ptr(model));
	m_fun->glUniformMatrix4fv(Uniform2, 1, GL_FALSE, glm::value_ptr(trans));
	m_fun->glUniformMatrix4fv(Uniform3, 1, GL_FALSE, glm::value_ptr(_matProj));

	m_fun->glMatrixMode(GL_TEXTURE);
	m_fun->glLoadIdentity();
	//绑定顶点缓存对象
	m_fun->glBindVertexArray(VAO2);
	//开始绘制
	m_fun->glUseProgram(ID);
	m_fun->glDrawArrays(GL_QUADS, 0, 24);

	//解除绑定
	m_fun->glBindVertexArray(0);


}



//加载着色器程序
void IconRender::CompileShader(unsigned int *id, const char* vertexPath, const char* fragmentPath, const char* geometryPath)
{
	std::string vertexCode;
	std::string fragmentCode;
	std::string geometryCode;
	std::ifstream vShaderFile;
	std::ifstream fShaderFile;
	std::ifstream gShaderFile;


	// 打开文件
	vShaderFile.open(vertexPath);
	fShaderFile.open(fragmentPath);
	std::stringstream vShaderStream, fShaderStream;
	// 读取文件的缓冲内容到数据流中
	vShaderStream << vShaderFile.rdbuf();
	fShaderStream << fShaderFile.rdbuf();
	// 关闭文件处理器
	vShaderFile.close();
	fShaderFile.close();
	// 转换数据流到string
	vertexCode = vShaderStream.str();
	fragmentCode = fShaderStream.str();

	if (geometryPath != NULL)
	{
		gShaderFile.open(geometryPath);
		std::stringstream gShaderStream;
		gShaderStream << gShaderFile.rdbuf();
		gShaderFile.close();
		geometryCode = gShaderStream.str();
	}

	const char* vShaderCode = vertexCode.c_str();
	const char* fShaderCode = fragmentCode.c_str();

	// 2. 编译着色器
	unsigned int vertex, fragment;
	int success;
	char infoLog[512];

	// 顶点着色器
	vertex = m_fun->glCreateShader(GL_VERTEX_SHADER);
	m_fun->glShaderSource(vertex, 1, &vShaderCode, NULL);
	//编译着色器
	m_fun->glCompileShader(vertex);
	//检测编译时错误
	m_fun->glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
	//如果编译错误进入语句
	if (!success)
	{
		//获取错误信息
		m_fun->glGetShaderInfoLog(vertex, 512, NULL, infoLog);
		//打印错误
		std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
	}


	//片元着色器
	fragment = m_fun->glCreateShader(GL_FRAGMENT_SHADER);
	m_fun->glShaderSource(fragment, 1, &fShaderCode, NULL);
	m_fun->glCompileShader(fragment);
	//检测错误
	m_fun->glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		//获取错误原因
		m_fun->glGetShaderInfoLog(fragment, 512, NULL, infoLog);
		//打印
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
	}

	//几何着色器
	unsigned int geometry;
	if (geometryPath != nullptr)
	{
		const char * gShaderCode = geometryCode.c_str();
		geometry = m_fun->glCreateShader(GL_GEOMETRY_SHADER);
		m_fun->glShaderSource(geometry, 1, &gShaderCode, NULL);
		m_fun->glCompileShader(geometry);
	}


	// 着色器程序
	*id = m_fun->glCreateProgram();
	m_fun->glAttachShader(*id, vertex);
	m_fun->glAttachShader(*id, fragment);
	if (geometryPath != nullptr)
		m_fun->glAttachShader(*id, geometry);
	m_fun->glLinkProgram(*id);
	//检测错误
	m_fun->glGetProgramiv(*id, GL_LINK_STATUS, &success);
	if (!success)
	{
		//获取错误信息
		m_fun->glGetProgramInfoLog(ID, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}

	// 删除着色器,它们已经链接到我们的程序中了,已经不再需要了
	m_fun->glDeleteShader(vertex);
	m_fun->glDeleteShader(fragment);
	if (geometryPath != nullptr)
		m_fun->glDeleteShader(geometry);
}
``//窗口类IconFram。h

#include <QWindow>
#include <QMouseEvent>
#include <QKeyEvent>
class IconFrame : public QWindow
{
	Q_OBJECT
public:
	IconFrame(const QSharedPointer<IconRender> & renderer);
	QSharedPointer<IconRender> m_iconRenderer;
	void exposeEvent(QExposeEvent *);

	void Render();
protected:
    void timerEvent(QTimerEvent *);
signals:
	void NeedRender(QSurface * surface, const QColor & color, const QSize & viewSize);
};

//窗口cpp
#include "   IconFram.h"
IconFrame::IconFrame(const QSharedPointer<IconRender> & renderer)
	:m_iconRenderer(renderer)
{
	setSurfaceType(QWindow::OpenGLSurface);
	setFormat(renderer->format());
	setGeometry(1500,80, 180,150);
	connect(this, SIGNAL(NeedRender(QSurface*, QColor, QSize)),
		renderer.data(), SLOT(Render(QSurface*, QColor, QSize)));
	 startTimer(50);
}
void IconFrame::Render()
{
	if (isExposed())
		emit NeedRender(this, QColor(0.0f, 0.0f, 0.0f, 1.0f), size());
}
void IconFrame::exposeEvent(QExposeEvent *)
{
	Render();
}
void IconFrame::timerEvent(QTimerEvent *)
{
    Render();
}
main文件加
	MainWindow w1;
	w1.show();	//qDebug() << "proc 1 window handle:" << w1.winId();
	QScreen * screen = QGuiApplication::primaryScreen();
	QSurfaceFormat format;
	format.setDepthBufferSize(16);
	format.setSamples(4);
	QSharedPointer<MyRenderer>renderer(new MyRenderer(format, 0, screen));
	IconFram w(renderer);
	//w1.wp = &w;
	WId proc1Window_HWND = WId(w1.winId()); //记下进程1的窗口句柄
		//TODO: 创建一个进程1的窗口代理
	QWindow* proc1Widow = QWindow::fromWinId(proc1Window_HWND);
	//TODO: 告诉w它的本地父窗口是proc1Window_HWND,这步务必要做不然w上的一些控件会出问题,比如qcombobox的下拉框可能会错位
	w.setProperty("_q_embedded_native_parent_handle", QVariant(proc1Window_HWND));
	iconwindow_1.setProperty("_q_embedded_native_parent_handle", QVariant(proc1Window_HWND))
	//TODO: 将进程1的窗口设置为w的父窗口(w嵌入到proc1的窗口中)
	w.winId();
	w.setParent(proc1Widow);
	//w.windowHandle()->setParent(proc1Widow);
	w.resize(1500,800);
	w.setPosition(0,130);
	w.show();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值