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

概述

在之前的教程中,世界看起来很无聊,因为所有对象都以相同的方式点亮。 本教程将介绍简单照明的概念及其应用方法。 使用的技术将是朗伯照明。

本教程的结果将修改前面的示例以包含光源。 该光源将附在轨道上的立方体上。 可以在中心立方体上看到光的影响。

资源目录

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

Github

灯光

在本教程中,将介绍最基本的照明类型:朗伯照明。 无论距离光线的距离如何,朗伯照明都具有均匀的强度。 当光照射到表面时,通过光在表面上的入射角计算反射的光量。 当光直接照射在表面上时,它显示出以最大强度反射所有光。 然而,随着光的角度增加,光的强度将逐渐消失。

为了计算光在表面上的强度,必须计算光方向与表面法线之间的角度。 表面的法线定义为垂直于表面的矢量。 角度的计算可以通过简单的点积来完成,该点积将光方向矢量的投影返回到法线上。 角度越宽,投影越小。 因此,这为我们提供了调制漫射光的正确功能。

本教程中使用的光源是定向照明的近似值。 描述光源的矢量确定光的方向。 由于它是近似值,无论物体在哪里,光线照射到它的方向都是相同的。 这种光源的一个例子是太阳。 对于场景中的所有物体,总是看到太阳朝同一方向发光。 另外,不考虑单个物体上的光强度。

其他类型的光包括从中心辐射均匀光的点光源和在所有物体上方向但不均匀的聚光灯。

初始化灯光

在本教程中,将有两个光源。 一个将静态地放置在立方体的上方和后方,另一个将围绕中心立方体进行轨道运行。 请注意,上一个教程中的轨道立方体已替换为此光源。

由于光照是由着色器计算的,因此必须声明变量,然后将其绑定到技术中的变量。 在此示例中,我们只需要光源的方向以及颜色值。 第一盏灯是灰色而不移动,而第二盏是轨道红灯。

// 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;
    }

 一旦通过像素着色器,像素将被光调制,您可以看到每个光在立方体表面上的效果。 请注意,在这种情况下,光看起来很平,因为同一表面上的像素将具有相同的法线。 漫反射是一种非常简单易用的计算照明模型。 您可以使用更复杂的照明模型来获得更丰富,更真实的材料。

最终效果

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏潇涧技术专栏

Numerical Methods using Matlab

内容包括:基本幂法,逆幂法和移位幂法,QR分解,Householder变换,实用QR分解技术,奇异值分解SVD

12320
来自专栏数据魔术师

论文拾萃 | 基于树表示法的变邻域搜索算法求解考虑后进先出的取派货旅行商问题(附C++代码和详细代码注释)

本文参考期刊论文信息如下: "The Tree Representation for the Pickup and Delivery Traveling Sa...

61040
来自专栏WOLFRAM

Mathematica 11在代数与数论中的新功能

20950
来自专栏数值分析与有限元编程

Newton–Raphson法解串联弹簧问题

如图所示的串联弹簧,F=100,弹簧刚度为k1 = 50 + 500u ,k2 = 100+ 200u ,u是弹簧伸长量,则平衡方程为 ? ? k1,k2带入得...

29460
来自专栏javascript趣味编程

4.1 数值积分、高等函数绘制

is defined informally as the signed area of the region in the xy-plane that is ...

10100
来自专栏数说工作室

机器学习/深度学习代码速查:6大工具库 &27种神经网络图览

Kailash Ahirwar,Mate Lab 联合创始人,Github的一位资深作者,也是一位活雷锋,近日在其Github个人主页上发表了一个机器学习/深度...

53450
来自专栏月色的自留地

从锅炉工到AI专家(3)

22990
来自专栏星回的实验室

在Spark上用LDA计算文本主题模型

在新闻推荐中,由于新闻主要为文本的特性,基于内容的推荐(Content-based Recommendation)一直是主要的推荐策略。基于内容的策略主要思路是...

60520
来自专栏数据科学与人工智能

【陆勤践行】最流行的4个机器学习数据集

机器学习算法需要作用于数据,而数据的本质则决定了应用的机器学习算法是否合适,而数据的质量也会决定算法表现的好坏程度。所以会研究数据,会分析数据很重要。本文作为学...

223100
来自专栏和蔼的张星的图像处理专栏

暗通道去雾改进算法及实现

上次搞的暗通道去雾的算法交给老师就算是交差了,当时也就是个调研而已。前几天又被老师叫过去说还是需要720p(1280*720)图像的实时处理,看能不能再做一些优...

41220

扫码关注云+社区

领取腾讯云代金券