OpenGl光照之材质

news2025/1/24 4:57:21

文章目录

  • 设置材质
  • 光的属性
  • 完整代码

 在现实世界里,每个物体会对光产生不同的反应。比如,钢制物体看起来通常会比陶土花瓶更闪闪发光,一个木头箱子也不会与一个钢制箱子反射同样程度的光。有些物体反射光的时候不会有太多的散射(Scatter),因而产生较小的高光点,而有些物体则会散射很多,产生一个有着更大半径的高光点。如果我们想要在OpenGL中模拟多种类型的物体,我们必须针对每种表面定义不同的材质(Material)属性。
 当描述一个表面时,我们可以分别为三个光照分量定义一个材质颜色(Material Color):环境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和镜面光照(Specular Lighting)。通过为每个分量指定一个颜色,我们就能够对表面的颜色输出有细粒度的控制了。现在,我们再添加一个反光度(Shininess)分量,结合上述的三个颜色,我们就有了全部所需的材质属性了:

#version 330 core
struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
}; 

uniform Material material;

 在片段着色器中,我们创建一个结构体(Struct)来储存物体的材质属性。我们也可以把它们储存为独立的uniform值,但是作为一个结构体来储存会更有条理一些。我们首先定义结构体的布局(Layout),然后简单地以刚创建的结构体作为类型声明一个uniform变量。
 如你所见,我们为冯氏光照模型的每个分量都定义一个颜色向量。ambient材质向量定义了在环境光照下这个表面反射的是什么颜色,通常与表面的颜色相同。diffuse材质向量定义了在漫反射光照下表面的颜色。漫反射颜色(和环境光照一样)也被设置为我们期望的物体颜色。specular材质向量设置的是表面上镜面高光的颜色(或者甚至可能反映一个特定表面的颜色)。最后,shininess影响镜面高光的散射/半径。

设置材质

 我们在片段着色器中创建了一个材质结构体的uniform,所以下面我们希望修改一下光照的计算来遵从新的材质属性。由于所有材质变量都储存在一个结构体中,我们可以从uniform变量material中访问它们:

void main()
{    
    // 环境光
    vec3 ambient = lightColor * material.ambient;

    // 漫反射 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = lightColor * (diff * material.diffuse);

    // 镜面光
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = lightColor * (spec * material.specular);  

    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
}

 可以看到,我们现在在需要的地方访问了材质结构体中的所有属性,并且这次是根据材质的颜色来计算最终的输出颜色的。物体的每个材质属性都乘上了它们各自对应的光照分量。
 我们现在可以通过设置适当的uniform来设置应用中物体的材质了。GLSL中一个结构体在设置uniform时并无任何区别,结构体只是充当uniform变量们的一个命名空间。所以如果想填充这个结构体的话,我们必须设置每个单独的uniform,但要以结构体名为前缀:

lightingShader.setVec3("material.ambient",  1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.diffuse",  1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
lightingShader.setFloat("material.shininess", 32.0f);

 我们将环境光和漫反射分量设置成我们想要让物体所拥有的颜色,而将镜面分量设置为一个中等亮度的颜色,我们不希望镜面分量过于强烈。我们仍将反光度保持为32。
在这里插入图片描述

光的属性

 这个物体太亮了。物体过亮的原因是环境光、漫反射和镜面光这三个颜色对任何一个光源都全力反射。光源对环境光、漫反射和镜面光分量也分别具有不同的强度。前面的章节中,我们通过使用一个强度值改变环境光和镜面光强度的方式解决了这个问题。我们想做类似的事情,但是这次是要为每个光照分量分别指定一个强度向量。如果我们假设lightColor是vec3(1.0),代码会看起来像这样:

vec3 ambient  = vec3(1.0) * material.ambient;
vec3 diffuse  = vec3(1.0) * (diff * material.diffuse);
vec3 specular = vec3(1.0) * (spec * material.specular);

 所以物体的每个材质属性对每一个光照分量都返回了最大的强度。对单个光源来说,这些vec3(1.0)值同样可以对每种光源分别改变,而这通常就是我们想要的。现在,物体的环境光分量完全地影响了立方体的颜色,可是环境光分量实际上不应该对最终的颜色有这么大的影响,所以我们会将光源的环境光强度设置为一个小一点的值,从而限制环境光颜色:

vec3 ambient = vec3(0.1) * material.ambient;

 我们可以用同样的方式影响光源的漫反射和镜面光强度。这和我们在上一节中所做的极为相似,你可以认为我们已经创建了一些光照属性来影响各个光照分量。我们希望为光照属性创建类似材质结构体的东西:

struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Light light;

 一个光源对它的ambient、diffuse和specular光照分量有着不同的强度。环境光照通常被设置为一个比较低的强度,因为我们不希望环境光颜色太过主导。光源的漫反射分量通常被设置为我们希望光所具有的那个颜色,通常是一个比较明亮的白色。镜面光分量通常会保持为vec3(1.0),以最大强度发光。注意我们也将光源的位置向量加入了结构体。
 和材质uniform一样,我们需要更新片段着色器:

vec3 ambient  = light.ambient * material.ambient;
vec3 diffuse  = light.diffuse * (diff * material.diffuse);
vec3 specular = light.specular * (spec * material.specular);

 我们接下来在应用中设置光照强度:

lightingShader.setVec3("light.ambient",  0.2f, 0.2f, 0.2f);
lightingShader.setVec3("light.diffuse",  0.5f, 0.5f, 0.5f); // 将光照调暗了一些以搭配场景
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f); 

 现在我们已经调整了光照对物体材质的影响,我们得到了一个与上一节很相似的视觉效果。但这次我们有了对光照和物体材质的完全掌控:
在这里插入图片描述

完整代码

main.cpp

#include <glad/glad.h> 
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath> 
#include "../shader.h"
#include "../stb_image.h"
#include "../camera.h"
#include <glm/glm.hpp> 
#include <glm/gtc/matrix_transform.hpp> 
#include <glm/gtc/type_ptr.hpp>


float vertices[] = {
	 -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	  0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	  0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	  0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	 -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
	 -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

	 -0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	  0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	  0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	  0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	 -0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,
	 -0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,

	 -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
	 -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	 -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	 -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
	 -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
	 -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

	  0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
	  0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	  0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	  0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
	  0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
	  0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

	 -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
	  0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
	  0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	  0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	 -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
	 -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

	 -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
	  0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
	  0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	  0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	 -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
	 -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
};


const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);


float ratio = 0.5;
void processInput(GLFWwindow* window);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
float deltaTime = 0.0f; // 距离上一帧的时间间隔 
float lastFrame = 0.0f; // 上一帧发生的时间
bool firstMouse = true;
float yaw = -90.0f;
float pitch = 0.0f;
float lastX = 800.0f / 2.0;
float lastY = 600.0 / 2.0;
float fov = 45.0f;


