学习threejs,使用ShaderMaterial自定义着色器材质

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录

  • 一、🍀前言
    • 1.1 ☘️THREE.ShaderMaterial
      • 1.1.1 ☘️注意事项
      • 1.1.2 ☘️构造函数
      • 1.1.3 ☘️属性
      • 1.1.4 ☘️方法
  • 二、🍀使用ShaderMaterial自定义着色器材质
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、🍀前言

本文详细介绍如何基于threejs在三维场景中使用ShaderMaterial自定义着色器材质,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.ShaderMaterial

THREE.ShaderMaterial使用自定义shader渲染的材质。 shader是一个用GLSL编写的小程序 ,在GPU上运行。

1.1.1 ☘️注意事项

  • ShaderMaterial 只有使用 WebGLRenderer 才可以绘制正常, 因为 vertexShader 和
    fragmentShader 属性中GLSL代码必须使用WebGL来编译并运行在GPU中。
  • 从 THREE r72开始,不再支持在ShaderMaterial中直接分配属性。 必须使用
    BufferGeometry实例,使用BufferAttribute实例来定义自定义属性。
  • 从 THREE r77开始,WebGLRenderTarget 或 WebGLCubeRenderTarget
    实例不再被用作uniforms。 必须使用它们的texture 属性。
  • 内置attributes和uniforms与代码一起传递到shaders。
    如果您不希望WebGLProgram向shader代码添加任何内容,则可以使用RawShaderMaterial而不是此类。
  • 您可以使用指令#pragma unroll_loop_start,#pragma unroll_loop_end
    以便通过shader预处理器在GLSL中展开for循环。 该指令必须放在循环的正上方。循环格式必须与定义的标准相对应。
  • 循环必须标准化normalized。
  • 循环变量必须是i。
  • 对于给定的迭代,值 UNROLLED_LOOP_INDEX 将替换为 i 的显式值,并且可以在预处理器语句中使用。
#pragma unroll_loop_start
for ( int i = 0; i < 10; i ++ ) {

	// ...

}
#pragma unroll_loop_end

代码示例

