当前位置: 首页 > article >正文

图形学面试题

仅用于个人学习记录主要参考乐书和这篇https://zhuanlan.zhihu.com/p/430541328还有这个网站https://learnopengl-cn.github.io/这个写的真的非常好数学方面点乘/点积/内积ab axbx ayby azbz |ab|cosθ几何意义1、a在b上的投影再乘以b的长度带方向2、投影正负号和方向有关投影0时垂直0时方向相反 0时方向相同。点乘是标量abba叉乘/叉积/外积AxB x1y2 -y1x2 |A||B|Sin(θ)AxB -(BxA)几何意义右手定则方向为和AB垂直的法线方向叉乘绝对值为平行四边形面积判断点是否在三角形内重心坐标法向量叉乘法沿逆时针方向三角形两两顶点构成三个向量比如AB,BC,CA分别用这三个向量与起点和P的交点构成的向量求叉乘如ABxAP, BCxBP, CAxCP由右手定则如果三个结果都是正的说明这个点都在向量的左边可以推导得出这个点在三角形内否则只要有一个是负数就说明在右手边在三角形外了。面积法叉乘可以算出面积三个小三角形面积之和 原三角形面积就在内部在外部。齐次坐标用 ​​N1 维的向量​​来表示一个 ​​N 维空间​​中的点或向量引入这个额外的维度 w通常称为齐次坐标的​​“重量”​​使得齐次坐标具有​​尺度不变性。在笛卡尔坐标系下引入一个维度使得齐次坐标具有尺度不变性原本旋转缩放用矩阵乘法而平移变换用加法引入齐次坐标后可以把平移放在第四维使得这几种变换都可以用矩阵乘法表示。并且可以用w分量来作投影除法将裁剪空间转为NDC空间。判断光线与三角形是否相交第一种方法代入点法式方程计算交点坐标N(P - P0) 0再用叉乘判断是否在三角形内部。第二种方法POtd代入满足t0αβγ0时相交。若只能命中一个三角形则根据t大小比较先命中小的t。封闭的物体射线从中穿过时一定命中奇数个三角形。1、渲染管线渲染流水线计算机绘制图像的过程图形渲染管线实际上指的是一堆原始图形数据途经一个输送管道期间经过各种变化处理最终出现在屏幕的过程。分为应用阶段、几何阶段、光栅化阶段、像素处理阶段1.1、应用阶段由CPU完成后面的阶段为GPU完成核心目标是准备渲染需要的数据并提交给GPU三个任务判断物体的可见性并剔除不可见物体设置每个模型的渲染状态包括材质纹理shader等通过DrawCall提交渲染图元给GPU。1.1.1、DrawCallDrawCall是通知GPU绘制的指令。DrawCall开销大主要是因为CPU的性能瓶颈。每次调用DrawCall需要CPU准备渲染数据通知GPU切换渲染状态。并且涉及用户态到内核态的切换。1.1.2、DrawCall优化优化方法批处理GPU实例化共用材质合并纹理图集遮挡剔除减少透明物体。静态批处理适合不会移动的静态物体但合并的网格数据放在内存中增加内存占用动态批处理适合顶点数少的动态物体小于300个顶点并且材质等相同CPU对顶点进行模型变换到统一的世界空间合并网格把所有顶点数据放到新的顶点缓冲区一次setpasscall和drawcall因此太多顶点反而可能导致性能下降GPU实例化适用于大量相同的物体允许相同的模型和材质批量渲染CPU准备共享的材质网格数据作为模板实例化数据缓冲区放矩阵变换uv偏移等数据还有顶点数据缓冲区放顶点数据由GPU进行矩阵变换CPU准备好共享数据和独有数据后打包成一个数组一次DrawCall发送所有数据GPU快速渲染。合并纹理/图集减少纹理切换LOD远处用低精度模型减少顶点数不减少drawcall共用材质材质相同才可以合批因为材质不同必须得切换渲染pass遮挡剔除减少不必要的DrawCall减少透明物体透明物体需要额外处理混合顺序混合依赖背景色容易破坏合批要求的连续渲染相同材质物体条件还会overdraw(一个像素处理多遍)。动态批处理和GPU实例化的区别GPU实例化是一次drawcall用相同的shader处理不同的参数而动态合批是让物体合并为一个网格1.2、几何阶段将3D顶点数据变换到屏幕空间。主要包含顶点着色器MVP变换、图元装配、曲面细分着色器、几何着色器、裁剪、屏幕映射1.2.1、顶点着色器可编程对每个顶点进行计算操作很多效果可以在这一阶段实现相对逐片元操作来说计算开销小但效果较差。模型变换将模型坐标从本地空间变换到世界空间类似于归一化视图变换从世界空间变换到观察空间从原点坐标改为观测点的坐标和方向投影变换从观察空间变换到裁剪空间将视锥体或立方体转为立方体空间1.2.2、其他图元装配不可变将顶点数据转为图元数据三角形、线段、点曲面细分着色器可编程动态添加更多的顶点动态细分LOD几何着色器可编程增减顶点及其他操作效率低变化回执后缓冲在渲染时可以用前缓冲的信息作为上一帧信息裁剪可配置剔除视野外的顶点屏幕映射不可变将裁剪空间转为屏幕空间1.3、光栅化阶段有的认为包含像素处理阶段利用上一阶段的数据生成屏幕图像。主要包含三角形设置、三角形遍历、片元着色器、逐片元操作最后生成屏幕图像。三角形设置不可变计算每个三角形的边函数和顶点属性梯度顶点属性梯度用于快速计算在三角形内部的颜色纹理等属性三角形遍历不可变遍历所有像素计算是否在三角形内输出片元序列MSAA在这里进行计算透视校正插值进行非线性插值1.3.1、像素处理阶段片元着色器可编程输出每个片元的颜色深度等逐片元操作可配置裁剪测试、透明测试、模板测试、深度测试以及色彩混合等2、各种测试2.1、深度测试根据深度值决定是否渲染。深度缓存储存了每个像素到相机的最近的深度计算每个物体时会与深度缓存对比当前深度小于缓存就更新缓存反之则当前点会被丢弃。需要在内存中维护深度缓存区。2.1.1、Early-ZEarly-Z技术将深度测试提前到片段着色器之前提前剔除不会显示的部分减少片元着色器中光照等计算操作减少OverDraw。在片元着色器修改深度值、有透明物体、alpha test等操作的情况时会自动关闭因为透明测试在片元着色器之后Early-Z在片元着色器之前这时候不知道遮挡的会不会通过透明测试可能会出现透明物体在不透明物体前结果不透明物体渲染不出来的情况。2.1.2、PreZ阶段一深度预写入通道Depth Prepass / Z-Prepass目标生成一张准确的、包含所有不透明与透明测试Alpha Test物体最终深度信息的深度缓冲区。渲染对象必须渲染所有不透明物体RenderQueue Geometry和所有使用clip/discard进行透明测试的物体如树叶、栅栏RenderQueue AlphaTest。 不渲染真正的半透明混合物体RenderQueue Transparent使用Alpha Blend。渲染状态与Shader深度测试开启通常为ZTest LEqual。 深度写入开启ZWrite On。 颜色写入关闭ColorMask 0不输出任何颜色只填充深度。 使用极简Shader仅包含必要的顶点变换对于透明测试物体需要执行clip操作。 关键原理此阶段唯一目的就是写入深度。虽然clip会导致本通道的Early-Z优化失效所有片元都需经过深度测试但这是必要的代价目的是为下一阶段“清扫战场”。结果GPU的深度缓冲区中存储了场景最终可见的不透明及透明测试表面的精确深度值。阶段二主着色通道Main Color Pass目标在阶段一生成的深度缓冲区“保护”下高效地执行所有复杂的像素着色计算纹理采样、光照模型等。渲染对象所有需要最终显示颜色的物体同样包括不透明和透明测试物体。半透明物体通常不在此流程中按标准方式渲染。核心渲染状态深度写入关闭ZWrite Off。避免破坏阶段一生成的完美深度图。 深度测试设置为 ZTest Equal或LEqual并配合深度偏移确保精确匹配。这是关键设置意味着只有深度值与缓冲区中存储值完全一致的像素才会被处理。 Shader使用完整的、包含光照和纹理的着色器但严禁任何会修改深度或导致深度测试不确定的操作如 再次使用clip/discard。 在片元着色器中写入深度SV_Depth。 开启Alpha To Coverage在某些硬件上会影响Early-Z。2.2、模板测试根据像素的范围决定是否渲染。可用于渲染物体轮廓边框限制渲染区域做复杂遮罩贴花效果等。需要模板缓冲区与深度缓存区共享内存。2.3、alpha测试根据透明度决定是否被渲染常用于不影响深度测试的全透明片段。将alpha值与参考值对比没通过就不会被渲染。2.4、裁剪测试简单设置一个矩形裁剪框限制渲染范围。灵活度低。顺序裁剪测试alpha测试模板测试深度测试。3、MVP变换矩阵这篇讲的不错https://blog.csdn.net/zsy721201/article/details/140572065模型变换model transform顶点变换的第一步将顶点坐标从模型空间变换到世界空间先进行缩放、旋转后再进行平移。观察变换view transform步骤推导已有条件摄像机坐标 Px,y,z向上方向up。把摄像机作为原点因此最终摄像机坐标x,y,z-(0,0,0)。那么原本世界空间所有点的平移(-x,-y,-z)。设平移矩阵为T。最终的变换矩阵VRT先平移再旋转。摄像机在世界空间的三个方向[up,right,forward]forwardP-Orightcross(forward,up)设[up,right,forward]为R’是从观察空间到世界空间的旋转变换而它的逆矩阵是世界空间到观察空间的旋转变换并且由于是正交矩阵因此转置即可求出逆矩阵(R’)TRVRT(R’)TT。详细整理第二步将顶点坐标从世界空间转到观察空间把摄像机作为原点变换结束后的坐标是相对于摄像机的三维坐标这里是从一个世界坐标系变为一个局部坐标系。如果摄像机在世界空间中的位置是 e(eyex​,eyey​,eyez​)那么平移矩阵 T 就是将整个世界平移 −e使得摄像机原点与世界原点重合设平移矩阵为Ttransform。摄像机世界坐标(x,y,z),方向矩阵[up,right,forward]。通过叉积计算得到了相机局部坐标系的三个​​单位基向量​​。将它们作为​​列向量​​组合成一个矩阵[up,right,forward]设为R’(Rotation’)。这个矩阵R’本身表示的是从​​相机空间​​到​​世界空间​​的旋转变换。然而观察变换的目的恰恰相反我们需要将顶点从​​世界空间​​变换到​​相机空间​​。因此我们需要的是矩阵R’的​​逆变换​​。MRT。旋转矩阵不好求但逆矩阵已经有了R’逆矩阵转置一下就等于旋转矩阵最终变换矩阵MRT(R-1)TT(R’)TT。因为OpenGL使用右手坐标系unity的观察空间也跟着用右手坐标系但模型空间和世界空间还是左手坐标系。投影变换projection transform投影变换将顶点坐标从观察空间转到裁剪空间再通过透视除法除以w分量标准化到NDC归一化设备坐标后续的屏幕映射用视口变换再转到屏幕空间。正交投影的w分量等于1因此数值和NDC一样。而透视投影w分量为当前顶点的深度zxy除以z后会有近大远小的区别越远z越大xy就越小z_ndc (A * z_view B) / (-z_view) -A - (B / z_view)存储在深度缓存中的ndc的深度值是非线性的反比例的越近精度越高。裁剪空间是一个立方体空间最终图像会投影到近裁剪面。透视投影透视投影可以看作先把梯形挤压为长方形再进行正交投影这里的挤压只针对x,y。某个点(x,y,z,1)挤压后变为(nx/z,ny/z,unknown,1)乘z后变为(nx,ny,unknown,z)带入下面的矩阵变换等式可得矩阵为带入两个特殊点1、近平面zn挤压后不变并且xy是变量矩阵应该是和xy无关的因此前两个空为0。2、远平面的中心点zf挤压后完全不变代入(nf)/2的点会发现非nf平面的点深度会变会靠向远平面这是非线性变换再乘以正交投影矩阵得到透视投影正交投影裁剪空间是长方体缩放至x,y,z∈[−1,1]长方体参数NearFar高Size宽高比Aspect1、平移到观察空间原点中心2、缩放到长宽高都为1-(-1)2的空间4、光照模型Lambert光照漫反射光照颜色 光源颜色 * 材质漫反射颜色 * max(0, 法线向量 * 光源向量)背面无光是0黑色而不是为负。记得单位化还有半兰伯特漫反射光照颜色 光源颜色 * 材质漫反射颜色 * (max(0, 法线向量 * 光源向量) * 0.5 0.5)Phong式高光高光反射颜色 光源颜色 * 材质高光反射颜色 * max(0, 观察方向向量 * 反射向量)幂Blin-Phong高光高光反射颜色 光源颜色 * 材质高光反射颜色 * max(0, 法线向量 * 半角方向向量)幂半角方向向量 入射光单位向量 视角单位向量原本的冯需要计算反射向量反射向量涉及点积和反射公式而半角向量只有加法高效很多并且高光过渡更为平滑。反射光线与观察方向向量夹角90°时phong式高光为0此时高光在边界处突然消失。详细区别可以看这个https://learnopengl-cn.readthedocs.io/zh/latest/05%20Advanced%20Lighting/01%20Advanced%20Lighting/光照模型物体表面光照颜色 环境光 漫反射 高光反射5、PBR基于物理的渲染基础三大条件基于微平面(Microfacet)的表面模型将物体表面分为无数随机朝向的理想镜面反射的小平面越粗糙漫反射越强越光滑高光越明显。能量守恒出射光线能量不超过入射光线的能量并且随着粗糙度提升有更多的反射光线被遮挡导致能量损失应用基于物理的BRDF采用ωi和ωo作为输入的 Blinn-Phong光照模型也是BRDF。但不符合能量守恒因此不是PBR。菲涅尔反射不同角度入射会有不同的反射率比如玻璃或水面镜面边缘更多是反射出来的高光而正对着的区域可以看清纹理不同物质也有不同反射率主要可分为金属和非金属。线性空间光照计算在线性空间完成。色调映射HDR渲染出来的亮度值会超过显示器最大亮度需要把光照亮度映射到显示器正常显示的范围。物质的光学特性渲染中主要分为金属和非金属。非金属具有灰色的镜面反射而金属是彩色镜面反射金是金色铁是银色铜是黄色。BRDF。5.1、辐射度量学辐射能Q光穿过平面的光能辐射通量ɸ单位时间内光穿过平面的光能辐射强度/光强度I单位立体角的辐射通量辐射率/光亮度L单位立体角单位面积的辐射通量是带方向的向量辐照度E单位面积的辐射通量是辐射率的积分。5.2、BRDFBRDF(Bidirectional Reflectance Distribution Function)译作双向反射分布函数是一个用来描述物体表面如何反射光线的方程。精确定义是出射光辐射率(Radiance)的微分和入射光辐照度(Irradiance)的微分之比。BRDF 定义了从某个特定方向入射的光线有多少比例被反射到另一个特定的出射方向。5.3、渲染方程在一个点看向物体一点看到的出射点亮度点的自发光亮度四面八方入射光对这个方向的反射光亮度之和渲染方程是一个描述光能在场景中流转的方程它基于能量守恒定律在理论上给出了一个完美的光能求解结果。其含义是在某个视点看向特定的位置x看到的出射光亮度(辐射率)Lo等于x点的自发光亮度Le(辐射率)以及该点的反射光亮度之和。5.4、Cook-Torrance BRDFalbedo是表面颜色/π是为了标准化。D法线分布函数决定高光反射的形态和集中程度​​以Trowbridge-Reitz GGX为例n为表面的法线h为半角向量a为表面的粗糙度G几何函数负责计算​​因微几何表面的自遮挡而损失的光线比例​​这里是GGX与Schlick-Beckmann近似的结合体因此又称为Schlick-GGXk是α的重映射(Remapping)F菲涅尔方程决定​​反射与折射的能量分配垂直观察物体时会看到正常的表面而观察角度与法线接近垂直时会有明显的高光菲涅尔方程是一个相当复杂的方程式不过幸运的是菲涅尔方程可以用Fresnel-Schlick近似法求得近似解F0表示平面的基础反射率它是利用所谓折射指数(Indices of Refraction)或者说IOR计算得出的。金属物体直接使用这个公式并不正确需要对照表代入计算。分母4(n·l)(n·v)是一个​​校正因子​​用于完成从微观几何局部空间到整个宏观表面的局部空间之间变换的微平面量的校正5.5 间接光/环境光IBL将环境光的积分操作预处理存在立方体贴图中也可分为漫反射和镜面反射计算公式和直接光照类似。漫反射预处理辐照度图对环境贴图进行余弦加权的半球卷积积分表示每个法线方向的入射光平均亮度运行时根据法线即可采样出漫反射光预滤波环境贴图进行不同粗糙度卷积储存到mipmap中镜面反射要预处理BRDF-LUT这是一个储存系数的纹理贴图里面包含菲涅尔方程的scale和bias直接查找表就可以得到数值再带入方程就可以得到镜面反射的环境光照。纹理过滤邻近过滤直接选择最近的像素适合像素风线性过滤基于附近的像素计算插值得出颜色mipmap远处物体只要用几个像素就能描述此时再用复杂纹理采样会浪费性能一个像素映射到纹理上有较大的范围计算较多。提前存储好不同分辨率的纹理可简化计算。每次都是当前分辨率/2占用内存为11/41/16…为1.3循环,额外内存占用并不多却能较明显加速。欧拉角、旋转矩阵、四元数表示旋转角度欧拉角表达直观存储占用小只有三个数。但有万向节死锁问题。计算效率低不能插值计算。用于人机交互方便旋转矩阵计算效率高避免万向节死锁。储存占用大9个参数无法线性插值。四元数非常不直观四个参数存储占用小。计算效率高可进行球面线性插值计算旋转中间形态避免万向节死锁。阴影lightmap适用于静态物体可渲染出静态阴影存储好静态物体对应的光照后就直接拿来混合就行但是在动态场景动态光源下阴影不会随运动变化而变化。shadowmap传统前向渲染1、从光源对整个场景计算深度图2、屏幕空间的每个像素变换到光源空间每个像素对比深度值在光源空间判断是否有阴影并在屏幕空间渲染。屏幕空间阴影延迟渲染1、得到摄像机视角的深度纹理延迟渲染自带G-Buffer2、得到光源视角的深度纹理3、全屏幕的后处理Pass(对所有物体渲染后对整个屏幕后处理因此把最终计算放到屏幕空间)把第一步的深度纹理变换到光源空间和第二步的深度纹理对比深度值输出到一张屏幕空间阴影图4、最终计算时采样屏幕空间阴影图的信息判断是否有阴影并在屏幕空间渲染。优化了对阴影的overdraw屏幕空间阴影的优化主要是原本一个物体被多个物体挡住会多次完整的计算光照和阴影overdraw。而屏幕空间阴影相当于在一张纹理图上作计算避免了overdraw但如果一个物体在摄像机视野之外它既不会出现在G-Buffer中也无法贡献阴影。这可能导致当物体移入或移出屏幕时阴影会突然出现或消失。存在一些缺点1、深度是浮点数本身存在精度问题在和光线平行的地方会出现自己挡住自己的现象存在抖动2、shadowmap本身也是一个像素图若太小会存在比较明显的锯齿太大又会占用过多内存。解决方法1、添加深度偏移固定偏移或法线偏移根据与光源夹角但会引起彼得潘效应阴影与物体存在一条缝隙好像阴影飘在物体上需要找准合适的偏移。2、软阴影软阴影不容易暴露锯齿3、提高阴影贴图分辨率4、级联阴影贴图CSM近处用高分辨率阴影贴图远处用低分辨率提升整体质量。/* 你问到了核心让我重新仔细分析——**实际上你的理解流程有个关键错误**这导致了困惑。 ## 重新梳理两种技术的本质区别 ### 传统 Shadow Mapping你的理解正确 光源视角渲染场景 → Shadow Map包含物体A、B、C的深度 ↓ 摄像机视角渲染场景时 像素P对应世界点X→ 变换到光源空间 → 采样Shadow Map对比深度 **关键点**Shadow Map是在**光源空间**生成的包含**所有在光源视野内的物体**不管它们在不在摄像机视野内。 ### 屏幕空间阴影你描述的流程有问题 你描述的流程 把第一步的深度纹理摄像机深度变换到光源空间和第二步的深度纹理对比 **这个描述是错误的** ❌ 如果真的是这样操作确实不会丢失屏幕外阴影。但实际的屏幕空间阴影**不是这样做的**。 --- ## 正确的屏幕空间阴影流程 屏幕空间阴影如UE的Contact Shadows真正的做法 步骤1G-Buffer Pass摄像机视角 - 得到屏幕空间的深度图、法线图、世界坐标等 步骤2屏幕空间Ray Marching关键 - 对每个屏幕像素沿光源方向在屏幕空间做Ray Marching - 采样G-Buffer深度判断射线是否被遮挡 - 完全不使用光源视角的Shadow Map **核心区别** | | 传统Shadow Map | 屏幕空间阴影 | |---|---|---| | **遮挡查询方式** | 像素→光源空间→采样Shadow Map | 屏幕空间Ray Marching采样G-Buffer | | **使用的数据源** | 光源视角的深度图 | 摄像机视角的G-Buffer | | **屏幕外物体** | 只要在光源视野内就能投射阴影 | 不在G-Buffer中 无法投射阴影 | --- ## 为什么你会混淆 可能你把**延迟渲染中的Shadow Map应用**和**屏幕空间阴影技术**搞混了 ### 情况A延迟渲染 传统Shadow Map不是屏幕空间阴影 1. G-Buffer Pass摄像机视角 2. 光源Shadow Map Pass光源视角 3. 光照Pass读取G-Buffer像素变换到光源空间采样Shadow Map **这个不会丢失屏幕外阴影**因为用了Shadow Map。 ### 情况B真正的屏幕空间阴影Contact Shadows 1. G-Buffer Pass 2. 屏幕空间Ray Marching只用G-Buffer不用Shadow Map **这个会丢失屏幕外阴影**因为遮挡查询完全依赖G-Buffer。 --- ## 图示说明 场景光源在上方墙在屏幕外角色在屏幕内 [光源] | ↓ [墙]屏幕外---- 投射阴影 ---- [角色]屏幕内 | 技术 | 结果 | 原因 | |------|------|------| | 传统Shadow Map | ✅ 角色有阴影 | Shadow Map包含墙的深度 | | 屏幕空间阴影 | ❌ 角色无阴影 | G-Buffer中没有墙的信息Ray Marching找不到遮挡物 | --- ## 总结 **你描述的流程摄像机深度变换到光源空间采样Shadow Map实际上是延迟渲染传统Shadow Map不是真正的屏幕空间阴影技术。** 真正的屏幕空间阴影**完全抛弃Shadow Map**只在屏幕空间做Ray Marching所以才会丢失屏幕外信息。这也是为什么它通常只作为**短距离接触阴影Contact Shadows**的补充而不是替代完整Shadow Map。 */光线追踪普通光线追踪考虑镜面反射只处理直接光照从观察点确定的向每个像素射线达到散射点就计算颜色达到折射面或镜面则继续直到最大递归深度或射出场景。路径追踪考虑漫反射在直接光照的基础上加入了间接光照每个像素随机的采样几条射线根据俄罗斯轮盘赌决定是否反射并按材质概率随机反射直到逃出场景、射中光源或轮盘决定不反射每条成功路径都对像素计算贡献。俄罗斯轮盘赌为了控制路径长度避免无限递归并且整体统计符合期望随机发射多条光线按照蒙特卡洛积分近似求解颜色。空间加速1、AABB包围盒轴对齐包围盒计算仅用轴向量计算快2、均匀格子效率较低3、八叉树有些还在用4、kd树无法保证一个物体在一个格子很难计算三角形和格子相交情况因此不好用5、层次包围盒Bounaing Volume Hierarchy(BVH)好用一个物体只出现在一个包围盒省去三角形和包围盒求交。抗锯齿SSAA简单以4xSSAA为例原本800x600变为1600x1200所有计算都乘4倍。SSAA在光栅化阶段对每个像素进行多重采样每个子样本独立执行完整的片元着色器计算最后在输出到帧缓冲区前进行一次下采样解析/滤波。MSAA只在光栅化阶段在一个像素采样4个点但是着色阶段片元着色器一个像素依然只计算一次而着色阶段是比较耗时的因此MSAA比SSAA好很多。MSAA在光栅化阶段需要对所有子样本进行几何计算计算有没有被遮挡然后延迟渲染有个gbuffer它在gbuffer里面存储了整个像素中心的几何信息但它这样就丢失了对子样本的几何信息的计算。FXAA计算一个边缘图在边缘图上进行范围加权平均。前向渲染和延迟渲染前向渲染对场景复杂度和光源数敏感类似暴力的对每个物体的片元每个光源遍历计算光照O(所有物体产生的总片元数*n)的复杂度并且会计算被遮挡的光源允许为每个物体使用高度定制化的shader对于很多shader的渲染画面表现较好但是多光源时效率低可以通过先计算深度的方式先剔除不需要的光照还有光源重要性分级等级高的逐像素计算次级逐顶点其他按球谐函数计算。延迟渲染分两步先计算所有顶点信息并存为一个二维的GbufferGbuffer储存了法线颜色世界坐标等信息第二步对Gbuffer的每个片元计算光照。这样做的复杂度是O(屏幕像素数*n)但要求存储较多信息手机带宽少无法使用且需要shader类型少多种shader时在光照阶段根据ID分支调用不同的shader这会增加复杂性和性能开销并且半透明物体需要延迟渲染后再前向渲染。双缓冲单缓冲的绘图操作直接在显示缓冲区进行屏幕同步读取因绘制未完成时屏幕就开始读取导致一帧内显示新旧不同内容。双缓冲分为前台缓冲区​ 和 后台缓冲区所有绘图操作先在后台缓冲区完成再一次性切换到前台切换操作非常快可能是交换指针地址。帧率太高渲染的慢的时候仍有可能出现撕裂用垂直同步强制绘制完一帧再刷新可避免画面撕裂但会有画面延迟。为什么有了VAO和VBO还要有EBO?在没有EBO的情况下如果要绘制一个矩形需要将6个顶点的数据全部传入GPU即使有两个顶点是重复的这会导致内存浪费和传输效率降低。EBO通过 “索引绘制”​ 解决了这个问题在顶点数组中定义不重复的顶点例如矩形的4个角。在索引数组中定义绘制的顺序即指明哪三个顶点构成一个三角形。半透明物体和不透明物体渲染顺序先渲染不透明物体开启深度测试和深度写入再渲染半透明物体开启深度测试关闭深度写入开启混合。如何优化shader计算量提前剔除early-zz-prepass计算频率优化将精细要求低的放到顶点着色器计算精度控制使用数据类型优先级fixed half float double非必要不用高精度运算优化优化运算表达式MAD多个标量间相同操作合并为一组向量操作SIMD等预处理与烘焙提前烘焙将一些计算储存在纹理贴图中合并纹理将多张小纹理放到一个图的不同通道性能优化——减少分支语句我的理解原本GPU对于所有的区域都有一个线程负责执行计算GPU基本调度单位称为wrap或wavefront。一个wrap的计算因为处理逻辑相同只有数据不同所以可以并行执行。而有了分支语句会破坏这个并行计算wrap会让活跃线程进入a语句执行其他线程通过​​执行掩码控制不让执行但仍然占用指令带宽再让部分线程进入b语句执行其他线程不动以此类推原本可能是一次32个线程并行计算8个分支后可能变为8次分别有4个线程先后串行计算。Warp 是物理单位不会拆分​​你的理解中“分割出两个wrap”或“变为8次分别有40个线程”是一种逻辑上的比喻。实际上​​物理上的 Warp (32线程) 并不会被拆分成更小的调度单位​​。它始终作为一个整体被调度器处理只是内部的线程在执行不同分支时会通过​​执行掩码 (Execution Mask)​​ 来控制哪些线程是活跃的。​​性能损失不仅是“串行”​​性能损失不仅来自于串行执行还来自于​​GPU实际上执行了所有分支的所有代码​​。对于那些被遮蔽的线程它们可能仍然占用了指令发射带宽或产生了开销尽管不执行有效操作。​​并非所有分支都如此糟糕​​如果你的分支条件是一个​​Uniform变量​​在一个Draw Call或Warp内所有线程的值都相同或者编译器能在编译时确定分支路径如使用宏#ifdef那么​​不会发生Warp Divergence​​因为所有线程都会做出相同的选择这时性能开销极小甚至为零。线性空间和srgb空间是怎么映射的线性空间是为了让计算机进行正确的物理计算而sRGB空间是为了让人眼看到舒适的图像。储存的是sRGB空间的值计算时先去除gamma矫正在线性空间中完成计算再用gamma矫正转到人类适应的sRGB空间。gamma矫正计算得出的线性空间的值计算0.45次幂转为gamma空间。因为人类对暗部特征信息比较敏感。为什么延迟渲染对MSAA支持不好MSAA在光栅化前顶点着色器后需要几何信息而延迟渲染将信息输出到G-buffer纹理上是二维空间丢失了几何信息。色调映射HDR与LDR的区别正常设备是LDR亮度范围是[0, 1]HDR技术允许亮度超过1渲染时通过色调映射转回LDR可以保证在明亮和黑暗区域无细节损失。FrameBuffer一个帧缓存是这样的两个帧缓存组成双缓冲区变换反馈OpenGL3.0的新特性主要是存储上一帧信息通常来计算粒子直接取上一帧数据提高效率cpu的命令缓冲区保证渲染顺序正确然后通过双缓冲前缓冲用于显示当前画面同时后缓冲在渲染时可以用前缓冲的信息作为上一帧信息双缓冲渲染管线通常使用前缓冲区用于当前显示和后缓冲区用于下一帧绘制来避免画面撕裂。当一帧绘制完成后通过“交换”操作呈现。这个过程本身就是一种最基础的“回执”确保我们总是基于一个完整的、最新的画面状态进行下一步。命令缓冲区CPU和GPU是并行工作的。CPU将渲染命令如DrawCall放入一个命令缓冲区GPU再从其中读取并执行。这个缓冲区保证了命令的有序提交和执行是协调CPU和GPU工作的“回执”系统。

