WebGL图形编程实战【4】:光影交织 × 逐片元光照与渲染技巧

现实世界中的物体被光线照射时,会反射一部分光。只有当反射光线进人你的眼睛时,你才能够看到物体并辩认出它的颜色。

光源类型

  • 平行光(Directional Light):光线是相互平行的,平行光具有方向。平行光可以看作是无限远处的光源(比如太阳)发出的光。因为太阳距离地球很远,所以阳光到达地球时可以认为是平行的。平行光很简单,可以用一个方向一个颜色来定义
  • 点光源(Point Light):是从一个点向周围的所有方向发出的光。点光源光可以用来表示现实中的灯泡、火焰等。我们需要指定点光源的位置和颜色。光线的方向将根据点光源的位置和被照射之处的位置计算出来,因为点光源的光线的方向在场景内的不同位置是不同的。
  • 环境光(Ambient Light):环境光(间接光)是指那些经光源(点光源或平行光源)发出后,被墙壁等物体多次反射,然后照到物体表面上的光。环境光从各个角度照射物体,其强度都是致的。比如说,在夜间打开冰箱的门,整个厨房都会有些微微亮,这就是环境光的作用。环境光不用指定位置和方向,只需要指定颜色即可。

在这里插入图片描述

反射类型

  • 漫反射(Diffuse Reflection):是针对平行光或点光源而言的。漫反射的反射光在各个方向上是均匀的,如果物体表面像镜子一样光滑,那么光线就会以特定的角度反射出去;但是现实中的大部分材质,比如纸张、岩石、塑料等,其表面都是粗糙的,在这种情况下反射光就会以不固定的角度反射出去。
  • 环境反射(Ambient Reflection):环境反射是针对环境光而言的。在环境反射中,反射光的方向可以认为就是人射光的反方向。由于环境光照射物体的方式就是各方向均匀、强度相等的,所以反射光也是各向均匀的。

漫反射颜色公式

漫反射颜色 = 入射光颜色 * 表面基底色 * cos A

式子中,入射光颜色指的是点光源或平行光的颜色,乘法操作是在颜色矢量上逐分量(R、G、B)进行的。因为漫反射光在各个方向上都是“均匀”的,所以从任何角度看上去其强度都相等。

在这里插入图片描述

环境反射颜色公式

环境反射颜色 = 环境光颜色 * 表面基底色

当漫反射和环境反射同时存在时,将两者加起来,就会得到物体最终被观察到的颜色

在这里插入图片描述

计算入射角

根据入射光的方向和物体表面的朝向(即法线方向)来计算出入射角。在创建三维模型的时候,无法预先确定光线将以怎样的角度照射到每个表面上
但是可以确定每个表面的朝向。在指定光源的时候,再确定光的方向,就可以用这两项信息来计算出入射角了。

在线性代数当中,对矢量n和1作点积运算,公式为:n·1 = |n||1|cosA,其中||符号表示向量的模(长度)。如果两个矢量长度都是1,则点积运算结果为
cosA。

那么就可以对前面漫反射颜色公式进行调整:

漫反射颜色 = 入射光颜色 * 表面基底色 * (光线方向 * 法线方向)

  • 光线方向矢量和表面法线矢量的长度必须为1(单位向量)
  • 光线方向,实际上是入射方向的反方向,即从入射点指向光源方向

法线:表面朝向

物体表面的朝向,即垂直于表面的方向,又称法线或法向量。法向量有三个分量,向量(Nx,Ny,Nz)表示从(0,0,0)到(Nx,Ny,Nz)的方向。

  • 矢量n为(Nx,Ny,Nz)则其长度为|n| = sqrt(Nx^2 + Ny^2 + Nz^2)
  • 对矢量进行归一化后的结果是(Nx/m,Ny/m,Nz/m),其中m是n的的模。如矢量(2.0,2.0,1.0)的长度|n|=sqrt(2.02+2.02+1.0^2)=sqrt(9)
    =3.0,那么归一化后的结果是(2.0/3.0,2.0/3.0,1.0/3.0)

