纹理可以用来存储任何表面属性。

可以通过使用渐变纹理来实现插画风格的渲染效果。

这项技术是由Valve公司提出的。Valve使用它来渲染游戏中具有插画风格的角色。

我们使用半兰伯特模型计算漫反射。

因为我们使用的实际上是一个一维纹理:

所以在片元着色器中,我们使用fixed2(halfLambert, halfLambert)作为uv坐标进行纹理采样。

代码实现如下:

Shader "Unity Shader Book/Chapter 7/RampTexture"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_RampTex ("RampTex", 2D) = "white" {}
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
#include "Lighting.cginc" fixed4 _Color;
sampler2D _RampTex;
float4 _RampTex_ST;
fixed4 _Specular;
float _Gloss; struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD;
}; struct v2f{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
}; v2f vert(a2v v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
//计算偏移后的纹理坐标
o.uv = TRANSFORM_TEX(v.texcoord, _RampTex);
return o;
} fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)); fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//使用半兰伯特计算模型
fixed halfLambert = 0.5 * dot(worldNormal, worldLightDir) + 0.5;
//使用纹理计算漫反射颜色
fixed3 diffuseColor = tex2D(_RampTex, fixed2(halfLambert, halfLambert)).rgb * _Color.rgb;
//计算漫反射项
fixed3 diffuse = _LightColor0.rgb * diffuseColor;
//高光反射
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfdir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfdir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}

把不同的纹理赋给应用此shader的材质,可以得到不同的效果。

使用突变的色块作为纹理可以模拟卡通风格。如下图所示。

另外,我们需要把渐变纹理的Wrap Mode设置为Clamp模式。

因为我们使用fixed2(halfLambert, halfLambert)进行纹理采样。Repeat模式下会舍弃整数部分,如果halfLambert大于1(如1.00001),会只保留0.00001,导致映射出现问题。

最新文章

  1. Redis为什么使用单进程单线程方式也这么快
  2. 使用CFURLCreateStringByAddingPercentEscapes进行URL编码
  3. SpringMVC解析4-DispatcherServlet逻辑脉络
  4. coreseek 提示 client version is higher than daemon version 解决办法
  5. POJ 1995
  6. linux学习笔记之文件结构和函数
  7. Jquery弹窗插件Lhgdialog的用法
  8. document.form.command.value
  9. Ubuntu下搜狗输入法突然无法输入中文
  10. 3、J2EE学习推荐书籍
  11. java10.0.2和java 11.0.1配置环境变量
  12. luoguU38228 签到题 (BSGS)
  13. React Native(十三)——ios键盘挡住textInput
  14. Trie树 - 字典树
  15. Python学习 day10
  16. 关于mysql启动问题---mysqld_safe mysqld from pid file * ended
  17. vmware虚拟机 C硬盘空间 无损扩容 新测
  18. 20145120黄玄曦《网络对抗》MSF基础应用
  19. Lua工具类
  20. 渗透测试框架-Fsociety

热门文章

  1. web项目中视频的上传和展示
  2. 利用angular4和nodejs-express构建一个简单的网站(一)——构建前后端开发环境
  3. 安装scrapy速度慢解决方案
  4. Unable to negotiate with xx.xxx.xxxx port 22: no matching host key type found. Their offer: ssh-rsa(解决的两种方式)
  5. CTF大赛模拟-CFS三层内网漫游
  6. Mybatis插入数据
  7. zabbix server&proxy部署操作过程
  8. Git上传本地仓库文件到Gitee(Github同理)
  9. 微信小程序组件封装及调用-原生
  10. JavaScript基础第01天笔记