Learn OpenGL 09 投光物+多光源

将光投射(Cast)到物体的光源叫做投光物(Light Caster)。

投光物主要分为点光源,聚光灯,平行光。

平行光

当一个光源处于很远的地方时,来自光源的每条光线就会近似于互相平行。不论物体和/或者观察者的位置,看起来好像所有的光都来自于同一个方向。当我们使用一个假设光源处于无限远处的模型时,它就被称为定向光,因为它的所有光线都有着相同的方向,它与光源的位置是没有关系的。

定向光非常好的一个例子就是太阳。太阳距离我们并不是无限远,但它已经远到在光照计算中可以把它视为无限远了。所以来自太阳的所有光线将被模拟为平行光线,我们可以在下图看到:

我们可以定义一个光线方向向量而不是位置向量来模拟一个定向光。 

所以修改片段着色器的结构

#version 330 core
out vec4 FragColor;struct Material {sampler2D diffuse;sampler2D specular;    sampler2D emission;float shininess;
}; struct Light {//vec3 position;vec3 direction;vec3 ambient;vec3 diffuse;vec3 specular;
};in vec3 FragPos;  
in vec3 Normal;  
in vec2 TexCoords;uniform vec3 viewPos;
uniform Material material;
uniform Light light;
uniform float time;void main()
{vec3 lightDir = normalize(-light.direction);// ambientvec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));  	// diffuse vec3 norm = normalize(Normal);//vec3 lightDir = normalize(light.position - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));    // specularvec3 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 * vec3(texture(material.specular, TexCoords)); vec3 emission;if(texture(material.specular, TexCoords).r==0)emission = texture(material.emission,TexCoords+vec2(0.0,time/2)).rgb;emission =   emission * (sin(2*time) * 0.5 + 0.5) ;//fadingvec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0);} 

点光源

定向光对于照亮整个场景的全局光源是非常棒的,但除了定向光之外我们也需要一些分散在场景中的点光源(Point Light)。点光源是处于世界中某一个位置的光源,它会朝着所有方向发光,但光线会随着距离逐渐衰减。想象作为投光物的灯泡和火把,它们都是点光源。

光照衰减

随着光线传播距离的增长逐渐削减光的强度通常叫做衰减(Attenuation)

在现实世界中,灯在近处通常会非常亮,但随着距离的增加光源的亮度一开始会下降非常快,但在远处时剩余的光强度就会下降的非常缓慢了。所以,我们需要一个不同的公式来减少光的强度。

幸运的是一些聪明的人已经帮我们解决了这个问题。下面这个公式根据片段距光源的距离计算了衰减值,之后我们会将它乘以光的强度向量:

在这里d代表了片段距光源的距离。接下来为了计算衰减值,我们定义3个(可配置的)项:常数项Kc、一次项Kl和二次项Kq。

  • 常数项通常保持为1.0,它的主要作用是保证分母永远不会比1小,否则的话在某些距离上它反而会增加强度,这肯定不是我们想要的效果。
  • 一次项会与距离值相乘,以线性的方式减少强度。
  • 二次项会与距离的平方相乘,让光源以二次递减的方式减少强度。二次项在距离比较小的时候影响会比一次项小很多,但当距离值比较大的时候它就会比一次项更大了。

由于二次项的存在,光线会在大部分时候以线性的方式衰退,直到距离变得足够大,让二次项超过一次项,光的强度会以更快的速度下降。这样的结果就是,光在近距离时亮度很高,但随着距离变远亮度迅速降低,最后会以更慢的速度减少亮度。下面这张图显示了在100的距离内衰减的效果:

 

但是,该对这三个项设置什么值呢?正确地设定它们的值取决于很多因素:环境、希望光覆盖的距离、光的类型等。在大多数情况下,这都是经验的问题,以及适量的调整。下面这个表格显示了模拟一个(大概)真实的,覆盖特定半径(距离)的光源时,这些项可能取的一些值。第一列指定的是在给定的三项时光所能覆盖的距离。这些值是大多数光源很好的起始点,它们由Ogre3D的Wiki所提供:

距离常数项一次项二次项
71.00.71.8
131.00.350.44
201.00.220.20
321.00.140.07
501.00.090.032
651.00.070.017
1001.00.0450.0075
1601.00.0270.0028
2001.00.0220.0019
3251.00.0140.0007
6001.00.0070.0002
32501.00.00140.000007

 实现衰减

只需要将衰减值乘上计算出来的环境光,漫反射光,以及镜面反射光

#version 330 core
out vec4 FragColor;struct Material {sampler2D diffuse;sampler2D specular;    sampler2D emission;float shininess;
}; struct Light {vec3 position;//vec3 direction;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;
uniform float time;void main()
{// vec3 lightDir = normalize(-light.direction);float distance    = length(light.position - FragPos);float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));// ambientvec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));  	// diffuse vec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));    // specularvec3 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 * vec3(texture(material.specular, TexCoords)); vec3 emission;if(texture(material.specular, TexCoords).r==0)emission = texture(material.emission,TexCoords+vec2(0.0,time/2)).rgb;emission =   emission * (sin(2*time) * 0.5 + 0.5) ;//fadingambient  *= attenuation; diffuse  *= attenuation;specular *= attenuation;vec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0);} 

聚光

聚光是位于环境中某个位置的光源,它只朝一个特定方向而不是所有方向照射光线。这样的结果就是只有在聚光方向的特定半径内的物体才会被照亮,其它的物体都会保持黑暗。聚光很好的例子就是路灯或手电筒。

OpenGL中聚光是用一个世界空间位置、一个方向和一个切光角(Cutoff Angle)来表示的,切光角指定了聚光的半径(译注:是圆锥的半径不是距光源距离那个半径)。对于每个片段,我们会计算片段是否位于聚光的切光方向之间(也就是在锥形内),如果是的话,我们就会相应地照亮片段。下面这张图会让你明白聚光是如何工作的:

  • LightDir:从片段指向光源的向量。
  • SpotDir:聚光所指向的方向。
  • Phiϕ:指定了聚光半径的切光角。落在这个角度之外的物体都不会被这个聚光所照亮。
  • Thetaθ:LightDir向量和SpotDir向量之间的夹角。在聚光内部的话θ�值应该比ϕ�值小。

所以我们要做的就是计算LightDir向量和SpotDir向量之间的点积(还记得它会返回两个单位向量夹角的余弦值吗?),并将它与切光角ϕ�值对比。你现在应该了解聚光究竟是什么了,下面我们将以手电筒的形式创建一个聚光。

手电筒

手电筒(Flashlight)是一个位于观察者位置的聚光,通常它都会瞄准玩家视角的正前方。基本上说,手电筒就是普通的聚光,但它的位置和方向会随着玩家的位置和朝向不断更新。

在片段着色器中我们需要的值有聚光的位置向量(来计算光的方向向量)、聚光的方向向量和一个切光角。我们可以将它们储存在Light结构体中:

接下来就是计算θ值,并将它和切光角ϕ对比,来决定是否在聚光的内部:

float theta = dot(lightDir, normalize(-light.direction));if(theta > light.cutOff) 
{       // 执行光照计算
}
else  // 否则,使用环境光,让场景在聚光之外时不至于完全黑暗color = vec4(light.ambient * vec3(texture(material.diffuse, TexCoords)), 1.0);

为了创建一种看起来边缘平滑的聚光,我们需要模拟聚光有一个内圆锥(Inner Cone)和一个外圆锥(Outer Cone)。我们可以将内圆锥设置为上一部分中的那个圆锥,但我们也需要一个外圆锥,来让光从内圆锥逐渐减暗,直到外圆锥的边界。

为了创建一个外圆锥,我们只需要再定义一个余弦值来代表聚光方向向量和外圆锥向量(等于它的半径)的夹角。然后,如果一个片段处于内外圆锥之间,将会给它计算出一个0.0到1.0之间的强度值。如果片段在内圆锥之内,它的强度就是1.0,如果在外圆锥之外强度值就是0.0。

我们可以用下面这个公式来计算这个值:

这里ϵ(Epsilon)是内(ϕ)和外圆锥(γ)之间的余弦值差(ϵ=ϕ−γ)。最终的I值就是在当前片段聚光的强度。

很难去表现这个公式是怎么工作的,所以我们用一些实例值来看看:

θ�θ�(角度)ϕ�(内光切)ϕ�(角度)γ�(外光切)γ�(角度)ϵ�I�
0.87300.91250.82350.91 - 0.82 = 0.090.87 - 0.82 / 0.09 = 0.56
0.9260.91250.82350.91 - 0.82 = 0.090.9 - 0.82 / 0.09 = 0.89
0.97140.91250.82350.91 - 0.82 = 0.090.97 - 0.82 / 0.09 = 1.67
0.83340.91250.82350.91 - 0.82 = 0.090.83 - 0.82 / 0.09 = 0.11
0.64500.91250.82350.91 - 0.82 = 0.090.64 - 0.82 / 0.09 = -2.0
0.966150.997812.50.95317.50.9978 - 0.953 = 0.04480.966 - 0.953 / 0.0448 = 0.29

片段着色器

#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()
{vec3 lightDir = normalize(light.position - FragPos);// check if lighting is inside the spotlight conefloat theta = dot(lightDir, normalize(-light.direction)); if(theta > light.cutOff) // remember that we're working with angles as cosines instead of degrees so a '>' is used.{    // ambientvec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;// diffuse vec3 norm = normalize(Normal);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;  // specularvec3 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;  // attenuationfloat distance    = length(light.position - FragPos);float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    // ambient  *= attenuation; // remove attenuation from ambient, as otherwise at large distances the light would be darker inside than outside the spotlight due the ambient term in the else branchdiffuse   *= attenuation;specular *= attenuation;   vec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0);}else {// else, use ambient light so scene isn't completely dark outside the spotlight.FragColor = vec4(light.ambient * texture(material.diffuse, TexCoords).rgb, 1.0);}
} 

 实现多光源

当我们在场景中使用多个光源时,通常使用以下方法:我们需要有一个单独的颜色向量代表片段的输出颜色。对于每一个光源,它对片段的贡献颜色将会加到片段的输出颜色向量上。所以场景中的每个光源都会计算它们各自对片段的影响,并结合为一个最终的输出颜色。

我们需要分别定义每一种光源的结构体,并且在main.cpp里设置他们需要的参数,另外还需要编写不同的函数计算不同的光源,这样不至于让代码变得太复杂。

最后效果

片元着色器代码

#version 330 core
out vec4 FragColor;struct Material {sampler2D diffuse;sampler2D specular;float shininess;
}; struct DirLight {vec3 direction;vec3 ambient;vec3 diffuse;vec3 specular;
};struct PointLight {vec3 position;float constant;float linear;float quadratic;vec3 ambient;vec3 diffuse;vec3 specular;
};struct SpotLight {vec3 position;vec3 direction;float cutOff;float outerCutOff;float constant;float linear;float quadratic;vec3 ambient;vec3 diffuse;vec3 specular;       
};#define NR_POINT_LIGHTS 4in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;uniform vec3 viewPos;
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight;
uniform Material material;// function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);void main()
{    // propertiesvec3 norm = normalize(Normal);vec3 viewDir = normalize(viewPos - FragPos);vec3 result;// phase 1: directional lighting// result+ = CalcDirLight(dirLight, norm, viewDir);// phase 2: point lightsfor(int i = 0; i < NR_POINT_LIGHTS; i++)// result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);    // phase 3: spot lightresult += CalcSpotLight(spotLight, norm, FragPos, viewDir);    FragColor = vec4(result, 1.0);
}// calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{vec3 lightDir = normalize(-light.direction);// diffuse shadingfloat diff = max(dot(normal, lightDir), 0.0);// specular shadingvec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// combine resultsvec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));return (ambient + diffuse + specular);
}// calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{vec3 lightDir = normalize(light.position - fragPos);// diffuse shadingfloat diff = max(dot(normal, lightDir), 0.0);// specular shadingvec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// attenuationfloat distance = length(light.position - fragPos);float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    // combine resultsvec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));ambient *= attenuation;diffuse *= attenuation;specular *= attenuation;return (ambient + diffuse + specular);
}// calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{vec3 lightDir = normalize(light.position - fragPos);// diffuse shadingfloat diff = max(dot(normal, lightDir), 0.0);// specular shadingvec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// attenuationfloat distance = length(light.position - fragPos);float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    // spotlight intensityfloat theta = dot(lightDir, normalize(-light.direction)); float epsilon = light.cutOff - light.outerCutOff;float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);// combine resultsvec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));ambient *= attenuation * intensity;diffuse *= attenuation * intensity;specular *= attenuation * intensity;return (ambient + diffuse + specular);
}

