【Threejs进阶教程-着色器篇】6. 2D SDF(三) 移动图形,限制图形,绘制多个图形

news2024/11/13 10:48:07

2D SDF 移动与合并图形

  • 前五篇地址,建议按顺序学习
  • 本篇使用到的初始代码
  • 减小扩散范围
    • clamp函数
    • 修改maxDistance来修改扩散范围
  • 移动扩散中心
  • 添加第二个扩散点
    • 降低点的同步率
    • 调整参数来优化效果
    • 添加更多扩散点
  • 完整源码
  • 如有不明白的,可以在下方留言或者加群

前五篇地址,建议按顺序学习

【Threejs进阶教程-着色器篇】1. Shader入门(ShadertoyShader和ThreejsShader入门)
【Threejs进阶教程-着色器篇】2. Uniform的基本用法与Uniform的调试
【Threejs进阶教程-着色器篇】3. Uniform的基本用法2与基本地球昼夜效果
【Threejs进阶教程-着色器篇】4. 2D SDF(一) SDF的基本用法
【Threejs进阶教程-着色器篇】5. 2D SDF(二)圆形波纹效果

本篇使用到的初始代码

【Threejs进阶教程-着色器篇】5. 2D SDF(二)圆形波纹效果
请在此文的最后,自行复制粘贴对应的上一篇完整代码,本篇将会以上一篇的代码为基础,扩展当前的效果

减小扩散范围

因为现在我们是用透明度来控制扩散效果的,所以,我们本次的修改也主要以透明度为准

我们现在的透明度情况,是以中心为准,每一圈的内圈起点处透明度最低,透明度为0,每一圈的外圈终点处,透明度为1,我们是用fract限制了这个值的最大值只能为1,但是并没有限制半径,所以我们从半径下手

  1. 先设定一个扩散半径
  2. 然后计算当前的auv值到扩散中心的距离,与半径的比值,
  3. 用这个比值,与最终计算的alp值相乘

以默认值为例,我们现阶段的默认的iFreq的值为10.0,也就是说,在图形的四个边缘处到中心的距离,等于半径,当前值为10,四个角上的顶点处,距离中心的距离为 sqrt(10 * 10),所以,我们可以先设置一个低于10的值

<!-- 片元着色器代码 -->
<script type="x-shader/x-fragment" id="fragmentShader">
    varying vec2 vUv;
    uniform float iTime;
    uniform float iFreq;
    uniform vec3 iColor;
    uniform float iSpeed;
    uniform float iPower;

    float sdCircle( vec2 p, float r ){
        return length(p) - r;
    }

    void main(){
        vec2 aUv = (vUv - 0.5) * iFreq;
        float alp = fract(sdCircle(aUv, 0.5) - iTime * iSpeed);
        alp = pow(alp,iPower);//对扩散的光波pow可以减少光波有颜色的部分的宽度

        float maxDistance = 5.0;//扩散半径
        alp *= distance(aUv,vec2(0.0)) / maxDistance;
        gl_FragColor = vec4(iColor,alp);
    }
</script>

在这里插入图片描述
但是,这个效果明显是不对的,不仅半径没有得到限制,且中心变的透明化了
既然是中心变的透明化了,说明最终的计算值已经是0了,那么想让中心实色化,就用1.0 - 计算结果即可,但是,因为计算的值,可能会小于1,那么,我们做个限制,让它取值为0~1即可

<!-- 片元着色器代码 -->
<script type="x-shader/x-fragment" id="fragmentShader">
    varying vec2 vUv;
    uniform float iTime;
    uniform float iFreq;
    uniform vec3 iColor;
    uniform float iSpeed;
    uniform float iPower;

    float sdCircle( vec2 p, float r ){
        return length(p) - r;
    }

    void main(){
        vec2 aUv = (vUv - 0.5) * iFreq;
        float alp = fract(sdCircle(aUv, 0.5) - iTime * iSpeed);
        alp = pow(alp,iPower);//对扩散的光波pow可以减少光波有颜色的部分的宽度

        float maxDistance = 5.0;//扩散半径
        alp *= 1.0 - distance(aUv,vec2(0.0)) / maxDistance;
        //一定注意,alp是float类型的,这里写大于的时候,后面的数字必须是float类型,不能是1,不然threejs会报错
        if(alp > 1.0){
            alp = 1.0;
        }else if(alp < 0.0){
            alp = 0.0;
        }
        gl_FragColor = vec4(iColor,alp);
    }
