首页 > 其他分享 >【Unity3D】素描特效

【Unity3D】素描特效

时间:2023-08-13 10:22:06浏览次数:50  
标签:Unity3D 特效 fixed4 素描 纹理 w2 w1 factor

1 非真实渲染

法线贴图和凹凸映射中讲述了普通光照的渲染原理,实现的效果比较贴近真实世界(照相写实主义,Photorealism),非真实渲染(Non-Photorealism Rendering,NPR)在照相写实主义的基础上添加了一些风格处理,如:卡通、水彩、素描等风格。

​ 本文完整资源见→Unity3D素描特效

2 素描特效原理

​ 素描特效不直接渲染漫反射效果,而是通过线条的疏密程度表现漫反射效果,即:较亮处线条稀疏,较暗处线条密集。

​ 线条采样方法:先计算顶点对应的漫反射强度,假设为 diffuse,再根据 diffuse 所处的区间在多个素描纹理(如下)中采样。

img

​ diffuse 计算如下,其中 normal 为顶点对应的单位法线向量,lightDir 为顶点指向光源的单位方向向量。

float diffuse = max(0, dot(normal, lightDir));

​ 为方便划分区间,我们将 diffuse 乘以 7(6 个素描纹理 + 空白纹理),记为 factor,即 factor = diffuse * 7,我们将 factor 均匀划分 7 个区间,假设 factor 值对应的空白纹理和 line1 ~ line6 纹理的权值分别为 w0 ~ w6,则 w0 ~ w6 的计算如下:

fixed w0 = 1; // 白色纹理权值
fixed w1 = 0, w2 = 0, w3 = 0, w4 = 0, w5 = 0, w6 = 0; // line_1~line_6纹理权值
if (factor > 6) { // 区间: (6, 7]
	return; // 白色, 直接跳出
} else if (factor > 5) { // 区间: (5, 6]
	w1 = factor - 5;
} else if (factor > 4) { // 区间: (4, 5]
	w1 = factor - 4;
	w2 = 1 - w1;
} else if (factor > 3) { // 区间: (3, 4]
	w2 = factor - 3;
	w3 = 1 - w2;
} else if (factor > 2) { // 区间: (2, 3]
	w3 = factor - 2;
	w4 = 1 - w3;
} else if (factor > 1) { // 区间: (1, 2]
	w4 = factor - 1;
	w5 = 1 - w4;
} else { // 区间: [0, 1]
	w5 = factor;
	w6 = 1 - w5;
}
w0 = 1 - w1 - w2 - w3 - w4 - w5 - w6;

​ 根据 w0 ~ w6 对白色纹理和 line1 ~ line6 纹理进行加权求和,得到顶点对应的素描颜色。

3 素描特效实现

​ SketchEffect.cs

using UnityEngine;

[DisallowMultipleComponent] // 不允许在同一对象上挂载多个该组件
public class SketchEffect : MonoBehaviour {
    private Material sketchMat; // 素描材质

    private void Awake() {
        sketchMat = Resources.Load<Material>("Sketch/Materials/SketchMat");
    }

    private void OnEnable() {
        Renderer[] renderers = GetComponentsInChildren<Renderer>();
        foreach (var renderer in renderers) { // 将rneder里的所有材质球都替换为sketchMat材质
            Material[] materials = new Material[renderer.sharedMaterials.Length];
            for (int i = 0; i < materials.Length; i++) {
                materials[i] = sketchMat;
            }
            renderer.materials = materials;
        }
    }
}

​ 说明:SketchEffect 脚本组件挂在需要渲染素描特效的对象上。

​ SketchEffect.shader