int main() {
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__ 
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
	GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
	if (window == NULL) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	//GLFW将窗口的上下文设置为当前线程的上下文
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);

	//GLAD
	// glad: 加载所有OpenGL函数指针
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	Shader ourShader("shaders/shader.vs","shaders/shader.fs");
	Shader lightShader("shaders/shader.vs", "shaders/lightShader.fs");

	//创建VBO和VAO对象,并赋予ID
	unsigned int VBO, VAO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	//绑定VBO和VAO对象
	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//为当前绑定到target的缓冲区对象创建一个新的数据存储。
	//如果data不是NULL,则使用来自此指针的数据初始化数据存储
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	//告知Shader如何解析缓冲里的属性值
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
	//开启VAO管理的第一个属性值
	glEnableVertexAttribArray(0);

	//告知Shader如何解析缓冲里的属性值
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
	//开启VAO管理的第一个属性值
	glEnableVertexAttribArray(1);


	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	stbi_set_flip_vertically_on_load(true);
	unsigned int texture, texture1;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);

	// 加载并生成纹理 
	int width, height, nrChannels;
	unsigned char* data = stbi_load("../pics/container.jpg", &width, &height, &nrChannels, 0); 
	if (data) 
	{
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

		//float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
		//glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	}
	else 
	{
			std::cout << "Failed to load texture" << std::endl;
	}
	stbi_image_free(data);

	glGenTextures(1, &texture1);
	glBindTexture(GL_TEXTURE_2D, texture1);
	data = stbi_load("../pics/awesomeface.png", &width, &height, &nrChannels, 0);
	if (data)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);


		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	}
	else
	{
		std::cout << "Failed to load texture" << std::endl;
	}
	stbi_image_free(data);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, texture);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, texture1);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

	ourShader.use();
	ourShader.setInt("texture1", 0);
	ourShader.setInt("texture2", 1);

	// 渲染循环
	while (!glfwWindowShouldClose(window)) {
		processInput(window);

		float currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;

		//glClearColor(0.2f, 0.3f, 0.3f, 1.0f); //状态设置
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //状态使用


		ourShader.use();
		glm::mat4 model = glm::mat4(1.0f);
		// pass projection matrix to shader (note that in this case it could change every frame)
		glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
		ourShader.setMat4("projection", projection);

		// camera/view transformation
		glm::mat4 view = camera.GetViewMatrix();
		ourShader.setMat4("view", view);


		ourShader.setFloat("ratio", ratio);

		glEnable(GL_DEPTH_TEST);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		// glfw: 交换缓冲区和轮询IO事件(按键按下/释放、鼠标移动等)

		glBindVertexArray(VAO);

		ourShader.setMat4("model", model);
		ourShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
		ourShader.setVec3("material.diffuse", 1.0f, 0.5f, 0.31f);
		ourShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
		ourShader.setFloat("material.shininess", 32.0f);

		glm::vec3 lightColor;
		lightColor.x = sin(glfwGetTime() * 2.0f);
		lightColor.y = sin(glfwGetTime() * 0.7f);
		lightColor.z = sin(glfwGetTime() * 1.3f);
		glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f);
		glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f);
		ourShader.setVec3("light.ambient", ambientColor);
		ourShader.setVec3("light.diffuse", diffuseColor);

		lightPos.x = sin(glfwGetTime()) * 3.0;
		lightPos.z = cos(glfwGetTime()) * 3.0;
		ourShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
		ourShader.setVec3("light.position", lightPos);

		ourShader.setVec3("viewPos", camera.Position);
		glDrawArrays(GL_TRIANGLES, 0, 36);


		lightShader.use();
		model = glm::mat4(1.0f);
		model = glm::translate(model, lightPos);
		model = glm::scale(model, glm::vec3(0.2f));
		lightShader.use();
		lightShader.setMat4("model", model);
		lightShader.setMat4("projection", projection);
		lightShader.setMat4("view", view);
		lightShader.setVec3("lightColor", lightColor);
		glDrawArrays(GL_TRIANGLES, 0, 36);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	// glfw: 回收前面分配的GLFW先关资源. 
	glfwTerminate();
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteProgram(ourShader.ID);

	return 0;
}

void processInput(GLFWwindow* window) 
{
	float cameraSpeed = 2.5f * deltaTime;
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);

	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
		camera.ProcessKeyboard(FORWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		camera.ProcessKeyboard(LEFT, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		camera.ProcessKeyboard(RIGHT, deltaTime);

}

void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
{
	float xpos = static_cast<float>(xposIn);
	float ypos = static_cast<float>(yposIn);

	if (firstMouse)
	{
		lastX = xpos;
		lastY = ypos;
		firstMouse = false;
	}

	float xoffset = xpos - lastX;
	float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top

	lastX = xpos;
	lastY = ypos;

	camera.ProcessMouseMovement(xoffset, yoffset);

}

void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
	fov -= (float)yoffset;
	if (fov < 1.0f) fov = 1.0f;
	if (fov > 75.0f) fov = 75.0f;
}

shader.vs

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out vec3 Normal;
out vec3 FragPos; 
out vec3 lightPos; 

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    Normal = mat3(transpose(inverse(model))) * aNormal;
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    FragPos = vec3(model * vec4(aPos,1.0));
}

shader.fs

#version 330 core 
out vec4 FragColor; 
in vec3 Normal;
in vec3 FragPos; 

