【Threejs进阶教程-着色器篇】3. Uniform的基本用法2与基本地球昼夜效果

Uniform的基本用法2

  • 关于本Shader教程
  • 前两篇地址,请按顺序学习
  • 本篇使用到的资源
  • 用uniform传递纹理
    • 代码分析
    • texture类型的uniform
    • 在shader中接收uniform
    • texture2D()
      • 处理图片压缩
      • 修改wrapS和wrapT
  • 切换成夜景
    • 效果切换
    • Mix()
  • 昼夜切换升级
    • 改动代码
    • 效果分析
      • 解决球体分界线太过明显的问题
  • 让昼夜动起来
    • 改动代码
    • 最终效果
  • 案例完整源码
  • 如有不明白的,可以在下方留言或者加群

关于本Shader教程

  1. 本教程着重讲解Shadertoy的shader和Threejs的Shader,与原生WebGLShader略有不同,如果需要学习原生WebGL的shader,请参考《WebGL编程指南》
  2. 本人的shader水平也比较基础,文章中所写代码,不一定是最佳的代码,思路也不一定是最好的思路,所以一切本人的Shader教程下,所有的代码及思路以及学习建议均仅供参考,且目前本教程可能不适用于WebGPU,如果有大佬路过看到本人文章,觉得有可以指点之处,可以在下面留言,我们一起进步
  3. 数学水平不行的人,尤其是高中数学都及格不了的,不建议入坑Shader
  4. 本教程会在讲解片元着色器时,使用Shadertoy来编写demo,所以教程中会出现一部分Shadertoy的代码
  5. 本段内容将会出现在本人所有的【进阶教程-着色器篇】的文章中

前两篇地址,请按顺序学习

【Threejs进阶教程-着色器篇】1. Shader入门(ShadertoyShader和ThreejsShader入门)
【Threejs进阶教程-着色器篇】2. Uniform的基本用法与Uniform的调试

本篇使用到的资源

threejs开发包中
three/examples/textures/plantes/earth_atmos_2048.jpg 注意这张图片后缀是jpg!
three/examples/textures/plantes/earth_lights_2048.png
three/examples/textures/transition/transition5.png

用uniform传递纹理

有些时候不是说所有的图形效果都需要用数学去实现,还可以使用贴图

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body{width:100vw;height: 100vh;overflow: hidden;margin: 0;padding: 0;border: 0;}</style>
</head>
<body>
<script type="importmap">{"imports": {"three": "../three/build/three.module.js","three/addons/": "../three/examples/jsm/"}}</script><script type="x-shader/x-vertex" id="vertexShader">varying vec2 vUv;void main(){vUv = vec2(uv.x,uv.y);vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_Position = projectionMatrix * mvPosition;}</script>
<script type="x-shader/x-fragment" id="fragmentShader">varying vec2 vUv;uniform sampler2D uDiffuse1;void main(){vec4 col = texture2D(uDiffuse1,vUv);gl_FragColor = col;}
</script><script type="module">import * as THREE from "../three/build/three.module.js";import {OrbitControls} from "../three/examples/jsm/controls/OrbitControls.js";window.addEventListener('load',e=>{init();addMesh();render();})let scene,renderer,camera;let orbit;function init(){scene = new THREE.Scene();renderer = new THREE.WebGLRenderer({alpha:true,antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);camera = new THREE.PerspectiveCamera(50,window.innerWidth/window.innerHeight,0.1,2000);camera.add(new THREE.PointLight());camera.position.set(15,15,15);scene.add(camera);orbit = new OrbitControls(camera,renderer.domElement);orbit.enableDamping = true;scene.add(new THREE.GridHelper(10,10));}let uniforms = {uDiffuse1:{value:null}}function addMesh() {let textureLoader = new THREE.TextureLoader();uniforms.uDiffuse1.value = textureLoader.load('./earth_atmos_2048.jpg');let geometry = new THREE.SphereGeometry(5,32,32);let material = new THREE.ShaderMaterial({uniforms,vertexShader:document.getElementById('vertexShader').textContent,fragmentShader:document.getElementById('fragmentShader').textContent,})let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);}function render() {renderer.render(scene,camera);orbit.update();requestAnimationFrame(render);}</script>
</body>
</html>

