图形API学习工程(10):基础光照

2024-09-06 23:32

本文主要是介绍图形API学习工程(10):基础光照,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

工程GIT地址:https://gitee.com/yaksue/yaksue-graphics

目标

在《图形API学习工程(6):创建并使用UniformBuffer》中,UniformBuffer的机制已经配置好,这其实可以让一大批功能得以实现。《图形API学习工程(7):进入3D空间》是其一,其中配置了相机矩阵和投影矩阵,使得能以一个虚拟的“相机”来观察3D世界。本篇的“光照”同样如此,它建立在UniformBuffer的功能上。

本篇的目标是创建一个有一定体积的“立方体”,并让它看起来“受到光照”。

此处概念介绍,可见DirectX11官方SDK中的教程范例【Direct3D11 - Tutorial 6: Lighting】

无光照的效果

为了测试,让“立方体”的所有顶点的颜色都是青色(0.0f, 0.7f, 0.7f, 1.0f):

//作为测试的顶点缓冲数据:
std::vector<RawVertexData> vertices = {	//六个面,颜色都是青色(0.0f, 0.7f, 0.7f, 1.0f){ {-1.0f, 1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, 1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, 1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, 1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, -1.0f, -1.0f},	{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, -1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, -1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, -1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, -1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, -1.0f, -1.0f},	{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, 1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, 1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, -1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, -1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, 1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, 1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, -1.0f, -1.0f},	{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, -1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, 1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, 1.0f, -1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, -1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, -1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {1.0f, 1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },{ {-1.0f, 1.0f, 1.0f},		{0.0f, 0.7f, 0.7f, 1.0f} },
};

效果:
在这里插入图片描述
可以看出,虽然从轮廓可以辨别出它是一个立方体。但这和实际在现实中看到的立方体差别很大。在现实中,一个立方体,就算是纯色的,也能辨认出各个表面,辨认出棱角。
而这主要归功于——光照。由于不同的表面相对的光照方向角度不一样,因此他们受光的程度不同。这很容易想象:“光照方向垂直于平面”时,会比“光照方向平行于平面”时更亮。

法线

为了表示表面朝向,引入法线
(另外,我将颜色这个顶点属性去掉,因为所有顶点都是同一种颜色,因此我选择将值暂时硬编码在shader中)

1. 顶点数据调整

顶点数据类型修改:
在这里插入图片描述
数据:

//作为测试的顶点缓冲数据:
std::vector<RawVertexData> vertices = {	//朝前:{ {-1.0f, 1.0f, -1.0f},		{0.0f, 1.0f, 0.0f} },{ {1.0f, 1.0f, -1.0f},		{0.0f, 1.0f, 0.0f} },{ {1.0f, 1.0f, 1.0f},		{0.0f, 1.0f, 0.0f} },{ {-1.0f, 1.0f, 1.0f},		{0.0f, 1.0f, 0.0f} },//朝后:{ {-1.0f, -1.0f, -1.0f},	{0.0f, -1.0f, 0.0f} },{ {1.0f, -1.0f, -1.0f},		{0.0f, -1.0f, 0.0f} },{ {1.0f, -1.0f, 1.0f},		{0.0f, -1.0f, 0.0f} },{ {-1.0f, -1.0f, 1.0f},		{0.0f, -1.0f, 0.0f} },//朝左:{ {-1.0f, -1.0f, 1.0f},		{-1.0f, 0.0f, 0.0f} },{ {-1.0f, -1.0f, -1.0f},	{-1.0f, 0.0f, 0.0f} },{ {-1.0f, 1.0f, -1.0f},		{-1.0f, 0.0f, 0.0f} },{ {-1.0f, 1.0f, 1.0f},		{-1.0f, 0.0f, 0.0f} },//朝右:{ {1.0f, -1.0f, 1.0f},		{1.0f, 0.0f, 0.0f} },{ {1.0f, -1.0f, -1.0f},		{1.0f, 0.0f, 0.0f} },{ {1.0f, 1.0f, -1.0f},		{1.0f, 0.0f, 0.0f} },{ {1.0f, 1.0f, 1.0f},		{1.0f, 0.0f, 0.0f} },//朝下:{ {-1.0f, -1.0f, -1.0f},	{0.0f, 0.0f, -1.0f} },{ {1.0f, -1.0f, -1.0f},		{0.0f, 0.0f, -1.0f} },{ {1.0f, 1.0f, -1.0f},		{0.0f, 0.0f, -1.0f} },{ {-1.0f, 1.0f, -1.0f},		{0.0f, 0.0f, -1.0f} },//朝上:{ {-1.0f, -1.0f, 1.0f},		{0.0f, 0.0f, 1.0f} },{ {1.0f, -1.0f, 1.0f},		{0.0f, 0.0f, 1.0f} },{ {1.0f, 1.0f, 1.0f},		{0.0f, 0.0f, 1.0f} },{ {-1.0f, 1.0f, 1.0f},		{0.0f, 0.0f, 1.0f} },
};
2. 顶点布局调整

