3D图像渲染和threejs交互坐标系入门知识整理

1. Games101

b站上面就有,看到第9节课基本对于图形渲染的原理和渲染过程有所了解。然后就可以使用openGL和GLSL。

点输入->投影到二维(生成三角形面)->光栅化为像素->z-buffer深度缓存判断层级->着色shading

2. openGL和GLSL

参考网站:https://www.shadertoy.com/
教程:https://learnopengl-cn.github.io/01%20Getting%20started/01%20OpenGL/
其他:
http://webgl3d.cn/pages/f66004/

3. 一些矩阵概念记录

点乘和叉乘

来自AI:

在图形学中,点乘(点积)和叉乘(叉积)是向量运算的基础,它们的方向判断和物理意义如下:

一、点乘(Dot Product)

1. 方向判断
  • 公式:a⋅b=∣a∣∣b∣cosθ 其中θ是两向量的夹角。
  • 符号含义
    • :θ < 90deg)(两向量方向大致相同)。
    • :θ = 90deg)(两向量垂直)。
    • :θ > 90deg)(两向量方向大致相反)。
2. 物理意义
  • 投影关系: 点乘结果等于向量a在b方向上的投影长度乘以b的模长。
  • 能量传递: 例如,光照计算中,光源方向与表面法线的点乘决定了光照强度(夹角越小,光照越强)。
  • 相似性度量: 用于判断两个向量的方向一致性(如判断物体是否面向光源)。

二、叉乘(Cross Product)

1. 方向判断
  • 公式: a×b=∣a∣∣b∣sinθ⋅n 其中θ是两向量的夹角,n是垂直于a和b所在平面的单位向量。
  • 方向规则(右手定则): 右手四指从a向b弯曲(夹角 < 180°),拇指指向即为叉乘结果的方向。
2. 物理意义
  • 法向量生成: 叉乘结果垂直于两向量所在平面,常用于计算平面法线(如3D建模中的多边形法线)。
  • 面积计算: 叉乘的模长等于两向量张成的平行四边形的面积。

三、图形学中的典型应用

1. 点乘的应用
  • 光照模型: 计算表面法线与光源方向的夹角,确定漫反射强度(如 Lambert 光照模型)。
  • 背面剔除: 判断多边形法线是否背离相机方向(点乘结果为负时剔除背面)。
  • 向量归一化: 点乘可快速计算向量长度的平方a⋅a=∣a∣^2。
2. 叉乘的应用
  • 法线计算: 由多边形的两个边向量叉乘得到面法线(如三角形面片的法向量)。
  • 坐标系构建: 在3D空间中,通过叉乘构建正交基向量(如切线、副切线和法线的 TBN 坐标系)。
  • 碰撞检测: 利用叉乘判断点是否在凸多边形内部(通过环绕测试)。

四、对比总结

运算结果类型方向规则物理意义
点乘标量无方向,符号表示夹角投影、能量传递、相似性
叉乘向量右手定则确定垂直方向法向量、旋转趋势、面积

五、示例说明

  • 点乘示例: 若表面法线 n 与光源方向 L 的点乘为正,则该区域被照亮;若为负,则处于阴影中。

  • 叉乘示例: 在3D建模中,三角形顶点 (A, B, C) 的边向量AB和AC的叉乘可得到该三角形的法向量,用于渲染时的光照计算。

通过点乘和叉乘的结合,图形学能够高效处理向量方向、空间关系和物理模拟等问题,是3D渲染和计算机图形学的核心工具。

4. 三维空间中的点击交互,坐标和点变换

有没有想过一个问题:你在屏幕上点了一个点,怎么映射到三维空间中的一个坐标?或者反过来,现在我们把物体放置在三维空间的一个位置,怎么知道用户在屏幕上的点击是不是点在这个物体上。
这就涉及三维空间中的坐标。可以看这个https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/

OpenGL希望在每次顶点着色器运行后,我们可见的所有顶点都为标准化设备坐标(Normalized Device Coordinate, NDC)。也就是说,每个顶点的x,y,z坐标都应该在-1.0到1.0之间,超出这个坐标范围的顶点都将不可见。我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将这些坐标变换为标准化设备坐标。然后将这些标准化设备坐标传入光栅器(Rasterizer),将它们变换为屏幕上的二维坐标或像素。

