shader篇-纹理-凹凸映射


  • shader篇-纹理-凹凸映射

    • 简介
    • 高度纹理
    • 法线纹理
    • 优缺点比较
    • 切线空间下进行计算
    • 在世界空间下进行计算

简介

纹理的一种常见运动是凹凸映射,使用一种纹理改变模型表面的法线,这种方法并不会真的改变模型的顶点位置,只是让模型看起来凹凸不平。

有2种主要的方法可以用来进行凹凸映射:
一种方法是使用一张高度纹理来模拟表面位移,然后得到一个修改后的法线值,这种方法也被称为高度映射
另一种方法是使用一张法线纹理来直接存储表面法线,这种方法被称为法线映射。

高度纹理

高度纹理使用一张高度图,高度图存储的是强度值,表面模型的海拔高度,颜色越浅表面位置越向外凸起,颜色越深越向里凹,这种方法的好处是非常直观,可以完全从高度图里了解到模型表面的凹凸情况。缺点是计算复杂,实时计算中需要间接从像素灰度值计算表面法线,消耗更多性能。
高度图通常和法线映射一起使用,用以给出表面凹凸的额外信息,也就是说我们会通常用法线映射修改光照。

法线纹理

法线纹理存储的是表面的法线方向。由于大学方向的分量在[-1,1],而像素的分量为[0,1],因此我们需要做一个映射:

pixel=normal+12

pixel=\frac{normal+1}{2}
这就要求我们在shader中对纹理采样后进行一次反映射得到法线方向。

有一种直接的想法是将修改后的模型空间的表面法线存储在一张纹理中,这种纹理被称为是模型空间的法线纹理。
但实际制作过程中我们我们会失忆模型空间的切线空间来存储法线。这种纹理被称为切线空间的法线纹理。实际上模型空间法线纹理更直观,但因为美术人员更喜欢切线空间的法线纹理。。、

优缺点比较

模型空间存储法线优点:
1.程序人员实现它简单,更加直观
2.纹理坐标的缝合处和尖锐边角处,突变少,更平滑。
切线空间存储法线优点:
1.自由度高,可运用到不同的模型
2.可进行Uv动画
3.可重用法线纹理
4.可压缩

切线空间下进行计算

基本思路是在片元着色器中通过纹理采样得到切线空间下的法线,然后再与切线空间下的视角方向、光照方向等进行计算