</script>

在这里插入图片描述

clamp函数

不过,上面的写法是可以优化的,glsl内置了clamp函数,来取代上面的if-else写法

//原写法
        if(alp > 1.0){
            alp = 1.0;
        }else if(alp < 0.0){
            alp = 0.0;
        }
//新写法
	alp = clamp(alp,0.0,1.0);

clamp函数不仅对float类型数据有效,对向量也可用,截图截取自《webgl编程指南》431页
注意使用的时候,看清楚函数的数据类型,以及,min值不要大于max值
在这里插入图片描述

修改maxDistance来修改扩散范围

通过修改maxDistance到2.0,我们就得到了这样的一个效果
在这里插入图片描述

移动扩散中心

既然我们可以更改扩散范围,那么,我们亦可更改扩散的中心点
在片元着色器中,修改 vUv - 0.5的位置为: vUv - vec2(0.2,0.5),即可让扩散中心向左侧偏移
这里的vec2(0.2,0.5),本质上就是扩散中心的位置

		//原代码
		vec2 aUv = (vUv - 0.5) * iFreq;
		//新代码
        vec2 aUv = (vUv - vec2(0.2,0.5)) * iFreq;

在这里插入图片描述

但是,我们这样来搞就麻烦了,所以我们现在需要封装一个方法出来,为了方便后续的开发内容

<!-- 片元着色器代码 -->
<script type="x-shader/x-fragment" id="fragmentShader">
    varying vec2 vUv;
    uniform float iTime;
    uniform float iFreq;
    uniform vec3 iColor;
    uniform float iSpeed;
    uniform float iPower;

    float sdCircle( vec2 p, float r ){
        return length(p) - r;
    }
	//三个参数分别为: 扩散中心,基本半径,最大半径
    float createWave(vec2 center,float radius,float maxDistance){
        vec2 aUv = (vUv - center) * iFreq;
        float alp = fract(sdCircle(aUv,0.5) - iTime * iSpeed);
        alp = pow(alp,iPower);
        alp *= 1.0 - distance(aUv,vec2(0.0)) / maxDistance;
        alp = clamp(alp,0.0,1.0);
        return alp;
    }

    void main(){
        float alp = createWave(vec2(0.2,0.5),0.5,2.0);
        gl_FragColor = vec4(iColor,alp);
    }
</script>

添加第二个扩散点

第二个扩散点其实非常简单,就是利用一下上面我们封装好的函数,直接追加一份即可

<!-- 片元着色器代码 -->
<script type="x-shader/x-fragment" id="fragmentShader">
    varying vec2 vUv;
    uniform float iTime;
    uniform float iFreq;
    uniform vec3 iColor;
    uniform float iSpeed;
    uniform float iPower;

    float sdCircle( vec2 p, float r ){
        return length(p) - r;
    }

    //三个参数分别为: 扩散中心,基本半径,最大半径
    float createWave(vec2 center,float radius,float maxDistance){
        vec2 aUv = (vUv - center) * iFreq;
        float alp = fract(sdCircle(aUv,0.5) - iTime * iSpeed);
        alp = pow(alp,iPower);
        alp *= 1.0 - distance(aUv,vec2(0.0)) / maxDistance;
        alp = clamp(alp,0.0,1.0);
        return alp;
    }

    void main(){
        float alp = createWave(vec2(0.2,0.5),0.5,2.0);
        alp += createWave(vec2(0.8,0.5),0.5,2.0);
        alp += createWave(vec2(0.5,0.2),0.5,2.0);
        alp += createWave(vec2(0.5,0.8),0.5,2.0);
        gl_FragColor = vec4(iColor,alp);
    }