const material = new THREE.ShaderMaterial( {
	uniforms: {
		time: { value: 1.0 },
		resolution: { value: new THREE.Vector2() }
	},
	vertexShader: document.getElementById( 'vertexShader' ).textContent,
	fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );

1.1.2 ☘️构造函数

ShaderMaterial( parameters : Object )
parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。

1.1.3 ☘️属性

共有属性请参见其基类Material。

.clipping : Boolean
定义此材质是否支持剪裁; 如果渲染器传递clippingPlanes uniform,则为true。默认值为false。

.defaultAttributeValues : Object
当渲染的几何体不包含这些属性但材质包含这些属性时,这些默认值将传递给shaders。这可以避免在缓冲区数据丢失时出错。

this.defaultAttributeValues = {
	'color': [ 1, 1, 1 ],
	'uv': [ 0, 0 ],
	'uv2': [ 0, 0 ]
};

.defines : Object
使用 #define 指令在GLSL代码为顶点着色器和片段着色器定义自定义常量;每个键/值对产生一行定义语句:

defines: {
	FOO: 15,
	BAR: true
}

这将在GLSL代码中产生如下定义语句:

#define FOO 15
#define BAR true

.extensions : Object
一个有如下属性的对象:

this.extensions = {
	derivatives: false, // set to use derivatives
	fragDepth: false, // set to use fragment depth values
	drawBuffers: false, // set to use draw buffers
	shaderTextureLOD: false // set to use shader texture LOD
};

.fog : Boolean
定义材质颜色是否受全局雾设置的影响; 如果将fog uniforms传递给shader,则为true。默认值为false。

.fragmentShader : String
片元着色器的GLSL代码。这是shader程序的实际代码。在上面的例子中, vertexShader 和 fragmentShader 代码是从DOM(HTML文档)中获取的; 它也可以作为一个字符串直接传递或者通过AJAX加载。

.glslVersion : String
定义自定义着色器代码的 GLSL 版本。仅与 WebGL 2 相关,以便定义是否指定 GLSL 3.0。有效值为 THREE.GLSL1 或 THREE.GLSL3。默认为空。

.index0AttributeName : String
如果设置,则调用gl.bindAttribLocation 将通用顶点索引绑定到属性变量。默认值未定义。

.isShaderMaterial : Boolean
只读标志,用于检查给定对象是否属于 ShaderMaterial 类型。

.lights : Boolean
材质是否受到光照的影响。默认值为 false。如果传递与光照相关的uniform数据到这个材质,则为true。默认是false。

.linewidth : Float
控制线框宽度。默认值为1。

由于OpenGL Core Profile与大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。

.flatShading : Boolean
定义材质是否使用平面着色进行渲染。默认值为false。

.uniforms : Object
如下形式的对象:

{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }

指定要传递给shader代码的uniforms;键为uniform的名称,值(value)是如下形式:

{ value: 1.0 }

这里 value 是uniform的值。名称必须匹配 uniform 的name,和GLSL代码中的定义一样。 注意,uniforms逐帧被刷新,所以更新uniform值将立即更新GLSL代码中的相应值。

.uniformsNeedUpdate : Boolean
可用于在 Object3D.onBeforeRender() 中更改制服时强制进行制服更新。默认为假。

.vertexColors : Boolean
定义是否使用顶点着色。默认为假。

.vertexShader : String
顶点着色器的GLSL代码。这是shader程序的实际代码。 在上面的例子中,vertexShader 和 fragmentShader 代码是从DOM(HTML文档)中获取的; 它也可以作为一个字符串直接传递或者通过AJAX加载。

.wireframe : Boolean
将几何体渲染为线框(通过GL_LINES而不是GL_TRIANGLES)。默认值为false(即渲染为平面多边形)。

.wireframeLinewidth : Float
控制线框宽度。默认值为1。

由于OpenGL Core Profile与大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。

1.1.4 ☘️方法

共有方法请参见其基类Material。

.clone () : ShaderMaterial this : ShaderMaterial
创建该材质的一个浅拷贝。需要注意的是,vertexShader和fragmentShader使用引用拷贝; attributes的定义也是如此; 这意味着,克隆的材质将共享相同的编译WebGLProgram; 但是,uniforms 是 值拷贝,这样对不同的材质我们可以有不同的uniforms变量。

二、🍀使用ShaderMaterial自定义着色器材质

1. ☘️实现思路

首先创建6个面着色器fragment-shader-1到fragment-shader-6。

  • 1、初始化renderer渲染器。
  • 2、初始化Scene三维场景scene。
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
  • 4、创建THREE.AmbientLight环境光源ambientLight,设置环境光ambientLight颜色,scene场景加入环境光源ambientLight。创建THREE.SpotLight聚光灯光源spotLight,设置聚光灯光源位置和投影,scene场景加入spotLight。
  • 5、加载几何模型:定义createMaterial方法用于创建ShaderMaterial自定义着色器材质,创建立方体集合对象cubeGeometry,调用createMaterial方法创建6个ShaderMaterial自定义着色器材质对象从meshMaterial1到meshMaterial6,传入创建的6个ShaderMaterial自定义着色器材质对象,创建MeshFaceMaterial几何体面材质对象material。传入cubeGeometry和material创建立方体网格对象cube,scene场景加入cube。定义render方法,实现立方体对象cube的旋转动画。具体代码参考下面代码样例。
  • 6、加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html>
<head>
    <title>学习threejs,使用ShaderMaterial自定义着色器材质</title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<script id="vertex-shader" type="x-shader/x-vertex">
    uniform float time;
    varying vec2 vUv;


    void main()
    {
    vec3 posChanged = position;
    posChanged.x = posChanged.x*(abs(sin(time*1.0)));
    posChanged.y = posChanged.y*(abs(cos(time*1.0)));
    posChanged.z = posChanged.z*(abs(sin(time*1.0)));
    //gl_Position = projectionMatrix * modelViewMatrix * vec4(position*(abs(sin(time)/2.0)+0.5),1.0);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(posChanged,1.0);
    }

</script>

<script id="fragment-shader-1" type="x-shader/x-fragment">
    precision highp float;
    uniform float time;
    uniform float alpha;
    uniform vec2 resolution;
    varying vec2 vUv;

    void main2(void)
    {
    vec2 position = vUv;
    float red = 1.0;
    float green = 0.25 + sin(time) * 0.25;
    float blue = 0.0;
    vec3 rgb = vec3(red, green, blue);
    vec4 color = vec4(rgb, alpha);
    gl_FragColor = color;
    }

    #define PI 3.14159
    #define TWO_PI (PI*2.0)
    #define N 68.5

    void main(void)
    {
    vec2 center = (gl_FragCoord.xy);
    center.x=-10.12*sin(time/200.0);
    center.y=-10.12*cos(time/200.0);

    vec2 v = (gl_FragCoord.xy - resolution/20.0) / min(resolution.y,resolution.x) * 15.0;
    v.x=v.x-10.0;
    v.y=v.y-200.0;
    float col = 0.0;

    for(float i = 0.0; i < N; i++)
    {
    float a = i * (TWO_PI/N) * 61.95;
    col += cos(TWO_PI*(v.y * cos(a) + v.x * sin(a) + sin(time*0.004)*100.0 ));
    }

    col /= 5.0;

    gl_FragColor = vec4(col*1.0, -col*1.0,-col*4.0, 1.0);
    }


</script>

<script id="fragment-shader-2" type="x-shader/x-fragment">

    uniform float time;
    uniform vec2 resolution;

    #define CGFloat float
    #define M_PI 3.14159265359

    vec3 hsvtorgb(float h, float s, float v)
    {
    float c = v * s;
    h = mod((h * 6.0), 6.0);
    float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
    vec3 color;

    if (0.0 <= h && h < 1.0)
    {
    color = vec3(c, x, 0.0);
    }
    else if (1.0 <= h && h < 2.0)
    {
    color = vec3(x, c, 0.0);
    }
    else if (2.0 <= h && h < 3.0)
    {
    color = vec3(0.0, c, x);
    }
    else if (3.0 <= h && h < 4.0)
    {
    color = vec3(0.0, x, c);
    }
    else if (4.0 <= h && h < 5.0)
    {
    color = vec3(x, 0.0, c);
    }
    else if (5.0 <= h && h < 6.0)
    {
    color = vec3(c, 0.0, x);
    }
    else
    {
    color = vec3(0.0);
    }

    color += v - c;

    return color;
    }

    void main(void)
    {

    vec2 position = (gl_FragCoord.xy - 0.5 * resolution) / resolution.y;
    float x = position.x;
    float y = position.y;

    CGFloat a = atan(x, y);

    CGFloat d = sqrt(x*x+y*y);
    CGFloat d0 = 0.5*(sin(d-time)+1.5)*d;
    CGFloat d1 = 5.0;

    CGFloat u = mod(a*d1+sin(d*10.0+time), M_PI*2.0)/M_PI*0.5 - 0.5;
    CGFloat v = mod(pow(d0*4.0, 0.75),1.0) - 0.5;

    CGFloat dd = sqrt(u*u+v*v);

    CGFloat aa = atan(u, v);

    CGFloat uu = mod(aa*3.0+3.0*cos(dd*30.0-time), M_PI*2.0)/M_PI*0.5 - 0.5;
    // CGFloat vv = mod(dd*4.0,1.0) - 0.5;

    CGFloat d2 = sqrt(uu*uu+v*v)*1.5;

    gl_FragColor = vec4( hsvtorgb(dd+time*0.5/d1, sin(dd*time), d2), 1.0 );
    }

</script>

<script id="fragment-shader-3" type="x-shader/x-fragment">
    uniform vec2 resolution;
    uniform float time;

    vec2 rand(vec2 pos)
    {
    return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0));
    }
    vec2 rand2(vec2 pos)
    {
    return rand(rand(pos));
    }

    float softnoise(vec2 pos, float scale)
    {
    vec2 smplpos = pos * scale;
    float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
    float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
    float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
    float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;

    vec2 a = fract(smplpos);
    return mix(
    mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
    mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
    smoothstep(0.0, 1.0, a.y));
    }

    void main(void)
    {
    vec2 pos = gl_FragCoord.xy / resolution.y;
    pos.x += time * 0.1;
    float color = 0.0;
    float s = 1.0;
    for(int i = 0; i < 8; i++)
    {
    color += softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0;
    s *= 2.0;
    }
    gl_FragColor = vec4(color);
    }