Properties {_Color ("Color Tint", Color) = (1, 1, 1, 1)_MainTex ("Main Tex", 2D) = "white" {}_BumpMap ("Normal Map", 2D) = "bump" {}_BumpScale ("Bump Scale", Float) = 1.0_Specular ("Specular", Color) = (1, 1, 1, 1)_Gloss ("Gloss", Range(8.0, 256)) = 20}SubShader {Pass { Tags { "LightMode"="ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;sampler2D _BumpMap;float4 _BumpMap_ST;float _BumpScale;fixed4 _Specular;float _Gloss;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;//target为切线方向float4 tangent : TANGENT;float4 texcoord : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;float4 uv : TEXCOORD0;float3 lightDir: TEXCOORD1;float3 viewDir : TEXCOORD2;};
v2f vert(a2v v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);//uv变量的xy分量和zw分量分别存储2张贴图的纹理坐标o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;//计算副切线float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w;//获取模型空间到切线空间的变换矩阵float3x3 rotation = float3x3(v.tangent.xyz, binormal, v.normal);//TANGENT_SPACE_ROTATION;//也可以使用TANGENT_SPACE_ROTATION;来帮助我们计算rotation矩阵,她来自UnityCG.cginco.lightDir = mul(rotation, normalize(ObjSpaceLightDir(v.vertex))).xyz;o.viewDir = mul(rotation, normalize(ObjSpaceViewDir(v.vertex))).xyz;return o;}
fixed4 frag(v2f i) : SV_Target {                fixed3 tangentLightDir = normalize(i.lightDir);fixed3 tangentViewDir = normalize(i.viewDir);fixed4 packedNormal = tex2D(_BumpMap, i.uv.zw);fixed3 tangentNormal;// If the texture is not marked as "Normal map"
//              tangentNormal.xy = (packedNormal.xy * 2 - 1) * _BumpScale;
//              tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));// Or mark the texture as "Normal map", and use the built-in funcitontangentNormal = UnpackNormal(packedNormal);//_BumpScale控制凹凸程度tangentNormal.xy *= _BumpScale;tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss);return fixed4(ambient + diffuse + specular, 1.0);}

在世界空间下进行计算

基本思路是在顶点着色器上计算切线空间到世界空间的变换矩阵。

//Ttow0,1,2存储切线空间到世界空间的变换矩阵
//多余的w分量用以存储世界空间下的顶点位置
struct v2f {float4 pos : SV_POSITION;float4 uv : TEXCOORD0;float4 TtoW0 : TEXCOORD1;  float4 TtoW1 : TEXCOORD2;  float4 TtoW2 : TEXCOORD3; };
v2f vert(a2v v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; // Compute the matrix that transform directions from tangent space to world space// Put the world position in w component for optimizationo.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);return o;}
fixed4 frag(v2f i) : SV_Target {// Get the position in world space      float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);// Compute the light and view dir in world spacefixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));// Get the normal in tangent spacefixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));bump.xy *= _BumpScale;bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));// Transform the narmal from tangent space to world spacebump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));fixed3 halfDir = normalize(lightDir + viewDir);fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);return fixed4(ambient + diffuse + specular, 1.0);}

shader篇-纹理-凹凸映射相关推荐

  1. Unity Shader入门精要第七章 基础纹理 凹凸映射之在世界空间下计算

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.pandas是什么? 二.使用步骤 2.Unity 中的法线纹理类型 参考 前言 现在,我们来实现第二种方法,即在世界空间下计算光照 ...

  2. Unity3D - Shader - 凹凸映射(Bump mapping)之美

    凹凸映射的目的:是使用纹理来修改模型表面的法线,用于为模型提供更多细节. 凹凸映射的方式: 高度纹理(height map):用于模拟表面位移(displacement),也称作高度映射(height ...

  3. Normal map (Bump mapping) 法线贴图(凹凸映射) Standard Shader系列10

    Normal map (Bump mapping) 法线贴图(凹凸映射) 本文档主要是对Unity官方手册的个人理解与总结(其实以翻译记录为主:>) 仅作为个人学习使用,不得作为商业用途,欢迎转 ...

  4. 凹凸映射中的法线纹理贴图

    凹凸映射(bump mapping) 凹凸映射的目的:使用一张纹理来修改模型表面的法线,让模型看上去"凹凸不平". 主要有两种方法:一.高度纹理来模拟表面位移,得到一个修改后的法线 ...

  5. Unity Shader凹凸映射

    纹理的另一种常见的应用就是凹凸映射.凹凸映射的目的是使用一张纹理来修改模型表面的法线,以便为模型提供更多细节.这种方法不会真的改变模型的顶点位置,只是让模型看起来是"凹凸不平"的, ...

  6. 第七章 凹凸映射 渐变纹理 遮罩纹理

    一.凹凸映射 1.切线空间存储法线纹理 优点: (1)自由度高,将纹理应用到其他模型上,有时候也能得到合理的结果 (2)可以进行uv动画,制作出火山熔岩的效果 (3)可以重用法线纹理 (4)可以压缩 ...

  7. 处理顶点——通过切线空间的凹凸映射添加逐像素细节

    问题 虽然前一个教程中具有不变法线的平面物体工作良好,但如果对一个曲面或有转角的表面进行凹凸映射仍会遇到麻烦. 主要问题是包含在凹凸映射中的偏离法线是在切线空间中的,这意味着它与默认法线有联系. 为了 ...

  8. 【UnityShader】凹凸映射之高度贴图和法线贴图

    目录 基础知识 高度纹理 Unity 中的法线纹理类型 法线纹理 基础知识 纹理的另一种场景的应用就是凹凸映射.凹凸映射的目的是使用一张纹理来修改模型表面的法线,以便为模型提供更多的细节.这种方法不会 ...

  9. 处理顶点——凹凸映射:固定法线

    问题 三角形的最主要问题是它是平的.如果你使用两个三角形绘制一堵巨大的墙并在墙上附上一个漂亮的纹理,结果是令人失望的平的. 你可以将三角形分割成更小的三角形以添加细节,这需要定义每个顶点的3D位置,但 ...

  10. 【Unity3D】法线贴图和凹凸映射

    1 法线贴图原理 表面着色器中介绍了使用表面着色器进行法线贴图,实现简单快捷.本文将介绍使用顶点和片元着色器实现法线贴图和凹凸映射,实现更灵活. 本文完整代码资源见→法线贴图和凹凸映射. 1)光照原理 ...

最新文章

  1. C语言结构体篇 结构体
  2. HBase HFile与Prefix Compression内部实现全解–KeyValue格式
  3. CSS属性之字体(Font)
  4. 第十七章 我国农业科学技术
  5. php 打印对象到文件,php实现将数组或对象写入到文件的方法小结【三种方法】...
  6. 使用注意力机制建模 - 标准化日期格式
  7. nohup 与 linux 程序后台执行
  8. highcharts中pie统计图获取数据
  9. epoll示例程序——客户端
  10. WP7 Tip:改变启动页
  11. 请勿在计算机室吃带果壳的食品英语,双语者如何在两种语言间切换?
  12. java-maven的配置
  13. java从入门到精通 韩顺平_韩顺平Java从入门到精通视频教程(94集)
  14. [BUUCTF][Zer0pts2020]Can you guess it?
  15. 用go来做图像相似性比较
  16. PS轻松制作四种扁平化风格图标
  17. OpenCV总结6——stitcher
  18. Linux学习笔记-随即更新-慢速学习
  19. 实现Python Http 接口测试
  20. Android Instant App

热门文章

  1. vue项目中使用高德地图实现添加点标记和获取点击位置信息
  2. 将视频的以flv格式转换mp4格式
  3. Leetcode刷题100天—剑指 Offer 50. 第一个只出现一次的字符(队列)—day13
  4. Wifi OKC 验证
  5. 求职经历--慎重的第二份工作
  6. 2021年茶艺师(中级)考试内容及茶艺师(中级)操作证考试
  7. Instagram帖子类型及标题撰写技巧
  8. NPIO 简单读写 EXCEL 小李子
  9. Tkinter:事件绑定
  10. 媒体专访 | 许彬教授:我们离元宇宙Big Bang有多近?