</script>

在这里插入图片描述
为什么直接添加就能出效果?
非常简单,那个位置的透明度为0,0加任何的数据,都等于任何数据

降低点的同步率

现在的四个点,同步率非常的高,我们只需要在iTime上做手脚,让他们的初始速度发生变化即可

  1. 在封装的createWave方法中,添加参数 waveValue
  2. 调用方法时,传入不同的值
<!-- 片元着色器代码 -->
<script type="x-shader/x-fragment" id="fragmentShader">
    varying vec2 vUv;
    uniform float iTime;
    uniform float iFreq;
    uniform vec3 iColor;
    uniform float iSpeed;
    uniform float iPower;

    float sdCircle( vec2 p, float r ){
        return length(p) - r;
    }

    //三个参数分别为: 扩散中心,基本半径,最大半径
    float createWave(vec2 center,float radius,float maxDistance, float waveValue){
        vec2 aUv = (vUv - center) * iFreq;
        float alp = fract(sdCircle(aUv,radius) - iTime * iSpeed + waveValue);
        alp = pow(alp,iPower);
        alp *= 1.0 - distance(aUv,vec2(0.0)) / maxDistance;
        alp = clamp(alp,0.0,1.0);
        return alp;
    }

    void main(){
        float alp = createWave(vec2(0.2,0.5),0.5,2.0,0.2);
        alp += createWave(vec2(0.8,0.5),0.5,2.0,0.4);
        alp += createWave(vec2(0.5,0.2),0.5,2.0,0.6);
        alp += createWave(vec2(0.5,0.8),0.5,2.0,0.8);
        gl_FragColor = vec4(iColor,alp);
    }
</script>

在这里插入图片描述

调整参数来优化效果

  1. 将maxDistance抽出,使用unifrom + lil.gui来控制
  2. 调整参数到效果接近想要的效果
    在这里插入图片描述

添加更多扩散点

首先要说明的是,在shader中,没有随机数!随机只能借助noise函数来实现
现阶段,暂时仅建议多手敲几个点到图像上,简单看一下效果即可,在后续讲到noise函数的时候,这里还会再次提及

<!-- 片元着色器代码 -->
<script type="x-shader/x-fragment" id="fragmentShader">
    varying vec2 vUv;
    uniform float iTime;
    uniform float iFreq;
    uniform vec3 iColor;
    uniform float iSpeed;
    uniform float iPower;
    uniform float maxDistance;

    float sdCircle( vec2 p, float r ){
        return length(p) - r;
    }

    //三个参数分别为: 扩散中心,基本半径,最大半径
    float createWave(vec2 center,float radius, float waveValue){
        vec2 aUv = (vUv - center) * iFreq;
        float alp = fract(sdCircle(aUv,radius) - iTime * iSpeed + waveValue);
        alp = pow(alp,iPower);
        alp *= 1.0 - distance(aUv,vec2(0.0)) / maxDistance;
        alp = clamp(alp,0.0,1.0);
        return alp;
    }

    void main(){
        float alp = createWave(vec2(0.2,0.5),0.5,0.1);
        alp += createWave(vec2(0.12,0.35),0.5,0.2);
        alp += createWave(vec2(0.6,0.33),0.5,0.3);
        alp += createWave(vec2(0.49,0.24),0.5,0.4);
        alp += createWave(vec2(0.87,0.14),0.5,0.5);
        alp += createWave(vec2(0.35,0.88),0.5,0.6);
        alp += createWave(vec2(0.23,0.34),0.5,0.7);
        alp += createWave(vec2(0.65,0.44),0.5,0.8);
        alp += createWave(vec2(0.57,0.12),0.5,0.9);
        alp += createWave(vec2(0.88,0.92),0.5,0.9);
        alp += createWave(vec2(0.75,0.72),0.5,0.9);
        gl_FragColor = vec4(iColor,alp);
    }
