Qt 3D的研究(七):渲染至纹理

Qt 3D的研究(七):渲染至纹理

最近几天都没有怎么研究Qt 3D了,但是随着Qt5.5发布的日子一天天的靠近,我也不能懈怠,希望利用Qt 3D,将能够实现的功能进行实现,并且对Qt3D获取一个新的认识。两天多没有研究了,现在信心却是满满的!

蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44156633。欢迎同行前来探讨。

Qt 3D还是在发展的过程中,也没有什么文档,所以有什么问题的话,只能去问库的作者了。我就在IRC频道上多次向Paul Lemire提问,并且得到了他的热情回答!这里表示深深的感谢!这几天的提问和回答,我了解了Qt 3D的使用方法,结合Qt 3D的一些例子,我实现了渲染到纹理的效果。

渲染到纹理的效果主要依赖于Frame Buffer Object(简称FBO)的支持。我花了一段时间研究FBO和PBO,发现他们还是不一样的,PBO感觉是为了暂存像素数据而提出的一个数据格式,FBO则类似于一个集线器,里面有很多插口,通过选用不同的插口,可以将渲染的结果存储至Render Target(连接屏幕)以及Texture(纹理)。这样一个早在OpenGL2.x就启用的功能,我也是只在Qt 3D上作第一次尝试,这次想要尝试的是渲染到纹理。

简而言之,就是对将要渲染的物体进行两遍渲染。第一遍是将模型渲染至纹理中,第二遍则是将该纹理显示在场景中。这样就达到了我们想要的效果。为什么需要两遍渲染而不是一遍就解决呢?因为如果我们需要对纹理做一些图像处理,并且显示出来,就有必要了。

下面看看我的运行结果吧!

这里使用了卡通渲染的方式进行渲染,并且为模型添加了边缘。其中卡通渲染这种方式渲染了两遍,第一遍保存在一个纹理中,第二遍则使用纹理提取边缘,并且将边缘和模型一起渲染。实现这样效果的qml代码如下所示:

import Qt3D 2.0
import Qt3D.Render 2.0