相关文章:

图形学面试题

仅用于个人学习记录 主要参考乐书和这篇:https://zhuanlan.zhihu.com/p/430541328 还有这个网站:https://learnopengl-cn.github.io/,这个写的真的非常好 数学方面 点乘/点积/内积 ab axbx ayby azbz |ab|cosθ 几何意义:1…...

QT开发桌面应用:集成Graphormer的分子属性预测软件

QT开发桌面应用:集成Graphormer的分子属性预测软件 1. 为什么化学研究者需要这个工具 化学研究领域每天都会产生大量新分子结构,快速预测这些分子的物理化学性质对药物研发、材料设计等工作至关重要。传统方法要么依赖昂贵的实验设备,要么需…...

百度网盘资源秒级解锁:告别手动搜索的智能提取码获取方案

百度网盘资源秒级解锁:告别手动搜索的智能提取码获取方案 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 当你在深夜找到一份急需的学习资料,点击百度网盘分享链接后,却被"请输入提取码…...

SanAndreasUnity编辑器工具使用教程:提升开发效率的10个技巧

SanAndreasUnity编辑器工具使用教程:提升开发效率的10个技巧 【免费下载链接】SanAndreasUnity Open source reimplementation of GTA San Andreas game engine in Unity 项目地址: https://gitcode.com/gh_mirrors/sa/SanAndreasUnity SanAndreasUnity是一款…...