代码效果
在这里插入图片描述

代码分析

texture类型的uniform

shader允许传递一个texture类型的对象到uniform,这里在threejs中,对应的是 THREE.Texture类型的对象,也就是TexthreLoader读取出来的图片,并转换成的texture实例

注意,一般情况下,图片的使用要考虑异步,本地化的读取效率非常高,不会出现渲染延迟,线上的话,可能会让地球变成一个黑色或者白色的球体

这个uniform的写法有两种,一种是像上面一样先赋值null,然后再读取,另一种是在读取的时候创建uniform的key,任选一个自己喜欢的风格即可,没有太多的要求,只是注意,给uniform赋值要这样写

//如果采用第二种写法,可以这样写
uniforms.uDiffuse1 = {value:texture}

在shader中接收uniform

    varying vec2 vUv;uniform sampler2D uDiffuse1; //这里在shader中,对应sampler2D这个类型void main(){vec4 col = texture2D(uDiffuse1,vUv); // 对图片逐uv取色gl_FragColor = col;}

texture2D()

texture2D函数的参数有两个,第一个是一个vec2的对象,第二个是一个sampler2D类型的数据
一般前者我们都使用uv,这个就是最基本的贴图代码,读取图片的uv并将颜色给到指定uv的顶点处

我们把几何体换成正方向平面,这样看的更明显一些

在这里插入图片描述
可以看出,在正方形平面的贴图上,图片出现了压缩,这是因为图片本身并不是一个正方形,但是以逐uv的形式来读取了这张图片,所以最终造成了压缩的问题

处理图片压缩

这里我们在shader中,把vUv.x 放大即可

    varying vec2 vUv;uniform sampler2D uDiffuse1;void main(){vec2 uUv = vec2(vUv.x / 2.0, vUv.y);vec4 col = texture2D(uDiffuse1,uUv);gl_FragColor = col;}

我们把uv.x除以2.0,这样我们就只加载 0 < uv.x < 0.5范围内的图片, 0< uv.y < 1的图片,所以我们可以看到,y轴没有变化,而x轴拉回去了
我们也可以继续修改,看看对uv的xy都乘或除2.0的效果怎么样

在这里插入图片描述
发现新的问题了,我们在除以2.0的情况下,我们只取了图片的左下角,但是乘以2.0的时候,并不如我们想的结果那样,平铺四张图

所以这里我们要对纹理做一下处理

修改wrapS和wrapT

        uniforms.uDiffuse1.value = textureLoader.load('./earth_atmos_2048.jpg');uniforms.uDiffuse1.value.wrapT = THREE.RepeatWrapping;uniforms.uDiffuse1.value.wrapS = THREE.RepeatWrapping;
    varying vec2 vUv;uniform sampler2D uDiffuse1;void main(){vec2 uUv = vec2(vUv.x * 2.0, vUv.y * 2.0);vec4 col = texture2D(uDiffuse1,uUv);gl_FragColor = col;}

在这里插入图片描述

这样,我们就解决了没有平铺图片的问题,这是一种通过shader的方式,来改变图片平铺方式的解决办法

切换成夜景

首先我们引入第二张图片,并改回球体和uv,并额外添加一个 uChange属性

