Direct3D光照

光照的组成

环境光:这种类型的光经其他表面反射到达物体表面,并照亮整个场景,要想以较低代价粗略模拟这类反射光,环境光是一个很好的选择

漫射光:这种类型光沿着特定的方向传播。当它到达某一表面时,将沿着各个方向均匀反射,无论从哪个方位观察,表面亮度均相同,所以采用该模型时无须考虑观察者的位置,这样,漫射光方程中仅需考虑光传播的方向以及表面朝向,从一个光源发出的光一般都是这种类型的。

镜面光:这种类型的光沿特定方向传播,当此类光到达一个表面时,将严格地沿着另一个方向反射,从而形成只能在一定角度范围内才能观察到的高亮度照射,所以在镜面光照方程中不仅需要考虑光线的入射方向和图元的表面朝向,还需要考虑观察点的位置。镜面光可用于模拟物体上的高光点,例如当光线照射到一个抛光的表面所形成的高亮照射。

镜面光比其他类型光计算量大,因此Direct3D提供了开关选项,默认状态下Direct不进行镜面反射计算,如果想启用镜面光,必须调用接口进行设置

Device->SetRenderState(D3DRS_SPECULARENABLE, true);

每种类型的光都可用结构D3DCOLORVALUE或者D3DXCOLOR来表示,描述光线的颜色时,D3DXCOLOR类中的Alpha值都将被忽略

D3DXCOLOR redAmbient(1.0f, 0.0f, 0.0f, 1.0f);
D3DXCOLOR blueDiffuse(0.0f, 0.0f, 1.0f, 1.0f);
D3DXCOLOR whiteSpecular(1.0f, 1.0f, 1.0f, 1.0f);

材质

现实世界中,我们所观察到的物体的颜色是由该物体所反射的光的颜色决定的,例如一个纯红色的球体反射了全部的红色入射光,并吸收了所有非红色的光,所以呈现为红色。当一个物体吸收了所有的光时,便呈现为黑色,如果一个物体能够100%地反射红色光、绿色光、蓝色光,它将呈现为白色,Direct3D通过定义物体的材质来模拟同样的现象,材质允许我们定义物体表面对各种颜色光的反射比例,材质用结构D3DMATERIAL9来表示。

typedef struct D3DMATERIAL9 {D3DCOLORVALUE   Diffuse;  D3DCOLORVALUE   Ambient;  D3DCOLORVALUE   Specular; D3DCOLORVALUE   Emissive; float           Power;    
} D3DMATERIAL9;

Diffuse:指定材质对漫射光的反着率
Ambient:指定材质对环境光的反射率
Specular:指定材质对镜面光的反射率
Emissive:该分量用于增强物体的亮度,使之看起来好像可以自己发光
Power:指定镜面高光点的锐度,该值越大,高光点的锐度越大

//只反射红色光
D3DMATERIAL9 red;
::ZeroMemory(&red, sizeof(red));
red.Diffuse = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);
red.Ambient= D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);
red.Specular = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f);
red.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
red.Power = 5.0f;

设置材质接口SetMaterial

D3DMATERIAL9 blueMaterial;
Device->SetMaterial(&blueMaterial);
//draw...

顶点法线

顶点法线描述的是构成多边形的各个顶点的法线,Direct3D需要知道顶点的法线方向,以确定光线到达表面时的入射角,由于光照计算是对每个顶点进行的,所以Direct3D需要知道表面在每个顶点处的局部朝向(法线方向),描述一个顶点法线需要修改顶点结构

struct Vertex
{float _x, _y, _z;float _nx, _ny, _nz;static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL;

计算三角形三个顶点的法线,可由计算该面的法向量得到,首先计算位于三角形平面内的俩个向量

void ComputeNormal(D3DXVECTOR3* p0, D3DXVECTOR3* p1, D3DXVECTOR3* p2, D3DXVECTOR3* out)
{D3DXVECTOR3 u = *p1 - *p0;D3DXVECTOR3 v = *p2 - *p0;D3DXVec3Cross(out, &u, &v);D3DXVec3Normalize(out, out);
}

当用三角形单元逼近表示曲面时,将面片法向量作为构成该面片的顶点法向量不可能产生很平滑的效果,一种更好的求取顶点法向量的方法是计算法向量均值,我们需要求出共享点v的所有三角形的面法向量,然后将这些法向量相加后除以个数进行平均。

在变换过程中,顶点法线有可能不再是规范的所以最好的方法是在变换完成后,通过设置绘制状态来重新规范化

Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);

