石首市 盐源县 台江县 呼玛县 华安县 收藏 蒲城县 柯坪县 垦利县 宜丰县 阿拉善右旗 绥棱县 西昌市 托克托县 成都市 阜新

捷豹_DX11 Without DirectX SDK--07 添加光照与常用几何模型

标签:七上八落 申请送98元体验金博彩网站

对于3D游戏来说,合理的光照可以让游戏显得更加真实。接下来会介绍光照的各种分量,以及常见的光照模型。除此之外,该项目还用到了多个常量缓冲区,因此还会提及HLSL的常量缓冲区打包规则以及如何设置多个常量缓冲区。

项目源码点此:https://github.com/MKXJun/DX11-Without-DirectX-SDK

颜色向量

一个4D的颜色向量,通常情况下会表示为(red, green, blue, alpha),每个分量的取值范围为[0.0f, 1.0f]。对于红绿蓝分量,用0.0f表示该没有该分量的颜色,用1.0f表示该分量的颜色达到饱和;对于alpha分量,用0.0f表示该分量完全透明,用1.0f表示该分量完全不透明。

对于8位色来说,每种分量的颜色亮度可以表达出256种,但使用浮点数会大大浪费存储空间。在内存要求苛刻的情况下,我们可以使用32位的数据类型,其中rgba各占8位,若需要映射到浮点数向量,则对应关系为f(x) = x / 255.0f,其中x为整数存储法,表示范围为[0,255]f(x)为浮点存储法,表示范围为[0.0f, 1.0f]

在头文件DirectXColors.h中,我们可以看到定义了一些4D的颜色向量,位于名称空间DirectX::Colors。在这里贴出来供大家参考:

    // Standard colors (Red/Green/Blue/Alpha)