修改代码

    let uniforms = {uDiffuse1:{value:null},uDiffuse2:{value:null},uChange:{value:0.0}}function addMesh() {let textureLoader = new THREE.TextureLoader();uniforms.uDiffuse1.value = textureLoader.load('./earth_atmos_2048.jpg');uniforms.uDiffuse1.value.wrapT = THREE.RepeatWrapping;uniforms.uDiffuse1.value.wrapS = THREE.RepeatWrapping;uniforms.uDiffuse2.value = textureLoader.load('./earth_lights_2048.png');uniforms.uDiffuse2.value.wrapT = THREE.RepeatWrapping;uniforms.uDiffuse2.value.wrapS = THREE.RepeatWrapping;let geometry = new THREE.SphereGeometry(5,32,32);let material = new THREE.ShaderMaterial({uniforms,vertexShader:document.getElementById('vertexShader').textContent,fragmentShader:document.getElementById('fragmentShader').textContent,})let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);let gui = new GUI();gui.add(uniforms.uChange,'value',0,1).name('渐变');}

片元着色器代码

    varying vec2 vUv;uniform sampler2D uDiffuse1;uniform sampler2D uDiffuse2;uniform float uChange;void main(){vec4 col = texture2D(uDiffuse2,vUv);gl_FragColor = col;}

在这里插入图片描述

效果切换

我们现在要做的是,如果uChange = 1 ,则显示白天的贴图,如果uChange = 0,则显示夜晚贴图

    varying vec2 vUv;uniform sampler2D uDiffuse1;uniform sampler2D uDiffuse2;uniform float uChange;void main(){vec4 col1 = texture2D(uDiffuse1,vUv);vec4 col2 = texture2D(uDiffuse2,vUv);gl_FragColor = vec4(col1.r * uChange + col2.r * (1.0 - uChange),col1.g * uChange + col2.g * (1.0 - uChange),col1.b * uChange + col2.b * (1.0 - uChange),col1.a * uChange + col2.a * (1.0 - uChange));}

我们这样想,既然change = 0.1的时候,那么此时图片1的颜色值为最淡,然后图片2的颜色值为最深,对应rgb三个颜色都是这样的结果

在这里插入图片描述

Mix()

但是其实,这个算法,官方早就给你想好了,我们只需使用mix即可,下面两种写法的效果完全一致

//旧代码gl_FragColor = vec4(col1.r * uChange + col2.r * (1.0 - uChange),col1.g * uChange + col2.g * (1.0 - uChange),col1.b * uChange + col2.b * (1.0 - uChange),col1.a * uChange + col2.a * (1.0 - uChange));
//新代码
gl_FragColor = mix(col2,col1,uChange);

mix是个非常非常常用的函数,主要用来线性混合数据,mix可以适用于很多种类型的数据,也有很多种用法,后续会经常用到和提到mix
在这里插入图片描述

昼夜切换升级

细心的朋友注意到了,这个切换效果,是全地球一起在切换,而并不是在模拟日出日落的那种昼夜切换,所以这个时候我们就要用到特殊的一种混合模式,这里我们加载第三张图,且拿掉uChange这个uniform

改动代码

我们加入第三张贴图,且加入时间变量iTime
由于在shadertoy中的时间变量也是iTime,所以后续所有的教程中,出现的时间变量都会命名为iTime

    let uniforms = {uDiffuse1:{value:null},uDiffuse2:{value:null},uChangeTexture:{value:null},iTime:{value:0.01}}function addMesh() {let textureLoader = new THREE.TextureLoader();uniforms.uDiffuse1.value = textureLoader.load('./earth_atmos_2048.jpg');uniforms.uDiffuse1.value.wrapT = THREE.RepeatWrapping;uniforms.uDiffuse1.value.wrapS = THREE.RepeatWrapping;uniforms.uDiffuse2.value = textureLoader.load('./earth_lights_2048.png');uniforms.uDiffuse2.value.wrapT = THREE.RepeatWrapping;uniforms.uDiffuse2.value.wrapS = THREE.RepeatWrapping;uniforms.uChangeTexture.value = textureLoader.load('./transition5.png');uniforms.uChangeTexture.value.wrapT = THREE.RepeatWrapping;uniforms.uChangeTexture.value.wrapS = THREE.RepeatWrapping;let geometry = new THREE.SphereGeometry(5,32,32);let material = new THREE.ShaderMaterial({uniforms,vertexShader:document.getElementById('vertexShader').textContent,fragmentShader:document.getElementById('fragmentShader').textContent,})let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);}function render() {renderer.render(scene,camera);orbit.update();requestAnimationFrame(render);uniforms.iTime.value += 0.01;}