练习

要复现这几个氛围,首先需要提取到几个氛围的背景色。

可以用拾色器获取到颜色值,然后除以255就是rgb的小数值

p1

第一个场景

效果

因为要设置点光源的颜色,所以要修改光源的片段着色器

#version 330 core
out vec4 FragColor;uniform vec3 lightcolor;void main()
{FragColor = vec4(lightcolor,1); 
}

 在循环渲染点光源的时候为他们设置颜色

 for (unsigned int i = 0; i < 4; i++){lightShader.setVec3("lightcolor", pointLightColors[i]);model = glm::mat4(1.0f);model = glm::translate(model, pointLightPositions[i]);model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cubelightShader.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);}

然后就是剩下的光照参数的设置

 // directional lightlightingShader.setVec3("dirLight.direction", glm::vec3(-0.2f, -1.0f, -0.3f));lightingShader.setVec3("dirLight.ambient", glm::vec3(0.3f, 0.24f, 0.14f));lightingShader.setVec3("dirLight.diffuse", glm::vec3(0.7f, 0.42f, 0.26f));lightingShader.setVec3("dirLight.specular", glm::vec3(0.5f, 0.5f, 0.5f));// point light 1lightingShader.setVec3("pointLights[0].position", pointLightPositions[0]);lightingShader.setVec3("pointLights[0].ambient", glm::vec3(0.1)*pointLightColors[0]);lightingShader.setVec3("pointLights[0].diffuse", pointLightColors[0]);lightingShader.setVec3("pointLights[0].specular", pointLightColors[0]);lightingShader.setFloat("pointLights[0].constant", 1.0f);lightingShader.setFloat("pointLights[0].linear", 0.09f);lightingShader.setFloat("pointLights[0].quadratic", 0.032f);// Point light 2lightingShader.setVec3("pointLights[1].position", pointLightPositions[1]);lightingShader.setVec3("pointLights[1].ambient", glm::vec3(0.1f) * pointLightColors[1]);lightingShader.setVec3("pointLights[1].diffuse", pointLightColors[1]);lightingShader.setVec3("pointLights[1].specular", pointLightColors[1]);lightingShader.setFloat("pointLights[1].constant", 1.0f);lightingShader.setFloat("pointLights[1].linear", 0.09f);lightingShader.setFloat("pointLights[1].quadratic", 0.032f);// Point light 3lightingShader.setVec3("pointLights[2].position", pointLightPositions[2]);lightingShader.setVec3("pointLights[2].ambient", glm::vec3(0.1f) * pointLightColors[2]);lightingShader.setVec3("pointLights[2].diffuse", pointLightColors[2]);lightingShader.setVec3("pointLights[2].specular", pointLightColors[2]);lightingShader.setFloat("pointLights[2].constant", 1.0f);lightingShader.setFloat("pointLights[2].linear", 0.09f);lightingShader.setFloat("pointLights[2].quadratic", 0.032f);// Point light 4lightingShader.setVec3("pointLights[3].position", pointLightPositions[3]);lightingShader.setVec3("pointLights[3].ambient", glm::vec3(0.1f) * pointLightColors[3]);lightingShader.setVec3("pointLights[3].diffuse", pointLightColors[3]);lightingShader.setVec3("pointLights[3].specular", pointLightColors[3]);lightingShader.setFloat("pointLights[3].constant", 1.0f);lightingShader.setFloat("pointLights[3].linear", 0.09f);lightingShader.setFloat("pointLights[3].quadratic", 0.032f);// spotLightlightingShader.setVec3("spotLight.position", glm::vec3(camera.Position.x, camera.Position.y, camera.Position.z));lightingShader.setVec3("spotLight.direction", glm::vec3(camera.Front.x, camera.Front.y, camera.Front.z));lightingShader.setVec3("spotLight.ambient", glm::vec3(0.0f, 0.0f, 0.0f));lightingShader.setVec3("spotLight.diffuse", glm::vec3(0.8f, 0.8f, 0.0f));lightingShader.setVec3("spotLight.specular", glm::vec3(0.8f, 0.8f, 0.0f));lightingShader.setFloat("spotLight.constant", 1.0f);lightingShader.setFloat("spotLight.linear", 0.09f);lightingShader.setFloat("spotLight.quadratic", 0.032f);lightingShader.setFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f)));lightingShader.setFloat("spotLight.outerCutOff", glm::cos(glm::radians(13.0f)));