将坐标变换为标准化设备坐标,接着再转化为屏幕坐标的过程通常是分步进行的,也就是类似于流水线那样子。在流水线中,物体的顶点在最终转化为屏幕坐标之前还会被变换到多个坐标系统(CoordinateSystem)。
将物体的坐标变换到几个过渡坐标系(Intermediate CoordinateSystem)的优点在于,在这些特定的坐标系统中,一些操作或运算更加方便和容易,这一点很快就会变得很明显。对我们来说比较重要的总共有5个不同的坐标系统:

  • 局部空间(Local Space,或者称为物体空间(Object Space))
  • 世界空间(World Space)
  • 观察空间(View Space,或者称为视觉空间(Eye Space))
  • 裁剪空间(Clip Space)
  • 屏幕空间(Screen Space)
    在这里插入图片描述

Cube空间中的点和屏幕坐标的转换

因为我们在做全景交互展示,所以是一个Cube空间,然后有两个需求:

  1. 热点展示,AI带看。
  2. 屏幕点击,找到某个物品。

1. 热点展示,AI带看

一般有两种热点锚定方案:

  1. 直接使用三维空间中的热点坐标,判断如果当前用户屏幕上能看到热点了,给一些标注提示。
// 定义视口接口
interface Viewport {width: number;height: number;x: number;y: number;
}/*** 将方向向量投影到屏幕坐标* * 这个函数将三维空间中的方向向量转换为屏幕上的2D坐标,如果不在视图内返回undefined.* 使用相机的视图投影矩阵进行变换,并处理透视除法* * @param camera 透视相机对象* @param direction 归一化的方向向量* @param viewport 视口信息(可选,默认使用窗口尺寸)* @returns 屏幕坐标对象 {x, y} 或 undefined(如果在视锥外)*/
export function projectDirectionToScreen(camera: PerspectiveCamera,direction: Vector3,viewport?: Viewport
): { x: number; y: number } | undefined {// 设置默认视口if (!viewport) {viewport = {width: window.innerWidth,height: window.innerHeight,x: 0,y: 0};}// 创建齐次坐标点 (w=1)const worldPoint = new Vector4(direction.x, direction.y, direction.z, 1);// 计算视图投影矩阵 (投影矩阵 * 世界矩阵的逆)const viewProjectionMatrix = new Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);// 应用视图投影矩阵const clipSpaceCoords = worldPoint.clone().applyMatrix4(viewProjectionMatrix);// 透视除法 (将齐次坐标转换为三维坐标)const w = clipSpaceCoords.w;// 如果点在相机后方,返回undefinedif (w <= 0) return undefined;// 归一化设备坐标 (NDC) [-1, 1]const ndc = new Vector3(clipSpaceCoords.x / w,clipSpaceCoords.y / w,clipSpaceCoords.z / w);// 视锥体剔除 - 检查点是否在视锥体内if (Math.abs(ndc.x) > 1 || Math.abs(ndc.y) > 1 || ndc.z < -1 || ndc.z > 1) {return undefined;}// 转换为屏幕坐标return {x: (ndc.x + 1) * 0.5 * viewport.width + viewport.x,y: (1 - ndc.y) * 0.5 * viewport.height + viewport.y};
}// 热点管理插件
class AIHotspot {private camera: PerspectiveCamera;private renderer: THREE.WebGLRenderer;private hotspots: { position: Vector3; element: HTMLElement }[] = [];constructor(camera: PerspectiveCamera, renderer: THREE.WebGLRenderer) {this.camera = camera;this.renderer = renderer;}/*** 添加热点* @param position 热点在3D空间中的位置* @param content 热点显示的HTML内容*/addHotspot(position: Vector3, content: string) {const element = document.createElement('div');element.className = 'hotspot';element.innerHTML = content;document.body.appendChild(element);this.hotspots.push({ position, element });}/*** 更新热点位置*/update() {const viewport = this.renderer.getSize(new Vector2());for (const hotspot of this.hotspots) {// 计算热点在屏幕上的位置const screenPos = projectDirectionToScreen(this.camera,hotspot.position.clone().normalize(),{width: viewport.x,height: viewport.y,x: 0,y: 0});if (screenPos) {hotspot.element.style.display = 'block';hotspot.element.style.left = `${screenPos.x}px`;hotspot.element.style.top = `${screenPos.y}px`;} else {hotspot.element.style.display = 'none';}}}
}/** 使用:在animation中持续调用update判断就行 */
// 创建AI带看热点系统
const hotspotSystem = new AIHotspot(camera, renderer);// 添加热点
hotspotSystem.addHotspot(new Vector3(1, 0, 0), '<div class="hotspot">这里是热点!</div>'
);
  1. 由后端计算生成,给你一个UV位置。(这时候就需要UV坐标转方向向量,然后再转成屏幕位置)其实就是再加一步将UV坐标转成上面那一步的向量位置。
projectDirectionToScreen(cubeUVToDirection(CubeUVPos))

在这里插入图片描述

// 定义立方体UV坐标接口
interface CubeUV {faceIndex: number; // 立方体面索引 (0-5)u: number;         // 水平UV坐标 [0, 1]v: number;         // 垂直UV坐标 [0, 1]
}/*** 将立方体UV坐标转换为三维空间方向向量* * 这个函数将立方体纹理坐标(面索引和UV)转换为三维空间中的方向向量(单位向量)* 立方体面索引定义:* 0: 右 (+X)* 1: 左 (-X)* 2: 上 (+Y)* 3: 下 (-Y)* 4: 前 (+Z)* 5: 后 (-Z)* * @param cubeUV 立方体UV坐标对象* @returns 归一化的三维方向向量*/
export function cubeUVToDirection(cubeUV: CubeUV): Vector3 {const { faceIndex, u, v } = cubeUV;// 将UV从[0,1]映射到[-1,1]const uc = u * 2 - 1;const vc = v * 2 - 1;let x, y, z;// 根据面索引计算方向switch (faceIndex) {case 0: // 右 (+X)x = 1;y = -vc; z = -uc;break;case 1: // 左 (-X)x = -1;y = -vc;z = uc;break;case 2: // 上 (+Y)x = uc;y = 1;z = vc;break;case 3: // 下 (-Y)x = uc;y = -1;z = -vc;break;case 4: // 前 (+Z)x = uc;y = -vc;z = 1;break;case 5: // 后 (-Z)x = -uc;y = -vc;z = -1;break;default:break; // 无效的面索引}// 创建向量并归一化const direction = new Vector3(x, y, z);return direction.normalize();/** * direction.normalize将这个向量“归一化”,也就是把长度(模)变成 1,只保留方向信息。* 归一化后的向量叫做单位向量,常用于表示方向,而不关心距离大小。* * 场景意义* 在三维图形/全景/射线等场景中,归一化方向向量可以方便地进行投影、旋转、相交等运算。* 例如:你要从立方体的某个面上的 UV 坐标,推算出“朝向哪里”,就需要一个单位方向向量。*/
}

2. 屏幕点击,找到某个物品。

刚才是将三维空间坐标转换为屏幕坐标,看屏幕里能不能看到。这个就是逆向,也是我们用最多的:用户点击屏幕确定点击的物品。将屏幕上的点击位置映射到立方体贴图(CubeUV)坐标。

现在我们场景里有很多mesh,然后要确认点击的是哪个mesh,以及点击的UV坐标(UV坐标还有一个用法是可以交由上个方法那里添加热点)
1. 屏幕坐标 → NDC 坐标:将像素坐标转换为标准化设备坐标(范围 [-1,1])
2. 创建射线:从相机位置出发,沿点击方向发射一条射线
3. 检测交点:计算射线与 Mesh 的交点
4. 确定面索引:根据交点所在面确定 faceIndex
5. 计算 UV 坐标:将交点位置转换为面内的 UV 坐标(范围 [0,1])
/*** 屏幕点击检测场景中的Mesh,并返回点击位置的CubeUV坐标(适用于立方体表面)* @param {THREE.PerspectiveCamera} camera - 当前相机* @param {number} screenX - 屏幕X坐标(像素)* @param {number} screenY - 屏幕Y坐标(像素)* @param {THREE.Object3D[]} meshes - 需要检测的Mesh数组(如场景中的所有可交互物体)* @param {Object} [viewport] - 视口信息 {x, y, width, height}* @returns { { object: THREE.Mesh; cubeUV: CubeUV } | null } - 包含Mesh和CubeUV的对象,或null*/
function screenToMeshCubeUV(camera: THREE.PerspectiveCamera,screenX: number,screenY: number,meshes: THREE.Object3D[],viewport?: Viewport
): { object: THREE.Mesh; cubeUV: CubeUV } | null {// 设置默认视口if (!viewport) {viewport = {width: window.innerWidth,height: window.innerHeight,x: 0,y: 0};}// 1. 屏幕坐标 → NDC坐标(屏幕坐标Y轴向下为正,和canvas相反,所以转换成NDC坐标要反过来)const ndcX = (screenX - viewport.x) / viewport.width * 2 - 1;const ndcY = -(screenY - viewport.y) / viewport.height * 2 + 1; // 翻转Y轴// 2. 创建射线投射器const raycaster = new THREE.Raycaster();raycaster.setFromCamera(new THREE.Vector2(ndcX, ndcY), camera);// 从相机位置出发,沿 NDC 坐标对应的方向发射射线// 3. 检测与所有Mesh的交点(按距离排序,取最近的)const intersects = raycaster.intersectObjects(meshes, true); // true表示检测子对象if (intersects.length === 0) return null;// 获取最近的交点const closestIntersect = intersects[0];const clickedMesh = closestIntersect.object as THREE.Mesh;const point = closestIntersect.point;// 4. 仅处理立方体类型的Mesh(需提前确保Mesh是立方体或平面)if (!(clickedMesh.geometry instanceof THREE.BoxGeometry)) {console.warn('仅支持立方体类型的Mesh');return null;}// 5. 计算CubeUV坐标(假设Mesh是单位立方体,中心在原点)const faceIndex = closestIntersect.face?.index || 0; // face.index是0-5的面索引let u = 0, v = 0;// 立方体每个面的顶点索引规则(Three.js BoxGeometry默认面顺序)// 参考:https://threejs.org/docs/#api/en/geometries/BoxGeometry// 面顺序:右(0)、左(1)、上(2)、下(3)、前(4)、后(5)// 每个面由两个三角形组成,顶点坐标范围[-0.5, 0.5](假设BoxGeometry未缩放)switch (faceIndex) {case 0: // 右面 (+X)u = 1 - (point.z + 0.5); // z ∈ [-0.5, 0.5] → u ∈ [0, 1]v = 1 - (point.y + 0.5); // y ∈ [-0.5, 0.5] → v ∈ [0, 1]break;case 1: // 左面 (-X)u = (point.z + 0.5);v = 1 - (point.y + 0.5);break;case 2: // 上面 (+Y)u = (point.x + 0.5);v = (point.z + 0.5);break;case 3: // 下面 (-Y)u = (point.x + 0.5);v = 1 - (point.z + 0.5);break;case 4: // 前面 (+Z)u = (point.x + 0.5);v = 1 - (point.y + 0.5);break;case 5: // 后面 (-Z)u = 1 - (point.x + 0.5);v = 1 - (point.y + 0.5);break;default:return null;}// 确保UV在[0,1]范围内(处理浮点精度误差)u = Math.max(0, Math.min(1, u));v = Math.max(0, Math.min(1, v));return {object: clickedMesh,cubeUV: { faceIndex, u, v }};
}

5. 纹理贴图

看这个:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/
但是纹理不能只有纹理贴图,如果想要更加真实,还要设置其他的贴图:

常见的贴图类型包括:

  1. 漫反射贴图 (Diffuse Map) - 物体表面的基础颜色和纹理
  2. 粗糙度贴图 (Roughness Map) - 控制表面微表面的粗糙程度,影响高光反射的锐利程度。用roughnessMap属性设置。
  3. 金属度贴图 (Metallic Map) - 控制表面是金属还是非金属。
  4. 法线贴图 (Normal Map) - 通过改变表面法线来模拟表面细节,不改变几何形状。用 normalMap 属性设置。
  5. 凹凸贴图(Bump Map) - 模拟表面高低起伏,但效果和法线贴图略有不同,通常用灰度图。用 bumpMap 属性设置。
  6. 环境贴图 (Environment Map) - 用于反射和折射的环境图像。用 envMap 属性设置。

在Three.js中,我们可以通过MeshStandardMaterialMeshPhysicalMaterial来使用这些贴图。

大概像这样:

import * as THREE from 'three';// 贴图加载器
const loader = new THREE.TextureLoader();const colorMap = loader.load('texture/color.jpg');         // 基础色
const roughnessMap = loader.load('texture/roughness.jpg'); // 粗糙度
const normalMap = loader.load('texture/normal.jpg');       // 法线
const bumpMap = loader.load('texture/bump.jpg');           // 凹凸
const envMap = new THREE.CubeTextureLoader().load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'
]); // 环境贴图通常是立方体贴图const material = new THREE.MeshStandardMaterial({map: colorMap,roughnessMap: roughnessMap,normalMap: normalMap,bumpMap: bumpMap,envMap: envMap,metalness: 0.5, // 金属度,配合 envMap 更真实roughness: 0.5, // 粗糙度,配合 roughnessMap
});const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1),material
);
scene.add(mesh);

