图形学面试题总结
图形学面试题总结
文章目录
- 图形学面试题总结
- Opengl 与 Vulkan
- 1、OpenGL的渲染管线有哪些主要阶段?分别做什么?
- 2、OpenGL中的VAO、VBO和EBO分别是什么?为什么需要它们?
- 3、细分着色器与几何着色器是什么
- 4、Vulkan与Opengl的区别是什么
- 5、OpenGL中的纹理映射(Texture Mapping)是怎么实现的?简述主要步骤
- 6、在OpenGL中,glViewport和glScissor的区别是什么?
- 7、Vulkan中的Instance、Device、Queue、CommandBuffer分别是什么?
- 8、Vulkan的Pipeline(渲染管线)为什么不可变?
- 9、OpenGL的FBO帧缓冲对象的作用是什么?有哪些常见的应用场景?
- 10、Vulkan中的Fence是用来干什么的?什么时候必须用?
- 11、Vulkan中的Descriptor Set和OpenGL中的Uniform Buffer有什么区别?
- 12、如何在OpenGL/Vulkan中实现LOD(Level of Detail)?
- 13、在OpenGL中,什么是GPU Instancing?
- 14、Vulkan的RenderPass和Subpass的作用
- 15、移动端和PC端的差异,渲染的区别
- 16、在移动端渲染大型场景时,如何优化内存?
- 17、什么是Mesh Shader?
- 18、OpenGL的深度测试(Depth Test)是如何工作的?为什么会出现深度冲突(Z-fighting)?
- 19、在OpenGL中,如果我想要绘制一个半透明的物体,应该怎么做?
- 20、在Vulkan中,为什么要设置多个VkCommandBuffer?而不是一个?
- 21、Vulkan中,为什么我们需要同步机制(Synchronization)?哪些同步机制最常用?
- 图形学算法
- 1、简述Blinn-Phong光照模型。Blinn-Phong光照模型与Phong光照模型的区别
- 2、谈谈Shadow Map
- 3、你知道BSP树、Octree、KD-Tree吗?它们在渲染中有什么作用?
- 4、什么是光线追踪(Ray Tracing)?与光栅化(Rasterization)的最大区别是什么?
- 5、在图形学中,PBR(Physically Based Rendering)是什么?什么是PBR材质?
- 6、在渲染引擎中,Forward Rendering和Deferred Rendering有什么优缺点?
- 7、什么是BRDF?
- 8、如何实现全局光照?
- 9、投影有正交投影和透视投影,矩阵如何推导?
Opengl 与 Vulkan
1、OpenGL的渲染管线有哪些主要阶段?分别做什么?
1、**CPU端处理:**加载模型信息(光照、贴图),处理用户输入(鼠标、键盘),更新场景状态(物体的位置、旋转,缩放),提交渲染指令(glDrawArrays)
2、**顶点着色器:**GPU上的唯二的可编程阶段,处理顶点属性,主要是位置属性,通过模型矩阵,视图矩阵和投影矩阵进行位置的变换。模型矩阵:将模型移动到世界坐标系中。视图矩阵:将世界空间变换到相机空间,该矩阵由相机的位置,朝向和偏移向三个向量决定。投影矩阵:相机空间是一个四棱台,投影矩阵将相机空间变换到裁剪空间中。有正交投影和透视投影两种变换。
3、图元装配阶段: 将顶点组合成图元,由opengl的接口决定是装配成点、线还是三角形。无法直接编程
4、**裁剪阶段:**将视锥体外的不可见的部分剔除
5、**光栅化阶段:**将三角形,线、点转化成Fragment
6:**片段着色器:**可编程的阶段,计算每个片段的最终颜色。输入Fragment的数据,比如纹理坐标,法向等输入。输入光源信息,比如环境光,镜面反射,光源坐标等。输出片段的颜色。
7、**测试与混合阶段:**深度测试、模板测试、混合。用于处理遮挡关系与透明渲染的阶段
8、写入帧缓冲区
2、OpenGL中的VAO、VBO和EBO分别是什么?为什么需要它们?
VBO:顶点缓冲对象。将顶点的信息,包括位置、法向、纹理等信息都存入VBO中。可以一次性的将数据从CPU传入到GPU中
EBO:索引缓冲对象。存放顶点的索引。
VAO:顶点数组对象 。是一个状态对象,用于记录 VBO、EBO 以及顶点属性指针的绑定状态,避免重复绑定VBO和EBO。
3、细分着色器与几何着色器是什么
顶点着色器->细分着色器->几何着色器->光栅化
细分着色器:计算细分顶点
几何着色器:动态生成额外的几何体,点、线、三角形。
4、Vulkan与Opengl的区别是什么
特性 | Opengl | Vulkan |
---|---|---|
设计理念 | 固定渲染管线+状态机 | 完全可控的渲染管线+现实驱动编程 |
显存管理 | 自动管理,不支持 | 手动管理,支持 |
多线程 | 不支持 | 支持 |
5、OpenGL中的纹理映射(Texture Mapping)是怎么实现的?简述主要步骤
1、纹理加载:使用stb图像库加载纹理
2、纹理绑定:使用glBindTexture(GL_TEXTURE_2D, texture)绑定纹理
3、为顶点指定纹理坐标
4、在顶点着色器中传递纹理坐标,在片段着色器中使用纹理坐标
6、在OpenGL中,glViewport和glScissor的区别是什么?
虽然他们都影响渲染结果的可视区域,但是还是有所不同的
功能 | glViewport | glScissor |
---|---|---|
作用 | 设置OpenGL渲染结果映射到窗口中的区域 | 限制像素绘制范围,只允许特定区域渲染 |
影响范围 | 影响所有渲染操作的投影区域 | 只影响像素绘制,不影响投影 |
对裁剪的影响 | 不进行任何裁剪 | 强制限定像素写入范围 |
修改投影坐标 | 将 NDC 映射到窗口区域 | 不修改任何投影坐标 |
常用场景 | 1、窗口缩放 2、设置视口 | 1、实现小窗口渲染 2、裁剪特定区域 |
7、Vulkan中的Instance、Device、Queue、CommandBuffer分别是什么?
名称 | 说明 | 功能 |
---|---|---|
Instance | VkInstance是与Vulkan库进行交互的入口点,表示一个Vulkan应用程序的上下文。它是创建其他Vulkan对象(如VkDevice、VkSurface等)的基础。 | 1、启动Vulkan应用程序所必需的基本结构。2、维护Vulkan驱动程序与操作系统之间的接口。3、负责枚举和查询支持的扩展、层(Layers)和设备(Device) |
Device | VkDevice表示与Vulkan API进行交互的一个物理GPU或虚拟GPU的抽象。它是应用程序与GPU交互的接口,包含了所有与图形处理和计算相关的功能。换句话说,Vulkan将一块任意的GPU抽象成相同的逻辑设备device | 1、VkDevice是创建命令队列(Queue)、缓冲区(Buffer)、图像(Image)、着色器模块(Shader Module)等其他Vulkan对象的基础。2、管理GPU资源的生命周期。3、用于执行图形、计算等工作。 |
Queue | VkQueue是GPU执行命令的一个通道,每个设备可能有多个队列,每个队列都有不同的优先级和类型。 | 队列用于提交渲染命令、计算命令等。可以将命令提交到不同类型的队列(如图形队列、计算队列、传输队列等),每个队列类型可以执行不同类型的操作。 |
CommandBuffer | VkCommandBuffer是一个用于记录命令的对象,它包含了一系列GPU将要执行的操作。命令缓冲区实际上并不执行命令,而是将命令记录到缓冲区中,之后可以将它们提交给队列执行。 | 1、通过vkBeginCommandBuffer和vkEndCommandBuffer来开始和结束命令的记录。2、在命令缓冲区中记录一系列图形、计算或传输命令(如绘制命令、资源绑定、数据传输命令等)。3、命令缓冲区可以是一次性的或多次使用的,在执行完成后,命令缓冲区可以被重新使用或重置。 |
8、Vulkan的Pipeline(渲染管线)为什么不可变?
在Vulkan中,渲染管线(Pipeline)是不可变的,意味着一旦创建管线对象后,管线的所有状态和配置都不能在运行时被修改。这是Vulkan设计的一部分,其主要目的是为了优化性能和简化状态管理。
1、减少运行时状态检查:由于Vulkan管线不可变,驱动程序不需要在每次渲染时去检查管线状态是否已经改变。
- 每次提交渲染命令时,渲染管线的状态都是一致的,GPU可以直接使用已经创建的管线,而无需重新设置状态。
- 这减少了CPU和GPU之间的状态同步和管理工作,从而加快渲染的速度。
2、管线创建时的资源预编译和优化:Vulkan要求在创建管线时,必须明确指定所有的渲染过程,包括着色器、输入布局、混合状态、深度/模板测试等。由于管线不可变,GPU可以在管线创建时执行预编译和优化,提前为硬件准备好渲染所需的资源。这种设计使得GPU在实际渲染时能直接加载已经优化过的管线,从而提高渲染效率。
9、OpenGL的FBO帧缓冲对象的作用是什么?有哪些常见的应用场景?
FBO(帧缓冲对象)是OpenGL中的一个工具,用来让渲染结果不直接显示在屏幕上,而是先存储在一个纹理或缓冲区中。这种方法常常用于一些复杂的渲染任务,比如:
离屏渲染:你可以将渲染的结果存储在纹理中,而不是直接显示在屏幕上。这可以用于后续的处理,比如做特效或者计算阴影。
后处理效果:先渲染一个场景到FBO,然后用这个渲染结果做各种特效(比如模糊、色彩调整等)。比如做阴影贴图时,先用FBO把场景的深度信息渲染到纹理中,之后计算光源下的阴影。
多渲染目标(MRT):可以把渲染结果同时保存到多个纹理里,做更复杂的效果,比如计算不同的渲染通道(颜色、法线、深度等)。
10、Vulkan中的Fence是用来干什么的?什么时候必须用?
Fence是用于同步不同线程或队列之间的操作,它通常用于等待命令执行的完成。栅栏主要用于队列之间的同步,确保一个操作在另一个操作完成后才能继续执行。
等待操作完成:当你提交命令到一个队列时,可以使用栅栏来等待命令执行完成。比如,等待GPU完成绘制或计算操作,然后再进行后续操作。
跨队列同步:当使用多个队列(例如图形队列和计算队列)时,栅栏可以用来同步这些队列。你可以等待一个队列的任务完成,再提交另一个队列的任务。
避免CPU与GPU的不同步:CPU在提交命令后可以使用栅栏检查GPU的状态,确保某些任务完成后才继续进行后续的CPU操作。
11、Vulkan中的Descriptor Set和OpenGL中的Uniform Buffer有什么区别?
在Vulkan和Opengl中,Descriptor Set和Uniform Buffer都是用于传递数据给着色器的方式。
不同的是,Descriptor Set更加灵活,Descriptor Set是Descriptor的集合,每一个Descriptor可以绑定不同类型的资源。当然着色器中也可以有多个Set,两个set和一个push_constant往着色器中传入数据:
layout(set = 0, binding = 0) uniform GlobalUbo {mat4 projection;mat4 view;mat4 invView;vec4 ambientLightColor; // w is intensityvec4 color;vec4 direction; } ubo; struct LineShelllet {vec2 point[2];float height[2];float angle[2]; double width; };//读取从CPU那里发送过来的数据 layout(set=1,binding = 0) readonly buffer Lets { LineShelllet lets[]; }; layout(set=1,binding = 1) readonly buffer Index { uint index[]; }; layout(set=1,binding = 2) readonly buffer Index2 { uint index2[]; }; layout(push_constant) uniform Push {mat4 modelMatrix;mat4 normalMatrix;int modeltype;int letsize; } push;
在Opengl的Uniform Buffer(UBO)是用于存储常量数据(如模型矩阵、视图矩阵、光源信息等)并传递到着色器中的对象。你可以将多个uniform变量存储在一个Buffer对象中,然后通过绑定该Buffer将数据传递给着色器。每个Uniform Buffer可以存储的内容是有限的,通常需要按照类型(如mat4、vec3等)组织数据。
12、如何在OpenGL/Vulkan中实现LOD(Level of Detail)?
1、预生成:预先为模型生成多个细节层次的网格(例如,高精度、中精度、低精度的网格)。
2、距离判断:根据相机到模型的距离来判断应该使用哪个精度的模型。
3、渲染时选择:在渲染过程中,选择最合适的模型进行绘制。
在Vulkan中可以使用MeshShader架构来优化这一过程
13、在OpenGL中,什么是GPU Instancing?
在传统渲染中,如果需要渲染多个相同的物体(如森林中的树、群体角色、粒子系统),每个物体都调用一次 glDrawElements() 或 glDrawArrays(),CPU 需要多次发送数据给 GPU,开销较大。
GPU Instancing 是 OpenGL 提供的一种技术,允许在一次绘制调用(Draw Call)中渲染多个相同的物体,只需提供少量不同的数据(如位置、颜色、旋转等)。这样可以大幅减少 CPU 和 GPU 之间的通信开销,提高渲染效率。
14、Vulkan的RenderPass和Subpass的作用
RenderPass:是一个Vulkan对象,用于表示一组渲染操作的集合。这些操作通常会影响多个颜色附件、深度/模板附件等,并按照特定的顺序执行。一个RenderPass通常包括多个Subpass,每个Subpass可以进行不同的渲染操作。
1、优化与重用:Vulkan的RenderPass主要目的是为了提高性能。在RenderPass中,渲染的操作是与帧缓冲区的状态相结合的,这样可以让驱动程序或硬件优化操作。例如,某些操作可能只涉及颜色附件,或者某些操作只会写入深度缓冲区。通过这些信息,Vulkan可以合理地优化内存访问和数据依赖,减少不必要的缓存无效化和同步开销。
2、附件(Attachment)管理:在RenderPass中,定义了多个附件(如颜色附件、深度附件、模板附件等),并描述这些附件的加载、存储和最终输出行为。例如,某些附件可以在某个Subpass中进行读写,而在其他Subpass中仅进行读取。
Subpass:是RenderPass中的一个子操作,表示一个渲染过程中的一部分。一个RenderPass可以包含多个Subpass,每个Subpass负责执行某个阶段的渲染操作。Subpass允许在同一个RenderPass中进行多次渲染,同时减少对附件的写入或同步要求。
1、分阶段渲染:Subpass表示渲染过程中不同阶段的操作,例如第一阶段可以是几何处理和光照计算,第二阶段可以是后处理(如全屏后处理效果)。每个Subpass通常会有一个特定的渲染目标(即颜色或深度附件)并与前一个Subpass共享这些目标。
2、附件的共享与依赖:不同Subpass之间可以共享某些附件(如颜色缓冲区或深度缓冲区)。Subpass允许通过共享附件来避免不必要的资源重新加载和同步。通过优化附件的读取/写入行为,可以减少内存访问冲突和性能瓶颈。
3、减少内存访问和同步:Vulkan中的Subpass可以通过将渲染阶段组织成多个Subpass来最小化对附件的写入和同步。例如,可以在一个Subpass中只写入颜色数据,而在另一个Subpass中只进行深度测试。通过这种方式,可以避免频繁的内存无效化操作,提高渲染效率。
15、移动端和PC端的差异,渲染的区别
移动端的内存带宽较低,计算能力较低
PC 端使用 IMR(即时模式渲染 Immediate Mode Rendering):顶点着色后,直接写入帧缓冲,可能有大量的 Overdraw(重复绘制相同像素)。
移动端使用 TBDR(基于 Tile 的延迟渲染 Tile-Based Deferred Rendering):先把几何数据划分为小块(Tile),再逐块渲染,减少 Overdraw。
16、在移动端渲染大型场景时,如何优化内存?
纹理压缩:使用适合移动设备的纹理压缩格式(如 ETC1/ETC2、ASTC、PVRTC),这些格式能够显著减少纹理的内存占用和带宽消耗。
Mipmap 生成:生成 Mipmap 纹理,并根据摄像机与物体的距离使用适当的 Mipmap 级别。这可以减少高分辨率纹理的加载和内存占用,提升渲染效率。
简化网格数据:使用低多边形数量的模型,或者通过 Level of Detail (LOD) 技术动态调整模型的细节。当摄像机距离较远时,使用更低细节的网格,减小内存占用和计算量。
GPU 实例化(Instancing):对于重复的物体,使用 GPU Instancing 技术,在内存中存储一个物体的实例数据,而不是为每个实例单独存储数据。这样可以显著减少内存的占用。
17、什么是Mesh Shader?
Mesh Shader 是一种在现代图形API(如Vulkan和DirectX 12)中引入的新型着色器阶段,它极大地改进了图形渲染的效率,特别是在复杂几何体的处理和剖分上。Mesh Shader 是相对于传统的顶点着色器(Vertex Shader)和几何着色器(Geometry Shader)的一种新型替代方案。它允许开发者将网格划分为更小的单元(Meshlet),并对这些单元进行并行处理。通过这种方式,减少了传统渲染管线中顶点处理的瓶颈,提高了并行度和性能。
18、OpenGL的深度测试(Depth Test)是如何工作的?为什么会出现深度冲突(Z-fighting)?
深度缓冲区:渲染每个像素时,Opengl会为每个像素存储一个深度值,通常这个值在0-1范围内,0代表离相机越近,1代表远。
深度测试:在渲染一个像素之前,OpenGL首先检查该像素的深度值(即它相对于摄像机的距离)是否小于当前深度缓冲区中存储的值。如果是,这意味着该像素比之前的像素更近,因此该像素会被绘制。如果不是,这意味着该像素被遮挡(距离摄像机更远),因此该像素不会被绘制,深度缓冲区中的值保持不变。
Z-fighting:当两个面非常近时,就会出现深度竞争。会出现撕裂,闪烁的效果,因为在这些像素中,有一些被判定为需要渲染A面,有一些则被判定为应该渲染B面。
19、在OpenGL中,如果我想要绘制一个半透明的物体,应该怎么做?
- 启用混合:glEnable(GL_BLEND); 因为一个像素中的颜色是透明物体的颜色和背景颜色混合起来的,因此需要启用混和,选取混合公式来计算颜色。
- 设置材质的透明度,在颜色的 α \alpha α项,设置一个小于1.0的值
- 禁用深度写入:因为透明的物体就算挡在了不透明的物体之前,不透明的物体也能被看见,反之则不成立。因此需要禁用深度写入,而打开深度测试。
20、在Vulkan中,为什么要设置多个VkCommandBuffer?而不是一个?
在 Vulkan 中,生成命令和提交命令是分开的。通过将多个命令缓冲区分开,可以在 CPU 上并行生成多个命令缓冲区,同时将它们提交到 GPU 上进行执行。这样可以减少 CPU 的等待时间,使 CPU 和 GPU 的工作更加并行。例如,CPU 可以在执行第一个命令缓冲区的同时准备第二个命令缓冲区,减少 CPU 的空闲时间,提高整体渲染效率。
21、Vulkan中,为什么我们需要同步机制(Synchronization)?哪些同步机制最常用?
在 Vulkan 中,GPU 的渲染和计算操作往往是 异步 执行的。GPU上的多个命令、操作可能并行运行,或者可能会依赖于之前的命令的结果,因此同步机制(Synchronization)是非常重要的,因为它们确保在不同操作之间的正确执行顺序,防止出现竞争条件和数据冲突。Vulkan是一个低级别、显式的API,它不为我们自动处理这些同步问题,因此开发者需要手动管理。没有正确的同步,会导致图形和计算操作的结果错误,甚至崩溃。
名称 作用 使用场景 工作方式 Fences
栅栏用于在主机(CPU)和设备(GPU)之间同步 通常用于等待 GPU 完成某个操作,特别是在提交命令缓冲区时,确保 GPU 的任务完成后再进行后续操作 当 GPU 完成某个任务时,Vulkan会触发 fence 信号,主机线程会等待 fence 被触发 Semaphores
信号量用于在不同的 GPU 操作之间同步,确保操作按正确的顺序执行 通常在渲染管线中的多个阶段之间进行同步,特别是在多个命令队列中,确保渲染操作的顺序 一个操作完成后会“发出”信号量,等待信号量的操作可以接着进行 Events
事件用于在 GPU 上的多个操作之间或 CPU 和 GPU 之间同步 可以在命令缓冲区内同步某些操作,或者触发 GPU 内部事件,然后CPU进行响应 事件可以处于两种状态:触发(signaled)或未触发(unsignaled)。操作可以等待事件被触发后继续执行 Pipeline Barriers
(管线屏障)用于在 Vulkan 渲染管线的不同阶段之间同步,确保命令之间的正确执行顺序 通常在渲染或计算命令之间使用,确保 GPU 正确地执行内存操作或图像处理操作 可以在进行渲染操作前等待纹理或缓冲区的传输操作完成,防止资源被不正确地读取或写入
图形学算法
1、简述Blinn-Phong光照模型。Blinn-Phong光照模型与Phong光照模型的区别
Blinn-Phong光照模型由三部分组成:环境光,漫反射光和镜面反射光。其中环境光通常为常数,漫反射光: I d i f f u s e = k d ∗ ( L ⋅ N ) I_{diffuse} = k_d * (L\cdot N) Idiffuse=kd∗(L⋅N),其中k是漫反射系数,L是光照方向,N是法向量。也就是说面越垂直与光照方向,那么漫反射越强烈。镜面反射光则是根据半向量和法向量的点乘进行计算: I s p e c u l a r = k s × m a x ( 0 , ( H ⋅ N ) ) n I_{specular} = k_s \times max(0,(H \cdot N))^n Ispecular=ks×max(0,(H⋅N))n。其中H是半向量,是光源方向+观察方向的单位向量。
Phong和Blinn的区别在于镜面反射的计算上,Blinn-Phong的镜面反射是利用半向量和法向量计算的,而Phong是利用反射向量与观察方向的点乘来计算的。Phong需要预先根据法向量和光照方向计算反射光照,开销较大。
2、谈谈Shadow Map
相当于以光源视角生成了一张深度图。在渲染某个像素之前,根据这个深度图,也就是Shadow Map进行判断,如果它到光源的距离小于深度图中记载的距离,那么就认为该处不是阴影,否则就是阴影。
优势:1、高效,适合实时渲染,尤其是在复杂场景中。2、可以适应不同类型的光源,如定向光、点光源等。
不足:阴影可能会出现锯齿或模糊。可以通过使用PCF(Percentage Closer Filtering)来平滑阴影的边缘。
3、你知道BSP树、Octree、KD-Tree吗?它们在渲染中有什么作用?
BSP树(Binary Space Partitioning Tree):是一种递归地将空间划分为两个半空间的空间划分数据结构。每个节点代表一个平面,通过这个平面将空间分为两个部分(左侧和右侧),每个子空间都可以继续递归划分。
八叉树 Octree:是一种三维空间划分数据结构,它将空间分成8个子区域(即八分之一空间),每个子区域可以进一步递归划分成8个子区域。Octree适用于存储和管理三维空间中的物体,尤其是那些分布不均匀的场景。
KD-Tree(K-Dimensional Tree):是一种空间划分数据结构,用于组织K维空间的数据(通常是二维或三维)。它通过选择一个维度(如X、Y或Z轴)将空间划分为两部分,然后递归地进行空间划分。每个节点包含一个数据点和一个划分平面,KD-Tree适合用于高维数据的搜索和查询。
这些树可以用于光线追踪,碰撞检测,LOD,视锥体剔除等相关算法的加速
4、什么是光线追踪(Ray Tracing)?与光栅化(Rasterization)的最大区别是什么?
光线追踪(Ray Tracing)是一种通过模拟光线传播的物理过程来生成图像的技术。在光线追踪中,光线从摄像机(观察点)出发,向场景中的物体发射,并根据物体的材质属性(如反射、折射、透光等)计算光线与物体的交互,最终得到颜色和亮度信息。
特性 | 光线追踪(Ray Tracing) | 光栅化(Rasterization) |
---|---|---|
渲染方向 | 从视点出发,模拟光线与物体的交互 | 从物体出发,投影到屏幕 |
光照计算 | 考虑直接光照和间接光照(反射、折射等) | 主要计算直接光照 |
真实性 | 高,能够精确模拟光线的传播,真实感强 | 较低,通常依赖于逼近方法(如光照贴图) |
计算量 | 高,尤其在需要多次光线反弹时 | 低,实时渲染时效率高 |
应用场景 | 高质量渲染(电影、动画、光线追踪游戏) | 实时渲染(视频游戏、互动应用) |
5、在图形学中,PBR(Physically Based Rendering)是什么?什么是PBR材质?
PBR(Physically Based Rendering,基于物理的渲染)是一种通过模拟光与物体表面相互作用的物理过程来生成逼真图像的渲染技术。它基于物理学的真实原理,考虑了光的反射、折射、散射等现象,使得渲染效果能够在不同的光照环境下保持一致性,能够生成更加自然和真实的图像。
PBR材质(Physically Based Rendering Material,基于物理的渲染材质)是一种通过物理属性来描述物体表面特性、光照与材质相互作用的材质模型。与传统的材质模型不同,PBR材质遵循物理学的真实规律,旨在使渲染结果更加自然和真实。PBR材质的关键在于其通过几个核心参数(如金属度、粗糙度等)来描述物体的物理属性,从而在不同的光照环境下能够产生一致的效果。
6、在渲染引擎中,Forward Rendering和Deferred Rendering有什么优缺点?
对比项 | Forward Rendering(前向渲染) | Deferred Rendering(延迟渲染) |
---|---|---|
光照计算 | 逐物体计算光照(每个像素计算所有光源) | 屏幕空间光照(仅计算可见像素的光照) |
性能 | 少光源时高效,多光源时性能下降 | 适合大量光源,仅对可见像素计算光照 |
显存占用 | 低,占用显存少 | 高,需要存 G-buffer(位置、法线等) |
透明度支持 | 直接支持透明度(Blending) | 不支持,需要额外处理(Forward+) |
后处理效果 | 难以实现 SSAO、HDR、Bloom | 适合高级特效(SSAO、HDR、光照体积) |
阴影处理 | 每个光源单独计算 Shadow Map,成本高 | 需要额外技术(Deferred Shadowing) |
适用场景 | 简单 3D 场景、VR/AR、移动端 | PC/主机端、动态光源多的场景(如城市夜景) |
7、什么是BRDF?
它是物体材质的体现,是渲染方程中重要的一项,它定义了表面反射的光强度相对于入射光方向和观察方向的关系。
具体的: f r ( w i , w o ) = d L o ( w o ) d E i ( w i ) f_r(\mathbf{w_i}, \mathbf{w_o}) = \frac{dL_o(\mathbf{w_o})}{dE_i(\mathbf{w_i})} fr(wi,wo)=dEi(wi)dLo(wo)
f r ( w i , w o ) f_r(\mathbf{w_i}, \mathbf{w_o}) fr(wi,wo)是 BRDF 函数,表示表面反射的光强度,依赖于入射光方向( w i \mathbf{w_i} wi)和观察方向( w o \mathbf{w_o} wo)。
d L o ( w o ) dL_o(\mathbf{w_o}) dLo(wo) 是单位立体角内从表面反射到观察者的光强度。
d E i ( w i ) dE_i(\mathbf{w_i}) dEi(wi)是单位立体角内从光源照射到表面的入射光强度。
8、如何实现全局光照?
全局光照指光在场景中多次散射,反射和折射,不仅仅考虑直接光照还考虑间接光照。一般用光线追踪的方式实现。
9、投影有正交投影和透视投影,矩阵如何推导?
正交投影:矩阵需要将三维坐标变换到一个二维平面,并且需要根据近平面(near plane)、远平面(far plane)、视口的宽度和高度等参数来定义。假设摄像机的视口是一个立方体(或者一个矩形框),其位置在视空域(view space)中,且投影过程中不涉及深度的压缩。正交投影矩阵的标准形式是:
M o r t h o = ( 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − t + b t − b 0 0 − 2 f − n − f + n f − n 0 0 0 1 ) M_{ortho} = \begin{pmatrix} \frac{2}{r - l} & 0 & 0 & -\frac{r + l}{r - l} \\ 0 & \frac{2}{t - b} & 0 & -\frac{t + b}{t - b} \\ 0 & 0 & -\frac{2}{f - n} & -\frac{f + n}{f - n} \\ 0 & 0 & 0 & 1 \end{pmatrix} Mortho= r−l20000t−b20000−f−n20−r−lr+l−t−bt+b−f−nf+n1
其中:
- r,l是视体的左、右边界。
- t,b是视体的下、上边界。
- n,f 是近平面和远平面的距离。
透视投影:是模拟现实世界的视觉效果,使得距离远的物体看起来更小,距离近的物体看起来更大。透视投影会将三维空间中的点通过透视缩放的方式映射到二维平面上。
透视投影的关键是根据物体距离视点的远近调整物体的大小。透视投影矩阵常常根据相机的视野(Field of View,FOV)、长宽比(aspect ratio)、近平面(near plane)和远平面(far plane)来进行定义。
透视投影矩阵的标准形式如下:
M p e r s p e c t i v e = ( 1 aspect ⋅ tan ( F O V 2 ) 0 0 0 0 1 tan ( F O V 2 ) 0 0 0 0 f + n n − f 2 f n n − f 0 0 − 1 0 ) M_{perspective} = \begin{pmatrix} \frac{1}{\text{aspect} \cdot \tan(\frac{FOV}{2})} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan(\frac{FOV}{2})} & 0 & 0 \\ 0 & 0 & \frac{f+n}{n-f} & \frac{2fn}{n-f} \\ 0 & 0 & -1 & 0 \end{pmatrix} Mperspective= aspect⋅tan(2FOV)10000tan(2FOV)10000n−ff+n−100n−f2fn0
其中:
- FOV 是视场角(通常是垂直视场角),表示相机的可视范围。
- aspect 是视口的宽高比,通常是宽度除以高度。
- n和f 近平面和远平面的距离。
相关文章:
图形学面试题总结
图形学面试题总结 文章目录 图形学面试题总结Opengl 与 Vulkan1、OpenGL的渲染管线有哪些主要阶段?分别做什么?2、OpenGL中的VAO、VBO和EBO分别是什么?为什么需要它们?3、细分着色器与几何着色器是什么4、Vulkan与Opengl的区别是什…...
Spring Cloud Alibaba 实战:Sentinel 保障微服务的高可用性与流量防护
1.1 Sentinel 作用 Sentinel 是阿里巴巴开源的一款 流量控制和熔断降级 框架,主要用于: 流量控制:限制 QPS,防止流量暴增导致系统崩溃熔断降级:当某个服务不可用时自动降级,避免故障扩散热点参数限流&…...
Comfyui 与 SDwebui
ComfyUI和SD WebUI是基于Stable Diffusion模型的两种不同用户界面工具,它们在功能、用户体验和适用场景上各有优劣。 1. 功能与灵活性 ComfyUI:ComfyUI以其节点式工作流设计为核心,强调用户自定义和灵活性。用户可以通过连接不同的模块&…...
面试之《前端常见的设计模式》
前端开发中运用多种设计模式可以提高代码的可维护性、可扩展性和可复用性。以下是一些常见的前端设计模式: 创建型模式 1. 单例模式 定义:确保一个类只有一个实例,并提供一个全局访问点。应用场景:在前端中,像全局状…...
PostgreSQL异常:An IO error occurred while sending to the backend
在使用PostgreSQL数据库批量写入数据的时候,遇到了一个问题,异常内容如下: Cause: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.报错内容 报错提示1 Caused by: org.postgresql.util.PSQLExc…...
嵌入式八股C语言---面向对象篇
面向对象与面向过程 面向过程 就是把整个业务逻辑分成多个步骤,每步或每一个功能都可以使用一个函数来实现面向对象 对象是类的实例化,此时一个类就内部有属性和相应的方法 封装 在C语言里实现封装就是实现一个结构体,里面包括的成员变量和函数指针,然后在构造函数中,为结构体…...
一周学会Flask3 Python Web开发-使用SQLAlchemy动态创建数据库表
锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 前面我们定义了模型,我们可以通过sqlalchemy对象提供的create_all()方法来映射和动态创建数据库表。 因为我们用到…...
【spring】springAOP
1.基本概念 AOP即面向切面编程,它利用的是一种横切技术,解剖开封装的对象内部,并将那些影响多个类的公共行为封装到一个可重 用模块,这就是所谓的Aspect方面/切面。所谓的切面,简单点所说,就是将哪些与业务…...
解决VMware虚拟机CentOS 7 忘记登陆密码问题
1. 重启虚拟机,在重启时不停按E键进入初始化脚本编辑界面 2.在初始化脚本编辑界面,按↓键向下拉到最后,找到LANG/zh_CN.UTF-8那里,输入空格,接着添加 "init/bin/sh" 。然后按ctrlX键进入下一步。 3. 在界面中…...
如何在 Windows 10 启用卓越性能模式及不同电源计划对比
在使用 powercfg -duplicatescheme 命令启用 “卓越性能模式”(即 Ultimate Performance 模式)之前,有几个前提条件需要注意: 前提条件: 系统版本要求:卓越性能模式 仅在 Windows 10 专业版 或更高版本&a…...
基于 GEE 利用 Sentinel-2 数据反演叶绿素与冠层水分含量
目录 1 数据加载与预处理 2 叶绿素含量反演 3 冠层水分反演 4 数据可视化与导出 5 完整代码 6 运行结果 在生态学和环境科学领域,植被的健康状况是评估生态系统稳定性和功能的关键指标之一。而叶绿素含量和冠层水分含量作为反映植被生理状态的重要参数&#x…...
《鸿蒙系统下AI模型训练加速:时间成本的深度剖析与优化策略》
在当今数字化浪潮中,鸿蒙系统凭借其独特的分布式架构与强大的生态潜力,为人工智能的发展注入了新的活力。随着AI应用在鸿蒙系统上的日益普及,如何有效降低模型训练的时间成本,成为了开发者与研究者们亟待攻克的关键课题。这不仅关…...
PyTorch分布式训练
本文结构: 分布式训练概述环境设置数据并行(DDP)模型并行启动训练性能优化建议示例代码参考资料和相关问题 以下是为您整理的PyTorch分布式训练教程指南: 一、PyTorch分布式训练核心概念 数据并行:通过分割数据集实…...
ubuntu22.04 关于挂在设备为nfts文件格式无法创建软连接的问题
最近遇到情况,解压工程报错,无法创建软连接 但是盘内还有130G空间,明显不是空间问题,查找之后发现是移动硬盘的文件格式是NTFS,在ubuntu上不好兼容,于是报错。 开贴记录解决方案。 1.确定文件格式 使用命…...
C++编程:进阶阶段—4.2对象
目录 4.2 对象特征 4.2.1 构造函数和析构函数 4.2.2 构造函数的分类 4.2.3 拷贝函数调用时机 4.2.4 构造函数调用规则 4.2.5 深拷贝与浅拷贝 4.2.6 初始化列表 4.2.7 类对象作为类成员 4.2.8 静态成员 4.2.9 成员变量和成员函数的存储 4.2.10 this指针 4.2.11 空指针…...
C++跨平台开发环境搭建全指南:工具链选型与性能优化实战
C跨平台开发环境搭建全指南:工具链选型与性能优化实战 目录 开发环境搭建工具链选型性能优化实战常见问题排查 开发环境搭建 操作系统环境准备 Windows# 安装Visual Studio Build Tools choco install visualstudio2022buildtools choco install cmake --instal…...
常见JVM命令
1. java -XX:PrintCommandLineFlags HelloGC 作用:打印 JVM 启动时的命令行参数,包括用户显式设置的参数和 JVM 自动默认设置的参数。用于确认 JVM 实际使用的配置。 2. java -Xmn10M -Xms40M -Xmx60M -XX:PrintCommandLineFlags -XX:PrintGC -XX:Prin…...
C语言实现队列数据结构:思路与代码详解
目录 一、引言 二、整体思路 三、代码模块分析 (一)头文件包含与宏定义 (二)数据类型定义 (三)队列操作函数 1. 队列初始化 2. 队列销毁 3. 入队操作 4. 出队操作 5. 获取队头元素 6…...
【Docker项目实战】使用Docker与Caddy部署BanBan任务管理工具
【Docker项目实战】使用Docker部署BanBan任务管理工具 一、BanBan介绍1.1 BanBan简介1.2 主要特点1.3 使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载BanBan镜像五、…...
AI重构私域增长:从流量收割到终身价值运营的三阶跃迁
私域运营的AI进化论:内容即服务的三个阶段 随着企业微信生态的成熟,私域运营正经历从"流量收割"到"关系养成"的本质转变。在AIGC技术的推动下,2024年私域场景正式进入**"内容即服务"**的价值共创期࿱…...
es扩容节点以后写入数据量增加1倍
背景: es扩容一倍的数据节点以后 写入数据量增加1倍 业务反馈业务访问量没增加。 最后定位是监控数据: PUT _cluster/settings {"persistent": {"xpack.monitoring.collection.enabled" : "false"} }这个索引记录的是 节…...
Go本地缓存设计与实现
本地缓存是一个项目中很常见的组件。在很多人的眼中就是一个简单的key-value的map存储即可实现,但实际上,设计一个本地缓存需要考虑的问题远比你想象的多,比如说,本地缓存是将数据存储在内存,若数据量激增突破了内存限…...
04 | 初始化 fastgo 项目仓库
提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);本节课最终…...
Spring中复杂对象的创建方式:FactoryBean、实例工厂与静态工厂全解析
1.反转控制与依赖注入 控制:对于成员变量赋值的控制权 反转控制:把对于成员变量赋值的控制权,从代码中反转(转移)到Spring工厂和配置文件中完成 好处:解耦合 底层实现:工厂设计模式 依赖注入: 注入…...
异或和之和 第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组
异或和之和 题目来源 第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组 原题链接 蓝桥杯 异或和之和 https://www.lanqiao.cn/problems/3507/learning/ 问题描述 问题分析 要点1:异或运算 概念 异或(Exclusive OR,简称 XOR)是一种数学运算符,常用于逻辑运算与计算机…...
设计模式 一、软件设计原则
一、理解设计原则 1、单一原则 1.1 如何理解单一职责原则(SRP) 单一职责原则(Single Responsibility Principle,简称SRP),他要求一个类或模块应该只负责一个特定的功能,这有助于降低类之间的耦合度…...
修复Electron项目Insecure Content-Security-Policy(内容安全策略CSP)警告的问题
将以下代码粘贴进html的<header>标签内 <metahttp-equiv"Content-Security-Policy"content"default-src self; style-src self unsafe-inline; img-src self data:; "> 解释一下上面代码中的属性含义 default-src self:配置加载策…...
机器人交互系统 部署构建
环境要求 Ubuntu 20.04 或更高版本ROS Noetic 或兼容版本Python 3.8 安装步骤 1. 安装ROS环境(如未安装) sudo apt update sudo apt install ros-noetic-desktop-full source /opt/ros/noetic/setup.bash2. 创建工作空间并克隆代码 mkdir -p ~/code…...
当AI回答问题时,它的“大脑”里在炒什么菜?
文章目录 1. 拆解订单:AI如何听懂你的“暗号”?2. 调用工具:AI的“万能工具箱”里有什么?3. 知识不够?去“图书馆”现学现卖!4. 人类的秘密武器:给AI戴上“镣铐”5. 为什么AI会“胡言乱语”&…...
linux 软件扩展GPU显存
概述 共享内存可以通过 Unified Memory(统一内存)来实现,它允许 CPU 和 GPU 共享相同的内存地址空间,从而方便数据的传输和访问。 利用该技术可解决家用GPU 机器学习时显存不足的问题 (注: 虽然解决了爆显…...
【RabbitMQ】Spring Boot 结合 RabbitMQ 完成应用间的通信
🔥个人主页: 中草药 🔥专栏:【中间件】企业级中间件剖析 Spring 框架与 RabbitMQ 的整合主要通过 Spring AMQP(Advanced Message Queuing Protocol)模块实现,提供了便捷的消息队列开发能力。 引…...
DeepSeek本地化部署(DeepSeek+olloma+Dify)
文章目录 概要需要准备的工具Ollama准备内容Docker准备内容Dify准备内容本地访问Dify 概要 提示:本篇文章主要讲述如何部署本地Deepseek私有大模型,使用Windows无显卡环境进行部署 需要准备的工具 Ollama、Docker Desktop 下载地址: Ollama…...
Spring boot3-WebClient远程调用非阻塞、响应式HTTP客户端
来吧,会用就行具体理论不讨论 1、首先pom.xml引入webflux依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId> </dependency> 别问为什么因为是响应式....…...
Ubuntu22.04安装数据
数据库安装步骤: sudo apt-get update sudo apt install mysql-server mysql-client sudo systemctl start mysql sudo systemctl status mysql (1)在命令行登录 MySQL 数据库,并使用 mysql 数据库 (必须使用这个…...
【python-uiautomator2】手机上的ATX应用界面报错问题处理:无法提供服务,非am instrument启动
目录 一、前期准备 1.1 插入设备 1.2 安装atx-agent 二、解决报错:无法提供服务,非am instrument启动 2.1 出现报错 2.2 尝试解决 2.3 最终解决 三、开启ATX的悬浮窗权限 一、前期准备 1.1 插入设备 本地插入待执行设备,待执行设备…...
自动化测试介绍及学习路线
目录 一、自动化测试 1.1 自动化测试的概念 1.2 自动化测试的主流领域 接口自动化测试 UI自动化测试 持续集成 二、学习路线 一、自动化测试 1.1 自动化测试的概念 自动化测试是指利用软件工具或脚本来执行测试用例和比较实际结果与预期结果的过程,通过运行…...
Python:函数(一)
python函数相关的知识点 1. 函数定义与调用 定义:使用 def 关键字,后接函数名和参数列表。 def greet(name):"""打印问候语(文档字符串)"""print(f"Hello, {name}!") 调用:…...
qml c++混合编程注意事项
在Qml和C类进行数据交互时,通用的办法都是注册C到Qml中,但是很多时候C的对象是在C中进行创建,如果在Qml中创建了,数据之间的交互就会出现无法控制的问题。 信号与槽、上下文等都是数据交互的方式,但是当嵌套多层时&…...
Leetcode6-Z字形变换
题目链接:6. Z 字形变换 - 力扣(LeetCode) 思路: 定义numRows个字符数组,用于存每一行的字符;再定义一个标志行数的变量cnt,cnt在0到numRows-1之间不停的加一或减一(当cnt到0了&am…...
【eNSP实战】配置交换机端口安全
拓扑图 目的:让交换机端口与主机mac绑定,防止私接主机。 主机PC配置不展示,按照图中配置即可。 开始配置之前,使用PC1 ping 一遍PC2、PC3、PC4、PC5,让交换机mac地址表刷新一下记录。 LSW1查看mac地址表 LSW1配置端…...
React.js 基础与进阶教程
React.js 基础与进阶教程 React.js 是由 Facebook 开发的流行前端 JavaScript 库,专为构建用户界面(UI)设计,尤其适用于单页面应用(SPA)。它采用组件化开发模式,使 UI 结构更加清晰、可维护性更…...
Docker基础入门(一)
初识Docker 什么是Docker Docker是一个快速交付应用、运行应用的技术: 可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离容器,各个应用互不干扰启动、移除都可以通过一行命令完成&…...
moment.js时间处理库
目录 一、moment().isValid()验证时间是否有效 二、moment().second()获取秒数或者设置秒数 三、moment().day()获取星期或者设置星期 四、moment().add()加法操作 五、moment().subtract()减法操作 六、moment.max()最大值 七、moment.min()最小值 八、克隆时间 一、mo…...
基于hive的电信离线用户的行为分析系统
标题:基于hive的电信离线用户的行为分析系统 内容:1.摘要 随着电信行业的快速发展,用户行为数据呈现出海量、复杂的特点。为了深入了解用户行为模式,提升电信服务质量和精准营销能力,本研究旨在构建基于 Hive 的电信离线用户行为分析系统。通…...
循环神经网络(RNN):时序建模的核心引擎与演进之路
在人工智能处理序列数据的战场上,循环神经网络(RNN)如同一个能够理解时间的智者。从 2015 年谷歌神经机器翻译系统颠覆传统方法,到 2023 年 ChatGPT 实现对话连续性,这些突破都植根于 RNN 对时序建模的深刻理解。本文将…...
docker 安装常用镜像
我们在上篇文章中已经修改了daemon.json 安装镜像时如果search超时就直接pull 安装mysql docker pull mysql:5.7 启动命令 docker run --name mysql-docker -p 3306:3306 -e MYSQL_ROOT_PASSWORDroot1234 -d mysql:5.7 ocker run:运行docker容器命令 --name my…...
大数据学习(63)- Zookeeper详解
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦🤞 …...
安卓Compose中accompanist库使用详解
安卓Compose中accompanist库使用详解 文章目录 安卓Compose中accompanist库使用详解一、Accompanist 库概览二、核心组件详解三、总结与建议 本文首发地址 https://h89.cn/archives/348.html 最新更新地址 https://gitee.com/chenjim/chenjimblog 一、Accompanist 库概览 Acco…...
Gateway:网关路由与登录鉴权
在微服务架构中,用户登录和身份校验的处理方式确实与单体应用有所不同。在单体架构中,一旦用户通过身份验证,其会话信息可以在整个应用范围内共享,所有模块都能访问到用户信息。然而,在微服务架构下,每个服…...
【MySQL篇】MySQL内置函数
目录 1,日期函数 2,字符串函数 3,数学函数 4,其他函数 实战OJ 1,日期函数 日期类型在之前文章【数据类型】中有描述 传送门:【MySQL篇】数据类型_mysql 数据类型-CSDN博客 函数名称描述current_dat…...