Entity
{
    id: root

    Camera
    {
        id: camera
        position: Qt.vector3d( 0.0, 0.0, -40.0 )
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 45
        aspectRatio: 16.0 / 9.0
        nearPlane : 0.1
        farPlane : 1000.0
        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
        viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
    }

    //! [7]
    Texture2D {
        id: colorAttachTex
        width: 1024
        height: 1024
        format: Texture.RGB8_UNorm
        generateMipMaps: false
        magnificationFilter: Texture.Nearest
        minificationFilter: Texture.Nearest
        wrapMode
        {
            x: WrapMode.ClampToEdge
            y: WrapMode.ClampToEdge
        }
    }

    Texture2D {
        id : depthAttachTex
        width: 1024
        height: 1024
        format: Texture.D32F
        generateMipMaps: false
        magnificationFilter: Texture.Nearest
        minificationFilter: Texture.Nearest
        wrapMode
        {
            x: WrapMode.ClampToEdge
            y: WrapMode.ClampToEdge
        }
    }
    //! [7]

    //! [8]
    components: FrameGraph
    {
        Viewport
        {
            rect: Qt.rect( 0.0, 0.0, 1.0, 1.0 )
            clearColor: Qt.rgba( 0.0, 0.4, 0.7, 1.0 )

            LayerFilter
            {
                layers: "scene"

                CameraSelector
                {
                    camera: camera

                    ClearBuffer
                    {
                        buffers: ClearBuffer.ColorDepthBuffer
                        RenderTargetSelector
                        {
                            target: RenderTarget
                            {
                                attachments:
                                [
                                    RenderAttachment
                                    {
                                        name: "colorAttachTex"
                                        type: RenderAttachment.ColorAttachment0
                                        texture: colorAttachTex
                                    },
                                    RenderAttachment
                                    {
                                        name : "depth"
                                        type : RenderAttachment.DepthAttachment
                                        texture : depthAttachTex
                                    }
                                ]
                            }
                        }
                    }
                }
            }

            ClearBuffer
            {
                buffers: ClearBuffer.ColorDepthBuffer
                CameraSelector
                {
                    camera: camera
                }
            }
        }
    }
    //! [8]

    Entity
    {
        Layer
        {
            id: sceneLayer
            names: "scene"
        }

        Mesh
        {
            id: mesh
            source: "qrc:/toyplane.obj"
        }

        Material
        {
            id: material
            effect: effect

            Effect
            {
                id: effect
                techniques: [ technique ]

                Technique
                {
                    id: technique
                    openGLFilter
                    {
                        api: OpenGLFilter.Desktop
                        profile: OpenGLFilter.None
                        majorVersion: 2
                        minorVersion: 0
                    }

                    parameters:
                    [
                        Parameter
                        {
                            name: "lightPosition"
                            value: camera.position
                        },
                        Parameter
                        {
                            name: "texPalette"
                            value: texPalette
                        }
                    ]

                    Texture2D
                    {
                        id: texPalette

                        TextureImage
                        {
                            source: "qrc:/discreetPalette.png"
                        }
                    }

                    renderPasses: [ grayMapPass ]
                    RenderPass
                    {
                        id: grayMapPass

                        shaderProgram: toonSP
                        ShaderProgram
                        {
                            id: toonSP
                            vertexShaderCode: loadSource( "qrc:/Toon.vert" )
                            fragmentShaderCode: loadSource( "qrc:/Toon.frag" )
                        }

//                        renderStates:
//                        [
//                            PolygonOffset { factor: 4; units: 4 },
//                            DepthTest { func: DepthTest.LessOrEqual }
//                        ]
                    }
                }
            }
        }

        components: [ sceneLayer, mesh, material ]
    }

    //! [9]
    Entity
    {
        Layer
        {
            id: screenLayer
            names: "screenQuad"
        }
        PlaneMesh
        {
            id: planeMesh
            width: 2.0
            height: 2.0
            meshResolution: Qt.size( 2, 2 )
        }
        Transform
        {
            id: planeTransform

            Rotate
            {
                axis : Qt.vector3d( 1.0, 0.0, 0.0 )
                angle : 90
            }
        }
        Material
        {
            id: planeMat

            effect: planeEffect

            Effect
            {
                id: planeEffect
                techniques: [ planeTech ]

                Technique
                {
                    id: planeTech

                    openGLFilter
                    {
                        api: OpenGLFilter.Desktop
                        profile: OpenGLFilter.None
                        majorVersion: 2
                        minorVersion: 0
                    }

                    parameters:
                    [
                        Parameter
                        {
                            name: "colorAttachTex"
                            value: colorAttachTex
                        },
                        Parameter
                        {
                            name: "texSize"
                            value : Qt.size( window.width,
                                            window.height )
                        },
                        Parameter
                        {
                            name: "texOffsetX"
                            value: 1.0 / colorAttachTex.width
                        },
                        Parameter
                        {
                            name: "texOffsetY"
                            value: 1.0 / colorAttachTex.height
                        }
                    ]

                    renderPasses: [ outputPass ]
                    RenderPass
                    {
                        id: outputPass

                        shaderProgram: outputSP
                        ShaderProgram
                        {
                            id: outputSP
                            vertexShaderCode: loadSource( "qrc:/Output.vert" )
                            fragmentShaderCode: loadSource( "qrc:/Output.frag" )
                        }

//                        renderStates:
//                        [
//                            PolygonOffset { factor: 4; units: 4 },
//                            DepthTest { func: DepthTest.Less }
//                        ]
                    }
                }
            }
        }

        components: [ screenLayer, planeMesh, planeTransform, planeMat ]
    }
    //! [9]

    Configuration
    {
        controlledCamera: camera
    }
}

我在代码的// ![7]部分,定义了两个纹理,这两个纹理表示了需要连接的部分,一部分是FBO连接的颜色部分,另外是FBO连接的深度部分。而在//![8]中,我们定义了一个含有Viewport、LayerFilter、CameraSelector、ClearBuffer、RenderTargetSelector的FrameGraph。FrameGraph是一个树状的组织结构,并且按照DFS的方式搜索,也就是说,代码块中最前面最深的部分最先得到执行。所以这个FrameGraph按照先设定render
attachment,接着清空缓冲区,再设定渲染层以及渲染的摄像机。在//! [9]的部分,我们再定义了一个纹理所在模型。这是一个矩形平面纹理,它覆盖我们摄像机的视口,这样我们第二遍渲染,就可以将我们提取的边缘覆盖到我们渲染的使用卡通渲染的模型上来了。

时间: 2024-10-14 22:28:10