XMGLOBALCONST XMVECTORF32 AliceBlue            = { { { 0.941176534f, 0.972549081f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 AntiqueWhite         = { { { 0.980392218f, 0.921568692f, 0.843137324f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Aqua                 = { { { 0.000000000f, 1.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Aquamarine           = { { { 0.498039246f, 1.000000000f, 0.831372619f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Azure                = { { { 0.941176534f, 1.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Beige                = { { { 0.960784376f, 0.960784376f, 0.862745166f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Bisque               = { { { 1.000000000f, 0.894117713f, 0.768627524f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Black                = { { { 0.000000000f, 0.000000000f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 BlanchedAlmond       = { { { 1.000000000f, 0.921568692f, 0.803921640f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Blue                 = { { { 0.000000000f, 0.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 BlueViolet           = { { { 0.541176498f, 0.168627456f, 0.886274576f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Brown                = { { { 0.647058845f, 0.164705887f, 0.164705887f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 BurlyWood            = { { { 0.870588303f, 0.721568644f, 0.529411793f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 CadetBlue            = { { { 0.372549027f, 0.619607866f, 0.627451003f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Chartreuse           = { { { 0.498039246f, 1.000000000f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Chocolate            = { { { 0.823529482f, 0.411764741f, 0.117647067f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Coral                = { { { 1.000000000f, 0.498039246f, 0.313725501f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 CornflowerBlue       = { { { 0.392156899f, 0.584313750f, 0.929411829f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Cornsilk             = { { { 1.000000000f, 0.972549081f, 0.862745166f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Crimson              = { { { 0.862745166f, 0.078431375f, 0.235294133f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Cyan                 = { { { 0.000000000f, 1.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkBlue             = { { { 0.000000000f, 0.000000000f, 0.545098066f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkCyan             = { { { 0.000000000f, 0.545098066f, 0.545098066f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkGoldenrod        = { { { 0.721568644f, 0.525490224f, 0.043137256f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkGray             = { { { 0.662745118f, 0.662745118f, 0.662745118f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkGreen            = { { { 0.000000000f, 0.392156899f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkKhaki            = { { { 0.741176486f, 0.717647076f, 0.419607878f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkMagenta          = { { { 0.545098066f, 0.000000000f, 0.545098066f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkOliveGreen       = { { { 0.333333343f, 0.419607878f, 0.184313729f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkOrange           = { { { 1.000000000f, 0.549019635f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkOrchid           = { { { 0.600000024f, 0.196078449f, 0.800000072f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkRed              = { { { 0.545098066f, 0.000000000f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkSalmon           = { { { 0.913725555f, 0.588235319f, 0.478431404f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkSeaGreen         = { { { 0.560784340f, 0.737254918f, 0.545098066f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkSlateBlue        = { { { 0.282352954f, 0.239215702f, 0.545098066f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkSlateGray        = { { { 0.184313729f, 0.309803933f, 0.309803933f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkTurquoise        = { { { 0.000000000f, 0.807843208f, 0.819607913f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DarkViolet           = { { { 0.580392182f, 0.000000000f, 0.827451050f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DeepPink             = { { { 1.000000000f, 0.078431375f, 0.576470613f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DeepSkyBlue          = { { { 0.000000000f, 0.749019623f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DimGray              = { { { 0.411764741f, 0.411764741f, 0.411764741f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 DodgerBlue           = { { { 0.117647067f, 0.564705908f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Firebrick            = { { { 0.698039234f, 0.133333340f, 0.133333340f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 FloralWhite          = { { { 1.000000000f, 0.980392218f, 0.941176534f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 ForestGreen          = { { { 0.133333340f, 0.545098066f, 0.133333340f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Fuchsia              = { { { 1.000000000f, 0.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Gainsboro            = { { { 0.862745166f, 0.862745166f, 0.862745166f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 GhostWhite           = { { { 0.972549081f, 0.972549081f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Gold                 = { { { 1.000000000f, 0.843137324f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Goldenrod            = { { { 0.854902029f, 0.647058845f, 0.125490203f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Gray                 = { { { 0.501960814f, 0.501960814f, 0.501960814f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Green                = { { { 0.000000000f, 0.501960814f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 GreenYellow          = { { { 0.678431392f, 1.000000000f, 0.184313729f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Honeydew             = { { { 0.941176534f, 1.000000000f, 0.941176534f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 HotPink              = { { { 1.000000000f, 0.411764741f, 0.705882370f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 IndianRed            = { { { 0.803921640f, 0.360784322f, 0.360784322f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Indigo               = { { { 0.294117659f, 0.000000000f, 0.509803951f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Ivory                = { { { 1.000000000f, 1.000000000f, 0.941176534f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Khaki                = { { { 0.941176534f, 0.901960850f, 0.549019635f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Lavender             = { { { 0.901960850f, 0.901960850f, 0.980392218f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LavenderBlush        = { { { 1.000000000f, 0.941176534f, 0.960784376f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LawnGreen            = { { { 0.486274540f, 0.988235354f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LemonChiffon         = { { { 1.000000000f, 0.980392218f, 0.803921640f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightBlue            = { { { 0.678431392f, 0.847058892f, 0.901960850f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightCoral           = { { { 0.941176534f, 0.501960814f, 0.501960814f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightCyan            = { { { 0.878431439f, 1.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightGoldenrodYellow = { { { 0.980392218f, 0.980392218f, 0.823529482f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightGreen           = { { { 0.564705908f, 0.933333397f, 0.564705908f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightGray            = { { { 0.827451050f, 0.827451050f, 0.827451050f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightPink            = { { { 1.000000000f, 0.713725507f, 0.756862819f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightSalmon          = { { { 1.000000000f, 0.627451003f, 0.478431404f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightSeaGreen        = { { { 0.125490203f, 0.698039234f, 0.666666687f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightSkyBlue         = { { { 0.529411793f, 0.807843208f, 0.98中国式相亲_2018年最新新闻网0392218f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightSlateGray       = { { { 0.466666698f, 0.533333361f, 0.600000024f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightSteelBlue       = { { { 0.690196097f, 0.768627524f, 0.870588303f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LightYellow          = { { { 1.000000000f, 1.000000000f, 0.878431439f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Lime                 = { { { 0.000000000f, 1.000000000f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 LimeGreen            = { { { 0.196078449f, 0.803921640f, 0.196078449f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Linen                = { { { 0.980392218f, 0.941176534f, 0.901960850f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Magenta              = { { { 1.000000000f, 0.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Maroon               = { { { 0.501960814f, 0.000000000f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumAquamarine     = { { { 0.400000036f, 0.803921640f, 0.666666687f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumBlue           = { { { 0.000000000f, 0.000000000f, 0.803921640f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumOrchid         = { { { 0.729411781f, 0.333333343f, 0.827451050f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumPurple         = { { { 0.576470613f, 0.439215720f, 0.858823597f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumSeaGreen       = { { { 0.235294133f, 0.701960802f, 0.443137288f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumSlateBlue      = { { { 0.482352972f, 0.407843173f, 0.933333397f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumSpringGreen    = { { { 0.000000000f, 0.980392218f, 0.603921592f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumTurquoise      = { { { 0.282352954f, 0.819607913f, 0.800000072f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MediumVioletRed      = { { { 0.780392230f, 0.082352944f, 0.521568656f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MidnightBlue         = { { { 0.098039225f, 0.098039225f, 0.439215720f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MintCream            = { { { 0.960784376f, 1.000000000f, 0.980392218f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 MistyRose            = { { { 1.000000000f, 0.894117713f, 0.882353008f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Moccasin             = { { { 1.000000000f, 0.894117713f, 0.709803939f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 NavajoWhite          = { { { 1.000000000f, 0.870588303f, 0.678431392f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Navy                 = { { { 0.000000000f, 0.000000000f, 0.501960814f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 OldLace              = { { { 0.992156923f, 0.960784376f, 0.901960850f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Olive                = { { { 0.501960814f, 0.501960814f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 OliveDrab            = { { { 0.419607878f, 0.556862772f, 0.137254909f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Orange               = { { { 1.000000000f, 0.647058845f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 OrangeRed            = { { { 1.000000000f, 0.270588249f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Orchid               = { { { 0.854902029f, 0.439215720f, 0.839215755f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 PaleGoldenrod        = { { { 0.933333397f, 0.909803987f, 0.666666687f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 PaleGreen            = { { { 0.596078455f, 0.984313786f, 0.596078455f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 PaleTurquoise        = { { { 0.686274529f, 0.933333397f, 0.933333397f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 PaleVioletRed        = { { { 0.858823597f, 0.439215720f, 0.576470613f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 PapayaWhip           = { { { 1.000000000f, 0.937254965f, 0.835294187f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 PeachPuff            = { { { 1.000000000f, 0.854902029f, 0.725490212f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Peru                 = { { { 0.803921640f, 0.521568656f, 0.247058839f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Pink                 = { { { 1.000000000f, 0.752941251f, 0.796078503f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Plum                 = { { { 0.866666734f, 0.627451003f, 0.866666734f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 PowderBlue           = { { { 0.690196097f, 0.878431439f, 0.901960850f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Purple               = { { { 0.501960814f, 0.000000000f, 0.501960814f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Red                  = { { { 1.000000000f, 0.000000000f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 RosyBrown            = { { { 0.737254918f, 0.560784340f, 0.560784340f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 RoyalBlue            = { { { 0.254901975f, 0.411764741f, 0.882353008f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SaddleBrown          = { { { 0.545098066f, 0.270588249f, 0.074509807f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Salmon               = { { { 0.980392218f, 0.501960814f, 0.447058856f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SandyBrown           = { { { 0.956862807f, 0.643137276f, 0.376470625f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SeaGreen             = { { { 0.180392161f, 0.545098066f, 0.341176480f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SeaShell             = { { { 1.000000000f, 0.960784376f, 0.933333397f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Sienna               = { { { 0.627451003f, 0.321568638f, 0.176470593f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Silver               = { { { 0.752941251f, 0.752941251f, 0.752941251f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SkyBlue              = { { { 0.529411793f, 0.807843208f, 0.921568692f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SlateBlue            = { { { 0.415686309f, 0.352941185f, 0.803921640f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SlateGray            = { { { 0.439215720f, 0.501960814f, 0.564705908f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Snow                 = { { { 1.000000000f, 0.980392218f, 0.980392218f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SpringGreen          = { { { 0.000000000f, 1.000000000f, 0.498039246f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 SteelBlue            = { { { 0.274509817f, 0.509803951f, 0.705882370f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Tan                  = { { { 0.823529482f, 0.705882370f, 0.549019635f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Teal                 = { { { 0.000000000f, 0.501960814f, 0.501960814f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Thistle              = { { { 0.847058892f, 0.749019623f, 0.847058892f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Tomato               = { { { 1.000000000f, 0.388235331f, 0.278431386f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Transparent          = { { { 0.000000000f, 0.000000000f, 0.000000000f, 0.000000000f } } };
XMGLOBALCONST XMVECTORF32 Turquoise            = { { { 0.250980407f, 0.878431439f, 0.815686345f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Violet               = { { { 0.933333397f, 0.509803951f, 0.933333397f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Wheat                = { { { 0.960784376f, 0.870588303f, 0.701960802f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 White                = { { { 1.000000000f, 1.000000000f, 1.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 WhiteSmoke           = { { { 0.960784376f, 0.960784376f, 0.960784376f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 Yellow               = { { { 1.000000000f, 1.000000000f, 0.000000000f, 1.000000000f } } };
XMGLOBALCONST XMVECTORF32 YellowGreen          = { { { 0.603921592f, 0.803921640f, 0.196078449f, 1.000000000f } } };

如果颜色相关的运算在C++代码层进行的话,则在最后需要调用XMVectorSaturate函数确保各个分量都控制在[0.0f, 1.0f]之间。

法向量

法向量用于表述物体表面的朝向,它是单位向量,并且垂直于该表面。对于曲面上一点,通常描述的是曲面该点的切面所对应的法向量。在光照的计算中会经常用到该向量。但是我们传入的通常是顶点数据而不是面的数据,因此顶点结构体内还会包含法向量数据:

struct VertexPosNormalColor
{
    DirectX::XMFLOAT3 pos;
    DirectX::XMFLOAT3 normal;
    DirectX::XMFLOAT4 color;
    static const D3D11_INPUT_ELEMENT_DESC inputLayout[3];
};

对应的每个输入元素的描述为:

const D3D11_INPUT_ELEMENT_DESC VertexPosNormalColor::inputLayout[3] = {
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}
};

对于棱角分明的物体,如立方体,一共由12个三角形组成,2个三角形的4个顶点构成一个面。由于该面的4个顶点要求法向量朝向一致,而一个顶点虽然与立方体的三个面邻接,但是法向量只有一个,因此需要分化出3个包含不同法向量盾牌_2018年最新新闻网的顶点。最终用于绘制该立方体的顶点数就需要24个,是立方体顶点数的3倍!

而对于没那么棱角分明的物体,表面只是稍微有些不平坦的话,我们可以求出该点相邻的所有面的平均法向量。

image

image

对于可以用函数表示的曲面,如球,则可以求出曲面一点对应切面的法向量。

对于函数:

[f(x,y,z)≡0]

则对应点切平面的法向量(非单位向量)为:

[frac{partial{f}}{partial{x}}vec{i}+frac{partial{f}}{partial{y}}vec{j}+frac{partial{f}}{partial{z}}vec{k}]

最后经过标准化后即为曲面该点对应的单位法向量。如球面方程:

[f(x,y,z)=x^2+y^2+z^2-1≡0]

最终对应的单位法向量为:
[vec{n}=(x,y,z)]

法向量的变换

这里省略变换的证明,若一个物体的向量u与法向量n正交,当向量u经过了矩阵变换得到了(u"=uA)时,对应变换后的法向量应为(n"=n(A^{-1})^{T})

物体材质

光在照射到物体上时,由于物体的材质特性会反射一部分光到人眼,最终我们观察到的物体颜色就是被反射的那部分光的颜色。不同的物体有不同的材质属性,决定了各种颜色分量的反射系数是多少。其中红绿蓝每个分量的取值范围为[0.0f, 1.0f]

在C++中的结构体表示为:

// 物体表面材质
struct Material
{
    Material() { memset(this, 0, sizeof(SpotLight)); }

    DirectX::XMFLOAT4 Ambient;
    DirectX::XMFLOAT4 Diffuse;
    DirectX::XMFLOAT4 Specular; // w = 镜面反射强度
    DirectX::XMFLOAT4 Reflect;
};

在HLSL中则表示为:

// 物体表面材质
struct Material
{
    float4 Ambient;
    float4 Diffuse;
    float4 Specular; // w = SpecPower
    float4 Reflect;
};

光的种类

环境光(Ambient Lighting)

环境光也可以说是间接光照,即光线经过了多次反射后最终被我们的人眼所见。即便在一个密闭的暗室使用手电筒照射,你还是可以感受到光充满了整个房间。同样,在阳光照射下,阴影部分也并不是纯粹的黑色,只是比其他地方暗上许多而已。因此在设置环境光的时候,可以考虑以你想呈现的阴影部分亮度进行设置。

在HLSL中,若环境光向量为la ,物体材质对环境光的反射向量为ma,最终环境光分量呈现的颜色为:

la * ma

这里的乘号表示各个分量相乘,最终得到的向量为

(la.r * ma.r, la.g * ma.g, la.b * ma.b, la.a * ma.a)

漫反射光(Diffuse Lighting)

在现实生活中,我们看到的光以漫反射光为主。对于粗糙的表面,光照射在物体表面一点后反射的方向是不确定的。我们可以近似认为光线在照射到物体表面完美世界_2018年最新新闻网一点后会朝任意方向反射等量的光照,这样我们人眼无论在哪个方向观察该点,呈现的亮度应该是不会变化的(在没有镜面反射的基础)。但是物体的亮度与光线照射的方向有所关系,比如当均匀光线垂直照射物体的时候,此时看到的物体表面是最亮的;而均匀光线不经过物体表面,与表面平行的时候,物体的表面此时几乎是看不到的(此时可能仍有少量的光会到达物体表面,取决于光束的汇聚程度和与物体的距离)。毕竟光束不可能做到完全同一个方向照射,仍会有少数的散射光。

朗伯余弦定理

既然光照方向与亮度有关系,我们可以使用朗伯余弦定理来表示这种现象,用L表示光反射后的单位方向向量,n表示平面单位法向量,则可以在HLSL写成:

kd = max(dot(L, n), 0.0f)

若漫反射光向量为ld,物体材质对环境光的反射向量为md,最终漫反射光分量呈现的颜色为:

kd * ld * md

镜面反射光(Specular Lighting)

某些较为光滑的平面可以均匀地反射光照。镜面反射光与人眼所在位置有联系,若人站在反射光的路径上看反射点,可以看到此时的点是最亮的,然后随着人眼远离反射光线的路径,看到的镜面反射光会越来越少,直至只能看到漫反射光和环境光的部分。

在HLSL中,若R为光反射后的单位方向向量,toEye为物体表面一点到人眼的单位方向向量,p为镜面系数(系数越大,表面越光滑,而且p的值必须大于等于1,否则会有很奇怪的效果),可以用下面的公式来表达镜面系数:

ks = pow(max(dot(R, toEye), 0.0f), p) 仅当dot(L, n) > 0
ks = 0 仅当dot(L, n) <= 0

若镜面反射光向量为ls,物体材质对镜面光的反射向量为ms,最终镜面反射光分量呈现的颜色为:

ks * ls * ms

HLSL常量缓冲区打包规则

首先要注意的是,C++中的结构体数据是以字节流传输给HLSL的

若C++结构体和HLSL常量缓冲区如下:

// cpp
struct S1
{
    XMFLOAT3 p1;
    XMFLOAT4 p2;
};

// HLSL
cbuffer C1
{
    float4 v1;
    float4 v2;
}

则最终C1两个向量接收到的数据如下:
(p1.x, p1.y, p1.z, p2.x)
(p2.y, p2.z, p2.w, empty)

其次,HLSL常量缓冲区中两个向量不允许拆分,若HLSL结构体如下:

// HLSL
cbuffer C2
{
    float3 v1;
    float4 v2;
};

p1将被单独打包成一个4D向量,确保常量缓冲区的内存按128位对齐。

C2的内存布局为:

(v1.x, v1.y, v1.z, empty)
(v2.x, v2.y, v2.z, v2.w)

这时用S1结构体的数据再传输给C2,结果如下:

(p1.x, p1.y, p1.z, p2.x)
(p2.y, p2.z, p2.w, empty)

然后,HLSL常量缓冲区多个相邻的变量如果可以,则优先打包进同一个4D向量中,如:

// HLSL
cbuffer C3
{
    float2 v1;
    float v2;
    float3 v3;
}

C3的内存布局为:

(v1.x, v1.y, v2.x, empty)
(v3.x, v3.y, v3.z, empty)

打包顺序是从最上面的变量开始往下的。

对于在常量缓冲区的结构体,内部也会进行打包操作,如:

// HLSL
struct S2
{
    XMFLOAT2 p1;
    XMFLOAT3 p2;
    XMFLOAT p3;
};

cbuffer C4
{
    float v1;
    S2 v2;
    float3 v3;
}

C4的内存布局为:

(v1.x, empty, empty, empty)
(v2.p1.x, v2.p1.y, empty, empty)
(v2.p2.x, v2.p2.y, v2.p2.z, v2.p3.x)
(v3.x, v3.y, v3.z, empty)

对于在常量缓冲区的数组来说,每个元素都会被强制按16字节的倍数进行打包。对于:

float2 arr[16]来说会造成一半空间的浪费,合理的做法是(在C++不能这样写):

// HLSL
cbuffer C5
{
    float4 v1[8];
}

static float2 arr[16] = (float2[16])v1;

光照模型

平行光/方向光

平行光通常是一种全局光,它有一个固定的照射方向。

经平行光照射下物体表面一点的颜色可以初步表示为:

ambient = la * ma;
kd = max(dot(L, n), 0.0f);
if (kd > 0)
    ks = pow(max(dot(R, toEye), 0.0f), p);
else
    ks = 0.0f;
diffuse = kd * ld * md;
specular = ks * ls * ms;
litColor = ambient + diffuse + specular;

在C++中,方向光的结构体表示为:

struct DirectionalLight
{
    DirectionalLight() { memset(this, 0, sizeof(DirectionalLight)); }

    DirectX::XMFLOAT4 Ambient;
    DirectX::XMFLOAT4 Diffuse;
    DirectX::XMFLOAT4 Specular;
    DirectX::XMFLOAT3 Direction;
    float Pad; // 最后用一个浮点数填充使得该结构体大小满足16的倍数,便于我们以后在HLSL设置数组
};

在HLSL则表示为:

struct DirectionalLight
{
    float4 Ambient;
    float4 Diffuse;
    float4 Specular;
    float3 Direction;
};

在HLSL中计算平行光/方向光的函数如下(光向量是与光照射方向相反的单位向量):

void ComputeDirectionalLight(Material mat, DirectionalLight L,
    float3 normal, float3 toEye,
    out float4 ambient,
    out float4 diffuse,
    out float4 spec)
{
    // 初始化输出
    ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
    diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
    spec = float4(0.0f, 0.0f, 0.0f, 0.0f);

    // 光向量与照射方向相反
    float3 lightVec = -L.Direction;

    // 添加环境光
    ambient = mat.Ambient * L.Ambient;

    // 添加漫反射光和镜面光
    float diffuseFactor = dot(lightVec, normal);

    // 展开,避免动态分支
    [flatten]
    if (diffuseFactor > 0.0f)
    {
        float3 v = reflect(-lightVec, normal);
        float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);

        diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
        spec = specFactor * mat.Specular * L.Specular;
    }
}

注意该函数的normaltoEye向量都为单位向量,除此之外输出了光的三种分量。

点光

点光是一种有源光照模型,确定光源位置后,它会朝所有方向辐射光照。

image

在HLSL,若已知光源位置向量Q和照射点P,则单位光向量为:

(Q - P) / length(Q - P)

光的衰弱

随着距离的增长,光源照射到物体表面更远一点时呈现的亮度更低。其中光的衰弱只对直接光照有效,对间接光(如环境光分量)没有影响。

d为光源到物体一点的距离,则有:

iamge

若灯光距离物体太远,计算到的衰弱因子接近于0.我们可以使用标量range来控制照射范围,对距离过大的物体提前避免了漫射光和镜面光的计算。

则经点光照射下物体表面一点的亮度可以初步表示为:

ambient = la * ma;
kd = max(dot(L, n), 0.0f);
if (length(Q - P) > range)
    return litColor = ambient;

if (kd > 0.0f)
    ks = pow(max(dot(R, toEye), 0.0f), p);
else
    ks = 0.0f;

diffuse = kd * ld * md;
specular = ks * ls * ms;
att = 1.0f / (a0 + a1 * d + a2 * d * d);
litColor = ambient + (diffuse + specular) * att;

在C++中,点光可以被表示为:

// 点光
struct PointLight
{
    PointLight() { memset(this, 0, sizeof(PointLight)); }

    DirectX::XMFLOAT4 Ambient;
    DirectX::XMFLOAT4 Diffuse;
    DirectX::XMFLOAT4 Specular;

    // 打包成4D向量: (Position, Range)
    DirectX::XMFLOAT3 Position;
    float Range;

    // 打包成4D向量: (A0, A1, A2, Pad)
    DirectX::XMFLOAT3 Att;
    float Pad; // 最后用一个浮点数填充使得该结构体大小满足16的倍数,便于我们以后在HLSL设置数组
};
// 点光
struct PointLight
{
    float4 Ambient;
    float4 Diffuse;
    float4 Specular;

    float3 Position;
    float Range黑暗血时代_2018年最新新闻网;

    float3 Att;
};

在HLSL中计算点光的函数如下

void ComputePointLight(Material mat, PointLight L, float3 pos, float3 normal, float3 toEye,
    out float4 ambient, out float4 diffuse, out float4 spec)
{
    // 初始化输出
    ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
    diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
    spec = float4(0.0f, 0.0f, 0.0f, 0.0f);

    // 从表面到光源的向量
    float3 lightVec = L.Position - pos;

    // 表面到光线的距离
    float d = length(lightVec);

    // 灯光范围测试
    if (d > L.Range)
        return;

    // 标准化光向量
    lightVec /= d;

    // 环境光计算
    ambient = mat.Ambient * L.Ambient;

    // 漫反射和镜面计算
    float diffuseFactor = dot(lightVec, normal);

    // 展开以避免动态分支
    [flatten]
    if (diffuseFactor > 0.0f)
    {
        float3 v = reflect(-lightVec, normal);
        float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);

        diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
        spec = specFactor * mat.Specular * L.Specular;
    }

    // 光的衰弱
    float att = 1.0f / dot(L.Att, float3(1.0f, d, d * d));

    diffuse *= att;
    spec *= att;
}

聚光灯

聚光灯也是一种有源光照模型,在确定光源位置后,其照射区域可以看作一个锥体,在同等照射距离下,越靠近照射中心,亮度越强。同样随着距离的增大,光照强度逐渐减弱。
image
在HLSL,若已知光源位置向量Q和照射点P,则单位光向量为:

(Q - P) / length(Q - P)

若已知光向量L和照射强度d,以及光的汇聚程度spot,则可以得到光照强度因子:

kspot = pow(max(dot(L, d), 0), spot)

通常spot的值越大,光束的汇聚程度越强。

则经聚光灯照射下物体表面一点的亮度可以初步表示为:

ambient = la * ma;
kd = max(dot(L, n), 0.0f);
if (kd > 0)
    ks = pow(max(dot(R, toEye), 0.0f), p);
else
    ks = 0.0f;
diffuse = kd * ld * md;
specular = ks * ls * ms;
att = 1.0f / (a0 + a1 * d + a2 * d * d);
kspot = pow(max(dot(L, d), 0), spot);
litColor = kspot * (ambient + (diffuse + specular) * att);

在HLSL中计算聚光灯的函数如下

void ComputeSpotLight(Material mat, SpotLight L, float3 pos, float3 normal, float3 toEye,
    out float4 ambient, out float4 diffuse, out float4 spec)
{
    // 初始化输出
    ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
    diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
    spec = float4(0.0f, 0.0f, 0.0f, 0.0f);

    // // 从表面到光源的向量
    float3 lightVec = L.Position - pos;

    // 表面到光源的距离
    float d = length(lightVec);

    // 范围测试
    if (d > L.Range)
        return;

    // 标准化光向量
    lightVec /= d;

    // 计算环境光部分
    ambient = mat.Ambient * L.Ambient;


    // 计算漫反射光和镜面反射光部分
    float diffuseFactor = dot(lightVec, normal);

    // 展开以避免动态分支
    [flatten]
    if (diffuseFactor > 0.0f)
    {
        float3 v = r我们是兄弟_2018年最新新闻网eflect(-lightVec, normal);
        float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);

        diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
        spec = specFactor * mat.Specular * L.Specular;
    }

    // 计算汇聚因子和衰弱系数
    float spot = pow(max(dot(-lightVec, L.Direction), 0.0f), L.Spot);
    float att = spot / dot(L.Att, float3(1.0f, d, d * d));

    ambient *= spot;
    diffuse *= att;
    spec *= att;
}

HLSL代码

在LightHelper.hlsli标头文件中包含了上述所有的HLSL结构体以及三种光照模型的函数

然后Light_VS.hlsl和Light_PS.hlsl都包含了Light.fx,用于生成顶点着色器和像素着色器

最后是Light.fx的代码:

// Light.fx
#include "LightHelper.hlsli"

cbuffer VSConstantBuffer : register(b0)
{
    row_major matrix gWorld; 
    row_major matrix gView;  
    row_major matrix gProj;  
    row_major matrix gWorldInvTranspose;
}

cbuffer PSConstantBuffer : register(b1)
{
    DirectionalLight gDirLight;
    PointLight gPointLight;
    SpotLight gSpotLight;
    Material gMaterial;
    float3 gEyePosW;
}



struct VertexIn
{
    float3 Pos : POSITION;
    float3 Normal : NORMAL;
    float4 Color : COLOR;
};

struct VertexOut
{
    float4 PosH : SV_POSITION;
    float3 PosW : POSITION;     // 在世界中的位置
    float3 NormalW : NORMAL;    // 法向量在世界中的方向
    float4 Color : COLOR;
};

// 顶点着色器
VertexOut VS(VertexIn pIn)
{
    VertexOut pOut;
    row_major matrix worldViewProj = mul(mul(gWorld, gView), gProj);
    pOut.PosH = mul(float4(pIn.Pos, 1.0f), worldViewProj);     
    pOut.PosW = mul(float4(pIn.Pos, 1.0f), gWorld).xyz;
    pOut.NormalW = mul(pIn.Normal, (float3x3)gWorldInvTranspose);
    pOut.Color = pIn.Color;                             // 这里alpha通道的值默认为1.0
    return pOut;
}


// 像素着色器
float4 PS(VertexOut pIn) : SV_Target
{
    // 标准化法向量
    pIn.NormalW = normalize(pIn.NormalW);

    // 顶点指向眼睛的向量
    float3 toEyeW = normalize(gEyePosW - pIn.PosW);

    // 初始化为0 
    float4 ambient, diffuse, spec;
    float4 A, D, S;
    ambient = diffuse = spec = A = D = S = float4(0.0f, 0.0f, 0.0f, 0.0f);

    ComputeDirectionalLight(gMaterial, gDirLight, pIn.NormalW, toEyeW, A, D, S);
    ambient += A;
    diffuse += D;
    spec += S;

    ComputePointLight(gMaterial, gPointLight, pIn.PosW, pIn.NormalW, toEyeW, A, D, S);
    ambient += A;
    diffuse += D;
    spec += S;

    ComputeSpotLight(gMaterial, gSpotLight, pIn.PosW, pIn.NormalW, toEyeW, A, D, S);
    ambient += A;
    diffuse += D;
    spec += S;

    float4 litColor = pIn.Color * (ambient + diffuse) + spec;
    
    litColor.a = gMaterial.Diffuse.a * pIn.Color.a;
    
    return litColor;
}

这里有两个常量缓冲区,一个用于顶点着色阶段,另一个用于像素着色阶段。

Geometry类--常用几何模型

该类包含了几个常用的3D模型:球、立方体和圆柱体。调用它可以生成模型数据以写入顶点和索引缓冲区。

#ifndef GEOMETRY_H_
#define GEOMETRY_H_

#include <Windows.h>
#include <DirectXMath.h>
#include <vector>


class Geometry
{
public:
    struct MeshData
    {
        std::vector<DirectX::XMFLOAT3> posVec;      // 位置数组
        std::vector<DirectX::XMFLOAT3> normalVec;   // 法向量数组
        std::vector<WORD> ind证券业协会_2018年最新新闻网exVec;                 // 索引数组
    };

    // 创建球体模型数据,levels和slices越大,精度越高。
    static MeshData CreateSphere(float radius = 1.0f, int levels = 20, int slices = 20);

    // 创建立方体模型数据
    static MeshData CreateBox(float width = 2.0f, float height = 2.0f, float depth = 2.0f);

    // 创建圆柱体模型数据,slices越大,精度越高。
    static MeshData CreateCylinder(float radius = 1.0f, float height = 2.0f, int slices = 20);
};


#endif

Geometry::CreateBox方法--创建立方体

该方法会创建包含24个顶点位置和24个单位法向量的两个数组,以及一个含36个索引的数组:

Geometry::MeshData Geometry::CreateBox(float width, float height, float depth)
{
    MeshData meshData;
    float w2 = width / 2, h2 = height / 2, d2 = depth / 2;

    meshData.posVec.resize(24);
    // 顶面
    meshData.posVec[0] = XMFLOAT3(-w2, h2, -d2);
    meshData.posVec[1] = XMFLOAT3(-w2, h2, d2);
    meshData.posVec[2] = XMFLOAT3(w2, h2, d2);
    meshData.posVec[3] = XMFLOAT3(w2, h2, -d2);
    // 底面
    meshData.posVec[4] = XMFLOAT3(w2, -h2, -d2);
    meshData.posVec[5] = XMFLOAT3(w2, -h2, d2);
    meshData.posVec[6] = XMFLOAT3(-w2, -h2, d2);
    meshData.posVec[7] = XMFLOAT3(-w2, -h2, -d2);
    // 左面
    meshData.posVec[8] = XMFLOAT3(-w2, -h2, d2);
    meshData.posVec[9] = XMFLOAT3(-w2, h2, d2);
    meshData.posVec[10] = XMFLOAT3(-w2, h2, -d2);
    meshData.posVec[11] = XMFLOAT3(-w2, -h2, -d2);
    // 右面
    meshData.posVec[12] = XMFLOAT3(w2, -h2, -d2);
    meshData.posVec[13] = XMFLOAT3(w2, h2, -d2);
    meshData.posVec[14] = XMFLOAT3(w2, h2, d2);
    meshData.posVec[15] = XMFLOAT3(w2, -h2, d2);
    // 背面
    meshData.posVec[16] = XMFLOAT3(w2, -h2, d2);
    meshData.posVec[17] = XMFLOAT3(w2, h2, d2);
    meshData.posVec[18] = XMFLOAT3(-w2, h2, d2);
    meshData.posVec[19] = XMFLOAT3(-w2, -h2, d2);
    // 正面
    meshData.posVec[20] = XMFLOAT3(-w2, -h2, -d2);
    meshData.posVec[21] = XMFLOAT3(-w2, h2, -d2);
    meshData.posVec[22] = XMFLOAT3(w2, h2, -d2);
    meshData.posVec[23] = XMFLOAT3(w2, -h2, -d2);

    meshData.normalVec.resize(24);
    for (int i = 0; i < 4; ++i)
    {
        meshData.normalVec[i] = XMFLOAT3(0.0f, 1.0f, 0.0f);         // 顶面
        meshData.normalVec[i + 4] = XMFLOAT3(0.0f, -1.0f, 0.0f);    // 底面
        meshData.normalVec[i + 8] = XMFLOAT3(-1.0f, 0.0f, 0.0f);    // 左面
        meshData.normalVec[i + 12] = XMFLOAT3(1.0f, 0.0f, 0.0f);    // 右面
        meshData.normalVec[i + 16] = XMFLOAT3(0.0f, 0.0f, 1.0f);    // 背面
        meshData.normalVec[i + 20] = XMFLOAT3(0.0f, 0.0f, -1.0f);   // 正面
    }
    
    meshData.indexVec = {
        0, 1, 2, 2, 3, 0,       // 顶面
        4, 5, 6, 6, 7, 4,       // 底面
        8, 9, 10, 10, 11, 8,    // 左面
        12, 13, 14, 14, 15, 12, // 右面
        16, 17, 18, 18, 19, 16, // 背面
        20, 21, 22, 22, 23, 20  // 正面
    };

    return meshData;
}

Geometry::CreateSphere方法--创建球体

由于3D模型都是用三角形模拟的,这里的球体如果想要效果更佳逼真,需要用到更多的三角形。球体的法向量如前面所述,使用微分法求出。在提供参数的时候,levels决定上下分多少层,slices决定一个圆分成多少份。levelsslices越高,生成的顶点数、索引数都会越多:

Geometry::MeshData Geometry::CreateS

当前文章:http://1xhg-yijingjiang-com.o5p022.tw/vfyn2w6/9ece5_155642.html

发布时间:2019-08-25 10:56:10

澳门银河送彩金  银河国际手机网址2949  澳门银河首页yh163am.com  小伙婚前全款买房 离婚后法院判99%房产归女方  澳门银河真人在线娱乐  澳门银河娱乐送彩金网站  澳门银河娱乐yh163am.com  银河娱乐是正规网站吗  澳门银河真人yh163am.com  世界杯官网