2025届必备的六大AI写作网站推荐榜单

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 作为大语言模型的DeepSeek,在学术论文写作里能够发挥多重辅助功能,在…...

终极指南:gh_mirrors/ema/emacs.d的Vim模拟——Evil模式配置详解

终极指南:gh_mirrors/ema/emacs.d的Vim模拟——Evil模式配置详解 【免费下载链接】emacs.d Fast and robust Emacs setup. 项目地址: https://gitcode.com/gh_mirrors/ema/emacs.d 如果你是Vim爱好者但又想体验Emacs的强大功能,那么gh_mirrors/em…...

Java面试必备:LiuJuan20260223Zimage常见问题解析

Java面试必备:LiuJuan20260223Zimage常见问题解析 本文针对Java面试中常见的LiuJuan20260223Zimage相关问题进行深度解析,涵盖核心原理、代码实现、优化策略等实用内容,帮助面试者系统掌握这一技术点。 1. 什么是LiuJuan20260223Zimage LiuJ…...

2026最权威的六大AI科研方案实测分析

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 作为具有先进性的大语言模型的DeepSeek,在论文写作里能够发挥出有着多种不同情况…...

保姆级教程:清音听真语音识别系统环境配置与API调用完整指南

保姆级教程:清音听真语音识别系统环境配置与API调用完整指南 1. 系统介绍与核心优势 清音听真语音识别系统搭载了Qwen3-ASR-1.7B旗舰引擎,相比前代0.6B版本有了质的飞跃。这个系统专为处理各种复杂语音场景而设计,无论是嘈杂环境录音、专业…...

