从源头看Dust3d | (十一)shadermesh:shader的生成

2021SC@SDUSC

目录

一、Shader介绍

二、在Dust3d中的渲染实现

(一)SimpleShaderMesh类

(二)类SimpleShaderMeshGenerator

1.takeRenderMesh

2.generate函数

 3.信号-槽机制


一、Shader介绍

      Shader(着色器),是用来实现图形渲染的,实现了图形渲染可以让模型的材质、光滑程度有更好的表现,能让模型在光照下显示出更真实的效果。目前渲染管线一般有两种,一种是固定渲染管线,另一种为可编程渲染管线,Dust3d中使用了可编程渲染管线对模型进行渲染。

      渲染管线:渲染管线实现的是将三维模型进行坐标转换、光照计算以及进行贴图,输出三维模型在摄像机下的样子,转换到屏幕空间进行输出。

      固定渲染管线:固定渲染管线分为三个阶段。

      第一个阶段是应用程序阶段,此阶段在CPU上进行,主要实现的是在视锥中进行可见性判断,将裁剪后的几何体及顶点坐标、法向量、纹理贴图坐标等传给GPU;

      第二个阶段是在GPU上进行的几何阶段,该阶段主要负责顶点坐标变换以及光照计算,坐标变换主要需要将三维空间坐标转换为二维平面坐标,光照计算是因为在现实生活中我们可以看到不同的材质对接收到的光照有不同的效果,有的会呈现漫反射效果,有的会呈现镜面反射效果,在此阶段的光照计算就是对物体在光照下呈现的效果的模拟;

      第三个阶段是光栅化处理,光栅化处理进行了着色运算和深度测试,计算每个像素点的颜色,实现了渲染。

      固定渲染管线就像是在渲染的各种方式上进行开关操作,通过不同的组合来实现不同的渲染效果。

 

      可编程渲染管线:可编程渲染管线正如它的名字,可以通过编程的方式来自定义光照的模式、贴图的方式等,有更高的自由度,同时也能实现比固定渲染管线更好的效果。

 

二、在Dust3d中的渲染实现

      通过向Dust3D中添加法线贴图、基本色、金属度等实现材质的改变,并将相关信息传输到渲染管线中进行渲染

 

(一)SimpleShaderMesh类

      SimpleShaderMesh类中设定了顶点信息、三角面片的信息以及法线的信息

class SimpleShaderMesh
{
public:
    SimpleShaderMesh(std::vector<QVector3D> *vertices,
            std::vector<std::vector<size_t>> *triangles,
            std::vector<std::vector<QVector3D>> *triangleCornerNormals) :
        m_vertices(vertices),
        m_triangles(triangles),
        m_triangleCornerNormals(triangleCornerNormals)
    {
    }
    
    SimpleShaderMesh(const SimpleShaderMesh &mesh)
    {
        if (nullptr != mesh.m_vertices)
            m_vertices = new std::vector<QVector3D>(*mesh.m_vertices);
        if (nullptr != mesh.m_triangles)
            m_triangles = new std::vector<std::vector<size_t>>(*mesh.m_triangles);
        if (nullptr != mesh.m_triangleCornerNormals)
            m_triangleCornerNormals = new std::vector<std::vector<QVector3D>>(*mesh.m_triangleCornerNormals);
    }
    
    ~SimpleShaderMesh()
    {
        delete m_vertices;
        delete m_triangles;
        delete m_triangleCornerNormals;
    }
    
    const std::vector<QVector3D> *vertices()
    {
        return m_vertices;
    }
    
    const std::vector<std::vector<size_t>> *triangles()
    {
        return m_triangles;
    }
    
    const std::vector<std::vector<QVector3D>> *triangleCornerNormals()
    {
        return m_triangleCornerNormals;
    }
    
private:
    std::vector<QVector3D> *m_vertices = nullptr;
    std::vector<std::vector<size_t>> *m_triangles = nullptr;
    std::vector<std::vector<QVector3D>> *m_triangleCornerNormals = nullptr;
};

(二)类SimpleShaderMeshGenerator

1.takeRenderMesh

      用于获取需要进行渲染的面片,通过上面的SimpleShaderMesh类可以得知renderMesh中携带着点、面以及法线信息

    SimpleShaderMesh *takeRenderMesh()
    {
        SimpleShaderMesh *renderMesh = m_renderMesh;
        m_renderMesh = nullptr;
        return renderMesh;
    }

2.generate函数

      根据顶点、面片以及发现信息生成SimpleShaderMesh;当没有法线信息的时候进行计算,其中triangleNormal是每个点对面的平面的单位法向量​​​​​​​

      normal(v1,v2,v3):求的是v3-v1、v2-v1所在平面的法向量

  

void SimpleRenderMeshGenerator::generate()
{
    if (nullptr == m_triangleCornerNormals ||
            m_triangleCornerNormals->empty()) {
        delete m_triangleCornerNormals;
        m_triangleCornerNormals = new std::vector<std::vector<QVector3D>>(m_triangles->size());
        for (size_t i = 0; i < m_triangles->size(); ++i) {
            const auto &triangle = (*m_triangles)[i];
            //normal(v1,v2,v3):求v2-v1、v3-v1所在平面的法向量
            QVector3D triangleNormal = QVector3D::normal(
                (*m_vertices)[triangle[0]],
                (*m_vertices)[triangle[1]],
                (*m_vertices)[triangle[2]]
            );
            (*m_triangleCornerNormals)[i] = {triangleNormal,
                triangleNormal, triangleNormal
            };
        }
    }
    delete m_renderMesh;
    m_renderMesh = new SimpleShaderMesh(m_vertices, m_triangles, m_triangleCornerNormals);
    m_vertices = nullptr;
    m_triangles = nullptr;
    m_triangleCornerNormals = nullptr;
}

 3.信号-槽机制

      信号函数:void finished();

      槽函数:void process();

      当接收到信号函数finished,就会触发process函数,执行generate函数,生成RenderMesh

void SimpleRenderMeshGenerator::process()
{
    generate();
    
    emit finished();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值