</script>

在这里插入图片描述

完整源码

<!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;

        gl_Position = projectionMatrix * modelMatrix * viewMatrix * vec4( position, 1.0 );
    }

</script>

<!-- 片元着色器代码 -->
<script type="x-shader/x-fragment" id="fragmentShader">
    varying vec2 vUv;
    uniform float iTime;
    uniform float iFreq;
    uniform vec3 iColor;
    uniform float iSpeed;
    uniform float iPower;
    uniform float maxDistance;

    float sdCircle( vec2 p, float r ){
        return length(p) - r;
    }

    //三个参数分别为: 扩散中心,基本半径,最大半径
    float createWave(vec2 center,float radius, float waveValue){
        vec2 aUv = (vUv - center) * iFreq;
        float alp = fract(sdCircle(aUv,radius) - iTime * iSpeed + waveValue);
        alp = pow(alp,iPower);
        alp *= 1.0 - distance(aUv,vec2(0.0)) / maxDistance;
        alp = clamp(alp,0.0,1.0);
        return alp;
    }

    void main(){
        float alp = createWave(vec2(0.2,0.5),0.5,0.1);
        alp += createWave(vec2(0.12,0.35),0.5,0.2);
        alp += createWave(vec2(0.6,0.33),0.5,0.3);
        alp += createWave(vec2(0.49,0.24),0.5,0.4);
        alp += createWave(vec2(0.87,0.14),0.5,0.5);
        alp += createWave(vec2(0.35,0.88),0.5,0.6);
        alp += createWave(vec2(0.23,0.34),0.5,0.7);
        alp += createWave(vec2(0.65,0.44),0.5,0.8);
        alp += createWave(vec2(0.57,0.12),0.5,0.9);
        alp += createWave(vec2(0.88,0.92),0.5,0.9);
        alp += createWave(vec2(0.75,0.72),0.5,0.9);
        gl_FragColor = vec4(iColor,alp);
    }
</script>

<script type="module">

    import * as THREE from "../three/build/three.module.js";
    import {OrbitControls} from "../three/examples/jsm/controls/OrbitControls.js";
    import {GUI} from "../three/examples/jsm/libs/lil-gui.module.min.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 = {
        iTime:{value:0},
        iFreq:{value:21},//频率,光波圈数
        iColor:{value:new THREE.Color('#d1d1d1')},//光波颜色
        iSpeed:{value:2},//扩散速度
        iPower:{value:2.5},//光波强度
        maxDistance:{value:6.37},//最大扩散半径
    }

    function addMesh() {
        //常规情况下,planeGeometry,circleGeometry是与z轴垂直的,改成与y轴垂直,只需要沿着x轴让几何体旋转-90度即可
        //let geometry = new THREE.PlaneGeometry(10,10).rotateX(-Math.PI/2);
        //为了让效果更适用于圆形,我们从方形的planeGeometry换成CircleGeometry
        let geometry = new THREE.CircleGeometry(5,32).rotateX(-Math.PI/2);
        let material = new THREE.ShaderMaterial({
            uniforms,
            vertexShader:document.getElementById('vertexShader').textContent,
            fragmentShader:document.getElementById('fragmentShader').textContent,
            transparent:true
        })
        let mesh = new THREE.Mesh(geometry,material);
        scene.add(mesh);


        let param = {
            color:"#d1d1d1" //lil.gui读取threejs的颜色比较麻烦,个人习惯在这里单独写一个来控制
        };

        let gui = new GUI();
        gui.add(uniforms.iFreq,'value',0,50,0.01).name('光波圈数');
        gui.add(uniforms.iPower,'value',0,50,0.01).name('光波强度');
        gui.add(uniforms.iSpeed,'value',0,50,0.01).name('扩散速度');
        gui.add(uniforms.maxDistance,'value',0,50,0.01).name('最大扩散半径');
        gui.addColor(param,'color').name('光波颜色').onChange(v=>{
            uniforms.iColor.value = new THREE.Color(v);
        })

    }


    function render() {
        uniforms.iTime.value += 0.01;
        renderer.render(scene,camera);
        orbit.update();
        requestAnimationFrame(render);
    }