Wan2.2-I2V-A14B高性能推理:PyTorch 2.4+CUDA 12.4极致算力释放

Wan2.2-I2V-A14B高性能推理:PyTorch 2.4CUDA 12.4极致算力释放 1. 镜像概述与核心价值 Wan2.2-I2V-A14B私有部署镜像是一款专为文生视频任务打造的高性能推理解决方案。这个镜像经过深度优化,能够充分发挥RTX 4090D显卡的24GB显存潜力,配合…...

OFA视觉蕴含模型应用案例:社交媒体图文检测实战教程

OFA视觉蕴含模型应用案例:社交媒体图文检测实战教程 1. 引言:社交媒体中的图文匹配挑战 在当今社交媒体环境中,图文不符的内容已经成为影响用户体验和信息真实性的重要问题。想象一下这样的场景:一张普通的风景照片配文"全…...

DeEAR部署案例:高校实验室利用DeEAR开展语音情感计算课程实验教学

DeEAR部署案例:高校实验室利用DeEAR开展语音情感计算课程实验教学 1. 引言:当语音遇见情感,教学有了新工具 想象一下,你正在上一门关于人机交互的课程。老师讲了很多理论知识,比如什么是语音情感识别,它在…...

Relm与GTK+深度集成:如何利用原生GUI组件构建现代化界面