Shader "MyShader/SketchEffect" {
	Properties {
		_Color ("Color", Color) = (1, 1, 1, 1) // 背景颜色
		_Tilling ("Tilling", Float) = 1 // 纹理缩放, 值越大线条越密集
		_Line1 ("Line 1", 2D) = "white" {} // 素描纹理1
		_Line2 ("Line 2", 2D) = "white" {} // 素描纹理2
		_Line3 ("Line 3", 2D) = "white" {} // 素描纹理3
		_Line4 ("Line 4", 2D) = "white" {} // 素描纹理4
		_Line5 ("Line 5", 2D) = "white" {} // 素描纹理5
		_Line6 ("Line 6", 2D) = "white" {} // 素描纹理6
	}
	
	SubShader {
		Tags { "RenderType"="Opaque" "Queue"="Geometry"}

		Pass {
			Tags { "LightMode"="ForwardBase" }
			
			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag 

			#include "UnityCG.cginc"
			
			fixed4 _Color; // 背景颜色
			float _Tilling; // 纹理缩放, 值越大线条越密集
			sampler2D _Line1; // 素描纹理1
			sampler2D _Line2; // 素描纹理2
			sampler2D _Line3; // 素描纹理3
			sampler2D _Line4; // 素描纹理4
			sampler2D _Line5; // 素描纹理5
			sampler2D _Line6; // 素描纹理6

			struct v2f {
				float4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
				fixed4 w1 : TEXCOORD1; // 前三张素描纹理的权值(w维存储白色)
				fixed3 w2 : TEXCOORD2; // 后三张素描纹理的权值
			};

			void getLineWeights(float diffuse, out fixed4 w1, out fixed3 w2) { // 根据漫反射值获取6张素描纹理的权重
				float factor = diffuse * 7.0;
				w1 = fixed4(0, 0, 0, 1);
				w2 = fixed3(0, 0, 0);
				if (factor > 6) { // 区间: (6, 7]
					return; // 白色, 直接跳出
				} else if (factor > 5) { // 区间: (5, 6]
					w1.x = factor - 5;
				} else if (factor > 4) { // 区间: (4, 5]
					w1.x = factor - 4;
					w1.y = 1 - w1.x;
				} else if (factor > 3) { // 区间: (3, 4]
					w1.y = factor - 3;
					w1.z = 1 - w1.y;
				} else if (factor > 2) { // 区间: (2, 3]
					w1.z = factor - 2;
					w2.x = 1 - w1.z;
				} else if (factor > 1) { // 区间: (1, 2]
					w2.x = factor - 1;
					w2.y = 1 - w2.x;
				} else { // 区间: [0, 1]
					w2.y = factor;
					w2.z = 1 - w2.y;
				}
				w1.w = 1 - w1.x - w1.y - w1.z - w2.x - w2.y - w2.z; // w维存储白色
			}
			
			v2f vert(appdata_base v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex); // 计算裁剪坐标系中顶点坐标, 等价于: mul(unity_MatrixMVP, v.vertex)
				o.uv = v.texcoord * _Tilling; // 对uv坐标进行缩放, 用于调整素描图像的稀疏和宽窄程度
				fixed3 worldLightDir = normalize(WorldSpaceLightDir(v.vertex)); // 计算世界空间中顶点指向光源的向量
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); // 计算世界空间中顶点法线向量
				fixed diffuse = max(0, dot(worldLightDir, worldNormal)); // 计算漫反射值
				getLineWeights(diffuse, o.w1, o.w2); // 根据漫反射值获取6张素描纹理的权重
				return o; 
			}
			
			fixed4 frag(v2f i) : SV_Target {			
				fixed4 lineTex1 = tex2D(_Line1, i.uv) * i.w1.x;
				fixed4 lineTex2 = tex2D(_Line2, i.uv) * i.w1.y;
				fixed4 lineTex3 = tex2D(_Line3, i.uv) * i.w1.z;
				fixed4 lineTex4 = tex2D(_Line4, i.uv) * i.w2.x;
				fixed4 lineTex5 = tex2D(_Line5, i.uv) * i.w2.y;
				fixed4 lineTex6 = tex2D(_Line6, i.uv) * i.w2.z;
				fixed4 whiteColor = fixed4(1, 1, 1, 1) * i.w1.w;
				fixed4 sketchColor = lineTex1 + lineTex2 + lineTex3 + lineTex4 + lineTex5 + lineTex6 + whiteColor;
				return fixed4(sketchColor.rgb * _Color.rgb, 1.0);
			}
			
			ENDCG
		}
	}

	FallBack "Diffuse"
}

​ 说明:在 Assets/Resources/Sketch/Materials 目录下创建 Material,重命名为 SketchMat ,将 SketchEffect.shader 赋给 SketchMat 材质,并将 line1 ~ line6 纹理拖拽到 SketchMat 材质中对应位置,调整 Tilling 属性的值。

4 运行效果

1)原图

img

2)素描特效

img

