c++中获取蓝图组件_[GPU Gems2] 15. 蓝图渲染和草图绘制

Chapter 15. Blueprint Rendering and "Sketchy Drawings"​developer.nvidia.com
d3713f4d039d434d26da015624afe778.png

介绍

本章介绍两种硬件加速的图像空间下的NPR(non-photorealistic rendering)技术:蓝图渲染(blueprint rendering)和草图绘制(sketchy drawing)。蓝图渲染勾勒出3D物体视觉上重要的可见和不可见的边缘,由轮廓表现半透明的渲染特性,由此使得复杂的物体空间结构易于理解。草图绘制用于传达视觉概念,粗略表达3D物体的重要边和内部颜色面片,使其像是潦草的绘画。

基本原理

蓝图渲染和草图绘制都基于三个基本原理:保存场景几何中间渲染的图像;实现边缘增强技术;应用深度子图像渲染。

  • 中间渲染结果(Intermediate Rendering Results)
    从3D几何体获取2D数据并渲染进纹理称为中间渲染结果,为此需要使用G-buffer来存储几何属性,此处要用到法线缓冲和z缓冲来生成边缘。在多pass渲染中,一旦生成了中间渲染结果就可以对它们重复使用。

0b718655f0f65718bb345e307e551dab.png
Steps in Creating an Edge Map
  • 边缘增强(Edge Enhancement)
    为了逐物体提取视觉上重要的边,我们使用一种图像空间的边缘增强技术(Nienhaus and Döllner 2003)。视觉上重要的边包括轮廓边、边界和折痕边。通过对相邻像素采样来检测法线缓存和z缓存的不连续性,从而获得这些边。检测不连续性产生的强度值渲染进一张纹理,称为边缘贴图(edge map)。

d782008dea1fee9772c340d0d9cc69dc.png
The Z-Buffer, Normal Buffer, and Edge Map for Each Layer
  • 深度子图像渲染(Depth Sprite Rendering)
    深度子图像是在每个像素上为深度测试提供额外z信息的2D图像,用来正确地解决图像空间渲染的可见性问题。实现步骤如下:
  1. 渲染一张和屏幕对齐的方格,纹理填充为包含z值的高精度纹理
  2. 使用来自纹理的z值取代原本光栅化生成的片元z值,同时丢弃掉z值为1的片元来优化填充率
  3. 继续用深度测试来进行渲染,如果片元通过测试那么帧缓冲就会被来自深度子图像的颜色和z值填充。

蓝图渲染

对于蓝图渲染,需要提取可见边和不可见边。可见边是可以直接被摄像机看见的边,不可见边是被几何面片遮挡的边。由此需要结合深度剥离(depth peeling)技术和边缘增强技术。

  • 深度剥离
    深度剥离是按深度排序的逐片元提取2D图层的技术。一般的深度测试只能检测每个像素的最小z值,而无法决定第二层、第三层深度,因此需要额外的深度检测来提取剩余n层。提取n层需要n个pass。将每个唯一深度复杂度的图层称为深度层(depth layer),该层的z缓冲生成的高精度纹理称为深度层贴图(depth layer map),对应的颜色缓冲生成的纹理则称为颜色层贴图(color layer map)。
    在第一个渲染pass中执行原来的深度测试,把z缓冲和颜色缓冲捕获到一个深度层图和颜色层图中。后续的渲染pass中(i>0),执行额外的深度测试,以上一个pass的深度层图作为纹理确定对应坐标在上一个pass的z值,如果当前的z值比它大则继续执行深度测试来获得次级的深度,处理结束后生成新的深度层图和颜色层图。此外可以利用遮挡查询来高效地实现终止条件。伪代码如下:
procedure depthPeeling(G <- 3DGeometry) begin    
	i=0    
	do      
		F <- rasterize(G)      
		/* Perform single depth test in the first rendering pass */        
		if(i==0)  begin        
			for all fragment ∈ F  begin          
				bool test <- performDepthTest(fragment)          
				if(test)  begin              
					fragment.depth -> z-buffer            
					fragment.color -> color buffer          
				end          
				else reject fragment        
			end      
		end        
		else begin        
		/* Perform two depth test */        
			for all fragment ∈ F  begin          
				if(fragment.depth > fragment.valuedepthLayerMap(i-1))  begin            
					/* First test */           
					bool test <- performDepthTest(fragment)           
					if(test)  begin             
						/* Second test */             
						fragment.depth -> z-buffer             
						fragment.color -> color buffer           
					end             
					else reject fragment         
				end         
				else reject fragment       
			end     
		end     
		depthLayerMap(i) <- capture(z-buffer)     
		colorLayerMap(i) <- capture(color buffer)     
		/* Edge intensities */       
		edgeMap(i) <- edges(depthLayerMap(i),colorLayerMap(i))     
		i++   
	while(occlusionQuery() != 0 )  /* Termination condition */  
