shader 雪 顶点位移_3.顶点外扩方法实现的描边shader

本文介绍了一种使用Shader实现描边的方法,通过顶点沿法线方向外拓,在两次Pass中分别进行描边和正常渲染,达到描边效果。这种方法对效率有一定影响,但适用于各种模型,尤其当描边大小调整得当时,可以得到理想的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描边shader的实现有很多种,顶点外扩是其中之一。顶点外扩的原理是用2个Pass 渲染物体2次

第一遍:描边,顶点沿法线方向外拓后用黑色渲染。外扩这一步的实现是在投影空间,也就是2D的,根绝法线的x和y值进行外扩,因为是沿着法线方向外扩,所以法线越和摄像机方向相同,也就是越接近面向摄像机的顶点,顶点的位置变化的越小,当法线和摄像机方向相同时,不会有任何变化。

第一遍渲染后,实际的图像如下:

0ddaa96f708e625dde8af481c88dceb7.pnga3542087408a3fa31d6f7dc4e0319899.png

第二遍:正常渲染物体,与第一遍渲染的混合在一起

37d74c2f35bba593857d099d149e0bd9.pngd2f4ccdeb246033b08b8329828b60aca.png

优点:

(1)效果最好。

(2)适用范围广。

缺点:

(1)对效率有一定影响。因为有2个Pass,所以DrawCall为正常的2倍

(2)对于法线过度不均匀的模型,比如立方体,轮廓会有缝隙。

上边的立方体例子我是特意把描边的外扩值调到很大,便于理解。由第一遍渲染后的图和第二遍渲染后的图的对比,很容易理解这个方法的原理。其实就是通过法线来把边缘进行位移,如果不是边缘,则不位移,比如立方体的正面。在第二次渲染后,会覆盖同位置的像素,因为边缘已经外扩,像素的位置已经不是原来的位置,因此不会被覆盖,而像位于立方体正面的像素,则会被第二次渲染时覆盖,最后就混合成了带黑边的效果图。

Shader "Study/3_OutLine"

{

Properties

{

_MainTex("Texture", 2D) = "white"{}

_LineSize("OutlineSize", range(0, 0.1)) = 0.02

_LineColor("LineColor", Color) = (0,0,0,1)

}

SubShader

{

Pass

{

Tags{ "LightMode" = "Always" }

// 先绘制这个纯色的顶点,然后在下一个pass绘制对象

//这里不存在前后面,关闭裁剪前后面,也不需要深度缓存

Cull Off // 关闭剔除,模型前后都会显示

ZWrite Off // 系统默认是开的,要关闭。关闭深度缓存,后渲染的物体会根据ZTest的结果将自己渲染输出写入

ZTest Always // 深度测试[一直显示],被其他物体挡住后,此pass绘制的颜色会显示出来

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

#include "UnityCG.cginc"

float _LineSize;

float4 _LineColor;

struct v2f

{

float4 pos:SV_POSITION;

float4 color : COLOR;

};

v2f vert(appdata_full v)

{

v2f o;

// 获取模型的最终的投影坐标

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

// UNITY_MATRIX_IT_MV为【模型坐标-世界坐标-摄像机坐标】【专门针对法线的变换】

// 法线乘以MV,将模型空间 转换 视图空间

float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);

// 转换 视图空间 到 投影空间 【3D转2D】

float2 offset = TransformViewToProjection(norm.xy);

// 得到的offset,模型被挤的非常大,然后乘以倍率

o.pos.xy += offset * _LineSize;

o.color = _LineColor;

return o;

}

float4 frag(v2f i) : COLOR

{

return i.color;

}

ENDCG

}

Pass

{

// 直接使用顶点和片段shader显示物体

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

#include "UnityCG.cginc"

sampler2D _MainTex;

float4 _MainTex_ST;

struct v2f

{

float4 pos:SV_POSITION;

float2 uv : TEXCOORD0;// 纹理,相对自身的坐标轴,float2是一个平面

};

v2f vert(appdata_full v)

{

v2f o;

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

return o;

}

float4 frag(v2f i) : COLOR

{

float4 texCol = tex2D(_MainTex, i.uv);

return texCol;

}

ENDCG

}

}

}

附上工程连接:http://download.csdn.net/detail/yinfourever/9565336

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值