​ 声明:本文转自【Unity3D】素描特效

标签:Unity3D,特效,fixed4,素描,纹理,w2,w1,factor
From: https://www.cnblogs.com/zhyan8/p/17624370.html

相关文章

  • jquery 特效专辑
     提示框弹窗类FaceboxFacebox是一个基于jQuery,Facebook-style的lightbox。能够展示示images,divs或者整个远程页面。FaceboxSimpleModalSimpleModal是一个轻量级jQuery插件提供了一个简单的接口来创建模式对话框。SimpleModaljTipjTip一个利用jQuery开发的提示......
  • 【Unity3D】Bloom特效
    1Bloom特效原理​Bloom特效是指:将画面中较亮的区域向外扩散,造成一种朦脓的效果。实现Bloom特效,一般要经过3个阶段处理:亮区域检测、高斯模糊、Bloom合成。​本文完整资源见→Unity3DBloom特效。​1)亮区域检测​根据亮度阈值检测亮区,如下从原图中提取......
  • 【Unity3D】运动模糊特效
    1运动模糊原理​开启混合(Blend)后,通过Alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合,当有物体运动时,就会将当前位置的物体影像与历史位置的物体影像进行混合,从而实现运动模糊效果,即模糊拖尾效果。主要代码如下:Pass{BlendSrcAlphaOneMinusSrcAlphaCGPROGR......
  • NUKE14 mac版电影后期特效合成软件功能强大、速度快
    NUKE14是一款电影后期特效合成软件,功能强大、速度快,拥有非常专业的后期效果。NUKE14Mac版是一款功能强大的电影后期特效合成软件,提供多种强大的电影后期处理效果,包括电影、动画、漫画、建筑等。可以将多个独立的视频文件合并成一个文件;或者将单个文件组合到一起;或者把两个或......
  • 【Unity3D】高斯模糊特效
    1高斯模糊原理​边缘检测特效中使用了卷积运算进行了边缘检测,本文实现的高斯模糊特效同样使用了卷积运算,关于卷积核和卷积运算的概念,读者可以参考边缘检测特效。​本文完整资源见→Unity3D高斯模糊特效。​我们将用于模糊处理的卷积核称为模糊算子,它一般满足以下......
  • 【Unity3D】边缘检测特效
    1边缘检测原理​边缘检测的原理是:检测每个像素周围的像素亮度差,如果亮度差异较大,就将该像素识别为边缘,并进行边缘着色。​本文完整资源见→Unity3D边缘检测特效。​使用过卷积神经网络(CNN)的人,一定知道卷积运算,笔者之前有写过相关文章(使用CNN实现MNIST数据集分类、......
  • 五百个炫酷文字特效——预设的使用
    需要安装Birdge新建一个文件动画-浏览预设进入到text就是本文特效特别多的动画想使用的话,直接拖动就好了就能做出这样的效果了调一下颜色可以出现这种高端的效果了这里面的效果很多,可以多试一试输出到渲染序列或Me也可以导入到PR里面......
  • 【Unity3D】广告牌特效
    1前言​广告牌特效是指:空间中的一个2D对象始终(或尽可能)面向相机,使得用户能够尽可能看清楚该2D物体。广告牌特效一共有以下3种:正视广告牌:广告牌始终以正视图姿态面向相机,即广告牌的x、y、z轴正方向始终指向相机的x、y、z轴正方向;血条广告牌:游戏中的血条效果广告......
  • 【Unity3D】调整屏幕亮度、饱和度、对比度
    1屏幕后处理流程​调整屏幕亮度、饱和度、对比度,需要使用到屏幕后处理技术。因此,本文将先介绍屏幕后处理流程,再介绍调整屏幕亮度、饱和度、对比度的实现。​本文完整资源见→Unity3D调整屏幕亮度、饱和度、对比度。​屏幕后处理即:渲染完所有对象后,得到一张屏幕图......
  • 高效控制轨道——折叠栅格化特效开
    第一个是折叠按钮我们在发现层太多了,我们不想看到他我们把需要的层先锁定起来,然后选中没用的层然后点上面的总控开关要注意,这里的层没有消失,只是让我们折叠起来了当我们把导入的东西放大后,会出现像素点但是我们选中栅格化后就变得清晰,也就是第二个按钮后面的哪个就......