Cg Programming In Unity Silhouette Enhancement(Wiki翻译自用)


本教程介绍了曲面法线向量的变换。
本教程的目的是实现一种效果:半透明对象的轮廓比该对象的其余部分更不透明。即使没有照明,这也增加了三维形状的印象。事实证明,转换法线对于获得此效果至关重要。

光滑表面的轮廓

在这里插入图片描述在光滑表面的情况下,轮廓表面上的点可通过法线矢量来表示特征,该法线矢量平行于观察平面,因此正交于观察者的方向。在左图中,图顶部轮廓上的蓝色法线矢量平行于观察平面,而其他法线矢量指向观察者(或相机)的方向更多。通过计算指向观察者的方向和法线向量并测试他们是否(几乎)彼此正交,因此我们可以测试点是否(几乎)在轮廓上。
更具体的说,如果V是观察者的归一化方向,N是归一化的表面法线向量,如果点积结果为0:V·N=0,那么者两个向量是正交的。在实际中,这种情况是很少的。但是如果点积V·N结果接近0,我们可以假设该点接近轮廓。

增加轮廓上的不透明度

为了达到我们想要的效果,因此,当点积V·N结果接近0,我们应该增加不透明度α。有多种方法可以增加观察者方向和法线矢量点积很小的不透明度。这是其中之一:从material的常规不透明度的alpha中增加不透明度alpha‘:
*

α ′ = m i n ( 1 , α ∣ V ⋅ N ∣ ) α' = min(1,\frac{\alpha }{|V\cdot N|}) α=min(1,VNα)

检查这样的方程的极端情况是有意义的。考虑一个接近轮廓的点的情况 V·N ≈ 0.在这种情况下,常规不透明度α将被一个小的正数除。(请注意,CPU通常会非常好的处理被0除的情况,因此,我们不必担心这一点)。因此,无论α的值是多少,α与小的正数的比例都会更大。取最小值函数min将使得所产生的不透明度不会大于1。
另一方面,对于远离轮廓的点,我们有V·N≈1。也就是说这些点的透明度不会发生太大的变化。这正是我们想要的。因此,我们刚刚检查了该方程至少是合理的。

在shader中实现方程

为了在着色器中实现类似α的方程,第一个问题应该是:应该在顶点着色器中实现还是在片元着色器中实现?在某些情况下,答案很明确,因为该实现需要纹理映射,而纹理映射通常仅在片段着色器中可用。但是,在许多情况下,没有通用的答案。顶点着色器的实现往往更快(因为顶点通常少于片段),但图像质量较低(因为法向矢量和其他顶点属性可能在顶点之间突然改变)。因此,如果您最关心性能,则在顶点着色器中实现可能是更好的选择。另一方面,如果您最关心图像质量,则在片段着色器中实施可能是更好的选择。
下一个问题是:方程应在哪个坐标系中实现?同样,也没有通用答案。 但是,在世界坐标中实现通常是Unity中的一个不错的选择,因为在世界坐标中指定了许多统一变量。
在实现方程式之前的最后一个问题是:我们从哪里得到方程式的参数?常规的不透明度alpha是通过一个shader的属性指定的。法线向量是标准顶点输入参数。观察者方向可以在顶点着色器中计算,可以看作是该顶点在世界坐标中的位置到世界空间中的相机位置(即_WorldSpaceCameraPos)的方向,该向量又Unity提供。
因此,在执行方程式之前,我们只需要将顶点位置和法线向量转换到世界空间即可。Unity提供了从对象空间到世界空间的变换矩阵unity_ObjectToWorld及其逆unity_WorldToObject。基本结果是通过将点和方向乘以变换矩阵即可对其进行变换。 将modelMatrix设置为unity_ObjectToWorld

 output.viewDir = normalize(_WorldSpaceCameraPos - mul(modelMatrix, input.vertex).xyz);

另外,通过将法线向量与转置的逆变换矩阵相乘来变换法向量。由于Unity为我们提供了逆变换矩阵(unity_WorldToObject),因此更好的选择是将法线向量从左侧乘以逆矩阵,这等效于将其从右侧乘以转置后的逆矩阵:

output.normal = normalize(mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);

现在,我们拥有编写着色器所需的所有内容。

shader 代码

Shader "Cg silhouette enhancement" {
   Properties {
      _Color ("Color", Color) = (1, 1, 1, 0.5) 
         // user-specified RGBA color including opacity
   }
   SubShader {
      Tags { "Queue" = "Transparent" } 
         // draw after all opaque geometry has been drawn
      Pass { 
         ZWrite Off // don't occlude other objects
         Blend SrcAlpha OneMinusSrcAlpha // standard alpha blending
 
         CGPROGRAM 
 
         #pragma vertex vert  
         #pragma fragment frag 
 
         #include "UnityCG.cginc"
 
         uniform float4 _Color; // define shader property for shaders
 
         struct vertexInput {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float3 normal : TEXCOORD0;
            float3 viewDir : TEXCOORD1;
         };
 
         vertexOutput vert(vertexInput input) 
         {
            vertexOutput output;
 
            float4x4 modelMatrix = unity_ObjectToWorld;
            float4x4 modelMatrixInverse = unity_WorldToObject; 
 
            output.normal = normalize(
               mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
            output.viewDir = normalize(_WorldSpaceCameraPos 
               - mul(modelMatrix, input.vertex).xyz);
 
            output.pos = UnityObjectToClipPos(input.vertex);
            return output;
         }
 
         float4 frag(vertexOutput input) : COLOR
         {
            float3 normalDirection = normalize(input.normal);
            float3 viewDirection = normalize(input.viewDir);
 
            float newOpacity = min(1.0, _Color.a 
               / abs(dot(viewDirection, normalDirection)));
            return float4(_Color.rgb, newOpacity);
         }
 
         ENDCG
      }
   }
}

请注意,我们在顶点着色器中(因为我们希望在方向之间进行插值,而对每个方向都没有施加更多或更少的权重)和片元着色器的开始处(因为插值可以在一定程度上扭曲我们的归一化)归一化了顶点输出参数output.normaloutput.viewDir。但是,在许多情况下,不需要在顶点着色器中对output.normal进行归一化。 同样,在大多数情况下,片段着色器中的output.viewDir归一化也是不必要的。

更多的艺术控制

尽管所描述的轮廓增强是基于物理模型的,但是却缺乏艺术上的控制。即,CG艺术家无法轻易创建比物理模型建议的更细或更粗的轮廓。为了进行更多的艺术控制,您可以引入另一个(正)浮点数属性,并采用点积| V·N |。 在上面的公式中使用它之前,请使用此数字的幂(使用内置的Cg函数pow(float x,float y))。这将使CG艺术家可以独立于基色的不透明度创建更薄或更厚的轮廓。

总结

本节中,我们讨论了:

  • 如何找到光滑表面的轮廓(使用法线向量和视图方向的点积)
  • 如何增强这些轮廓的不透明度。( α ′ = m i n ( 1 , α ∣ V ⋅ N ∣ ) α' = min(1,\frac{\alpha }{|V\cdot N|}) α=min(1,VNα)
  • 如何在着色器中实现方程式。
  • 如何将点和法线向量从对象空间转换为世界空间(对法向向量使用转置逆模型矩阵)。
  • 如何计算观察方向(从摄影机位置到顶点位置的差)
  • 如何插值归一化方向(即两次归一化:在顶点着色器和片段着色器中)。
  • 如何对轮廓的厚度提供更多的艺术控制。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了取得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主知识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值