一些贴图网站和纹理说明:
https://juejin.cn/post/7129065605461884964
https://ambientcg.com/

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

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

相关文章

跨平台架构区别

文章目录 重编译时轻运行时&#xff08;uniapp&#xff09;轻编译时重运行时&#xff08;Taro&#xff09; 重编译时轻运行时&#xff08;uniapp&#xff09; 对 vue 语法直接进行编译转换成对应平台代码&#xff0c;再通过添加运行时代码去补充能力&#xff0c;比如 nextTick…

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…

HarmonyOS 应用开发学习记录 - 从Windows开发者视角看鸿蒙开发

起始 2024年6月21日召开的华为开发者大会2024上宣布Harmony OS NEXT&#xff08;即鸿蒙星河版&#xff09;面向开发者启动Beta版&#xff0c;这也被人们称为“纯血鸿蒙”&#xff0c;它基于鸿蒙内核&#xff0c;不再兼容安卓开发的APP应用。 时至今日近一年了&#xff0c;我也有…

MySQL 事务管理与锁优化:确保数据一致性和并发性

在多用户并发访问的数据库系统中,如何确保数据的**一致性(Consistency)和并发性(Concurrency)**是一个核心挑战。**事务(Transaction)和锁(Lock)**是 MySQL 应对这一挑战的两大利器。事务保证了操作的原子性、一致性、隔离性和持久性,而锁机制则在并发环境下协调不同…