平行光

角度的余弦值

首先来补充一下数学知识,看一下各个角度的余弦值:(这里一起把正弦和正切都加上了)

角度 (°)余弦值 (Cos)正弦值 (Sin)正切值 (Tan)
0100
30√3/21/2√3/3
45√2/2√2/21
601/2√3/2√3
9001无定义 (∞)
120-1/2√3/2-√3
135-√2/2√2/2-1
150-√3/21/2-√3/3
180-100
210-√3/2-1/2√3/3
225-√2/2-√2/21
240-1/2-√3/2√3
2700-1无定义 (-∞)
3001/2-√3/2-√3
315√2/2-√2/2-1
330√3/2-1/2-√3/3
360100

那么再根据前面的入射角的公式,那么我们简单计算一下几个案例,在反射之后的颜色值

漫反射颜色 = 入射光颜色 * 表面基底色 * (光线方向 * 法线方向) = 入射光颜色 * 表面基底色 * cos A

入射光颜色表面基底色角度角度余弦值计算RGB漫反射颜色
(1.0,1.0,1.0) 白色(1.0,0,0)红色01.0R=(1 * 1 * 1)
G=(1 * 0 * 1)
B=(1 * 0 * 1)
(1,0,0)
(1.0,1.0,1.0) 白色(1.0,0,0)红色900R=(1 * 1 * 0)
G=(1 * 0 * 0)
B=(1 * 0 * 0)
(0,0,0)

平行光案例

补充:前面都是采用drawArray方法绘制的正方体,这样的话数组对象太多内容了,看的头都晕了,还可以采用drawElements对前面的代码进行重构优化一下。

数据对象可以进行一个拆分。boxArray数组表示的是每一个面的四个顶点的坐标位置,以第一行为例,就是从v0-v1-v2-v3的位置。那么对应的index就表示顶点位置的索引(因为一个正方形要拆分成两个三角形,这也是这里的index一行为什么是6个数据的原因)。

    //    v6----- v5//   /|      /|//  v1------v0|//  | |     | |//  | |v7---|-|v4//  |/      |///  v2------v3let boxArray = [1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, // v0-v1-v2-v31.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, // v0-v3-v4-v51.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, // v0-v5-v6-v1-1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, // v1-v6-v7-v2-1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, // v7-v4-v3-v21.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0 // v4-v7-v6-v5
];let index = [0, 1, 2, 0, 2, 3,    // front4, 5, 6, 4, 6, 7,    // right8, 9, 10, 8, 10, 11,    // up12, 13, 14, 12, 14, 15,    // left16, 17, 18, 16, 18, 19,    // down20, 21, 22, 20, 22, 23     // back
];

后面进行数据组合的方法和之前是一样的。注意一下绑定的着色器的变量即可,以及最后drawElements方法,

let pointPosition = new Float32Array(boxArray);
let aPsotion = webGL.getAttribLocation(program, 'a_position');
let triangleBuffer = webGL.createBuffer();
webGL.bindBuffer(webGL.ARRAY_BUFFER, triangleBuffer);
webGL.bufferData(webGL.ARRAY_BUFFER, pointPosition, webGL.STATIC_DRAW);
webGL.enableVertexAttribArray(aPsotion);
webGL.vertexAttribPointer(aPsotion, 4, webGL.FLOAT, false, 4 * 4, 0);let indexBuffer = webGL.createBuffer();
let indices = new Uint8Array(index);
webGL.bindBuffer(webGL.ELEMENT_ARRAY_BUFFER, indexBuffer);
webGL.bufferData(webGL.ELEMENT_ARRAY_BUFFER, indices, webGL.STATIC_DRAW);webGL.drawElements(webGL.TRIANGLES, 36, webGL.UNSIGNED_BYTE, 0);