P2

和上一个一样的思路

效果:

这次将参数设置的代码精炼了很多,一次循环设置了四个点光源的参数

// directional lightlightingShader.setVec3("dirLight.direction", glm::vec3(-0.2f, -1.0f, -0.3f));lightingShader.setVec3("dirLight.ambient", glm::vec3(0.05f, 0.05f, 0.1f));lightingShader.setVec3("dirLight.diffuse", glm::vec3(0.2f, 0.2f, 0.7f));lightingShader.setVec3("dirLight.specular", glm::vec3(0.7f, 0.7f, 0.7f));// Point lightsfor (int i = 0; i < 4; ++i) {std::string pointLightIndex = "pointLights[" + std::to_string(i) + "].";lightingShader.setVec3(pointLightIndex + "position", pointLightPositions[i]);lightingShader.setVec3(pointLightIndex + "ambient", glm::vec3(pointLightColors[i].x * 0.1, pointLightColors[i].y * 0.1, pointLightColors[i].z * 0.1));lightingShader.setVec3(pointLightIndex + "diffuse", pointLightColors[i]);lightingShader.setVec3(pointLightIndex + "specular", pointLightColors[i]);lightingShader.setFloat(pointLightIndex + "constant", 1.0f);lightingShader.setFloat(pointLightIndex + "linear", 0.09f);lightingShader.setFloat(pointLightIndex + "quadratic", 0.032f);}// SpotLightlightingShader.setVec3("spotLight.position", glm::vec3(camera.Position.x, camera.Position.y, camera.Position.z));lightingShader.setVec3("spotLight.direction", glm::vec3(camera.Front.x, camera.Front.y, camera.Front.z));lightingShader.setVec3("spotLight.ambient", glm::vec3(0.0f, 0.0f, 0.0f));lightingShader.setVec3("spotLight.diffuse", glm::vec3(1.0f, 1.0f, 1.0f));lightingShader.setVec3("spotLight.specular", glm::vec3(1.0f, 1.0f, 1.0f));lightingShader.setFloat("spotLight.constant", 1.0f);lightingShader.setFloat("spotLight.linear", 0.009f);lightingShader.setFloat("spotLight.quadratic", 0.0032f);lightingShader.setFloat("spotLight.cutOff", glm::cos(glm::radians(10.0f)));lightingShader.setFloat("spotLight.outerCutOff", glm::cos(glm::radians(12.5f)));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/743452.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软考高级:需求验证概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