片元着色器改动

    varying vec2 vUv;uniform sampler2D uDiffuse1;uniform sampler2D uDiffuse2;uniform sampler2D uChangeTexture;void main(){vec4 col1 = texture2D(uDiffuse1,vUv);vec4 col2 = texture2D(uDiffuse2,vUv);vec4 col3 = texture2D(uChangeTexture,vUv);gl_FragColor = mix(col2,col1,col3.r);}

效果分析

在这里插入图片描述
在这里插入图片描述

这样,我们看到的效果,就是一边是白天,一边是黑夜的效果了

我们切换回plane,来看看效果演变
在这里插入图片描述
在这里插入图片描述
可以看出,最黑的地方,最终使用的是夜晚的图片,也就是说此处的值,r值是最低的
最白的地方,最终使用的是白天的图片,也就是说此处的值,r值是最高的
中间的部分,随着上图的颜色变化而变化,白色越强的地方,白天图片的强度越高
黑色越强的地方,黑夜图片的强度越高

解决球体分界线太过明显的问题

但是这里有个很明显的问题,就是应用到球体上之后,左右两侧的颜色差距太大,导致了明显的分界线

我们切换回球体,然后对uv做一下处理

首先,我们的图片,是左边黑右边白,那么我们试着移动一下图片的像素,给uv.x - 0.5

此时图片会变成下面圈出来的这一块
在这里插入图片描述
然后,接下来,我们让负数变正数,则左边的这一块变成了,对abs(uv.x - 0.5)
在这里插入图片描述
原先按照正常的取值流程,红框的最左边是-0.5,但是我们给它变成正的了,所以后面会产生镜像效果

但是这一块黑色区域太大,所以我们要把最终结果再乘2,让图片截取到完全白色的区域

在这里插入图片描述
此时,uv.x的取值范围,就变成了 -1 ~1,就变成了上面的图片效果

然后我们带入到代码中试一下