Relm与GTK深度集成:如何利用原生GUI组件构建现代化界面 【免费下载链接】relm Idiomatic, GTK-based, GUI library, inspired by Elm, written in Rust 项目地址: https://gitcode.com/gh_mirrors/re/relm Relm是一个基于Rust语言的GUI库,深受Elm…...

PP-DocLayoutV3多场景应用:发票识别前的印章区/金额区/文字区分割实践

PP-DocLayoutV3多场景应用:发票识别前的印章区/金额区/文字区分割实践 1. 引言:发票识别的痛点与版面分析的解法 发票识别是很多企业财务自动化、供应链管理中的常见需求。传统的做法是直接把整张发票图片扔给OCR(文字识别)模型…...

gh_mirrors/ema/emacs.d的拼写检查:wucuo与flyspell对比

gh_mirrors/ema/emacs.d的拼写检查:wucuo与flyspell对比 【免费下载链接】emacs.d Fast and robust Emacs setup. 项目地址: https://gitcode.com/gh_mirrors/ema/emacs.d 在gh_mirrors/ema/emacs.d项目中,拼写检查是提升代码质量和文档准确性的重…...

dialog-polyfill 实战教程:5个真实场景教你构建现代Web弹窗

dialog-polyfill 实战教程:5个真实场景教你构建现代Web弹窗 【免费下载链接】dialog-polyfill Polyfill for the HTML dialog element 项目地址: https://gitcode.com/gh_mirrors/di/dialog-polyfill dialog-polyfill是一款轻量级的HTML弹窗元素兼容工具&…...

