Unity shader学习之切线空间下计算凹凸映射
切线空间,即使用顶点的切线作为x轴,法线作为z轴,法线与切线的叉积作为y轴。
使用切线空间存储法线,使得法线纹理可以复用,很好。
在切线空间中计算光照,比在世界空间中计算光照少了很多计算量。在切线空间中计算,需要在顶点中将光线和视角方向转换到切线空间中,而在世界空间中计算时需要在每个片段中将法线从切线空间转换到界面空间。
shader如下:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Normal map tangent space"
{
Properties
{
_MainTex("Main texture", 2D) = "white"
_NormalMap("Normal map", 2D) = "bump"
_Gloss("Gloss", float) =
} SubShader
{
Pass
{
Tags
{
"LightMode" = "ForwardBase"
} CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
#include "Lighting.cginc" struct v2f
{
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float3 tangentLightDir : TEXCOORD1;
float3 tangentViewDir : TEXCOORD2;
}; v2f vert(appdata_tan v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord; TANGENT_SPACE_ROTATION; float3 objLightDir = ObjSpaceLightDir(v.vertex);
o.tangentLightDir = normalize(mul(rotation, objLightDir)); float3 objViewDir = ObjSpaceViewDir(v.vertex);
o.tangentViewDir = normalize(mul(rotation, objViewDir)); return o;
} sampler2D _MainTex;
sampler2D _NormalMap;
float _Gloss; float4 frag(v2f i) : SV_TARGET
{
float4 tex = tex2D(_MainTex, i.uv); float4 normalTex = tex2D(_NormalMap, i.uv);
float3 tangentNormal = UnpackNormal(normalTex); // 切线空间 float3 diff = tex.rgb * _LightColor0.rgb * (dot(tangentNormal, i.tangentLightDir) * 0.5 + 0.5); float3 halfDir = i.tangentViewDir + i.tangentLightDir;
halfDir = normalize(halfDir);
float3 spec = tex.rgb * _LightColor0.rgb * pow(saturate(dot(halfDir, tangentNormal)), _Gloss); float3 col = spec + diff + UNITY_LIGHTMODEL_AMBIENT.rgb; return float4(col, );
} ENDCG
}
}
}
转载请注明出处:http://www.cnblogs.com/jietian331/p/7132277.html
效果如下:

资源如下:
http://files.cnblogs.com/files/jietian331/TangentSpaceNormalMap.rar
Unity shader学习之切线空间下计算凹凸映射的更多相关文章
- 【Unity Shader学习笔记】Unity基础纹理-法线贴图
1 高度纹理 使用一张纹理改变物体表面法线,为模型提供更多细节. 有两种主要方法: 1.高度映射:使用一张高度纹理(height map)来模拟表面位移(displacement).得到一个修改后的法 ...
- Unity Shader 学习之旅
Unity Shader 学习之旅 unityshader图形图像 纸上学来终觉浅,绝知此事要躬行 美丽的梦和美丽的诗一样 都是可遇而不可求的——席慕蓉 一.渲染流水线 示例图 Tips:什么是 GP ...
- Unity Shader 学习之旅之SurfaceShader
Unity Shader 学习之旅之SurfaceShader unity shader 图形图像 如果大地的每个角落都充满了光明 谁还需要星星,谁还会 在夜里凝望 寻找遥远的安慰——江河 官方文档 ...
- Unity Shader入门精要学习笔记 - 第5章 开始 Unity Shader 学习之旅
一个顶点/片元 着色器的结构大概如下: Shader "MyShaderName" { Properties { //属性 } SubShader { //针对显卡A的SubSha ...
- 第四章 开始Unity Shader学习之旅(1)
1. 一个最简单的顶点/片元着色器 现在,我们正式开始学习如何编写Unity Shader,更准确的说是,学习如何编写顶点/片元着色器 2.顶点/片元着色器的基本结构 我们在以前已经讲过了Unity ...
- Unity Shader学习笔记-1
本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...
- 【Unity Shader学习笔记】Unity基础纹理-单张纹理
1 单张纹理 1.1 纹理 使用纹理映射(Texture Mapping)技术,我们把一张图片逐纹素(Texel)地控制模型的颜色. 美术人员建模时,会在建模软件中利用纹理展开技术把纹理映射坐标(Te ...
- 第四章 开始Unity Shader学习之旅(2)
目录 1. 强大的援手:Unity提供的内置文件和变量 1.1 内置的包含文件 1.2 内置的变量 2. Unity提供的Cg/HLSL语义 2.1 什么是语义 2.2 Unity支持的语义 2.3 ...
- 【Unity Shader学习笔记】Unity光照基础-漫反射光照
本代码只适用于平行光. 1.逐顶点漫反射光照 1.1漫反射光照原理 1.2代码实现 在Properties语义块中声明一个漫反射颜色属性 Properties { //漫反射参数,用于调整漫反射效果 ...
随机推荐
- PHP之字符串类型
PHP之存取和修改字符串中的字符 PHP中的字符串,在存储的时候是按照字节存储的.利用一个字节数组存储字符串. PHP一个字符串string就是由一系列的字符组成,其中每个字符等同于一个字节. str ...
- [knowledge] netmap
900MHz的单核处理10GB的包收/发. netmap has been implemented in FreeBSD and Linux and Gbit/s network adapters. ...
- AndroidStudio_ListView
在这里梳理一下ListView的用法: 1.建立一个activity,例如建立一个ListViewActivity,这时将生成两个文件:ListViewActivity.java和activity_l ...
- Django实现邮件发送功能
首先申请邮箱并在设置中申请到授权码,授权码的目的仅仅是让你有权限发邮件,但是不能登录到邮箱进行修改,发送邮件时,可以代替密码 1,配置文件settings.py #邮件服务配置文件 EMAIL_USE ...
- vue项目使用vue-photo-preview插件实现点击图片放大预览和移动
官方链接: http://npm.taobao.org/package/vue-photo-preview # 安装 npm install vue-photo-preview --save # 引入 ...
- 不能往Windows Server 2008 R2 Server中复制文件的解决方法
目前一直直接往Windows 2008 R2 Server中复制文件(暂时还没有搭建ftp服务),突然不能复制了,于是百度找到了解决方法,特此记录(记忆). 1.在任务管理器中找到“rdpclip.e ...
- nodejs 学习一 process.execPath 、 __dirname、process.cwd()的区别
process.execPath node.exe的绝对路径 __dirname 当前执行到__dirname文件文件路径 process.cwd() 启动node命令的目录的绝对路劲
- 【Loadrunner】Loadrunner 手动关联技术
Loadrunner 手动关联技术 录制成功,回放失败,怀疑和动态数据有关: 1 重新录制一份脚本,两次录制的脚本进行比对,确定动态数据,复制动态数据: 2 找到第一次产生该动态数据的响应对应的相应 ...
- python-面向对象-05_面向对象封装案例 II
面向对象封装案例 II 目标 士兵突击案例 身份运算符 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 创建 对象, ...
- windows(64位)下使用curl安装
windows(64位)下使用curl安装 转自:https://blog.csdn.net/wkj001/article/details/54889907 2017年02月06日 09:46:47 ...