OpenPrompt 有没有实现连续提示词和提手动示词一起优化的

OpenPrompt 有没有实现连续提示词和提手动示词一起优化的 OpenPrompt 中连续提示词与手动提示词的混合优化 OpenPrompt 确实支持同时优化连续提示词(Soft Prompt)和手动设计的离散提示词(Manual Prompt)。这种混合优化策略可以结合两者的优势: 连续提示词:通过梯度下降…

Android添加语言列表

方式一 frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java Settings.System.putString(context.getContentResolver(),Settings.System.SYSTEM_LOCALES, "ru-RU,en-US"); 方式2 packages/apps/Settings/src/co…

解决uniapp开发app map组件最高层级 遮挡自定义解决底部tabbar方法

subNvue&#xff0c;是 vue 页面的原生子窗体&#xff0c;把weex渲染的原生界面当做 vue 页面的子窗体覆盖在页面上。它不是全屏页面&#xff0c;它给App平台vue页面中的层级覆盖和原生界面自定义提供了更强大和灵活的解决方案。它也不是组件&#xff0c;就是一个原生子窗体。 …

如何保障服务器的安全

如何保障服务器的安全 以下是保障服务器安全的核心措施及实施建议&#xff1a; 一、基础设施层防护 物理安全 机房设置防火/防水/防雷系统&#xff0c;部署门禁监控设备。 服务器固定于抗震机架&#xff0c;避免物理损坏。 网络防护 防火墙规则&#xff1a;仅开放业务必要端…

C语言 学习 C程序的内存模型 2025年6月10日08:55:13