struct Material { 
vec3 ambient; 
vec3 diffuse; 
vec3 specular; 
float shininess; 
}; 
uniform Material material;

struct Light { 
vec3 position; 
vec3 ambient; 
vec3 diffuse; 
vec3 specular; 
}; 
uniform Light light;
uniform vec3 viewPos; 
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); 
}

LightShader.fs

#version 330 core 
out vec4 FragColor; 
uniform vec3 lightColor;

void main() { 
	FragColor = vec4(lightColor,1.0); 
}

参考链接

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

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

相关文章

6月10日,今日信息差

1、中国科学家实现含氯废塑料高效无害升级回收。近日&#xff0c;中国科学院上海硅酸盐研究所首席研究员黄富强团队采用新型常温脱氯法&#xff0c;将含氯废塑料直接转化成多种高附加值新材料&#xff0c;成功实现高效无害升级回收&#xff0c;可广泛应用于绿色环保、新型储能、…

Linux5.2 LVS+keepalived高可用群集

文章目录 计算机系统5G云计算第三章 LINUX LVSKeepalived群集一、Keepalived 概述1. Keepalived 作用2.Keepalived 实现原理剖析3.VRRP协议&#xff08;虚拟路由冗余协议&#xff09;4.Keepalived 主要模块及其作用5.健康检查方式&#xff08;学名&#xff1a;探针&#xff09;…

chatgpt赋能python:Python怎么删库:谨慎使用

Python怎么删库&#xff1a;谨慎使用 Python是一种强大的编程语言&#xff0c;它被广泛用于各种项目中&#xff0c;不仅仅是数据科学和机器学习。但它也可以被用来执行危险的任务&#xff0c;比如删库。当你需要在Python中进行数据库操作时&#xff0c;一定要特别小心。在这篇…

Stable-Diffusion|文生图 拍立得纪实风格的Lora 图例(三)

上篇【Stable-Diffusion|入门怎么下载与使用civitai网站的模型&#xff08;二&#xff09;】介绍了如何使用c站进行文生图&#xff0c;尤其一些Lora可能随时会下架&#xff0c;所以及时测试&#xff0c;及时保存很关键&#xff0c;更新一些笔者目前尝试比较有意思的Lora。 本篇…

【python】【excel】在UI中加载EXCEL并修改

界面 代码 import tkinter as tk from tkinter import filedialog from pandastable import Table import pandas as pd import pyperclipclass ExcelEditor(tk.Frame):def __init__(self, parentNone):tk.Frame.__init__(self, parent)self.parent parentself.grid()self.cr…

chatgpt赋能python:如何在Python中添加空行?

如何在Python中添加空行&#xff1f; 如果你是一个有经验的Python工程师&#xff0c;在编写代码时你可能会遇到需要添加空行的情况。但是有几种方法可以实现这一点&#xff0c;你应该用哪种方法呢&#xff1f;在本文中&#xff0c;我们将探讨如何在Python中添加空行以及各种添…

TypeScript 5.1发布,新功能更新

文章目录 1&#xff1a;返回类型增加undefined2&#xff1a;getter可以设置和 setter 的不相关类型3&#xff1a;对 JSX 元素和 JSX 标签的异步支持4&#xff1a;支持命名空间属性名称 JSX5&#xff1a;typeRoots在模块更新6&#xff1a;JSX 标签的链接游标7&#xff1a;param …

Python中对文件的基本操作

文章目录 文件和目录路径文件的读取、写入、复制、删除、变更位置及修改名称解压缩zip格式的文件剪切板的应用使用python-docx处理Word文档使用openpyxl处理Excel文档示例&#xff1a;获取Excel文档中的数据生成Word文档 文件和目录路径 os库是Python内置的标准库&#xff0c;…

张天禹移动端学习

文章目录 相关概念&#xff08;一&#xff09;屏幕相关1. 屏幕大小2. 屏幕分辨率3. 屏幕密度 &#xff08;二&#xff09;像素相关1.物理像素2. css 像素3. 设备独立像素4.像素比5.像素之间的关系 &#xff08;三&#xff09;图片高清显示位图像素图片的高清显示&#xff08;媒…