<script type="x-shader/x-fragment" id="fragmentShader">varying vec2 vUv;uniform sampler2D uDiffuse1;uniform sampler2D uDiffuse2;uniform sampler2D uChangeTexture;void main(){vec4 col1 = texture2D(uDiffuse1,vUv);vec4 col2 = texture2D(uDiffuse2,vUv);//对vUv.x - 0.5然后绝对值,再乘2vec4 col3 = texture2D(uChangeTexture, vec2(abs(vUv.x - 0.5) * 2.0,vUv.y));gl_FragColor = mix(col2,col1,col3.r);}
</script>

在这里插入图片描述

让昼夜动起来

改动代码

    varying vec2 vUv;uniform sampler2D uDiffuse1;uniform sampler2D uDiffuse2;uniform sampler2D uChangeTexture;uniform float iTime;void main(){vec4 col1 = texture2D(uDiffuse1,vec2(vUv.x + iTime,vUv.y));vec4 col2 = texture2D(uDiffuse2,vec2(vUv.x + iTime,vUv.y));vec4 col3 = texture2D(uChangeTexture,vec2(abs(vUv.x - 0.5) * 2.0,vUv.y));gl_FragColor = mix(col2,col1,col3.r);}

由于col3中的vUv.x已经做了太多处理了,所以我们把跟随时间动的代码,放到了前面两张图上,让前面两张图动起来

然后发现动的实在是太快了,所以我们把运动速度也做了调整

    function render() {renderer.render(scene,camera);orbit.update();requestAnimationFrame(render);//旧代码 uniforms.iTime.value += 0.001;uniforms.iTime.value += 0.001;}

最终效果

在这里插入图片描述

完整效果由于gif图近10M,csdn承受不了,所以就不发了

案例完整源码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body{width:100vw;height: 100vh;overflow: hidden;margin: 0;padding: 0;border: 0;}</style>
</head>
<body><script type="importmap">{"imports": {"three": "../three/build/three.module.js","three/addons/": "../three/examples/jsm/"}}</script><script type="x-shader/x-vertex" id="vertexShader">varying vec2 vUv;void main(){vUv = vec2(uv.x,uv.y);vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_Position = projectionMatrix * mvPosition;}</script>
<script type="x-shader/x-fragment" id="fragmentShader">varying vec2 vUv;uniform sampler2D uDiffuse1;uniform sampler2D uDiffuse2;uniform sampler2D uChangeTexture;uniform float iTime;void main(){vec4 col1 = texture2D(uDiffuse1,vec2(vUv.x + iTime,vUv.y));vec4 col2 = texture2D(uDiffuse2,vec2(vUv.x + iTime,vUv.y));vec4 col3 = texture2D(uChangeTexture,vec2(abs(vUv.x - 0.5) * 2.0,vUv.y));gl_FragColor = mix(col2,col1,col3.r);}
</script><script type="module">import * as THREE from "../three/build/three.module.js";import {OrbitControls} from "../three/examples/jsm/controls/OrbitControls.js";window.addEventListener('load',e=>{init();addMesh();render();})let scene,renderer,camera;let orbit;function init(){scene = new THREE.Scene();renderer = new THREE.WebGLRenderer({alpha:true,antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);camera = new THREE.PerspectiveCamera(50,window.innerWidth/window.innerHeight,0.1,2000);camera.add(new THREE.PointLight());camera.position.set(15,15,15);scene.add(camera);orbit = new OrbitControls(camera,renderer.domElement);orbit.enableDamping = true;scene.add(new THREE.GridHelper(10,10));}let uniforms = {uDiffuse1:{value:null},uDiffuse2:{value:null},uChangeTexture:{value:null},iTime:{value:0.01}}function addMesh() {let textureLoader = new THREE.TextureLoader();uniforms.uDiffuse1.value = textureLoader.load('./earth_atmos_2048.jpg');uniforms.uDiffuse1.value.wrapT = THREE.RepeatWrapping;uniforms.uDiffuse1.value.wrapS = THREE.RepeatWrapping;uniforms.uDiffuse2.value = textureLoader.load('./earth_lights_2048.png');uniforms.uDiffuse2.value.wrapT = THREE.RepeatWrapping;uniforms.uDiffuse2.value.wrapS = THREE.RepeatWrapping;uniforms.uChangeTexture.value = textureLoader.load('./transition5.png');uniforms.uChangeTexture.value.wrapT = THREE.RepeatWrapping;uniforms.uChangeTexture.value.wrapS = THREE.RepeatWrapping;let geometry = new THREE.SphereGeometry(5,32,32);let material = new THREE.ShaderMaterial({uniforms,vertexShader:document.getElementById('vertexShader').textContent,fragmentShader:document.getElementById('fragmentShader').textContent,})let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);}function render() {renderer.render(scene,camera);orbit.update();requestAnimationFrame(render);uniforms.iTime.value += 0.001;}</script>
</body>
</html>

如有不明白的,可以在下方留言或者加群

如有其他不懂的问题,可以在下方留言,也可以加入qq群咨询,本人的群于2024/7/8日正式创建,群号867120877,欢迎大家来群里交流
在这里插入图片描述

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

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

相关文章

医疗器械网络安全| 常见安全漏洞与防护措施

医疗器械网络安全顾问​https://link.zhihu.com/?targethttps%3A//www.wanyun.cn/Support%3Fshare%3D24315_ea8a0e47-b38d-4cd6-8ed1-9e7711a8ad5e 一、常见安全漏洞 医疗器械软件在现代医疗体系中扮演着至关重要的角色&#xff0c;然而&#xff0c;随着技术的不断发展&…

关于centos7自带的nginx1.20.1开启https后,XP系统的IE6和IE8无法显示网页的问题

CentOS7自带的nginx-1.20.1是支持HTTP/2和TLS1.3的。 软件包名称&#xff1a;nginx-1.20.1-10.el7.x86_64 CentOS7默认开启了HTTP/2&#xff0c;但没有开启TLS1.3&#xff0c;以及IE6和IE8的https访问。 开启方法&#xff1a; ssl_ciphers HIGH:!aNULL:!MD5;改为ssl_ciphers…

【Word】快速对齐目录

目录标题 1. 全选要操作的内容 → 右键 → 段落2. 选则制表位3. 配置制表符4. Tab键即可 1. 全选要操作的内容 → 右键 → 段落 2. 选则制表位 3. 配置制表符 4. Tab键即可

36.哀家要长脑子了!--前缀和差分

前缀和 1.一维的795. 前缀和 - AcWing题库 前缀和公式 s[i] a[1] a[2] a[3] ... a[i] 即 s[i] s[i-1] a[i] #include<iostream> using namespace std;const int N 1e5 10; int a[N], s[N];int main(){int m, n;cin >> n >> m;for(int i 1; i <…

Elasticsearch基础(三):Elasticsearch核心原理介绍

文章目录 Elasticsearch核心原理介绍 一、基本概念 1、集群&#xff08;cluster&#xff09; 2、节点&#xff08;node&#xff09; 3、索引&#xff08;index&#xff09; 4、类型&#xff08;type&#xff09; 5、映射&#xff08;mapping&#xff09; 二、 Elastic…

LabVIEW开发高灵敏静电计

开发了一套基于LabVIEW平台的高灵敏静电计控制软件&#xff0c;用于提升闪烁薄膜探测器在中子和伽马射线探测中的灵敏度标定精度。传统的标定方法存在数据准确性不高和操作复杂性高的问题&#xff0c;因此开发这款软件解决这些挑战&#xff0c;通过自动化控制和高效的数据处理&…

Windows下载、配置Java JDK开发环境的方法

本文介绍在Windows电脑中&#xff0c;安装JDK&#xff08;Java Development Kit&#xff09;&#xff0c;也就是Java开发工具包的详细方法。 JDK是Java软件开发的基础&#xff0c;由Oracle公司提供&#xff0c;用于构建在Java平台上运行的应用程序与组件等&#xff1b;其已经包…

[C++]入门基础(1)

Hello大家好&#xff0c;今天通过本篇文章&#xff0c;我们来初步学习C&#xff0c;C可以说是对C语言的一个升级&#xff0c;我们会一步一步的由浅入深的学习C。 目录 1.第一个C程序 2.命名空间 2.1 命名空间出现的意义 2.2 namespace的定义 2.3 命名空间的使用 3.C输入…

亚信安全:《2024云安全技术发展白皮书》

标签 云计算 安全威胁 云安全技术 网络攻击 数据保护 一句话总结 《云安全技术发展白皮书》全面分析了云计算安全威胁的演进&#xff0c;探讨了云安全技术的发展历程、当前应用和未来趋势&#xff0c;强调了构建全面云安全防护体系的重要性。 摘要 云安全威胁演进&#xff…

c#第五次作业

目录 1. 实现通用打印泛型类&#xff0c;可以打印各个集合中的值&#xff0c;方便调试 2. 计算遍历目录的耗时 3. 有哪些算术运算符&#xff0c;有哪些关系运算符&#xff0c;有哪些逻辑运算符&#xff0c;有哪些位运算符&#xff0c;有哪些赋值运算符 1&#xff09;算术运算…

电商数据仓库

目录 1.数据仓库的数据来源为业务数据库&#xff08;mysql&#xff09; 初始化脚本 2.通过sqoop将mysql中的业务数据导入到大数据平台&#xff08;hive&#xff09; 在hive中建立映射的数据库 导入数据 3.通过hive进行数据计算和数据分析 形成数据报表 补全用户信息表中的…

【密码学】流密码的基本概念

在介绍流密码之前&#xff0c;我们先来弄明白一个基础前置知识点——异或运算。 一、异或运算&#xff08;XOR&#xff09; 运算规则&#xff1a;相同为0&#xff0c;不同为1 特点&#xff1a;一个比特进行两次异或运算&#xff0c;可以恢复成原来的比特。 明文&#xff1a;110…

降Compose十八掌之『飞龙在天』| Layout

公众号「稀有猿诉」 原文链接 降Compose十八掌之『飞龙在天』| Layout 页面布局是GUI应用开发的核心&#xff0c;决定着一个UI具体如何实现。今天将延着路线图来练习『降Compose十八掌』的第二招式&#xff0c;学习一下如何使用Compose中的布局来构建页面。 基础骨架 基…

Jenkins教程-15-常用插件-Blue Ocean

上一小节我们学习了Jenkins定时任务构建的方法&#xff0c;本小节我们讲解一下Jenkins常用插件Blue Ocean的使用方法。 Blue Ocean 提供了一套可视化操作界面来帮助创建、编辑 Pipeline 任务。 Blue Ocean 特性&#xff1a; 流水线编辑器&#xff1a;用于创建贯穿始终的持续交…

游戏软件缺少d3dx9_42.dll怎么修复?五种方法助你轻松解决

D3DX9_42.dll的丢失是一种常见的操作系统异常问题&#xff0c;由于日常使用电脑时的不当操作&#xff0c;可能会导致一些dll文件的丢失&#xff0c;D3DX9_42.dll就是其中之一。对于这种情况&#xff0c;我们可以通过谨慎的修复来解决。以下是一种科学的解决D3DX9_42.dll丢失的方…

小白学C++(第一天)基础入门

温馨提醒&#xff1a;本篇文章&#xff0c;请各位c基础不行的童鞋不要贸然观看 C的第一个程序 第一个关键字namespace namespace 是定义空间的名字的关键字&#xff0c;使用格式格式如下&#xff1a; namespace 空间名 { } 其中{ }内的命名空间的成员&#xff0c;可以定义…

初识数组!

目录 1.概念 2.一维数组的创建和初始化 1&#xff09;数组创建 2&#xff09;数组的初始化 3&#xff09;数组的类型 3.一维数组的使用 1) 数组下标 2) 数组元素的打印 3) 数组的输入 4.一维数组在内存中的存储 5.sizeof计算数组元素个数 6.二维数组的创建 1.概念 …

【qt】获取主机信息系统

话不多说,先一睹芳颜! 如果你也想达到这种效果,那咱们就开始吧! 目录 一.登录界面设计1.ui登录设计 二.加载界面1.lineEdit的密码输入模式2.lineEdit按回车跳转的信号3.密码的判断4.创建加载界面5.创建定时器来进行进度条的移动6.定时器执行的槽函数 三.主机信息界面1.主机信息…

解析java128陷阱

一、提要 在java开发时&#xff0c;由于基本类型不能调用方法&#xff0c;在某些方面很不方便&#xff0c;因此产生了包装类。我们把基本类型和对应的包装类的转换叫装箱、拆箱。 1.装箱 基本类型转成包装类对象 关键字valueOf->装箱,可以指定进制&#xff1a; Integer…

非参数检测5——双输入检测系统

在很多情况下&#xff0c;信号常常存在于两个带有独立噪声的信道中。所以很有必要研究双输入系统。双输入系统广泛应用于无线电天文学、水下声波检测和地球物理学等领域。