堆栈与内存管理 堆栈(Stack) : 后进先出(LIFO) 线性数据结构 包含压栈(Push) ,弹栈(Pop) 用途:临时存储数据(函数调用,局部变量) 管理:由系统自动分配和回收 速度快 ,容量有限! 堆栈代码示例: //堆栈示例 :局部变量 void getText() {int text20;//储存在堆栈中 } 内存管理…

CppCon 2015 学习:Implementing class properties effectively

这段内容讲的是C中“属性”&#xff08;Property&#xff09;的实现及其设计理念&#xff0c;并结合一个实际类Text来说明。中文理解如下&#xff1a; 关于“属性”&#xff08;Property&#xff09; 属性&#xff1a;介于类的字段&#xff08;field&#xff09;和方法&#…

[electron]预脚本不显示内联script

script-src self 是 Content Security Policy (CSP) 中的一个指令&#xff0c;它的作用是限制加载和执行 JavaScript 脚本的来源。 具体来说&#xff1a; self 表示 当前源。也就是说&#xff0c;只有来自当前网站或者当前页面所在域名的 JavaScript 脚本才被允许执行。"…

基于安卓的文件管理器程序开发研究源码数据库文档

摘 要 伴随着现代科技的发展潮流&#xff0c;移动互联网技术快速发展&#xff0c;各种基于通信技术的移动终端设备做的也越来越好了&#xff0c;现代智能手机大量的进入到了我们的生活中。电子产品的各种软硬技术技术的发展&#xff0c;操作系统的不断更新换代&#xff0c;谷歌…

MySQL主从复制实现指南

MySQL主从复制实现指南 一、主从复制原理 #mermaid-svg-i1zOswdD4OORQ35t {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-i1zOswdD4OORQ35t .error-icon{fill:#552222;}#mermaid-svg-i1zOswdD4OORQ35t .error-text…

spring jms使用

文章目录 一、背景介绍二、注意点说明三、代码pom.xmlmq.propertiesActiveMqConfigJmsSenderActiveMqInfoActivemqProtocolEnum生产者消费者 一、背景介绍 <dependency> 标签中列出的 spring-jms 是 Spring Framework 提供的一个模块&#xff0c;用于简化 Java Message …

笔记——学习HTTP协议

HTTP协议 文章目录 HTTP协议一、统一资源定位符&#xff08;url&#xff09;&#xff1a;URL编码格式&#xff1a; 二、HTTP报文结构&#xff1a;三、HTTP请求方法&#xff1a;四、HTTP常见请求头&#xff1a;五、HTTP状态码&#xff1a;六、HTTP常见响应头&#xff1a;七、HTT…

Unity中的Mathf.Clamp01

2025年6月8日&#xff0c;周日晚上 Mathf.Clamp01 是 Unity 中的一个数学函数&#xff0c;它的作用是将一个浮点数&#xff08;float&#xff09;限制在0 到 1的范围内。具体来说&#xff1a; 如果输入值 小于 0&#xff0c;则返回 0。 如果输入值 大于 1&#xff0c;则返回 1…

1 Studying《Linux Media Documentation》

目录 1 MEDIA SUBSYSTEM ADMIN AND USER GUIDE 1.1.2 Building support for a media device 1.1.3 Infrared remote control support in video4linux drivers 1.1.4 Digital TV 1.1.5 Cards List 1.1.5.2 PCI drivers 1.1.6 Video4Linux (V4L) driver-specifific docume…

编译原理 学习 2025年6月10日11:17:54

编译原理 将高级编程语言编写的源代码转换成机器可执行的代码(二进制或汇编代码) 核心任务: 词法分析(正则表达式和有限自动机): 示例Token分类&#xff1a;关键字&#xff1a;if, while 运算符&#xff1a;, 标识符&#xff1a;变量名 分解源代码为单词 识别 其中关键字 …

风中低语:Linux 信号处理的艺术与实践

文章目录 &#x1f307;前言&#x1f3d9;️正文1、信号的处理时机1.1、处理情况1.2、“合适” 的时机 2、用户态与内核态2.1、概念2.2、重谈进程地址空间2.3、信号的处理过程 3、信号的捕捉3.1、内核如何实现信号的捕捉&#xff1f;3.2、sigaction 4、信号部分小结 补充 5、可…