chatgpt赋能python:Python下如何给网页添加背景图片

Python下如何给网页添加背景图片 随着现代互联网的快速发展&#xff0c;人们对于网页设计的要求越来越高&#xff0c;其中非常重要的一项就是背景图。在Python编程中&#xff0c;我们也可以很容易的为网页添加背景图片。 HTML中的background属性 要给网页加上背景图&#xf…

chatgpt赋能python:Python加法表达式,快速简便的计算方式

Python加法表达式&#xff0c;快速简便的计算方式 介绍 Python是一种可读性强、简洁、易于学习的编程语言&#xff0c;同时也是一种高级编程语言&#xff0c;由于其简洁性和可读性&#xff0c;越来越多的程序员们选择Python作为他们的工作语言。在Python中&#xff0c;加法表…

C++技能 - 详解使用Lambda表达式【再也不怕看不懂别人的代码了,干货还是蛮多的】

系列文章目录 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 C技能系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream w…

C语言之函数初阶(2)

目录 1. 函数是什么 2. 库函数 3. 自定义函数 4. 函数参数 5. 函数调用 6. 函数的嵌套调用和链式访问 7. 函数的声明和定义 8. 函数递归 上一篇博客我们讲解了函数的前六个比较容易理解的部分&#xff0c;这一篇博客我们来讲解最后两个部分 在讲这篇博客之前&am…

Shell免交互操作

目录 一、Here Document 免交互 1.免交互定义 2.格式和使用方法 二、Expect 免交互 1.简介 2.格式和使用 &#xff08;1&#xff09;声明解释器 &#xff08;2&#xff09;spawn&#xff08;跟踪&#xff09; &#xff08;3&#xff09;expect&#xff08;期望&#x…

SpringBoot整合minio服务(超详细)

一、使用docker部署minio 1、拉取镜像 docker pull minio/minio 2、创建目录 mkdir -p /home/minio/config mkdir -p /home/minio/data 3、创建Minio容器并运行 docker run -p 9000:9000 -p 9090:9090 \--nethost \--name minio \-d --restartalways \-e "MINIO_ACC…

基于OpenCV的自动报靶识别实验

基于OpenCV的自动报靶识别实验 问题方案实验结论 问题 户外胸环靶自动报靶问题&#xff0c;目前是通过声电等方式来识别&#xff0c;成本较高&#xff0c;本文尝试使用图像处理的方法来识别。 方案 前提&#xff1a;固定相机 确定靶子的四个顶点&#xff1a;目前使用人工手…

使用imp和exp命令对orcale进行导入和导出

docker 进行orcale 查看这篇文章 https://editor.csdn.net/md/?articleId131026846 1、进入orcale 1、进入orcale容器 docker exec -it oracle11g bash2、orcale连接sysdba用户 进入root su root密码&#xff1a;helowin切换到oracle用户 su oracle使用sqlplus登录test用户…

chatgpt赋能python:Python中如何删除字符串中某个字符

Python中如何删除字符串中某个字符 Python是一种功能强大的编程语言&#xff0c;许多开发人员喜欢使用它来编写应用程序。字符串是Python中的常见数据类型之一&#xff0c;可用于存储文本。有时&#xff0c;我们可能需要删除字符串中的某个字符。本文将介绍如何在Python中使用…

GDB的学习

目录&#xff1a; 什么是gdb&#xff1f;gdb的安装gdb的使用 gdb的一些骚操作watch命令的使用调试core文件 什么是gdb&#xff1f; gdb的全称是GNU debugger&#xff0c;看名字就知道 gdb 是用来对程序进行 debug 的&#xff0c;不管是学习还是工作中&#xff0c;用好gdb&…

redis五种数据类型具体时候的底层编码

redis随着值的类型不同&#xff0c;其在底层编码类型会不相同。目前现有的编码格式有 #define OBJ_ENCODING_RAW 0 /* Raw representation */ #define OBJ_ENCODING_INT 1 /* Encoded as integer */ #define OBJ_ENCODING_HT 2 /* Encoded as hash table */ #def…