end
  • 提取可见边和不可见边
    为每个深度层构建边缘贴图来补充深度剥离技术。法线缓冲和z缓冲的不连续性组成了可见边,此外由于深度剥离,所以不可见的边也会按可见边处理。上面的组图已经展示了深度剥离后的法线缓冲、z缓冲和生成的边缘贴图。
    需要注意的是可能会出现在不同深度层中边缘重复计算的情况,比如遮挡物和被遮挡物体有共享边的情况以及某物体被部分遮挡时剥离第一层后第二层仍然不连续的情况。

307ca0bebe7b0b1f7c16dafa0fcf620b.png
  • 合成蓝图
    按深度顺序来把边缘贴图合成为蓝图。使用一张和屏幕对齐的方格作为渲染输出,将深度层图作为输入实现深度子图像,使用从边缘贴图获取的边缘强度值来计算片元的RGB值,再根据边缘强度设置片元的alpha值。

04b6fd92903e95df69555f3a4b02914d.png
  • 使用深度蒙版(depth masking)来优化
    深度蒙版可以用来改变终止条件来优化渲染pass数,即给定某个阈值,当深度层图中通过深度测试的片元数目低于该阈值时则终止计算,否则继续深度剥离。
procedure depthPeeling(G <- 3DGeometry, C <- geometryOfOccludedComponent) begin    
	depthMask <- depthTexture(C)    
	quad <- createTexturedScreenAlignedQuad(depthMask)    
	renderDepthSprite(quad)    /* Render quad as depth sprite */      
	int Q = occlusionQuery()  /* Number of fragments of the components */   
	. . .    
	do      
		. . .      
		renderDepthSprite(quad)      
		int R = occlusionQuery()   /* Number of visible fragments of the component */    
	while(R<fraction(Q))         /* Termination condition */  
end

草图绘制

草图绘制使用不确定性来将重要边和表面颜色绘制成不均匀的草图。就像蓝图渲染一样,首先生成表示边和颜色的中间渲染结果,再在图像空间中应用不确定值来非均匀地绘制纹理,最后以同样方式调整深度信息使得草图绘制可以和3D场景融合在一起。

199fdb29e612af61ea6558d63ac89241.png
  • 边缘和色块
    使用边缘增强技术来将3D几何的边缘存储为边缘贴图,同时用3D几何的表面颜色来生成覆盖表面细节的色块,从而达到卡通效果,将色块的纹理称为着色贴图(shade map)
  • 应用不确定性
    使用边缘贴图和着色贴图来填充和屏幕对其的方格,并需要额外一张存储了不确定值的纹理。为了草图边缘的连续性和帧之间的连贯,本文中使用Perlin噪声贴图使得相邻的不确定值有相关性。噪声贴图作为边缘贴图和着色贴图的偏移纹理,即使用噪声值扰动片元的纹理坐标。此外引入不确定度来控制扰动的程度,不确定度是自定义的2x2矩阵,乘以噪声贴图的不确定值来统一权重得到最终偏移。

ea2a85a3f552f7f66e7e1176ccd3bf31.png
Applying Uncertainty in Image Space

为了更好的效果,需要分别不同地扰动边缘贴图和着色贴图的纹理坐标,为它们分别应用不同地不确定度矩阵即可。最后将扰动后的边缘贴图和着色贴图合成到一起。

6ae77edb792b29f2a4f3158378e88b87.png
Different Styles of Sketchy Rendering
  • 调整深度
    此时,该方法会出现严重的缺点是z值在某些情况下无法和片元对应。于是需要根据之前的扰动来生成屏幕对齐的高精度的深度子图像,分别用边缘贴图的扰动和着色贴图的扰动对原本的深度贴图进行扰动并取最小值来作为最终的z值,由本节最开始的图可看出。

以下介绍草图绘制的两个变种:

  • 粗糙轮廓和颜色变化:之前的方法就像在平滑表面的铅笔绘制,可以粗糙化轮廓和颜色来模拟不同的绘画工具及媒介比如粗糙表面上的粉笔画,为此可以随机选择噪声值来减少相邻片元的不确定性的相关性,产生了模糊和磨损的边缘和颜色变化,如上图(b),粗糙度和粒度的变化仿佛是粉笔画中压力的变化造成的。
  • 重复边缘:手绘的一个特点是重复的绘制边缘来起草布局,可以通过重复绘制重要边来模拟该特点。为此,对边缘贴图多次使用不同的不确定度(和不同的边缘颜色),结果如上图(c)。当然也要用它们对应的不确定度来多次处理深度贴图。

此方法的另外一个问题是,不确定度在图像空间保持不变且与原始几何属性无明显关联,会导致雨窗效应(shower-door effect),即动画时绘制的草图像是会游泳,我们像是隔着一道布满水珠的透明玻璃观看被玻璃扭曲的景色。为了解决该问题,需要完成如下手段:

  • 保存几何属性来控制不确定度:将几何属性如位置、法线等存进G-buffer,在计算不确定度时将几何属性作为参数加入计算,即f (s, t) = p(s, t, g(s, t))。
  • 扩大几何体:通过在模型空间烟顶点法线移动顶点来扩大几何体,使得图像空间中靠近几何体的位置也有几何信息,从而扰动生成的外部区域也可以用几何信息来计算不确定度。

整体流程如下图:

e53bf12995e2edf1d0b0958fadf5f618.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值