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

來源:互聯網
上載者:User

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

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

       Qt 3D的一個很大的優勢就是採用資料驅動的方式,將C++和GLSL使用QML來表示,動態語言的優勢盡顯。在上一次的研究中,我實現了一個非常簡單的著色器,接下來,我們可以在此基礎上,通過設定著色器的資料,製作出更加絢麗的著色效果。作為開始,我們先從幾個非真實渲染(Non-Photorealistic Rendering,NPR)開始吧。

蔣彩陽原創文章,首發地址:http://blog.csdn.net/gamesdev/article/details/44007495。歡迎同行前來探討。

       首先我們開始研究Gooch著色器。Gooch著色器是Phong著色器的一個變種,一般用於技術插圖中,比如說下面這張插圖的效果就可以使用Gooch著色器完成。


       接下來我們將上一篇文章的QML代碼稍微修改一下,以支援我們的Gooch著色器。下面是新增的代碼:

import Qt3D 2.0import Qt3D.Render 2.0Entity{    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 )    }    components: FrameGraph    {        ForwardRenderer        {            clearColor: Qt.rgba( 1.0, 0.8, 0.2, 1 )            camera: camera        }    }    Entity    {        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                    }                    renderPasses: [ renderPass ]                    //! [5]                    parameters:                    [                        Parameter                        {                            name: "lightPosition"                            value: camera.position                        },                        Parameter                        {                            name: "surfaceColor"                            value: Qt.rgba( 0.9, 0.9, 0.9, 1 )                        },                        Parameter                        {                            name: "warmColor"                            value: Qt.rgba( 0.8, 0.3, 0.0, 1 )                        },                        Parameter                        {                            name: "coolColor"                            value: Qt.rgba( 0.0, 0.3, 0.2, 1 )                        },                        Parameter                        {                            name: "diffuseWarm"                            value: 0.4                        },                        Parameter                        {                            name: "diffuseCool"                            value: 0.6                        }                    ]                    //! [5]                    RenderPass                    {                        id: renderPass                        shaderProgram: goochSP                        ShaderProgram                        {                            id: goochSP                            vertexShaderCode: loadSource( "qrc:/Gooch.vert" )                            fragmentShaderCode: loadSource( "qrc:/Gooch.frag" )                        }                    }                }            }        }        components: [ mesh, material ]    }    Configuration    {        controlledCamera: camera    }}

       在//! [5]中我們定義了一些需要傳入的參數。它們是lightPosition、surfaceColor、warmColor、coolColor、diffuseWarm和diffuseCool。這些是要在著色器中定義的uniform參數,所以我們必須要在QML中顯示地指定它。其實Parameter定義在哪裡,Qt 3D是有講究的。Qt 3D是這樣一個規律:Parameter定義在外層的,會覆蓋在內層的同名Parameter,也就是說,內層的Parameter作為一個預設的參數,可以通過外層的Parameter進行修改。目前,Qt3D的覆蓋優先順序是:Material→Effect→Technique→RenderPass→GLSL預設值。

       介紹完了這些,讓我們看看GLSL是如何的吧。


// Gooch.vert#version 100// Qt 3D預設提供的參數attribute vec3 vertexPosition;attribute vec3 vertexNormal;uniform mat4 modelView;uniform mat4 modelNormalMatrix;uniform mat4 mvp;// 自己提供的參數uniform vec3 lightPosition;varying vec3 reflectVec;varying vec3 viewVec;varying float NdotL;void main( void ){    vec3 ecPos = ( modelView * vec4( vertexPosition, 1.0 ) ).xyz;    vec3 normal = normalize( modelNormalMatrix * vec4( vertexNormal, 1.0 ) ).xyz;    vec3 lightVec = normalize( lightPosition - ecPos );    reflectVec = normalize( reflect( -lightVec, normal ) );    viewVec = normalize( -ecPos );    NdotL = ( dot( lightVec, normal ) + 1.0 ) * 0.5;    gl_Position = mvp * vec4( vertexPosition, 1.0 );}


       頂點著色器中我們仍然像Phong光照模型一樣,求出NdotL,在片斷著色器中使用;然後我們算出reflectVec,和viewVec,作為反射和視向量的單位向量,留到片斷著色器中使用。