</script>

<script id="fragment-shader-4" type="x-shader/x-fragment">


    uniform float time;
    uniform vec2 resolution;

    vec2 rand(vec2 pos)
    {
    return
    fract(
    (
    pow(
    pos+2.0,
    pos.yx+2.0
    )*555555.0
    )
    );
    }

    vec2 rand2(vec2 pos)
    {
    return rand(rand(pos));
    }

    float softnoise(vec2 pos, float scale) {
    vec2 smplpos = pos * scale;
    float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
    float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
    float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
    float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;

    vec2 a = fract(smplpos);
    return mix(mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
    mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
    smoothstep(0.0, 1.0, a.x));
    }

    void main( void ) {
    vec2 pos = gl_FragCoord.xy / resolution.y - time * 0.4;

    float color = 0.0;
    float s = 1.0;
    for (int i = 0; i < 6; ++i) {
    color += softnoise(pos + vec2(0.01 * float(i)), s * 4.0) / s / 2.0;
    s *= 2.0;
    }
    gl_FragColor = vec4(color,mix(color,cos(color),sin(color)),color,1);
    }

</script>

<script id="fragment-shader-5" type="x-shader/x-fragment">

    uniform float time;
    uniform vec2 resolution;

    // tie nd die by Snoep Games.

    void main( void ) {

    vec3 color = vec3(1.0, 0., 0.);
    vec2 pos = (( 1.4 * gl_FragCoord.xy - resolution.xy) / resolution.xx)*1.5;
    float r=sqrt(pos.x*pos.x+pos.y*pos.y)/15.0;
    float size1=2.0*cos(time/60.0);
    float size2=2.5*sin(time/12.1);

    float rot1=13.00; //82.0+16.0*sin(time/4.0);
    float rot2=-50.00; //82.0+16.0*sin(time/8.0);
    float t=sin(time);
    float a = (60.0)*sin(rot1*atan(pos.x-size1*pos.y/r,pos.y+size1*pos.x/r)+time);
    a += 200.0*acos(pos.x*2.0+cos(time/2.0))+asin(pos.y*5.0+sin(time/2.0));
    a=a*(r/50.0);
    a=200.0*sin(a*5.0)*(r/30.0);
    if(a>5.0) a=a/200.0;
    if(a<0.5) a=a*22.5;
    gl_FragColor = vec4( cos(a/20.0),a*cos(a/200.0),sin(a/8.0), 1.0 );
    }