平行光案例实现:调整着色器代码,看一下整个着色器代码调整的完整流程。

graph TBsubgraph 顶点着色器 by modifyA(顶点坐标 a_position)B(透视投影 u_formMatrix)C(法向量 a_Normal)D(光照方向 u_LightDirection)E(漫射光 u_DiffuseLight)F(环境光 u_AmbientLight)G(颜色 v_Color)endsubgraph 片元着色器Z(v_Color)endC --> C1(归一化法向量 normalize)D --> D1(归一化光线方向 normalize)C1 -- dot计算点积、max取最大值 --> H(法向量与光线方向的点积)D1 --> HE --> I(计算漫反射颜色)H --> IF --> F1(计算环境光颜色)F1 -- 相加 --> J(颜色合并)I -- 相加 --> JG -- 利用varying变量传值 --> 片元着色器J --> 片元着色器

通过这个流程图也就结合了前面计算漫反射公式得到了漫反射的颜色,所以最后在片元着色器中利用varying变量传值,进行颜色合并。那么也就渲染到了物体上。

let vertexString = `attribute vec4 a_position;uniform mat4 u_formMatrix;attribute vec4 a_Normal;uniform vec3 u_LightDirection;uniform vec3 u_DiffuseLight;uniform vec3 u_AmbientLight;varying vec4 v_Color;void main(void){gl_Position = u_formMatrix * a_position;vec3 normal = normalize(a_Normal.xyz);vec3 LightDirection = normalize(u_LightDirection.xyz);float nDotL = max(dot(LightDirection, normal), 0.0);vec3 diffuse = u_DiffuseLight * vec3(1.0,0,1.0)* nDotL;vec3 ambient = u_AmbientLight * vec3(1.0,0,1.0);v_Color = vec4(diffuse + ambient, 1);}`;
let fragmentString = `precision mediump float;varying vec4 v_Color;void main(void){gl_FragColor =v_Color;}`;

第二步就是设置法向量和光线方向,以及漫反射和环境光。而后结合前面的通过drawElements进行绘制。那也就完成了平行光案例。

let normals = new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,  // v0-v1-v2-v3 front1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,  // v0-v3-v4-v5 right0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,  // v0-v5-v6-v1 up-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,  // v1-v6-v7-v2 left0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0,  // v7-v4-v3-v2 down0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0   // v4-v7-v6-v5 back
]);
let aNormal = webGL.getAttribLocation(program, 'a_Normal');
let normalsBuffer = webGL.createBuffer();
let normalsArr = new Float32Array(normals);
webGL.bindBuffer(webGL.ARRAY_BUFFER, normalsBuffer);
webGL.bufferData(webGL.ARRAY_BUFFER, normalsArr, webGL.STATIC_DRAW);
webGL.enableVertexAttribArray(aNormal);
webGL.vertexAttribPointer(aNormal, 3, webGL.FLOAT, false, 3 * 4, 0);let u_DiffuseLight = webGL.getUniformLocation(program, 'u_DiffuseLight');
webGL.uniform3f(u_DiffuseLight, 1.0, 1.0, 1.0);
let u_LightDirection = webGL.getUniformLocation(program, 'u_LightDirection');
webGL.uniform3fv(u_LightDirection, [0, 0, 10.0]);
let u_AmbientLight = webGL.getUniformLocation(program, 'u_AmbientLight');
webGL.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);

在这里插入图片描述

点光源

漫反射光颜色 = 入射光颜色 * 表面基底色 * cos A

cos A = 光线方向 * 法线方向

在点光源是没有光照方向的,光照方向需要通过光源位置-顶点位置来计算。两者相减就会得到入射光方向向量。这样就需要调整一下着色器代码。

  • 新增变量:u_PointLightPosition,u_NormalMatrix(法线变换矩阵)
  • 计算normal,将法线向量从模型空间转换到视图空间或世界空间
  • 计算入射光方向向量