解锁Qwen3-TTS新玩法:在复古游戏界面中创作你的AI语音作品

解锁Qwen3-TTS新玩法:在复古游戏界面中创作你的AI语音作品 1. 当AI语音遇上复古游戏:一场声音的像素冒险 还记得小时候玩红白机时,那些简单却充满魔力的8-bit音效吗?现在,你可以用同样的怀旧方式创作属于自己的AI语音…...

快速构建GraphQL服务器:Mercurius入门完整指南

快速构建GraphQL服务器:Mercurius入门完整指南 【免费下载链接】mercurius Implement GraphQL servers and gateways with Fastify 项目地址: https://gitcode.com/gh_mirrors/me/mercurius Mercurius是一个专为Fastify设计的GraphQL适配器,它让开…...

Phi-4-mini-reasoning环境配置:CUDA版本兼容性检查与nvidia-smi验证

Phi-4-mini-reasoning环境配置:CUDA版本兼容性检查与nvidia-smi验证 1. 环境准备与CUDA兼容性检查 在部署Phi-4-mini-reasoning模型前,确保您的GPU环境满足基本要求是至关重要的第一步。这个轻量级开源模型虽然对硬件要求相对友好,但仍需要…...

别再只用均值滤波了!用Python实战对比4种滤波方法(附代码避坑指南)

