Direct3D 11 Tutorial 6:Lighting_Direct3D 11 教程6:燈光

概述

在以前的教程中,世界看起來很無聊,由於全部對象都以相同的方式點亮。 本教程將介紹簡單照明的概念及其應用方法。 使用的技術將是朗伯照明。git

本教程的結果將修改前面的示例以包含光源。 該光源將附在軌道上的立方體上。 能夠在中心立方體上看到光的影響。github

 

資源目錄

(SDK root)\Samples\C++\Direct3D11\Tutorials\Tutorial06函數

Githuborm

 

燈光

在本教程中,將介紹最基本的照明類型:朗伯照明。 不管距離光線的距離如何,朗伯照明都具備均勻的強度。 當光照射到表面時,經過光在表面上的入射角計算反射的光量。 當光直接照射在表面上時,它顯示出以最大強度反射全部光。 然而,隨着光的角度增長,光的強度將逐漸消失。對象

爲了計算光在表面上的強度,必須計算光方向與表面法線之間的角度。 表面的法線定義爲垂直於表面的矢量。 角度的計算能夠經過簡單的點積來完成,該點積將光方向矢量的投影返回到法線上。 角度越寬,投影越小。 所以,這爲咱們提供了調製漫射光的正確功能。blog

本教程中使用的光源是定向照明的近似值。 描述光源的矢量肯定光的方向。 因爲它是近似值,不管物體在哪裏,光線照射到它的方向都是相同的。 這種光源的一個例子是太陽。 對於場景中的全部物體,老是看到太陽朝同一方向發光。 另外,不考慮單個物體上的光強度。教程

其餘類型的光包括從中心輻射均勻光的點光源和在全部物體上方向但不均勻的聚光燈。資源

 

初始化燈光

在本教程中,將有兩個光源。 一個將靜態地放置在立方體的上方和後方,另外一個將圍繞中心立方體進行軌道運行。 請注意,上一個教程中的軌道立方體已替換爲此光源。get

因爲光照是由着色器計算的,所以必須聲明變量,而後將其綁定到技術中的變量。 在此示例中,咱們只須要光源的方向以及顏色值。 第一盞燈是灰色而不移動,而第二盞是軌道紅燈。input

// Setup our lighting parameters
    XMFLOAT4 vLightDirs[2] =
    {
        XMFLOAT4( -0.577f, 0.577f, -0.577f, 1.0f ),
        XMFLOAT4( 0.0f, 0.0f, -1.0f, 1.0f ),
    };
    XMFLOAT4 vLightColors[2] =
    {
        XMFLOAT4( 0.5f, 0.5f, 0.5f, 1.0f ),
        XMFLOAT4( 0.5f, 0.0f, 0.0f, 1.0f )
    };

  

在上一個教程中,軌道光的旋轉方式與立方體同樣。 應用的旋轉矩陣將改變光的方向,以顯示它始終朝向中心發光的效果。 注意,函數XMVector3Transform用於將矩陣與向量相乘。 在上一個教程中,咱們將轉換矩陣乘以世界矩陣,而後傳遞到着色器進行轉換。 可是,爲簡單起見,在這種狀況下,咱們實際上正在對CPU中的光進行世界變換。

// Rotate the second light around the origin
    XMMATRIX mRotate = XMMatrixRotationY( -2.0f * t );
    XMVECTOR vLightDir = XMLoadFloat4( &vLightDirs[1] );
    vLightDir = XMVector3Transform( vLightDir, mRotate );
    XMStoreFloat4( &vLightDirs[1], vLightDir );

  

燈光的方向和顏色都像矩陣同樣傳遞到着色器。 調用關聯變量進行設置,並傳入參數。

    //
    // Update matrix variables and lighting variables
    //
    ConstantBuffer cb1;
    cb1.mWorld = XMMatrixTranspose( g_World );
    cb1.mView = XMMatrixTranspose( g_View );
    cb1.mProjection = XMMatrixTranspose( g_Projection );
    cb1.vLightDir[0] = vLightDirs[0];
    cb1.vLightDir[1] = vLightDirs[1];
    cb1.vLightColor[0] = vLightColors[0];
    cb1.vLightColor[1] = vLightColors[1];
    cb1.vOutputColor = XMFLOAT4(0, 0, 0, 0);
    g_pImmediateContext->UpdateSubresource( g_pConstantBuffer, 0, NULL, &cb1, 0, 0 );

  

渲染像素着色器中的燈光

一旦咱們設置了全部數據而且着色器正確地提供了數據,咱們就能夠計算來自光源的每一個像素的朗伯照明術語。 咱們將使用以前討論過的點積規則。

一旦咱們將光線與正常光線的點積相乘,就能夠將其與光線的顏色相乘,以計算光線的效果。 該值經過飽和函數傳遞,該函數將範圍轉換爲[0,1]。 最後,將兩個單獨的燈的結果相加在一塊兒以建立最終的像素顏色。

考慮到表面自己的材料沒有考慮到這個光計算中。 表面的最終顏色是燈光顏色的結果。

    //
    // Pixel Shader
    //
    float4 PS( PS_INPUT input) : SV_Target
    {
        float4 finalColor = 0;
        
        //do NdotL lighting for 2 lights
        for(int i=0; i<2; i++)
        {
            finalColor += saturate( dot( (float3)vLightDir[i],input.Norm) * vLightColor[i] );
        }
        return finalColor;
    }

  

 一旦經過像素着色器,像素將被光調製,您能夠看到每一個光在立方體表面上的效果。 請注意,在這種狀況下,光看起來很平,由於同一表面上的像素將具備相同的法線。 漫反射是一種很是簡單易用的計算照明模型。 您可使用更復雜的照明模型來得到更豐富,更真實的材料。

 

最終效果

相關文章
相關標籤/搜索