</script>

<script id="fragment-shader-6" type="x-shader/x-fragment">


    uniform float time;
    uniform vec2 resolution;


    void main( void )
    {

    vec2 uPos = ( gl_FragCoord.xy / resolution.xy );//normalize wrt y axis
    //suPos -= vec2((resolution.x/resolution.y)/2.0, 0.0);//shift origin to center

    uPos.x -= 1.0;
    uPos.y -= 0.5;

    vec3 color = vec3(0.0);
    float vertColor = 2.0;
    for( float i = 0.0; i < 15.0; ++i )
    {
    float t = time * (0.9);

    uPos.y += sin( uPos.x*i + t+i/2.0 ) * 0.1;
    float fTemp = abs(1.0 / uPos.y / 100.0);
    vertColor += fTemp;
    color += vec3( fTemp*(10.0-i)/10.0, fTemp*i/10.0, pow(fTemp,1.5)*1.5 );
    }

    vec4 color_final = vec4(color, 1.0);
    gl_FragColor = color_final;
    }

</script>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Js 代码块-->
<script type="text/javascript">

    // 初始化
    function init() {

        var stats = initStats();

        // 创建三维场景scene
        var scene = new THREE.Scene();

        // 创建相机
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // 创建渲染器并设置大小
        var renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(new THREE.Color(0x000000, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;


        var cubeGeometry = new THREE.BoxGeometry(20, 20, 20);

        var meshMaterial1 = createMaterial("vertex-shader", "fragment-shader-1");
        var meshMaterial2 = createMaterial("vertex-shader", "fragment-shader-2");
        var meshMaterial3 = createMaterial("vertex-shader", "fragment-shader-3");
        var meshMaterial4 = createMaterial("vertex-shader", "fragment-shader-4");
        var meshMaterial5 = createMaterial("vertex-shader", "fragment-shader-5");
        var meshMaterial6 = createMaterial("vertex-shader", "fragment-shader-6");


        var material = new THREE.MeshFaceMaterial(
                [meshMaterial1,
                    meshMaterial2,
                    meshMaterial3,
                    meshMaterial4,
                    meshMaterial5,
                    meshMaterial6]);
//        var material = new THREE.MeshFaceMaterial([meshMaterial2, meshMaterial2, meshMaterial1, meshMaterial1, meshMaterial1, meshMaterial1]);

        var cube = new THREE.Mesh(cubeGeometry, material);

        // 场景中添加立方体网格对象
        scene.add(cube);

        // 设置相机位置和方向
        camera.position.x = 30;
        camera.position.y = 30;
        camera.position.z = 30;
        camera.lookAt(new THREE.Vector3(0, 0, 0));

        // 添加环境光源
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // 添加聚光灯光源,设置位置和投影
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);


        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        var step = 0;
      
        render();

        function render() {
            stats.update();
			// 立方体旋转动画
            cube.rotation.y = step += 0.01;
            cube.rotation.x = step;
            cube.rotation.z = step;

			// 着色器更新
            cube.material.materials.forEach(function (e) {
                e.uniforms.time.value += 0.01;
            });
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

        function initStats() {

            var stats = new Stats();

            stats.setMode(0);

            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }

        function createMaterial(vertexShader, fragmentShader) {
            var vertShader = document.getElementById(vertexShader).innerHTML;
            var fragShader = document.getElementById(fragmentShader).innerHTML;

            var attributes = {};
            var uniforms = {
                time: {type: 'f', value: 0.2},
                scale: {type: 'f', value: 0.2},
                alpha: {type: 'f', value: 0.6},
                resolution: {type: "v2", value: new THREE.Vector2()}
            };

            uniforms.resolution.value.x = window.innerWidth;
            uniforms.resolution.value.y = window.innerHeight;

            var meshMaterial = new THREE.ShaderMaterial({
                uniforms: uniforms,
                attributes: attributes,
                vertexShader: vertShader,
                fragmentShader: fragShader,
                transparent: true

            });


            return meshMaterial;
        }


    }
    window.onload = init;
</script>
</body>
</html>

效果如下:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Selenium自动化测试框架快速搭建

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、介绍 Selenium目前主流的web自动化测试框架&#xff1b;支持多种编程语言Java、pythan、go、js等&#xff1b;selenium 提供一系列的api 供我们使用&#xf…

【文献阅读】A Survey on Hardware Accelerators for Large Language Models

大语言模型硬件加速器综述 大语言模型&#xff08;LLMs&#xff09;已成为自然语言处理任务的强大工具&#xff0c;凭借其理解和生成类似人类文本的能力&#xff0c;彻底改变了该领域。随着对更复杂大语言模型的需求持续增长&#xff0c;迫切需要应对与其规模和复杂性相关的计…

机器幻觉产生的原因

机器幻觉是指模型生成的不符合现实的内容&#xff0c;比如图像生成中的错误或者不合理的输出。 线性函数在神经网络中的作用通常是传递梯度&#xff0c;但如果每一层都是线性的&#xff0c;整个网络就相当于一个单层的线性模型&#xff0c;无法学习复杂的模式。所以如果只有线性…

python-leetcode-颜色分类

75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; class Solution:def sortColors(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""low, mid, high 0, 0, len(nums) - 1while mid < h…

如何使用LLDB 在VSCode调试C++代码

LLDB VSCode调试 第一步.拷贝lldb-server到android系统 adb push ${NDK_PATH}/toolchains/llvm/prebuilt/darwin-x86_64/lib64/clang/9.0.9/lib/linux/arm/lldb-server /data/local/tmp/lldb-server第二步.进入到安卓设备&#xff0c;打开lldb-server adb shell cd /data/lc…

2025中建二测笔试考什么?北森题库考点复习|附精华备考面试攻略

大家好&#xff0c;我是职小豚&#xff0c;将为大家详细解析2025年中建二测的笔试内容&#xff0c;并提供备考面试的全方位攻略。 希望这份指南能帮助大家在求职路上更加顺利&#xff01; 一、中国建筑集团公司介绍 中国建筑集团有限公司&#xff08;简称“中建集团”&#…

GD32F450 使用

GB32F450使用 1. 相关知识2. 烧写程序3. SPI3.1 spi基础3.2 spi代码 4. 串口4.1 串口引脚4.2 串口通信代码 问题记录1. 修改晶振频率 注意&#xff1a;GD32F450 总共有三种封装形式&#xff0c;本文所述的相关代码和知识&#xff0c;均为 GD32F450IX 系列。 1. 相关知识 参数配…

Spring Boot 测试:单元、集成与契约测试全解析

一、Spring Boot 分层测试策略 Spring Boot 应用采用经典的分层架构&#xff0c;不同层级的功能模块对应不同的测试策略&#xff0c;以确保代码质量和系统稳定性。 Spring Boot 分层架构&#xff1a; Spring Boot分层架构 A[客户端] -->|HTTP 请求| B[Controller 层] …

(十 三)趣学设计模式 之 模版方法模式!

目录 一、 啥是模板方法模式&#xff1f;二、 为什么要用模板方法模式&#xff1f;三、 模板方法模式的实现方式四、 模板方法模式的优缺点五、 模板方法模式的应用场景六、 总结 &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢博主的讲解方式&a…

汽车刹车系统设计

摘 要 本次设计内容为汽车刹车系统&#xff0c;其可靠性与驾驶人的生命息息相关&#xff0c;是汽车所有组成部分中最重要的一环。刹车系统是在车辆行驶过程中出现紧急情况时首先保护车辆与驾驶人员安全的反应系统&#xff0c;工作原理是依靠制动装置工作时产生的大量摩擦力来抵…

卷积神经网络梯度下降方向与参数更新方向的一致性论述

梯度下降是一种常用的优化算法&#xff0c;用于最小化损失函数&#xff0c;在机器学习和深度学习领域有着广泛的应用。分别对梯度下降、梯度方向以及参数更新采用负梯度方向的原因进行论述。 1.梯度下降 它的基本思想是通过迭代的方式来更新模型的参数&#xff0c;使得损失函数…

Starrocks入门(二)

1、背景&#xff1a;考虑到Starrocks入门这篇文章&#xff0c;安装的是3.0.1版本的SR&#xff0c;参考&#xff1a;Starrocks入门-CSDN博客 但是官网的文档&#xff0c;没有对应3.0.x版本的资料&#xff0c;却有3.2或者3.3或者3.4或者3.1或者2.5版本的资料&#xff0c;不要用较…

可以免费无限次下载PPT的网站

前言 最近发现了一个超实用的网站&#xff0c;想分享给大家。 在学习和工作的过程中&#xff0c;想必做PPT是一件让大家都很头疼的一件事。 想下载一些PPT模板减少做PPT的工作量&#xff0c;但网上大多精美的PPT都是需要付费才能下载使用。 即使免费也有次数限制&#xff0…

[Java基础] JVM常量池介绍(BeanUtils.copyProperties(source, target)中的属性值引用的是同一个对象吗)

文章目录 1. JVM内存模型2. 常量池中有什么类型&#xff1f;3. 常量池中真正存储的内容是什么4. 判断一个字符串(引用)是否在常量池中5. BeanUtils.copyProperties(source, target)中的属性值引用的是同一个对象吗&#xff1f;6. 获取堆内存使用情况、非堆内存使用情况 1. JVM内…

DeepSeek模型昇腾部署优秀实践

2024年12月26日&#xff0c;DeepSeek-V3横空出世&#xff0c;以其卓越性能备受瞩目。该模型发布即支持昇腾&#xff0c;用户可在昇腾硬件和MindIE推理引擎上实现高效推理&#xff0c;但在实际操作中&#xff0c;部署流程与常见问题困扰着不少开发者。本文将为你详细阐述昇腾 De…

python编写liunx服务器登陆自动巡检脚本

前言&#xff1a; 用户需要一份用Python编写的Linux系统巡检脚本&#xff0c;检查内存、磁盘、CPU使用率&#xff0c;还有网络连通性。 首先&#xff0c;我得确定用户的使用场景。可能用户是系统管理员&#xff0c;需要定期监控服务器状态&#xff0c;确保系统正常运行。 或者…

鸿蒙 ArkUI 实现敲木鱼小游戏

敲木鱼是一款具有禅意的趣味小游戏&#xff0c;本文将通过鸿蒙 ArkUI 框架的实现代码&#xff0c;逐步解析其核心技术点&#xff0c;包括动画驱动、状态管理、音效震动反馈等。 一、架构设计与工程搭建 1.1 项目结构解析 完整项目包含以下核心模块&#xff1a; ├── entry…

ShenNiusModularity项目源码学习(14:ShenNius.Infrastructure项目分析)

ShenNius.Infrastructure项目用于定义ShenNius.Admin.Mvc项目和ShenNius.Admin.API项目共用的特性类、数据操作接口实现类、上下文类、通讯类&#xff0c;主要文件的用途如下&#xff1a;   Attributes文件夹保存特性类或过滤器类定义&#xff0c;主要包括&#xff1a;   …

Mysql表字段字符集未设置导致乱码问题

项目场景&#xff1a; 在使用mysql的text类型作为字段类型【未设置编码】&#xff0c;且表结构【设置了编码集】的条件下&#xff0c;查询表这个字段会出现乱码的情况。 问题描述 今日测试小伙伴给题主提出了一个bug&#xff0c;数据库当中的text文本字段在存储json的情况下&…

staruml绘制时序图和用例图

文章目录 1.文章介绍2.绘制用例图3.绘制时序图 1.文章介绍 之前&#xff0c;我们初步介绍了这个staruml软件的安装和如何使用这个软件对于uml类图进行绘制&#xff0c;当时我们是绘制了这个user类&#xff0c;实现了相关的接口&#xff0c;表示他们之间的关系&#xff0c;在今…