Python实战:4种滤波方法深度对比与避坑指南 当你面对一组来自Arduino或树莓派的传感器数据时,那些不规则的波动曲线是否让你头疼不已?均值滤波可能是大多数人的第一反应,但今天我要告诉你——数据处理的世界远不止这一种选择。本文…...

Pixel Couplet Gen 模型压缩与量化实践:在低显存GPU上的部署优化

Pixel Couplet Gen 模型压缩与量化实践:在低显存GPU上的部署优化 1. 轻量化部署的技术挑战与突破 在AI图像生成领域,Pixel Couplet Gen以其出色的生成质量广受好评。但当我们尝试在消费级显卡上部署这个模型时,很快就遇到了显存不足的问题—…...

【前沿技术】Set Transformer:突破置换不变性挑战的高效注意力机制

1. Set Transformer:当集合数据遇上注意力机制 想象你面前有一袋五颜六色的积木,无论你怎么摇晃袋子改变积木的顺序,这袋积木的总重量始终不变——这就是置换不变性的生动体现。在机器学习领域,处理这类无序集合数据(如…...

轻量级TTS神器:CosyVoice-300M Lite功能体验与效果测评

轻量级TTS神器:CosyVoice-300M Lite功能体验与效果测评 1. 产品定位与技术背景 1.1 为什么需要轻量级TTS 在智能硬件和边缘计算快速发展的今天,传统的云端语音合成方案面临三大挑战: 硬件依赖:大多数高质量TTS需要GPU加速&…...

Fish-Speech 1.5实战教程:用默认参数生成第一段语音的完整步骤

Fish-Speech 1.5实战教程:用默认参数生成第一段语音的完整步骤 1. 准备工作:访问WebUI界面 首先确保你已经完成了Fish-Speech 1.5的部署。如果你使用的是预装镜像,只需在浏览器地址栏输入: http://你的服务器IP:7860等待3-8秒页…...

Blink-Diff:终极图像对比解决方案,让像素级差异无处遁形

Blink-Diff:终极图像对比解决方案,让像素级差异无处遁形 【免费下载链接】blink-diff A lightweight image comparison tool. 项目地址: https://gitcode.com/gh_mirrors/bl/blink-diff Blink-Diff 是一款轻量级图像对比工具,专为精准…...

C# 基于Ble的蓝牙通讯数据交互实战指南

1. BLE蓝牙通讯基础与C#开发环境搭建 低功耗蓝牙(BLE)已经成为物联网设备的主流通讯方案,相比传统蓝牙,它的功耗更低、连接速度更快。在智能手环、健康监测设备等场景中,BLE技术随处可见。作为C#开发者,我们…...

Python FastAPI 异步请求调度逻辑

Python FastAPI 异步请求调度逻辑解析 在当今高并发的互联网应用中,异步编程已成为提升性能的关键技术。Python的FastAPI框架凭借其原生支持异步请求处理的能力,成为开发高效API的热门选择。本文将深入探讨FastAPI的异步请求调度逻辑,帮助开…...

Auto-GPT-ZH 性能优化技巧:10个方法提升AI代理运行效率

Auto-GPT-ZH 性能优化技巧:10个方法提升AI代理运行效率 【免费下载链接】Auto-GPT-ZH Auto-GPT中文版本及爱好者组织 同步更新原项目 AI领域创业 自媒体组织 用AI工作学习创作变现 项目地址: https://gitcode.com/gh_mirrors/au/Auto-GPT-ZH Auto-GPT-ZH作为…...

**发散创新:基于Go语言的服务网格实践与流量治理实战**在微服务架构日益复杂的今天,**服务网格(Serv

发散创新:基于Go语言的服务网格实践与流量治理实战 在微服务架构日益复杂的今天,服务网格(Service Mesh) 已成为云原生生态中不可或缺的一环。它通过将服务间通信的控制逻辑从应用代码中剥离出来,实现了更细粒度的流量…...

DLSS Swapper深度解析:如何在不更新游戏的情况下提升30%画质表现

DLSS Swapper深度解析:如何在不更新游戏的情况下提升30%画质表现 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 想象一下,当你正在玩一款心爱的3A大作时,发现游戏中的DLSS版本已经落…...