</script>
</body>
</html>

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

如有其他不懂的问题,可以在下方留言,也可以加入qq群咨询,
Web3D+GIS开源社区为新群,群内相对来说学习气氛良好,群号131995948
本人的群,群号867120877
欢迎大家来群里交流技术
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

01:【stm32HAL】对GPIO的操作

对GPIO的操作 1、LED闪烁2、按键控制LED3、芯片调试接口被锁死导致无法下载程序 1、LED闪烁 使用的是STM32CubeMXKeilv5进行HAL库的开发。 开发的步骤&#xff1a; 第一步&#xff1a;新建工程 第二步&#xff1a;选择芯片 第三步&#xff1a;如下图哈哈 第四步&#xff1a;…

图像识别智能垃圾桶项目开发--语音命令识别垃圾

一、项目思维导图 二、语音模块配置信息 三、项目程序 main.c garbage.c garbage.h uartTool.c //串口发送数据 uartTool.h

IPv6配置实验(OSPFv3)

1.搭建拓扑图 2.配置接口IP地址

文件上传的学习

文件上传漏洞 文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷&#xff0c;而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马&#xff0c;病毒&#xff0c;恶意脚本或者WebShell等。“文件上传”本身没有…

计算机毕业设计推荐-基于python的公司员工考勤管理系统

&#x1f496;&#x1f525;作者主页&#xff1a;毕设木哥 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; 实战项目 文章目录 实战项目 一、基于python的公司员工考勤管…

电池点焊机设计要点记录及个人分析

想要设计的由来 有些电路板或动力元件需要电池和镍片的连接&#xff0c;虽然临时使用焊锡焊接在了一起&#xff0c;但焊接过程中的热量和焊接后的厚度太大。最终想要设计一个用于点焊的板子 点焊的原理和操作上的误区 原理&#xff1a;两个点焊笔和镍片的接触点直径相比于导…

Local GAP - Financial Statement Version 【海外BS\PL报表】

业务场景&#xff1a; 基于海外IFRS等会计准则为客户定义一套BS\PL报表 BS - 从科目余额抓取 PL - 从利润中心报表抓取 会计报表版本的建立&#xff1a; 路径&#xff1a;IMG>财务会计&#xff08;新&#xff09;>总账会计核算&#xff08;新&#xff09;主数据>总…

【电子通识】失效分析中的电测试技术——电阻测试方法及注意事项

失效分析通常需要对测试数据进行仔细的分析&#xff0c;因此&#xff0c;测试设备的数据准确性和可靠性是至关重要的基本要求。为了确保数据的准确性&#xff0c;失效分析所使用的测试设备需要进行定期计量。 测试设备选择 在测试电阻、电容和电感的设备中&#xff0c;最常见的…

watchdog: BUG: soft lockup

故障现象&#xff1a; 故障原因&#xff1a; 不知道。 解决办法&#xff1a; 由12个改成2个&#xff1b;然后重新开机虚拟机&#xff0c; 临时解决了。

使用Golang的协程竟然变慢了|100万个协程的归并排序耗时分析

前言 这篇文章将用三个版本的归并排序&#xff0c;为大家分析使用协程排序的时间开销&#xff08;被排序的切片长度由128到1000w&#xff09; 本期demo地址&#xff1a;https://github.com/BaiZe1998/go-learning 往期视频讲解 &#x1f4fa;&#xff1a;B站&#xff1a;白泽…

145. 利用 Redis Bitmap实践: 用户签到统计

文章目录 一、Redis Bitmap简介二、Bitmap 的主要应用三、Go使用Redis实现签到统计用户签到查询用户签到状态统计今年累计签到天数统计当月的签到情况 总结 在现代应用程序中&#xff0c;用户签到是一个常见的功能。我们通常使用 MySQL 数据库来存储用户的签到记录。然而&#…

