当前位置:网站首页>Introduction to unityshader - sketch effect rendering
Introduction to unityshader - sketch effect rendering
2022-04-22 20:51:00 【Jelly Yoshihiro】


Shader "Unity Shaders Book/Chapter 14/Hatching" {
Properties {
_Color ("Color Tint", Color) = (1, 1, 1, 1)
_TileFactor ("Tile Factor", Float) = 1 // Texture tiling factor , The greater the numerical , The denser the sketch lines
_Outline ("Outline", Range(0, 1)) = 0.1
_Hatch0 ("Hatch 0", 2D) = "white" {}
_Hatch1 ("Hatch 1", 2D) = "white" {}
_Hatch2 ("Hatch 2", 2D) = "white" {}
_Hatch3 ("Hatch 3", 2D) = "white" {}
_Hatch4 ("Hatch 4", 2D) = "white" {}
_Hatch5 ("Hatch 5", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
// Call the... Of the rendered contour Pass
UsePass "Unity Shaders Book/Chapter 14/Toon Shading/OUTLINE"
Pass {
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "UnityShaderVariables.cginc"
fixed4 _Color;
float _TileFactor;
sampler2D _Hatch0;
sampler2D _Hatch1;
sampler2D _Hatch2;
sampler2D _Hatch3;
sampler2D _Hatch4;
sampler2D _Hatch5;
struct a2v {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed3 hatchWeights0 : TEXCOORD1;
fixed3 hatchWeights1 : TEXCOORD2;
float3 worldPos : TEXCOORD3;
SHADOW_COORDS(4)
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord.xy * _TileFactor;
fixed3 worldLightDir = normalize(WorldSpaceLightDir(v.vertex));
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed diff = max(0, dot(worldLightDir, worldNormal));
o.hatchWeights0 = fixed3(0, 0, 0);
o.hatchWeights1 = fixed3(0, 0, 0);
float hatchFactor = diff * 7.0;
if (hatchFactor > 6.0) {
// Pure white, do nothing
} else if (hatchFactor > 5.0) {
o.hatchWeights0.x = hatchFactor - 5.0;
} else if (hatchFactor > 4.0) {
o.hatchWeights0.x = hatchFactor - 4.0;
o.hatchWeights0.y = 1.0 - o.hatchWeights0.x;
} else if (hatchFactor > 3.0) {
o.hatchWeights0.y = hatchFactor - 3.0;
o.hatchWeights0.z = 1.0 - o.hatchWeights0.y;
} else if (hatchFactor > 2.0) {
o.hatchWeights0.z = hatchFactor - 2.0;
o.hatchWeights1.x = 1.0 - o.hatchWeights0.z;
} else if (hatchFactor > 1.0) {
o.hatchWeights1.x = hatchFactor - 1.0;
o.hatchWeights1.y = 1.0 - o.hatchWeights1.x;
} else {
o.hatchWeights1.y = hatchFactor;
o.hatchWeights1.z = 1.0 - o.hatchWeights1.y;
}
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed4 hatchTex0 = tex2D(_Hatch0, i.uv) * i.hatchWeights0.x;
fixed4 hatchTex1 = tex2D(_Hatch1, i.uv) * i.hatchWeights0.y;
fixed4 hatchTex2 = tex2D(_Hatch2, i.uv) * i.hatchWeights0.z;
fixed4 hatchTex3 = tex2D(_Hatch3, i.uv) * i.hatchWeights1.x;
fixed4 hatchTex4 = tex2D(_Hatch4, i.uv) * i.hatchWeights1.y;
fixed4 hatchTex5 = tex2D(_Hatch5, i.uv) * i.hatchWeights1.z;
fixed4 whiteColor = fixed4(1, 1, 1, 1) * (1 - i.hatchWeights0.x - i.hatchWeights0.y - i.hatchWeights0.z -
i.hatchWeights1.x - i.hatchWeights1.y - i.hatchWeights1.z);
fixed4 hatchColor = hatchTex0 + hatchTex1 + hatchTex2 + hatchTex3 + hatchTex4 + hatchTex5 + whiteColor;
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
return fixed4(hatchColor.rgb * _Color.rgb * atten, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
Vertex shader :
We first make a basic coordinate transformation of the vertex . then , Use _TileFactor The texture sampling coordinates are obtained . In the calculation 6 Before the blending weight of the texture , We first need to calculate the lighting per vertex . therefore , We use the illumination direction and normal direction in world space to get the diffuse reflection coefficient diff. after , We initialize the weight value to 0, And put diff Zoom to [0,7] Range , obtain hatchFactor. We put [0, 7] The interval of is evenly divided into 7 Sub interval , By judgment hatchFactor The corresponding texture blending weight is calculated according to the sub interval . Last , We calculated the world coordinates of the vertices , And use TRANSFER SHADOW Macro to calculate the sampling coordinates of shadow texture .
// Each bit stores the weight of a graph , Six figures in total
o.hatchWeights0 = fixed3(0, 0, 0);
o.hatchWeights1 = fixed3(0, 0, 0);
// The greater the diffuse reflection coefficient , Indicates that the brighter the part , The thinner the sketch lines
if (hatchFactor > 6.0) {
// Pure white, do nothing
} else if (hatchFactor > 5.0) {
o.hatchWeights0.x = hatchFactor - 5.0; // Greater than 5 The part of is assigned to the first figure
} else if (hatchFactor > 4.0) {
o.hatchWeights0.x = hatchFactor - 4.0; // Greater than 4 The part of is assigned to the first figure
o.hatchWeights0.y = 1.0 - o.hatchWeights0.x; // The rest is assigned to the second figure
} else if (hatchFactor > 3.0) {
o.hatchWeights0.y = hatchFactor - 3.0; // Greater than 3 The part of is assigned to the second figure
o.hatchWeights0.z = 1.0 - o.hatchWeights0.y; // The rest is assigned to the third figure
} else if (hatchFactor > 2.0) { // The same below
o.hatchWeights0.z = hatchFactor - 2.0;
o.hatchWeights1.x = 1.0 - o.hatchWeights0.z;
} else if (hatchFactor > 1.0) {
o.hatchWeights1.x = hatchFactor - 1.0;
o.hatchWeights1.y = 1.0 - o.hatchWeights1.x;
} else {
o.hatchWeights1.y = hatchFactor;
o.hatchWeights1.z = 1.0 - o.hatchWeights1.y;
}
Chip shader :
Got it. 6 After the blending weights of six textures , We sample each texture and multiply it by its corresponding weight value to obtain the sampling color of each texture . We also calculated the contribution of pure white in rendering , This is done through 1 Subtract all 6 The weight of the texture . This is because there are often blank parts in the sketch , So we want the brightest part of the final rendering to be pure white . Last , We mixed various color values , And the shadow value atten、 Model color Color Multiply and return the final rendering result .
版权声明
本文为[Jelly Yoshihiro]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204222048338468.html
边栏推荐
- 一文讲透,商业智能BI的未来形态,发展现状及前景分析|推荐收藏
- Tiktok + Shopify independent station evaluation, seller's new outlet
- Building a new generation of computing platform, stepvr will open the "door" of metauniverse in 2022
- buuctf-[Flask]SSTI
- 编程实用工具,总有一个你用的上
- 排序方式(8种)详解8—桶排序
- MySQL高可用架构设计分析
- 如何让机器人更像“人”,让slam更灵活?
- Design and analysis of MySQL high availability architecture
- [suggestions collection] no highlights in the interview
猜你喜欢

MySQL高可用架构设计分析

面试官宁愿要刚刚毕业工作1年的我小弟,也不要工作5年的我,年薪25w

How to make robots more like "people" and make slams more flexible?

On "waiting for awakening mechanism"

Jingdong new product Intelligence Bureau spoilers oppo K10 series or linkage Guoman IP surprise?

H. Maximal AND

The annual salary is 170W. Alibaba P8 blind date requires the woman's monthly salary of 10000. Netizen: it's a little high

【状态机】388. 文件的最长绝对路径

CmsEasy7.6.3.2逻辑漏洞

Semi synchronous replication of MySQL master-slave replication
随机推荐
MySQL高可用架构设计分析
Windows安装Redis
After working for three years as a programmer in a small 9K factory with a monthly salary, he finally won the byte offer he had been longing for for for for a long time in his spare time. The salary c
Redis's key and value best practices
【dfs】386. 字典序排数
Evaluaion mark in natural language processing field//updating
What is a SAML assertion?
H. Maximal AND
Implementation of simple FreeRTOS task blocking delay based on gd32f1x0 manual programming
Leetcode Hot 100
Four ways to create threads
做了5年Android,靠着这份190页的面试资料,成功入职腾讯
智慧农业成为发展道路,充分发挥智能化,解放人力
DA14580作为server发送数据
[state machine] 388 The longest absolute path of the file
浅学 “等待唤醒机制 ”
Fault analysis | federated storage engine table causes the monitoring thread to be in the opening table state
【youcans 的 OpenCV 例程200篇】160. 图像处理之OTSU 方法
一文讲透,商业智能BI的未来形态,发展现状及前景分析|推荐收藏
MySQL advanced trigger -- trigger introduction, trigger syntax and trigger case