let vertexString = `attribute vec4 a_position;uniform mat4 u_formMatrix;attribute vec4 a_Normal;uniform vec3 u_PointLightPosition;uniform vec3 u_DiffuseLight;uniform vec3 u_AmbientLight;varying vec4 v_Color;uniform mat4 u_NormalMatrix;void main(void){gl_Position = u_formMatrix * a_position;vec3 normal = normalize(vec3(u_NormalMatrix * a_Normal));vec3 LightDirection = normalize(vec3(gl_Position.xyz) - u_PointLightPosition);float nDotL = max(dot(LightDirection, normal), 0.0);vec3 diffuse = u_DiffuseLight * vec3(1.0,0,1.0)* nDotL;vec3 ambient = u_AmbientLight * vec3(1.0,0,1.0);v_Color = vec4(diffuse + ambient, 1);}`;

接着就是在js当中设置u_PointLightPosition,u_NormalMatrix。

let u_PointLightPosition = webGL.getUniformLocation(program, 'u_PointLightPosition');
webGL.uniform3fv(u_PointLightPosition, [10, 0, 0]);let uniformNormalMatrix = webGL.getUniformLocation(program, 'u_NormalMatrix');
let normalMatrix = mat4.create();
mat4.identity(normalMatrix);
mat4.invert(normalMatrix, ModelMatrix);
mat4.transpose(normalMatrix, ModelMatrix);
webGL.uniformMatrix4fv(uniformNormalMatrix, false, normalMatrix);

在这里插入图片描述

环境光

环境光相对于平行光和点光源来说,相对简单些,不用再去计算漫反射光了,只需要计算环境光。那么其着色器代码调整如下:只需要传递一个环境光进来,然后直接和基底色相乘就是渲染后的颜色了。

let vertexString = `attribute vec4 a_position;uniform mat4 u_formMatrix;uniform vec3 u_AmbientLight;varying vec4 v_Color;void main(void){gl_Position = u_formMatrix * a_position;vec3 ambient = u_AmbientLight * vec3(1.0,1.0,1.0);v_Color = vec4(ambient, 1);}`;

传值也将其他的都进行删去,设置u_AmbientLight即可。那么这里的值就是(0.8,0.1,0)颜色值就是 (2550.8, 2550, 255*0.1) = (
204,0,51) 橙红色。

let u_AmbientLight = webGL.getUniformLocation(program, 'u_AmbientLight');
webGL.uniform3f(u_AmbientLight, 0.8, 0.1, 0);

在这里插入图片描述

逐片元光照

再来先回顾一下webGL整个渲染的流程

js
缓冲区对象
顶点着色器
顶点坐标
图形装配
光栅化
片元着色器
浏览器

逐顶点着色

在逐顶点渲染中,前面讲的光照或颜色的计算是在顶点着色器中进行的,顶点着色器运行结束后,每一个顶点都有一个颜色值,在片元着色器执行前,webGL会对这些顶点的颜色数据进行线性插值,从而得到每个片元处的颜色。这就是webGL绘制三角形的原理,为什么只给了3个顶点的颜色值就能得到一个彩色的三角形的缘故,即三角形中其他点(片元)的颜色值都是通过这给定的3个顶点的颜色值通过线性插值得到的。

在这里插入图片描述

逐片元着色

每个像素都被填充了光栅化处理后的颜色,并写入颜色缓冲区,直到最后一个片元被处理完成,浏览器就会显示出最终的彩色三角形

逐片元的计算光照条件:

  • 片元在世界坐标系下的坐标。
  • 片元处表面的法向量。可以在顶点着色器中,将顶点的世界坐标和法向量以varying变量的形式传人片元着色器,片元着色器中的同名变量就已经是内插后的逐片元值了。

绘制球

在前面绘制立体图形都是长方体这种可以确定具体的顶点坐标,那么绘制球体的时候我们怎么拿到对应的坐标再进行绘制呢?

球体任意一点点坐标

