当前位置:网站首页>Unity shader beginner's Essentials (I) -- basic lighting notes
Unity shader beginner's Essentials (I) -- basic lighting notes
2022-07-07 08:54:00 【Zero if】
A personal Shader note , Mainly through analysis Shader Code to summarize several lighting models .
0. Standard illumination model
The standard model is mainly divided into four parts , Spontaneous light + Specular reflection + Diffuse reflection + The ambient light
According to different lighting models , Calculate different rays and add them
Per vertex and per pixel
There are two main types of model illumination calculation , Per pixel and per vertex , namely Grouraud Shading and Phone Shading
per-vertex
Calculate illumination at each vertex , Linear interpolation is performed inside the rendering entity , Finally, output the imager color
shortcoming : Vertices are interpolated within the calculated illumination , The interior of an entity is always darker than the highest color value at the vertex , And there will be edges and corners
But it also tells us , Lighting is calculated in vertex shaders
Pixel by pixel
On a per pixel basis , Get his normal , ( It can be vertex normal interpolation , You can sample from the normal texture ), Perform illumination calculation
therefore , Illumination is calculated in the slice shader
1. Diffuse reflection model
Lambert Basis of diffuse reflection model , The main thing is to satisfy Lambert The laws of : That is, the intensity of the reflected light is directly proportional to the cosine of the angle between the surface normal and the direction of the light source
The formula is :
Cdiffuse = ( Clight · mdiffuse )max (0, n · l)
Clight : The color of the light source
mdiffuse: Material diffuse color
n : The surface normals
l : Point to the light source unit vector
1.1 Diffuse per vertex
mdiffuse Definition of diffuse color of material , Colors can be found in unity Take from oneself
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1)
}
Namely a2v and v2f, namely application to vertex shader and vertex shader To fragment shader The definition of .
Calculate lighting in vertex shaders , So you need to a2v Access to vertices and normals ; To transfer the light color in the vertex shader to the slice shader , therefore ,v2f You need to convert vertices into clipping space and store color value
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
};
This is the specific calculation in vertex shader .Clight and mdiffuse One is directly obtained, and the other is defined before , What needs to be solved is n · l . You need to convert these two values to world space for dot multiplication .
Normal in world coordinates :unity Built in
unity_WorldToObject
You can convert from world coordinates to local coordinates , Then use the inverse operation of matrix , Get the world coordinates of the normal .
Others are brought into the formula
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb *saturate(dot(worldNormal,worldLight));
o.color = ambient + diffuse;
return o;
}
Just output directly from the slice shader
fixed4 frag(v2f i) : SV_TARGET
{
return fixed4(i.color, 1.0);
}
1.2 Per pixel diffuse
The main reason is that the contents of calculation in the two shaders are different .
In the vertex shader , There is no need to calculate the illumination , Just pass the vertices and normals in world space to the slice shader .
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
return o;
}
The key point is to calculate the illumination in the slice shader ., The ideas are the same , Pay attention to the unitization of various vectors .
fixed4 frag(v2f i) : SV_TARGET
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 color = ambient + diffuse;
return fixed4(color, 1.0);
}
2. Specular reflection model
Specular reflection model points Phone and Blinn Phone Two kinds of
The former model is , Specular reflection and Viewing angle direction and reflection direction Is related to the dot multiplication value of , The latter believes that it is the normal direction and the viewing angle direction Point multiplication value of half range vector and normal relevant .
Phone Highlight model :
Cspecular = (Clight · mspecular) max(0, v, r)mgloss
Clight : The color and intensity of the incident light
mspecular: The specular reflection coefficient of the material
v: Direction of view
r : Direction of reflection
mgloss: Glossiness , Reflectance
Blinn Phone Highlight model :
Cspecular = (Clight · mspecular) max(0, n, h)mgloss
n : normal ,h It's a half range vector
The others are roughly the same
2.1 per-vertex Phone Specular reflection
Diffuse color , Specular reflection coefficient and gloss are customized as follows
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1)
_Specular("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
Calculating lighting in vertex shaders , Mainly calculate highlights , So we get the ambient light directly . The calculation method of diffuse reflection is not much written , Highlight into the formula of a meal calculation , Plus ambient light return
reflectDir Directly through built-in functions , Write the ray incidence direction and vertex normal direction to get the exit direction
viewDir Through the world position of the camera - The world position of the vertex gets the field of view vector
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
o.color = ambient + diffuse + specular;
return o;
Finally, just output the color directly in the slice shader , Consistent with the above .
2.2 Pixel by pixel Phone Specular reflection
Obviously, the illumination is calculated in the slice shader , Think the same way . In the vertex shader , Just calculate the world coordinates of the vertex and the position under the world of the normal
fixed4 frag(v2f i) : SV_TARGET
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
2.3 Pixel by pixel Blinn Phone Highlight model
Roughly the same , The main thing is to calculate the illumination of the slice , One more half way vector calculation and use
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(reflectDir, viewDir)), _Gloss);
边栏推荐
- Tronapi wave field interface - source code without encryption - can be opened twice - interface document attached - package based on thinkphp5 - detailed guidance of the author - July 6, 2022 - Novice
- channel. Detailed explanation of queuedeclare parameters
- Golang etcdv3 reports an error. The attribute in grpc does not exist
- [MySQL] detailed explanation of trigger content of database advanced
- Problems encountered in the use of go micro
- Mock.js用法详解
- Required String parameter ‘XXX‘ is not present
- Selenium automation integration, eight years of testing experience, soft test engineer, an article to teach you
- Qt Charts使用(重写QChartView,实现一些自定义功能)
- Simple use of Xray
猜你喜欢
指针进阶,字符串函数
Greenplum 6.x monitoring software setup
[Yugong series] February 2022 U3D full stack class 007 - production and setting skybox resources
調用華為遊戲多媒體服務的創建引擎接口返回錯誤碼1002,錯誤信息:the params is error
Output all composite numbers between 6 and 1000
Explain Huawei's application market in detail, and gradually reduce 32-bit package applications and strategies in 2022
2022-07-06 Unity核心9——3D动画
数据分析方法论与前人经验总结2【笔记干货】
[Nanjing University] - [software analysis] course learning notes (I) -introduction
C language for calculating the product of two matrices
随机推荐
NCS Chengdu Xindian interview experience
Output all composite numbers between 6 and 1000
Required String parameter ‘XXX‘ is not present
Greenplum 6.x monitoring software setup
Test pits - what test points should be paid attention to when adding fields to existing interfaces (or database tables)?
A bug using module project in idea
[南京大学]-[软件分析]课程学习笔记(一)-introduction
With an annual salary of 50W, Alibaba P8 will come out in person to teach you how to advance from testing
JS operation
【踩坑】nacos注册一直连接localhost:8848,no available server
Uniapp wechat applet monitoring network
Sign and authenticate API interface or H5 interface
systemd
oracle一次性说清楚,多种分隔符的一个字段拆分多行,再多行多列多种分隔符拆多行,最终处理超亿亿。。亿级别数据量
Image segmentation in opencv
Implement custom memory allocator
Greenplum6.x搭建_环境配置
Analysis of using jsonp cross domain vulnerability and XSS vulnerability in honeypot
Oracle makes it clear at one time that a field with multiple separators will be split into multiple rows, and then multiple rows and columns. Multiple separators will be split into multiple rows, and
cmake命令行使用