Qt 3D的研究(七):渲染至纹理的相关文章

Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader

Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader 之前写了两篇文章,介绍了我在边缘检测上面的研究,实际上,使用GPU对渲染图像进行边缘检测,前提是需要进行两遍渲染,前一遍渲染的结果作为后一遍结果的输入纹理,接着在第二遍渲染的时候,对二维图像做一些图像处理,最终得出带轮廓的描边渲染效果,接着和正常渲染混合在一起,就成为渲染的最终图像.可是,这样的做法,是对二维图像做的图像处理,即使像上次对提取的深度进行图像处理,也无法准确地根据深度的突变来提取我们需要的边缘.所以

Qt 3D的研究(五):Gooch Shader

Qt 3D的研究(五):Gooch Shader Qt 3D的一个很大的优势就是采用数据驱动的方式,将C++和GLSL使用QML来表示,动态语言的优势尽显.在上一次的研究中,我实现了一个非常简单的着色器,接下来,我们可以在此基础上,通过设定着色器的数据,制作出更加绚丽的着色效果.作为开始,我们先从几个非真实渲染(Non-Photorealistic Rendering,NPR)开始吧. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/deta

Qt 3D的研究(八):边缘检测

Qt 3D的研究(八):边缘检测 上一篇文章讲到了如何使用渲染至纹理技术将我们第一遍渲染保存至纹理以便做一些操作.还是上一次的例子,我简要地分析一下如何进行边缘检测. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44194475.欢迎同行前来探讨. 还是上次的图片: 我们这里做了两遍渲染.第一遍渲染使用卡通渲染的方法执行,如下: 有关第一遍卡通渲染的着色器代码,可以参考我以前写的一篇文章.接下来,我们通过渲染至纹理技术,将

Qt 3D的研究(六):Toon Shader

Qt 3D的研究(六):Toon Shader 在上次的实验中,我们实现了Gooch Shader,并给出了通过调色板进行个性化的Gooch Shader设置.Toon Shader又称Cell Shader,是以离散的颜色来表示光照的强弱.很多动画片的渲染方式都是使用Toon Shader的.下面这样图就可以使用Toon Shader实现. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44084021.欢迎同行前来探讨.

Qt 3D的研究(九):尝试另外一种边缘检测方法

Qt 3D的研究(九):尝试另外一种边缘检测方法 三维应用程序,通过FBO,将3D图像渲染成纹理,然后对渲染成的纹理进行图像处理,最终显示在屏幕上的,是风格化后的图案.上一次我使用了一种普通的图像处理方法:索贝尔边缘检测法,与我们的卡通渲染结合起来,实现了这样的效果,接着,我将采用另外一种边缘检测方法--普雷维特(Prewitt)边缘检测方法来重新渲染图案. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44405219.欢

Qt 3D的研究(二)

上一篇文章给大家看了很多Qt 3D的例子,如果大家有Qt 3D的源代码,就会发现,开发这些例子,花费的代码还真不少.这就是不一样的地方,Qt 3D毕竟和三维图形打交道,多了一个维度,问题的难度变得更大了. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/43801957.欢迎同行前来探讨. 研究了多日的Qt 3D,我了解到为了适应跨平台.不同的着色器编译器标准.多重渲染目标,Qt 3D提出了很多的方案,创新了许多的概念,这多多

Qt 3D的研究(一)

Qt3D的研究(一) Qt 3D是有可能即将在Qt 5.5中正式启用的模块之一.它建立的目标是能够让开发者快速地创建3D场景,通过各式各样的渲染技术来达到3D交互的场景.Qt3D除了和Qt一样跨平台之外,还能够选择OpenGL的具体实现,定制GLSL,从而能够根据不同性能的机器,来调整渲染效果. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/43800383.欢迎同行前来探讨. Qt 3D在Qt 5.2的时候就传言即将登场了

Qt 3D研究(三):显示3D模型

Qt 3D研究(三):显示3D模型 上一篇文章介绍了如何使用最少的代码创建一个Qt 3D的应用.和大家最初接触的glut一样,对于3D应用来说,需要做的准备工作还真不少,不过呢,Qt 3D把一些窗口相关的琐碎事情解决了,剩下的,该由我们完成重要的渲染部分了,可以说,带来了某种程度的方便. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/43964499.欢迎同行前来探讨. 我们接下来要使用Qt 3D将一个模型显示出来.Qt 3

NeHe OpenGL教程 第三十六课:从渲染到纹理

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第三十六课:从渲染到纹理 放射模糊和渲染到纹理: 如何实现放射状的滤镜效果呢,看上去很难,其实很简单.把渲染得图像作为纹理提取出来,在利用OpenGL本身自带的纹理过滤,就能实现这种效果,不信,你试试. 嗨,我是Dario Corn