linux环境下安装运行环境JDK、Docker、Maven、MySQL、RabbitMQ、Redis、nacos、Elasticsearch

安装JDK 1、提前下载好jdk 官网&#xff1a;点击下载 2、将下载的文件放到自己喜欢的目录下 然后使用下面命令进行解压 tar -zxvf jdk-8u161-linux-x64.tar.gz3、配置环境变量 使用命令 vim /etc/profile在文件的最后插入 export JAVA_HOME/source/java/jdk1.8.0_161 #…

内存操作函数

memcpy mem--memory--内存 指向计算机内存 cpy-copy-拷贝 也就是内存拷贝 针对内存的函数 void* memcpy(void * destination,const void * source,size_t num) 把source的空间 复制到 destination的部分 长度是num 如果source 和 dest 的部分有重叠,会复制的结果是未定义的(建…

如何让Windows 10的开始菜单回到7的样子?这里提供详细步骤

前言 在新版本的Windows推出时,你可能会听到一个抱怨,那就是他们对开始菜单做了什么,如果你只想让Windows 10中的开始菜单像Windows 7的开始菜单那样外观和功能,我们将提供帮助。 准备条件 除了Windows 10安装之外,我们唯一需要的是一个非常方便的小程序,那就是Classic…

监听抖音直播间的评论并实现存储

监听抖音直播间评论&#xff0c;主要是动态监听dom元素的变化&#xff0c;如果评论是图片类型的&#xff0c;获取alt的值 主要采用的是MutationObserver&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver index.js如下所示:function getPL() {…

基于深度学习的图像去雨去雾

基于深度学习的图像去雨去雾 文末附有源码下载地址 b站视频地址&#xff1a; https://www.bilibili.com/video/BV1Jr421p7cT/ 基于深度学习的图像去雨去雾&#xff0c;使用的网络为unet&#xff0c; 网络代码&#xff1a; import torch import torch.nn as nn from torchsumm…

拼图小游戏制作教程:用HTML5和JavaScript打造经典游戏

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

【数据结构】栈与队列的“双向奔赴”

目录 前言 1.使用“栈”检查符号是否成对出现 2.使用“栈”实现字符串反转 3.使用“队列”实现“栈” 4.使用“栈”实现“队列” 前言 什么是栈&#xff1f; 栈&#xff08;stack&#xff09;是一种特殊的线性数据集合&#xff0c;只允许在栈顶按照后进先出LIFO&#xff…

网上商城购物系统|基于springboot框架+ Mysql+Java+B/S架构的网上商城购物系统设计与实现(可运行源码+数据库+设计文档+部署说明)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能模块 系统功能设计 数据库E-R图设计 lunwen参…

ip广播智慧工地广播喊话号角 IP网络号角在塔吊中应用 通过寻呼话筒预案广播

ip广播智慧工地广播喊话号角 IP网络号角在塔吊中应用 通过寻呼话筒预案广播 SV-704XT是深圳锐科达电子有限公司的一款壁挂式网络有源号角&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和号角喇叭输出播放&#xff0c;可达到功率50W。SV-704XT内置有…

OneDrive教育版迁移记录

背景 微软再次削减教育版优惠的OneDrive容量&#xff0c;从原先的5T直接砍到100G/人&#xff0c;同时对每个学校保留总共100TB的共享存储容量。 右键Onedrive图标——设置——存储容量可见 100GB对于重度用户显然是不够使用的&#xff0c;为此笔者改换Microsoft Office365家庭…

mac启动skywalking报错

这个命令显示已经成功 但是日志报错了以上内容。 然后去修改。vim .bash_profile 查看全局变量&#xff0c;这个jdk却是有2个。所以这个问题没解决。

【哈希映射】【 哈希集合】 381. O(1) 时间插入、删除和获取随机元素 - 允许重复

作者推荐 视频算法专题 本文涉及知识点 哈希映射 哈希集合 LeetCode 381. O(1) 时间插入、删除和获取随机元素 - 允许重复 RandomizedCollection 是一种包含数字集合(可能是重复的)的数据结构。它应该支持插入和删除特定元素&#xff0c;以及删除随机元素。 实现 Randomiz…

python爬虫实战——小红书

目录 1、博主页面分析 2、在控制台预先获取所有作品页的URL 3、在 Python 中读入该文件并做准备工作 4、处理图文类型作品 5、处理视频类型作品 6、异常访问而被中断的现象 7、完整参考代码 任务&#xff1a;在 win 环境下&#xff0c;利用 Python、webdriver、JavaS…

<.Net>VisaulStudio2022下用VB.net实现socket与汇川PLC进行通讯案例(Eazy521)

前言 此前&#xff0c;我写过一个VB.net环境下与西门子PLC通讯案例的博文&#xff1a; VisaulStudio2022下用VB.net实现socket与西门子PLC进行通讯案例&#xff08;优化版&#xff09; 最近项目上会用到汇川PLC比较多&#xff0c;正好有个项目有上位机通讯需求&#xff0c;于是…

[剪藏] - 由哇哈哈和农夫山泉所想到的

哇哈哈和农夫山泉的缠斗最近冒出来一个有趣的点&#xff1a;营销大于内容的胜利。 具体来说是这样的&#xff1a;农夫山泉很多年前做广告&#xff0c;说纯净水没有矿物质&#xff0c;长期喝是不利于人体健康的。农夫还做了个营销的对比实验&#xff0c;大概是用矿泉水养水仙花&…

音视频开发之旅(75)- AI数字人进阶--GeneFace++

目录 1.效果展示和玩法场景 2.GeneFace原理学习 3.数据集准备以及训练的过程 5.遇到的问题与解决方案 6.参考资料 一、效果展示 AI数字人进阶--GeneFace&#xff08;1&#xff09; AI数字人进阶--GeneFace&#xff08;2&#xff09; 想象一下&#xff0c;一个专为你打造的…

为什么 VSCode 不用 Qt 而要用 Electron?

为什么 VSCode 不用 Qt 而要用 Electron? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Qt 的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&am…

Python基础课堂最后一课23——正则对象

文章目录 前言一、正则对象是什么&#xff1f;二、正则表达式基本分类1.普通字符2.元字符 总结 前言 很开心能和你们一些学习进步&#xff0c;在这一个多月的时间中&#xff0c;是你们让我坚持了下来&#xff0c;完成了python基础课堂编写&#xff0c;不管如何&#xff0c;我们…

Linux系统——Nginx脚本拦截拓展

可能会有些无聊的人对服务器的Nginx服务进行恶意访问网站、API接口&#xff0c;会影响到用户的体验&#xff0c;我们可以做一个简单的脚本对恶意访问的IP做一个有效的拦截&#xff0c;揪出这些IP地址&#xff0c;然后将其进行禁用。 在Nginx的conf目录下新建一个blockip.conf文…