光源

Direct3D支持3种类型的光源,分别是点光源、方向光、聚光灯

点光源:该光源在世界坐标系中有固定的位置,并向所有的方向发射光线(D3DLIGHT_POINT)
方向光:该光源没有位置信息,所发射的光线相互平行地沿某一特定方向传播(D3DLIGHT_DIRECTIONAL)
聚光灯:这种类型的光源与手电筒类似,该光源有位置信息,其发射的光线呈锥形沿着特定方向传播(D3DLIGHT_SPOT)

typedef struct D3DLIGHT9 {D3DLIGHTTYPE    Type;        D3DCOLORVALUE   Diffuse;     D3DCOLORVALUE   Specular;    D3DCOLORVALUE   Ambient;     D3DVECTOR       Position;    D3DVECTOR       Direction;   float           Range;       float           Falloff;     float           Attenuation0;float           Attenuation1;float           Attenuation2;float           Theta;       float           Phi;         
} D3DLIGHT9;

Type:定义创建的光源类型,可取以下3种枚举值,D3DLIGHT_POINTD3DLIGHT_SPOTD3DLIGHT_DIRECTIONAL
Diffuse:该光源所发出的漫射光的颜色
Specular:该光源所发出的镜面光的颜色
Ambient:该光源所发出的环境光的颜色
Position:用于描述光源在世界坐标系中位置的向量,对于方向光该参数无意义
Direction:一个描述光在世界坐标系中传播方向的向量,对于点光源该参数无意思
Range:光线"消亡"前,所能到达的最大光程,该值的最大取值为\sqrt{FLT\_MAX},对于方向光该参数无意义
Falloff:该值用于聚光灯,该参数定义了光强从内锥形到外锥形的衰减方式,该参数一版取为1.0f
Attenuation0Attenuation1Attenuation2这些衰减变量定义了光强随距离衰减的方式,这些变量仅用于点光源和聚光灯,分别表示光的常量、线性、2次距离衰减系数,衰减公式为attenuation=\frac{1}{A_{0}+A_{1}\cdot D+A_{2}\cdot D^{2}},其中D为光源到顶点的距离。
Theta:仅用于聚光灯,指定了内部锥形的圆锥角,单位为弧度
Phi:仅用于聚光灯,指定了外部锥形的圆锥角,单位为弧度

与D3DMATERIAL9结构初始化类似,当需要一个简单的光源时,D3DLIGHT9结构的初始化也很繁琐

D3DLIGHT9 d3d::InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color)
{D3DLIGHT9 light;::ZeroMemory(&light, sizeof(light));light.Type = D3DLIGHT_DIRECTIONAL;light.Ambient = *color * 0.4f;light.Diffuse = *color;light.Specular = *color * 0.6f;light.Direction = *direction;return light;
}D3DXVECTOR3 dir(1.0f, 0.0f, 0.0f);
D3DXCOLOR c = d3d::WHITE;
D3DLIGHT9 dirLight = d3d::InitDirectionalLight(&dir, &c);

D3DLIGHT9实例初始化完毕之后,我们需要在Direct3D所维护的一个光源内部列表中对所要使用的光源进行注册,注册成功后就可以对其开关状态进行控制

Device->SetLight(0, &light);
Device->LightEnable(0, true);

光照例程