将原先的颜色属性改为法线属性:
D3D11
在这里插入图片描述
D3D12
在这里插入图片描述
Vulkan
在这里插入图片描述
OpenGL
在这里插入图片描述
不过,由于OpenGL在创建顶点数据的时候还需要做些转换。因此也需要处理。

3. 着色器调整

将颜色的输入改为法线。
另外,加一个硬编码的光照方向,作为测试。
glsl版
在这里插入图片描述
hlsl版
在这里插入图片描述

效果

在这里插入图片描述

将光照方向加入UniformBuffer

在上一步骤中,光源方向被硬编码到着色器中,在实际中一般不会这么做。因为着色器中的代码应该只记录逻辑,而光源方向这种会被外部调整的数据,应该作为一个UniformBuffer传入。

将光照方向加入UniformBuffer结构体中:
在这里插入图片描述
当然,着色器中也要配合加入。

另外,由于是在像素着色器中获取这个信息,而之前只是在顶点着色器中,所以设置部分有需要改变:
OpenGL
不需要调整

D3D11
在这里插入图片描述

D3D12
将UniformBuffer的可见从D3D12_SHADER_VISIBILITY_VERTEX改为D3D12_SHADER_VISIBILITY_ALL
然后将之前管线中的flag去掉D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS
在这里插入图片描述
Vulkan
UniformBuffer的flag添加一个VK_SHADER_STAGE_FRAGMENT_BIT
在这里插入图片描述

鼠标控制光源

这里和《图形API学习工程(7):进入3D空间》中的相机类似,只不过将CameraManager又向上抽象为一个MouseArmController,供光源的控制使用。
另外,为了能分开控制相机和光源,我向MouseArmController加入了“激活键”的概念,仅在这个键被按时才有效。

效果:
在这里插入图片描述
同时按住两个“激活键”就可以让光照方向时刻面对着相机
在这里插入图片描述

这篇关于图形API学习工程(10):基础光照的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143421

相关文章

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

安装centos8设置基础软件仓库时出错的解决方案

《安装centos8设置基础软件仓库时出错的解决方案》:本文主要介绍安装centos8设置基础软件仓库时出错的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录安装Centos8设置基础软件仓库时出错版本 8版本 8.2.200android4版本 javas

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)

《使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)》字体设计和矢量图形处理是编程中一个有趣且实用的领域,通过Python的matplotlib库,我们可以轻松将字体轮廓... 目录背景知识字体轮廓的表示实现步骤1. 安装依赖库2. 准备数据3. 解析路径指令4. 绘制图形关键

Linux基础命令@grep、wc、管道符的使用详解

《Linux基础命令@grep、wc、管道符的使用详解》:本文主要介绍Linux基础命令@grep、wc、管道符的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录grep概念语法作用演示一演示二演示三,带选项 -nwc概念语法作用wc,不带选项-c,统计字节数-

python操作redis基础

《python操作redis基础》Redis(RemoteDictionaryServer)是一个开源的、基于内存的键值对(Key-Value)存储系统,它通常用作数据库、缓存和消息代理,这篇文章... 目录1. Redis 简介2. 前提条件3. 安装 python Redis 客户端库4. 连接到 Re

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

SpringBoot基础框架详解

《SpringBoot基础框架详解》SpringBoot开发目的是为了简化Spring应用的创建、运行、调试和部署等,使用SpringBoot可以不用或者只需要很少的Spring配置就可以让企业项目快... 目录SpringBoot基础 – 框架介绍1.SpringBoot介绍1.1 概述1.2 核心功能2