// Gooch.frag#version 100// 自己提供的參數uniform vec3 surfaceColor;uniform vec3 warmColor;uniform vec3 coolColor;uniform float diffuseWarm;uniform float diffuseCool;varying vec3 reflectVec;varying vec3 viewVec;varying float NdotL;void main( void ){    vec3 kcool    = min( coolColor + diffuseCool * surfaceColor, 1.0 );    vec3 kwarm    = min( warmColor + diffuseWarm * surfaceColor, 1.0 );    vec3 kfinal   = mix( kcool, kwarm, NdotL );    float spec = max( dot( reflectVec, viewVec ), 0.0 );    spec = pow( spec, 32.0 );    gl_FragColor = vec4( min( kfinal + spec, 1.0 ), 1.0 );}


在片斷著色器中,我們定義了平面顏色、暖色調顏色、冷色調顏色以及他們相應的參數。這些參數需要我們通過mix函數(線性插值函數)最終得出基本的顏色,緊接著我們計算鏡面反射光,讓模型飛機具有光澤效果,最後將這些值添加起來,得到的是片斷顏色。

       示範程式如下:

       嗯,通過調節參數來擷取更好的效果,不過呢,更好的方法是定義一個顏色版紋理來得到一些更有趣的渲染效果:

       方法是:首先我們定義一個顏色調色版的紋理:

       然後在QML中添加這樣一個參數以及相應的紋理對象:

 

parameters:[Parameter{name: "lightPosition"value: camera.position},Parameter{name: "surfaceColor"value: Qt.rgba( 0.9, 0.9, 0.9, 1 )},Parameter{name: "warmColor"value: Qt.rgba( 0.8, 0.3, 0.0, 1 )},Parameter{name: "coolColor"value: Qt.rgba( 0.0, 0.3, 0.2, 1 )},Parameter{name: "diffuseWarm"value: 0.4},Parameter{name: "diffuseCool"value: 0.6},//! [6]Parameter{name: "texPalette"value: texPalette}]Texture2D{id: texPaletteTextureImage{source: "qrc:/texturePalette.png"}}//! [6]

       這裡定義了Texture2D類以及TextureImage類。TextureImage類作為紋理的載入者,可以接受QImage能夠載入的圖片類型,接著作為Texture2D類的預設屬性被產生一個紋理採樣器(texture sampler2D),作為一個uniform變數載入到GLSL中。

GLSL中頂點著色器不變,片斷著色器作如下的修改:

// Gooch.frag#version 100// 自己提供的參數uniform vec3 surfaceColor;uniform vec3 warmColor;uniform vec3 coolColor;uniform float diffuseWarm;uniform float diffuseCool;varying vec3 reflectVec;varying vec3 viewVec;varying float NdotL;uniform sampler2D texPalette;void main( void ){    vec3 kcool    = min( coolColor + diffuseCool * surfaceColor, 1.0 );    vec3 kwarm    = min( warmColor + diffuseWarm * surfaceColor, 1.0 );    //! [6]    vec3 kfinal   = texture2D( texPalette, vec2( NdotL, 1.0 ) ).xyz;    //! [6]    float spec = max( dot( reflectVec, viewVec ), 0.0 );    spec = pow( spec, 32.0 );    gl_FragColor = vec4( min( kfinal + spec, 1.0 ), 1.0 );}

這裡添加了texturePalette這個sampler2D變數,並且修改了kfinal的值。

 

參考文獻:

http://www.jonatron.ca/tag/shader/

http://shiba.hpe.sh.cn/jiaoyanzu/wuli/showArticle.aspx?articleId=333&classId=4

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.