在QOpenGLWidget()中实现阴影效果
发布时间:2024-01-02 10:12:01
在QOpenGLWidget中实现阴影效果可以使用阴影贴图(Shadow Mapping)的方法。阴影贴图是一种实时计算阴影的技术,它通过渲染场景的深度信息到一个纹理中,然后在渲染阴影时使用这个纹理进行比较,从而判断哪些片元处于阴影之中。
以下是一个简单的例子,演示了如何在QOpenGLWidget中实现阴影效果:
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
class ShadowWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
ShadowWidget(QWidget *parent = nullptr)
: QOpenGLWidget(parent)
{
}
protected:
void initializeGL() override
{
initializeOpenGLFunctions();
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
// 创建和编译顶点着色器和片段着色器
m_shadowShaderProgram = new QOpenGLShaderProgram;
m_shadowShaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, "vertex_shader.glsl");
m_shadowShaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, "fragment_shader.glsl");
m_shadowShaderProgram->link();
// 创建纹理
m_shadowMapTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
m_shadowMapTexture->create();
m_shadowMapTexture->setSize(width(), height());
m_shadowMapTexture->setFormat(QOpenGLTexture::D16);
m_shadowMapTexture->setMinMagFilters(QOpenGLTexture::Nearest, QOpenGLTexture::Nearest);
m_shadowMapTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
// 创建渲染缓冲对象
m_depthRenderBuffer = new QOpenGLFramebufferObject(width(), height(), QOpenGLFramebufferObject::Depth);
// 将纹理和渲染缓冲对象绑定到帧缓冲对象
m_fbo = new QOpenGLFramebufferObject(width(), height());
m_fbo->bind();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_shadowMapTexture->textureId(), 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderBuffer->handle());
m_fbo->release();
}
void resizeGL(int width, int height) override
{
m_fbo->bind();
m_shadowMapTexture->setSize(width, height);
m_depthRenderBuffer->setSize(width, height);
m_fbo->release();
}
void paintGL() override
{
// 渲染场景到阴影贴图
m_fbo->bind();
glViewport(0, 0, width(), height());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_shadowShaderProgram->bind();
// 将阴影贴图传递给片段着色器
m_shadowShaderProgram->setUniformValue("shadowMap", 0);
// 渲染场景
m_shadowShaderProgram->release();
m_fbo->release();
// 渲染正常场景
glViewport(0, 0, width(), height());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 渲染物体
// 渲染阴影
m_shadowShaderProgram->bind();
// 使用阴影贴图进行渲染
m_shadowMapTexture->bind();
// 渲染阴影
m_shadowMapTexture->release();
m_shadowShaderProgram->release();
}
private:
QOpenGLShaderProgram *m_shadowShaderProgram;
QOpenGLTexture *m_shadowMapTexture;
QOpenGLFramebufferObject *m_fbo;
QOpenGLFramebufferObject *m_depthRenderBuffer;
};
上述代码中,ShadowWidget是继承自QOpenGLWidget的自定义类。在initializeGL()函数中,我们进行了OpenGL的初始化工作,包括初始化函数指针、启用深度测试、启用光照、创建和编译着色器、创建纹理和渲染缓冲对象等。
在paintGL()函数中,我们首先通过绑定帧缓冲对象,将场景渲染到阴影贴图上。然后,我们渲染正常的场景,并将阴影贴图传递给片段着色器。最后,我们再次渲染阴影,使用阴影贴图进行渲染。
需要注意的是,上述代码中使用到了vertex_shader.glsl和fragment_shader.glsl两个着色器文件,你需要根据自己的场景和需求来编写这两个着色器文件。
以上就是在QOpenGLWidget中实现阴影效果的一个简单示例。当然,实际应用中还会涉及到更多的细节和优化,如深度偏移、阴影边缘柔化等。但是通过这个示例,你可以了解到如何在QOpenGLWidget中使用阴影贴图来实现阴影效果。
