当前位置:网站首页>OpenGL - Lighting
OpenGL - Lighting
2022-07-05 09:18:00 【Farmer er】
We see in real life that the color of an object is not the color that the object really has , But what it reflects (Reflected) Color . let me put it another way , Those that cannot be absorbed by objects (Absorb) The color of is the color of the object we can perceive .
The simple understanding is RGB
Multiplication of components :
glm::vec3 lightColor(0.33f, 0.42f, 0.18f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor; // = (0.33f, 0.21f, 0.06f);
To simulate a more realistic lighting effect , according to Feng's illumination model (Phong Lighting Model)
It is divided into The ambient light (Ambient Lighting)
、 Diffuse reflection (Diffuse Lighting)
and Specular reflection (Specular Lighting)
.
Ambient lighting
One property of light is , It can diverge in many directions and bounce , So that we can reach points that are not very directly adjacent . therefore , Light can be reflected on other surfaces , Have an indirect effect on an object . We use a small constant ( light ) Color , Add to the final color of the object segment , In this way, even if there is no direct light source in the scene, it can appear that there is some divergent light .
// fragment shader
void main()
{
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
vec3 result = ambient * objectColor;
FragColor = vec4(result, 1.0);
}
Diffuse lighting
For calculating diffuse reflection , We need to know :
- The normal vector (
Normal vector
): A vector perpendicular to the vertex surface . - Directional light (
The directed light ray
): The direction vector as the vector difference between the position of the light source and the position of the clip .
For specific calculation examples, please refer to ->
The normal vector acts in the world coordinate system , In order to solve the problem that the normal vector is not perpendicular to the surface caused by the non proportional scaling of the object , Can pass Normal matrix (Normal Matrix)
Correct this behavior :
Normal = mat3(transpose(inverse(model))) * aNormal;
Specular Lighting
Just like diffuse lighting , Specular illumination also depends on the direction vector of light and the normal vector of the object , But it also depends on the direction of observation , For example, in what direction does the player look at this clip . We calculate the reflection vector by inverting the direction of the incident light according to the normal vector . Then we calculate the angle difference between the reflection vector and the viewing direction , The smaller the angle between them , The greater the effect of mirror light . The result is , When we look at the reflection direction of the incident light on the surface , You'll see a little highlights .
To calculate the reflection vector, you can use reflect( The light source points to the vector of the clip , The normal vector )
, To calculate the mirror component, you can use :
// This 32 value is the shininess value of the highlight.
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
Integrate three lighting effects to superimpose , The final code can refer to ->
Materials
In the real world, different objects behave differently under the same light source , The reason is that the materials are different :
#version 330 core
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
For light sources , The influence proportions of the three attributes on objects are also different :
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
Combine the two structures , The actual color of the object is calculated as follows :
in vec3 FragPos;
in vec3 Normal;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
// ambient
vec3 ambient = light.ambient * material.ambient;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * (diff * material.diffuse);
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * (spec * material.specular);
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}
Lighting maps
In the last section, the color of diffuse and specular reflection in the material is the same for the whole object , If you apply texture to reflection , It can be called diffuse map and specular map . The ambient color is equal to the diffuse color in almost all cases , So we don't need ambient light mapping .
For specific examples, please refer to ->
Light casters
In the real world , We have many kinds of light , Each performance is different . Project light (Cast) The light source to the object is called Projector (Light Caster)
.
Directional Light
When a light source is far away , Each ray from the light source will be approximately parallel to each other , Only the direction of the light source is needed to simulate the directional light .
struct Light {
// vec3 position; // Using directional light is no longer needed
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
...
void main()
{
vec3 lightDir = normalize(-light.direction);
...
}
Point lights
A point light is a light at a certain position in the world , It will shine in all directions , But as the distance of light propagation increases , Will gradually reduce the intensity of light , be called attenuation (Attenuation)
, Rules are as follows :
Due to the existence of quadratic terms , Light will decay in a linear manner most of the time , Until the distance becomes large enough , Let the second term exceed the first term , The intensity of light decreases at a faster rate . This is the result , Light is very bright at close range , But as the distance increases, the brightness decreases rapidly , Finally, the brightness will be reduced at a slower speed . The picture below shows the following in 100 The effect of attenuation within a distance :
As for how to choose these constant terms , You can refer to ->
The code implementation is as follows :
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
// ambient
vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
// attenuation
float distance = length(light.position - FragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}
Spotlight
A spotlight is a light source located somewhere in the environment , It shines light in only one direction, not all directions . The result is that only objects within a specific radius in the direction of the spotlight will be illuminated , Other objects will remain dark . A good example of spotlight is a street lamp or flashlight .
For each clip , We calculate whether the clip is between the tangent directions of the spotlight ( That is, in the cone ), Computation LightDir
Vector and SpotDir
Dot product between vectors , And connect it with Cutting angle ϕ
Value comparison , If it meets the requirements , We will illuminate the fragment accordingly .
To create a spotlight that looks smooth at the edges , We need to simulate a spotlight Inner cone (Inner Cone)
And a Outer cone (Outer Cone)
. We can set the inner cone to the one in the previous section , But we also need an outer cone , To darken the light from the inner cone , To the boundary of the outer cone .
To create an outer cone , We only need to define a cosine value to represent the focusing direction vector and the outer cone vector ( Equal to its radius ) The angle between . then , If a clip is between the inner and outer cones , I'll give it a 0.0 To 1.0 Strength value between . If the fragment is within the inner cone , Its strength is 1.0, If outside the outer cone, the strength value is 0.0.
The code implementation is as follows :
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
// ambient
vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
// spotlight (soft edges)
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = (light.cutOff - light.outerCutOff);
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
// attenuation
float distance = length(light.position - FragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}
Combine the above three light sources , The effect can refer to ->
边栏推荐
- 【阅读笔记】图对比学习 GNN+CL
- Solution to the problem of the 10th Programming Competition (synchronized competition) of Harbin University of technology "Colin Minglun Cup"
- 3D reconstruction open source code summary [keep updated]
- 驾驶证体检医院(114---2 挂对应的医院司机体检)
- 深入浅出PyTorch中的nn.CrossEntropyLoss
- Golang foundation -- map, array and slice store different types of data
- 2011-11-21 training record personal training (III)
- Nodejs modularization
- Solution to the problems of the 17th Zhejiang University City College Program Design Competition (synchronized competition)
- [ctfhub] Title cookie:hello guest only admin can get flag. (cookie spoofing, authentication, forgery)
猜你喜欢
Svgo v3.9.0+
[beauty of algebra] singular value decomposition (SVD) and its application to linear least squares solution ax=b
[code practice] [stereo matching series] Classic ad census: (4) cross domain cost aggregation
Introduction Guide to stereo vision (3): Zhang calibration method of camera calibration [ultra detailed and worthy of collection]
OpenGL - Lighting
Rebuild my 3D world [open source] [serialization-3] [comparison between colmap and openmvg]
Huber Loss
Applet (subcontracting)
嗨 FUN 一夏,与 StarRocks 一起玩转 SQL Planner!
AUTOSAR from getting started to mastering 100 lectures (103) -dbc file format and creation details
随机推荐
嗨 FUN 一夏,与 StarRocks 一起玩转 SQL Planner!
nodejs_ 01_ fs. readFile
scipy.misc.imread()
Shutter uses overlay to realize global pop-up
C#绘制带控制点的Bezier曲线,用于点阵图像及矢量图形
Uni app implements global variables
【阅读笔记】图对比学习 GNN+CL
Attention is all you need
牛顿迭代法(解非线性方程)
2310. 个位数字为 K 的整数之和
LeetCode 556. 下一个更大元素 III
C # draw Bezier curve with control points for lattice images and vector graphics
【愚公系列】2022年7月 Go教学课程 003-IDE的安装和基本使用
OpenGL - Coordinate Systems
Rebuild my 3D world [open source] [serialization-3] [comparison between colmap and openmvg]
图神经网络+对比学习,下一步去哪?
AdaBoost use
什么是防火墙?防火墙基础知识讲解
信息與熵,你想知道的都在這裏了
Kotlin introductory notes (II) a brief introduction to kotlin functions