c++11新特性-智能指针

1. 智能指针的概念及原理 1.1 什么是智能指针 智能指针RAII(Resource Acquisition Is Initialization)&#xff0c;是一种利用对象的生命周期来管理资源的技术。如果我们采用传统的new/delete来申请和释放资源&#xff0c;如果忘记调用delete&#xff0c;或者在调用delete之前…

World of Warcraft [CLASSIC][80][Grandel] Call to Arms: Arathi Basin

PVP战场阿拉希盆地15人 /i 开局队伍分配&#xff1a;圣骑士飙车光环 /i [铁匠铺]坦克、治疗3个、输出6个&#xff08;10人组&#xff09; /i [伐木场]坦克、治疗、输出2&#xff08;4个人组&#xff09; /i [农场]留一个守&#xff08;1个人组&#xff09; /i 不要恋战&#x…

如何准确物理定位EMC Unity存储的磁盘位置

上周收到一个客户的咨询&#xff0c;问题是想主动更换一个Unity存储的磁盘&#xff0c;但不知道这个盘具体在存储的什么位置&#xff0c;有没有命令或者方法准确找到这个磁盘的物理位置&#xff1f; 以前也碰到过过类似的问题&#xff0c;但大部分是来自VNX存储。在现场让客户…

ChatGPT-4o:多领域创新应用的智能助手

ChatGPT-4o&#xff1a;多领域创新应用的智能助手 前言1. 数学建模&#xff1a;ChatGPT-4o的精确计算1.1 专业术语简介1.2 代码示例&#xff1a;线性规划问题问题描述代码实现运行结果 2. AI绘画&#xff1a;ChatGPT-4o的视觉创造力2.1 角色设计示例&#xff1a;火焰魔法师角色…

Leangoo领歌敏捷管理:助力敏捷高效协作,轻松实现Scrum敏捷转型

在当今快速变化的商业环境中&#xff0c;企业面临着前所未有的挑战。如何在激烈的竞争中保持领先&#xff1f;如何快速响应市场需求&#xff1f;答案就在于敏捷转型。而在这一过程中&#xff0c;有一个高效的敏捷工具至关重要——Leangoo领歌&#xff08;Leangoo领歌 - 免费一站…

盛京银行营收、利润双降下的负重难行,症结在哪儿?

撰稿|芋圆 来源|贝多财经 盛京银行自2020开年始&#xff0c;经营业绩除了在2022年稍有回暖外&#xff0c;均处于营收、利润双降的局面。 2024年半年报显示&#xff0c;盛京银行的资产总额为10683亿元&#xff0c;规模较2023年末收缩1.1%&#xff1b;营业收入46亿元&#xff0…

【前缀和算法】--- 进阶题目赏析

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey 本篇我们来赏析前缀和算法的进阶题目。 &#x1f3e0; 和可被K整除的子数组 &#x1f4cc; 题目解析 和可被k整除的子数组 &#x1f4cc; …

软件单元测试工程模版化

一、简介 在汽车领域混了这么多年也做了不少项目&#xff0c;发现很多公司对软件单元测试和代码覆盖率测试根本不重视&#xff0c;或者开发流程就没有单元测试这个流程。但是有的客户需要评审单元测试这个流程&#xff0c;需要有相关的单元测试报告和代码覆盖率统计的报告。如…

百度 AI Studio 脚本任务篇,它不同于notebook任务是支持免费的, 脚本任务是需要算力卡的,更好的算力 支持四张显卡,

aistudio 脚本任务是需要算力卡的&#xff0c;是收费的一个项目&#xff0c;估计是运行效率更高&#xff0c;支持4张显卡&#xff0c;同时计算。 # -*- coding: utf-8 -*- """ 空白模板 """ ###### 欢迎使用脚本任务&#xff0c;首先让我们熟悉…