bool SetUpPyramid()
{//启用光照(默认是启用的)Device->SetRenderState(D3DRS_LIGHTING, true);Device->CreateVertexBuffer(12 * sizeof(PyramidVertex), D3DUSAGE_WRITEONLY, PyramidVertex::FVF, D3DPOOL_MANAGED, &Pyramid, 0);PyramidVertex* v;Pyramid->Lock(0, 0, (void**)&v, 0);v[0] = PyramidVertex(-1.0f, 0.0f, -1.0f, 0.0f, 0.707f, -0.707f);v[1] = PyramidVertex(0.0f, 1.0f, 0.0f, 0.0f, 0.707f, -0.707f);v[2] = PyramidVertex(1.0f, 0.0f, -1.0f, 0.0f, 0.707f, -0.707f);v[3] = PyramidVertex(-1.0f, 0.0f, 1.0f, -0.707f, 0.707f, 0.0f);v[4] = PyramidVertex(0.0f, 1.0f, 0.0f, -0.707f, 0.707f, 0.0f);v[5] = PyramidVertex(-1.0f, 0.0f, -1.0f, -0.707f, 0.707f, 0.0f);v[6] = PyramidVertex(1.0f, 0.0f, -1.0f, 0.707f, 0.707f, 0.0f);v[7] = PyramidVertex(0.0f, 1.0f, 0.0f, 0.707f, 0.707f, 0.0f);v[8] = PyramidVertex(1.0f, 0.0f, 1.0f, 0.707f, 0.707f, 0.0f);v[9] = PyramidVertex(1.0f, 0.0f, 1.0f, 0.0f, 0.707f, 0.707f);v[10] = PyramidVertex(0.0f, 1.0f, 0.0f, 0.0f, 0.707f, 0.707f);v[11] = PyramidVertex(-1.0f, 0.0f, 1.0f, 0.0f, 0.707f, 0.707f);Pyramid->Unlock();D3DMATERIAL9 mtrl;mtrl.Ambient = d3d::WHITE;mtrl.Diffuse = d3d::WHITE;mtrl.Specular= d3d::WHITE;mtrl.Emissive = d3d::BLACK;mtrl.Power = 5.0f;Device->SetMaterial(&mtrl);D3DLIGHT9 dir;::ZeroMemory(&dir, sizeof(dir));dir.Type = D3DLIGHT_DIRECTIONAL;dir.Diffuse = d3d::WHITE;dir.Specular = d3d::WHITE * 0.3f;dir.Ambient = d3d::WHITE * 0.6f;dir.Direction = D3DXVECTOR3(1.0f, 0.0f, 0.0f);Device->SetLight(0, &dir);Device->LightEnable(0, true);//规范化法向量Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);//启用镜面高光Device->SetRenderState(D3DRS_SPECULARENABLE, true);//取景变换(观察者坐标系)D3DXVECTOR3 position(3.0f, 2.0f, -3.0f);D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);D3DXMATRIX V;D3DXMatrixLookAtLH(&V, &position, &target, &up);Device->SetTransform(D3DTS_VIEW, &V);//投影变换D3DXMATRIX proj;D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI*0.5f, (float)Width / (float)Height, 1.0f, 1000.0f);Device->SetTransform(D3DTS_PROJECTION, &proj);return true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/132050.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 内置函数详解 (2) 逻辑运算

近期在外旅游,本篇是出发编辑的,准备定时发布用,不完整,旅游回来后再补充。 Python 内置函数 Python3.11共有75个内置函数,其来历和分类请参考:Python 新版本有75个内置函数,你不会不知道吧_Hann Yang的博客-CSDN博客https://blog.csdn.net/boysoft2002/article/detai…

群晖Cloud Sync数据同步到百度云、另一台群晖、nextcloud教程

群晖Cloud Sync数据同步到百度云、另一台群晖、nextcloud教程 一、群晖套件中下载Cloud Sync 二、同步到百度云盘 打开Cloud Sync,点击左上角的号,云供应商选择百度云。 这里可以选择双向备份,也可以只上穿到百度云的仅上传本地更改。因为百…

服务器中了勒索病毒怎么办?勒索病毒解密,数据恢复

勒索病毒是一种比较常见的电脑病毒,它们给企业的生产经营和发展带来了很大的影响。可是绝大多数企业在这方面并没有做合理的预案,这也导致当安全运维人员或者企业主发现中了勒索病毒以后手足无措。那云天数据恢复中心就用这篇文章来告诉大家当服务器中了…

联通数科赋能中国联通DCMM5级评估!

近日,中国电子信息行业联合会发布了“关于公布获得数据管理能力成熟度等级证书单位的通知”,中国联通获得最高等级优化级(5级),成为通信行业率先获得最高等级的单位,标志着中国联通数据管理能力进入国家第一…

MyBatis基础之概念简介

文章目录 基本概念1. 关于 MyBatis2. MyBatis 的体系结构3. 使用 XML 构建 SqlSessionFactory4. SqlSession5. 默认的别名6. 补充 [注意] 放前面前 很多人可能在使用 MyBatis-plus 进行代码开发,MyBatis的这部分内容是用来更好的讲述之后的内容。 基本概念 1. 关于…

Apollo介绍和入门

文章目录 Apollo介绍配置中心介绍apollo介绍主流配置中心功能特性对比 Apollo简介 入门简单的执行流程Apollo具体的执行流程Apollo对象执行流程分步执行流程 核心概念应用,环境,集群,命名空间企业部署方案灰度发布全量发布 配置发布的原理发送…

小程序引入高德/百度地图坐标系详解

小程序引入高德/百度地图坐标系详解 官网最近更新时间:最后更新时间: 2021年08月17日 高德官网之在原生小程序中使用的常见问题 链接 目前在小程序中使用 高德地图只支持以下功能 :地址描述、POI和实时天气数据 小结:从高德api中获取数…

PaddleOCR以及CUDA、cuDNN安装踩坑记录

PaddleOCR安装参考官网或者Gitee说明文档:https://gitee.com/paddlepaddle/PaddleOCR/blob/release/2.6/doc/doc_ch/quickstart.md 可以先安装CPU版本跑起来: python3 -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple pip instal…

【操作系统】进程的概念、组成、特征

概念组成 程序:静态的放在磁盘(外存)里的可执行文件(代码) 作业:代码+数据+申请(JCB)(外存) 进程:程序的一次执行过程。 …

python自学

自学第一步 第一个简单的基础,向世界说你好 启动python 开始 print是打印输出的意思,就是输出引号内的内容。 标点符号必须要是英文的,因为他只认识英文的标点符号。 exit()推出python。 我们创建一个文本文档&…

计算机竞赛 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 🔥 优质竞赛项目系列&#x…

【每日一题】73. 矩阵置零

73. 矩阵置零 - 力扣(LeetCode) 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[…

Thinkphp6 配置并使用redis图文详解 小皮面板

这篇文章主要介绍了Thinkphp6 配置并使用redis的方法,结合实例形式详细分析了Redis的安装、配置以及thinkphp6操作Redis的基本技巧,需要的朋友可以参考下 一、安装redis ThinkPHP内置支持的缓存类型包括file、memcache、wincache、sqlite。ThinkPHP默认使用自带的采用think\Ca…

多台以太网交换机怎么连接?

当一台交换机不能满足端口数量和某种特定功能需求时,通常用户会将多台以太网交换机连接在一起,那么在网络部署时如何将多台以太网交换机连接在一起呢?目前常见的三种连接方式有:级联、堆叠和集群。本文旨在阐明这三种技术以及其中…

快速幂 c++

一般大家写都是 int ans 1; for (int i 1; i < a; i )ans * x;时间复杂度 但是这对于我们还不够&#xff0c;我们要 首先我们得知道一个数学知识 那么求 就有以下递归式 a 能被2整除 a 不能被2整除 (这里a/2是整除) 所以每次都调用 不就是么 最后补充一个东西…

9个值得收藏的WebGL性能优化技巧

在这里&#xff0c;我们推荐一些经证明非常适合创建基于 Web 的交互体验的优化技术。 本章主要基于 Soft8Soft 在 Verge3Day Europe 2019 会议上的演讲。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 1、几何/网格 几何是 3D 应用程序的基础&#xff0c;因为它构成了…

靠差异化上了短剧“牌桌”后,百度准备怎么做生态?

从最初的野蛮生长到如今的百花齐放&#xff0c;短剧市场已然进入了质量与创意的竞争。 据《中国网络视听发展研究报告》数据显示&#xff0c;行业内重点网络微短剧上线数量从2021年的58部&#xff0c;飙升到2022年的172部。相比起前几年处于风口时的爆发式增长&#xff0c;“分…

帧结构的串行数据接收器——Verilog实现

用Verilog 实现一个帧结构的串行数据接收器&#xff1b; 串行数据输入为&#xff1a;NRZ数据加位时钟&#xff08;BCL&#xff09;格式&#xff0c;高位在前 帧结构为&#xff1a;8位构成一个字&#xff0c;64字构成一个帧。每帧的第一个字为同步字。同步字图案存储在可由CPU读…

Linux——进程间通信(管道及共享内存)

目录 0. 前言 1. 进程通信的目的 2. 进程通信发展及分类 3. 进程通信匿名管道 3.1 什么是管道&#xff1f; 3.2 匿名管道系统调用 3.3 fork后子进程继承&#xff08;基于内存级&#xff09; 3.4 站在文件描述符角度-深度理解管道 3.5 站在内核角度-管道本质 3.6 父子…

C++之map迭代器函数begin、end、rbegin、rend、cbegin、cend、crbegin、crend总结(二百零五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…