如下图所示,这是一个球,现在已知半径为r,求球上一点P的坐标,其中该点与中心点连线与z轴的夹角为θ,该点往平面做投影,投影到中心点连线和x轴的夹角为φ。
在这里插入图片描述

那么就可以得到p点的xyz坐标:并且现在只需要将φ转360度,θ转180度,即可得到球上任意一点的xyz坐标。

  • x=rsinθcosφ
  • y=rsinθsinφ
  • z=rcosθ
webGL渲染球体(逐顶点着色)

在webGL当中所有的图形都是通过很多个三角形进行组成的,下面开始计算球体的顶点坐标:也就是将上面的数学公式转成js代码。(在前面所有学习和实现的效果都是采用的逐顶点着色,也就是js将颜色值传递到顶点着色器当中,顶点着色器将所有的颜色都处理好了之后再通过varying传递给片元着色器)

let positions = [];
const SPHERE_DIV = 10;let i, ai, si, ci;
let j, aj, sj, cj;for (j = 0; j <= SPHERE_DIV; j++) {aj = j * Math.PI / SPHERE_DIV;sj = Math.sin(aj);cj = Math.cos(aj);for (i = 0; i <= SPHERE_DIV; i++) {ai = i * 2 * Math.PI / SPHERE_DIV;si = Math.sin(ai);ci = Math.cos(ai);positions.push(ci * sj);  // Xpositions.push(cj);       // Ypositions.push(si * sj);  // Z}
}webgl.drawArrays(webgl.TRIANGLES, 0, positions.length / 3);

使用drawArrays进行渲染,直接根据顶点缓冲区的数据顺序绘制。这里的顶点数量不够,因为只计算了一些点,并且这些点没有复用,组成的三角形不能完全覆盖球体,所以就是这种效果

在这里插入图片描述

改用drawElements进行渲染,需要再加上计算点索引的数组的代码。

let p1, p2;for (j = 0; j < SPHERE_DIV; j++) {for (i = 0; i < SPHERE_DIV; i++) {p1 = j * (SPHERE_DIV + 1) + i;p2 = p1 + (SPHERE_DIV + 1);indices.push(p1);indices.push(p2);indices.push(p1 + 1);indices.push(p1 + 1);indices.push(p2);indices.push(p2 + 1);}
}webGL.drawElements(webGL.TRIANGLES, indices.length, webGL.UNSIGNED_BYTE, 0);

在这里插入图片描述

webGL渲染球体(逐片元着色)

逐片元着色和逐顶点着色的区别就是,逐片元着色是在片元着色器中计算光照,逐顶点着色是在顶点着色器中计算光照。那么就调整一下着色器代码

let vertexString = `attribute vec4 a_position;uniform mat4 u_formMatrix;attribute vec4 a_Normal;varying vec4 v_Normal;varying vec4 v_position;void main(void){gl_Position = u_formMatrix * a_position;v_position = gl_Position;v_Normal= a_Normal;}`;
let fragmentString = `precision mediump float;varying vec4 v_Normal;varying vec4 v_position;uniform vec3 u_PointLightPosition;uniform vec3 u_DiffuseLight;uniform vec3 u_AmbientLight;void main(void){vec3 normal = normalize(v_Normal.xyz);vec3 lightDirection = normalize(u_PointLightPosition - vec3(v_position.xyz));float nDotL = max(dot(lightDirection, normal), 0.0);vec3 diffuse = u_DiffuseLight * vec3(1.0,0,1.0) * nDotL;vec3 ambient = u_AmbientLight * vec3(1.0,0,1.0);gl_FragColor = vec4(diffuse + ambient, 1);}`;

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

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

相关文章

【Hive入门】Hive基础操作与SQL语法:DDL操作全面指南

目录 1 Hive DDL操作概述 2 数据库操作全流程 2.1 创建数据库 2.2 查看数据库 2.3 使用数据库 2.4 修改数据库 2.5 删除数据库 3 表操作全流程 3.1 创建表 3.2 查看表信息 3.3 修改表 3.4 删除表 4 分区与分桶操作 4.1 分区操作流程 4.2 分桶操作 5 最佳实践与…

YOLO数据处理

YOLO&#xff08;You Only Look Once&#xff09;的数据处理流程是为了解决目标检测领域的核心挑战&#xff0c;核心目标是为模型训练和推理提供高效、规范化的数据输入。其设计方法系统性地解决了以下关键问题&#xff0c;并对应发展了成熟的技术方案&#xff1a; 一、解决的问…

Ubuntu-Linux中vi / vim编辑文件,保存并退出

1.打开文件 vi / vim 文件名&#xff08;例&#xff1a; vim word.txt &#xff09;。 若权限不够&#xff0c;则在前方添加 sudo &#xff08;例&#xff1a;sudo vim word.txt &#xff09;来增加权限&#xff1b; 2.进入文件&#xff0c;按 i 键进入编辑模式。 3.编辑结…

PCL绘制点云+法线

读取的点云ASCII码文件&#xff0c;每行6个数据&#xff0c;3维坐标3维法向 #include <iostream> #include <fstream> #include <vector> #include <string> #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pc…

如何在学习通快速输入答案(网页版),其他学习平台通用,手机上快速粘贴

目录 1、网页版&#xff08;全平台通用&#xff09; 2、手机版&#xff08;学习通&#xff0c;其他平台有可能使用&#xff09; 1、网页版&#xff08;全平台通用&#xff09; 1、首先CtrlC复制好答案 2、在学习通的作业里输入1 3、对准1&#xff0c;然后鼠标右键 &#xff…

002 六自由度舵机机械臂——姿态解算理论

00 DH模型的核心概念 【全程干货【六轴机械臂正逆解计算及仿真示例】】 如何实现机械臂的逆解计算-机器谱-robotway DH模型是机器人运动学建模的基础方法&#xff0c;通过​​四个参数​​描述相邻关节坐标系之间的变换关系。其核心思想是将复杂的空间位姿转换分解为绕轴旋转…

pymongo功能整理与基础操作类

以下是 Python 与 PyMongo 的完整功能整理&#xff0c;涵盖基础操作、高级功能、性能优化及常见应用场景&#xff1a; 1. 安装与连接 (1) 安装 PyMongo pip install pymongo(2) 连接 MongoDB from pymongo import MongoClient# 基础连接&#xff08;默认本地&#xff0c;端口…

Trae+DeepSeek学习Python开发MVC框架程序笔记(四):使用sqlite存储查询并验证用户名和密码

继续通过Trae向DeepSeek发问并修改程序&#xff0c;实现程序运行时生成数据库&#xff0c;用户在系统登录页面输入用户名和密码后&#xff0c;控制器通过模型查询用户数据库表来验证用户名和密码&#xff0c;验证通过后显示登录成功页面&#xff0c;验证失败则显示登录失败页面…

如何识别金融欺诈行为并进行分析预警

金融行业以其高效便捷的服务深刻改变了人们的生活方式。然而,伴随技术进步而来的,是金融欺诈行为的日益猖獗。从信用卡盗刷到复杂的庞氏骗局,再到网络钓鱼和洗钱活动,金融欺诈的形式层出不穷,其规模和影响也在不断扩大。根据全球反欺诈组织(ACFE)的最新报告,仅2022年,…

纷析云:开源财务管理软件的创新与价值

在企业数字化转型中&#xff0c;纷析云作为一款优秀的开源财务管理软件&#xff0c;正为企业财务管理带来新变革&#xff0c;以下是其核心要点。 一、产品概述与技术架构 纷析云采用微服务架构&#xff0c;功能组件高内聚低耦合&#xff0c;可灵活扩展和定制。前端基于现代框…

蛋白质大语言模型ESM介绍

ESM(Evolutionary Scale Modeling)是 Meta AI Research 团队开发的一系列用于蛋白质的预训练语言模型。这些模型在蛋白质结构预测、功能预测和蛋白质设计等领域展现出了强大的能力。以下是对 ESM 的详细介绍: 核心特点 大规模预训练:基于大规模蛋白质序列数据进行无监督学…

OpenCv高阶(七)——图像拼接

目录 一、图像拼接的原理过程 1. 特征检测与描述&#xff08;Feature Detection & Description&#xff09; 2. 特征匹配&#xff08;Feature Matching&#xff09; 3. 图像配准&#xff08;Image Registration&#xff09; 4. 图像变换与投影&#xff08;Warping&…

Native层Trace监控性能

一、基础实现方法 1.1 头文件引用 #include <utils/Trace.h> // 基础版本 #include <cutils/trace.h> // 兼容旧版本1.2 核心宏定义 // 区间追踪&#xff08;推荐&#xff09; ATRACE_BEGIN("TraceTag"); ...被监控代码... ATRACE_END();// 函数级自…

金融行业微服务架构设计与挑战 - Java架构师面试实战

金融行业微服务架构设计与挑战 - Java架构师面试实战 本文通过模拟一位拥有十年Java研发经验的资深架构师马架构与面试官之间的对话&#xff0c;深入探讨了金融行业项目在微服务架构下的技术挑战与解决方案。 第一轮提问 面试官&#xff1a; 马架构&#xff0c;请介绍一下您…

服务器虚拟化:技术解析与实践指南

在信息技术飞速发展的今天,企业对服务器资源的需求日益增长,传统物理服务器存在资源利用率低、部署周期长、管理成本高等问题。服务器虚拟化技术应运而生,它通过将物理服务器的计算、存储、网络等资源进行抽象和整合,划分成多个相互隔离的虚拟服务器,从而提高资源利用率、…

OpenCV 图形API(54)颜色空间转换-----将图像从 RGB 色彩空间转换到 HSV色彩空间RGB2HSV()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像从 RGB 色彩空间转换为 HSV。该函数将输入图像从 RGB 色彩空间转换到 HSV。R、G 和 B 通道值的常规范围是 0 到 255。 输出图像必须是 8 位…

Spring Boot的优点:赋能现代Java开发的利器

Spring Boot 是基于 Spring 框架的快速开发框架&#xff0c;自 2014 年发布以来&#xff0c;凭借其简洁性、灵活性和强大的生态系统&#xff0c;成为 Java 后端开发的首选工具。尤其在 2025 年&#xff0c;随着微服务、云原生和 DevOps 的普及&#xff0c;Spring Boot 的优势更…

基于强化学习的智能交通控制系统设计

标题:基于强化学习的智能交通控制系统设计 内容:1.摘要 随着城市交通流量的不断增长&#xff0c;传统交通控制方法在应对复杂多变的交通状况时逐渐显现出局限性。本文旨在设计一种基于强化学习的智能交通控制系统&#xff0c;以提高交通运行效率、减少拥堵。通过构建强化学习模…

数据挖掘技术与应用课程论文——数据挖掘中的聚类分析方法及其应用研究

数据挖掘中的聚类分析方法及其应用研究 摘要 聚类分析是数据挖掘技术中的一个重要组成部分,它通过将数据集中的对象划分为多个组或簇,使得同一簇内的对象具有较高的相似性,而不同簇之间的对象具有较低的相似性。 本文系统地研究了数据挖掘中的多种聚类分析方法及其应用。首先…

Java基础语法10分钟速成

Java基础语法10分钟速成&#xff0c;记笔记版 JDKhello world变量字符串 类&#xff0c;继承&#xff0c;多态&#xff0c;重载 JDK JDK即Java development key&#xff0c;Java环境依赖包 在jdk中 编译器javac将代码的Java源文件编译为字节码文件&#xff08;.class&#xff…