Unity Shader入门精要第七章 基础纹理 单张纹理

2023-11-18

Unity系列文章目录

前言

纹理最初的目的就是使用一张图片来控制模型的外观。使用纹理映射(texture mapping)技
术,我们可以把一张图“黏”在模型表面,逐纹素(texel)(纹素的名字是为了和像素进行区分)
地控制模型的颜色。
在美术人员建模的时候, 通常会在建模软件中利用纹理展开技术把纹理映射坐标
(texture-mapping coordinates)存储在每个顶点上。纹理映射坐标定义了该顶点在纹理中对应的
2D 坐标。通常,这些坐标使用一个二维变量(u, v)来表示,其中u 是横向坐标,而v 是纵向坐标。
因此,纹理映射坐标也被称为UV 坐标。
尽管纹理的大小可以是多种多样的,例如可以是256×256 或者1024×1024,但顶点UV 坐标
的范围通常都被归一化到[0, 1]范围内。需要注意的是,纹理采样时使用的纹理坐标不一定是在[0,
1]范围内。实际上,这种不在[0, 1]范围内的纹理坐标有时会非常有用。与之关系紧密的是纹理的
平铺模式,它将决定渲染引擎在遇到不在[0, 1]范围内的纹理坐标时如何进行纹理采样。我们将在
7.1.2 节中更加详细地进行阐述。
在本书之前的章节中,我们曾不止一次地提
到过OpenGL 和DirectX 在二维纹理空间中的坐
标系差异问题。重要的事情要说很多次,我们再
来回顾一下。在OpenGL 里,纹理空间的原点位
于左下角,而在DirectX 中,原点位于左上角。
幸运的是,Unity 在绝大多数情况下(特例情况
可以参见5.6 节)为我们处理好了这个差异问题,
也就是说, 即便游戏的目标平台可能既有
OpenGL 风格的,也有DirectX 风格的,但我们
在Unity 中使用的通常只有一种坐标系。Unity
使用的纹理空间是符合OpenGL 的传统的,也就
是说,原点位于纹理左下角,如图7.1 所示。
本章将介绍如何在Unity 中利用纹理采样来
实现更加丰富的视觉效果。在7.1 节中,我们将
学习如何在Unity Shader 中进行最基本的纹理采
样,并介绍纹理的属性等基本概念。7.2 节将介绍游戏中应用广泛的凹凸纹理,还会解释Unity 中
法线纹理的一些实现细节。7.3 节和7.4 节将分别介绍两类特殊的纹理类型,即渐变纹理和遮罩纹
理,这些纹理在游戏中的应用非常广泛。
需要提醒读者注意的是,本章着重讲述纹理采样的原理,因此实现的Shader 往往并不能直接
应用到实际项目中(直接使用的话会缺少阴影、光照衰减等效果)。我们会在9.5 节给出包含了纹
理采样和完整光照模型的可真正使用的Unity Shader。

在这里插入图片描述

一、7.1单张纹理

我们通常会使用一张纹理来代替物体的漫反射颜色。在本节中,我们将学习如何在Unity
Shader 中使用单张纹理来作为模拟的颜色。在学习完本节后,我们会得到类似图7.2 中的效果。
在这里插入图片描述
在本例中,我们仍然使用Blinn-Phong 光照模型来计算光照。准备工作如下。
(1)在Unity 中新建一个场景。在本书资源中,该场景名为Scene_7_1。在Unity 5.2 中,默
认情况下场景将包含一个摄像机和一个平行光,并且使用了内置的天空盒子。在Window ->
Lighting -> Skybox 中去掉场景中的天空盒子。
(2)新建一个材质。在本书资源中,该材质名为SingleTextureMat。
(3)新建一个Unity Shader。在本书资源中,该Unity Shader 名为Chapter7-SingleTexture。把
新的Unity Shader 赋给第2 步中创建的材质。
(4)在场景中创建一个胶囊体,并把第2 步中的材质赋给该胶囊体。
(5)保存场景。
打开新建的Chapter7-SingleTexture,删除所有已有代码,并进行如下修改。
(1)首先,我们需要为这个Unity Shader 起一个名字:
Shader “Unity Shaders Book/Chapter 7/Single Texture” {
(2)为了使用纹理,我们需要在Properties 语义块中添加一个纹理属性:
Properties {
_Color (“Color Tint”, Color) = (1,1,1,1)
_MainTex (“Main Tex”, 2D) = “white” {}
_Specular (“Specular”, Color) = (1, 1, 1, 1)
_Gloss (“Gloss”, Range(8.0, 256)) = 20
}
上面的代码声明了一个名为_MainTex 的纹理,在3.3.2 节中,我们已经知道2D 是纹理属性
的声明方式。我们使用一个字符串后跟一个花括号作为它的初始值,“white”是内置纹理的名字,
也就是一个全白的纹理。为了控制物体的整体色调,我们还声明了一个_Color 属性。
(3)然后,我们在SubShader 语义块中定义了一个Pass 语义块。而且,我们在Pass 的第一行
指明了该Pass 的光照模式:
SubShader {
Pass {
Tags { “LightMode”=“ForwardBase” }
LightMode 标签是Pass 标签中的一种,它用于定义该Pass 在Unity 的光照流水线中的角色。
(4)接着,我们使用CGPROGRAM 和ENDCG 来包围住Cg 代码片,以定义最重要的顶点着
色器和片元着色器代码。首先,我们使用#pragma 指令来告诉Unity,我们定义的顶点着色器和片
元着色器叫什么名字。在本例中,它们的名字分别是vert 和frag:
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
(5)为了使用Unity 内置的一些变量,如_LightColor0,还需要包含进Unity 的内置文件
Lighting.cginc:
#include “Lighting.cginc”
(6)我们需要在Cg 代码片中声明和上述属性类型相匹配的变量,以便和材质面板中的属性
建立联系:
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Specular;
float _Gloss;
与其他属性类型不同的是,我们还需要为纹理类型的属性声明一个float4 类型的变量
_MainTex_ST。其中,_MainTex_ST 的名字不是任意起的。在Unity 中,我们需要使用纹理名_ST
的方式来声明某个纹理的属性。其中,ST 是缩放(scale)和平移(translation)的缩写。_MainTex_ST
可以让我们得到该纹理的缩放和平移(偏移)值,_MainTex_ST.xy 存储的是缩放值,而
_MainTex_ST.zw 存储的是偏移值。这些值可以在材质
面板的纹理属性中调节,如图7.3 所示。在7.1.2 节中,
我们将更详细地解释这些纹理属性。
(7)接下来,我们需要定义顶点着色器的输入和
输出结构体:
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
在上面的代码中,我们首先在a2v 结构体中使用TEXCOORD0 语义声明了一个新的变量
texcoord,这样Unity 就会将模型的第一组纹理坐标存储到该变量中。然后,我们在v2f 结构体中
添加了用于存储纹理坐标的变量uv,以便在片元着色器中使用该坐标进行纹理采样。
(8)然后,我们定义了顶点着色器:
v2f vert(a2v v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(_Object2World, v.vertex).xyz;
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
// Or just call the built-in function
// o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
在顶点着色器中,我们使用纹理的属性值_MainTex_ST 来对顶点纹理坐标进行变换,得到最
终的纹理坐标。计算过程是,首先使用缩放属性_MainTex_ST.xy 对顶点纹理坐标进行缩放,然后
再使用偏移属性_MainTex_ST.zw 对结果进行偏移。Unity 提供了一个内置宏TRANSFORM_TEX
来帮我们计算上述过程。TRANSFORM_TEX 是在UnityCG.cginc 中定义的:
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
它接受两个参数,第一个参数是顶点纹理坐标,第二个参数是纹理名,在它的实现中,将利
用纹理名_ST 的方式来计算变换后的纹理坐标。
(9)我们还需要实现片元着色器,并在计算漫反射时使用纹理中的纹素值:
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
// Use the texture to sample the diffuse color
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal,
halfDir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
上面的代码首先计算了世界空间下的法线方向和光照方向。然后,使用Cg 的tex2D 函数对
纹理进行采样。它的第一个参数是需要被采样的纹理,第二个参数是一个float2 类型的纹理坐标,
它将返回计算得到的纹素值。我们使用采样结果和颜色属性_Color 的乘积来作为材质的反射率
albedo,并把它和环境光照相乘得到环境光部分。随后,我们使用albedo 来计算漫反射光照的结
果,并和环境光照、高光反射光照相加后返回。
(10)最后,我们为该Shader 设置了合适的Fallback:
Fallback “Specular”
保存后返回Unity 中查看。在SingleTextureMat 的面板上,我们使用本书资源中的
Brick_Diffuse.jpg 纹理对Main Tex 属性进行赋值。
7.1.2 纹理的属性
虽然很多资料把Unity 的纹理映射描述得很简单—声明一个纹理变量,再使用tex2D 函数
采样。实际上,在渲染流水线中,纹理映射的实现远比我们想象的复杂。在本书不会过多涉及一
些具体的实现细节,但要解释一些我们认为读者必须要知道的事情。在本节中,我们将关注Unity

中的纹理属性。
在我们向Unity 中导入一张纹理资源后,可以在它的材质面板上调整其属性,如图7.4 所示。
纹理面板中的第一个属性是纹理类型。在本节中,我们使用的是Texture 类型,在下面的法线
纹理一节中,我们会使用Normal map 类型。而在后面的章节中,我
们还会看到Cubemap 等高级纹理类型。我们之所以要为导入的纹理
选择合适的类型,是因为只有这样才能让Unity 知道我们的意图,
为Unity Shader 传递正确的纹理,并在一些情况下可以让Unity 对该
纹理进行优化。
当把纹理类型设置成Texture 后,下面会有一个Alpha from
Grayscale 复选框,如果勾选了它,那么透明通道的值将会由每个像
素的灰度值生成。关于透明效果,我们会在第8 章中讲到。在这里
我们不需要勾选它。
下面一个属性非常重要—Wrap Mode。它决定了当纹理坐标超过[0, 1]范围后将会如何被平
铺。Wrap Mode 有两种模式:一种是Repeat,在这种模式下,如果纹理坐标超过了1,那么它的
整数部分将会被舍弃,而直接使用小数部分进行采样,这样的结果是纹理将会不断重复;另一种
是Clamp,在这种模式下,如果纹理坐标大于1,那么将会截取到1,如果小于0,那么将会截取
到0。图7.5 给出了两种模式下平铺一张纹理的效果(读者可在本书资源中的Scene_7_1_2_a 中找
到相应场景)。
▲图7.5 Wrap Mode 决定了当纹理坐标超过[0, 1]范围后将会如何被平铺
图7.5 展示了在纹理的平铺(Tiling)属性为(3, 3)时分别使用两种Wrap Mode 的结果。左图
使用了Repeat 模式,在这种模式下纹理将会不断重复;右图使用了Clamp 模式,在这种模式下超
过范围的部分将会截取到边界值,形成一个条形结构。
需要注意的是,想要让纹理得到这样的效果,我们必须使用纹理的属性(例如上面的
_MainTex_ST 变量)在Unity Shader 中对顶点纹理坐标进行相应的变换。也就是说,代码中需要
包含类似下面的代码:
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
// Or just call the built-in function
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
我们还可以在材质面板中调整纹理的偏移量,图7.6 给出了两种模式下调整纹理偏移量的一
个例子。
图7.6 展示了在纹理的偏移属性为(0.2, 0.6)时分别使用两种Wrap Mode 的结果,左图使用了
Repeat 模式,右图使用了Clamp 模式。
纹理导入面板中的下一个属性是Filter Mode 属性,它决定了当纹理由于变换而产生拉伸时将
会采用哪种滤波模式。Filter Mode 支持3 种模式:Point,Bilinear 以及Trilinear。它们得到的图片
滤波效果依次提升,但需要耗费的性能也依次增大。纹理滤波会影响放大或缩小纹理时得到的图

片质量。例如,当我们把一张64×64 大小的纹理贴在一个512×512 大小的平面上时,就需要放
大纹理。图7.7 给出了3 种滤波模式下的放大结果。读者可以在本书资源中的Scene_7_1_2_b 中
找到该场景。
▲图7.6 偏移(Offset)属性决定了纹理坐标的偏移量
▲图7.7 在放大纹理时,分别使用3 种Filter Mode 得到的结果
纹理缩小的过程比放大更加复杂一些,此时原纹理中的多个像素将会对应一个目标像素。纹
理缩小更加复杂的原因在于我们往往需要处理抗锯齿问题,一个最常使用的方法就是使用多级渐
远纹理(mipmapping)技术。其中“mip”是拉丁文“multum in parvo”的缩写,它的意思是“在
一个小空间中有许多东西”。如同它的名字,多级渐远纹理技术将原纹理提前用滤波处理来得到很
多更小的图像,形成了一个图像金字塔,每一层都是对上一层图像降采样的结果。这样在实时运
行时,就可以快速得到结果像素,例如当物体远离摄像机时,可以直接使用较小的纹理。但缺点
是需要使用一定的空间用于存储这些多级渐远纹理,通常会多占用33%的内存空间。这是一种典
型的用空间换取时间的方法。在Unity 中,我们可以在纹理导入面板中,首先将纹理类型(Texture
Type)选择成Advanced,再勾选Generate Mip Maps 即可开启多级渐远纹理技术。同时,我们还
可以选择生成多级渐远纹理时是否使用线性空间(用于伽玛校正,详见18.4.2 节)以及采用的滤
波器等,如图7.8 所示。
图7.9 给出了从一个倾斜的角度观察一个网格结构的地板时,使用不同Filter Mode(同时也
使用了多级渐远纹理技术)得到的效果。读者可以在本书资源中的Scene_7_1_2_c 中找到该场景。
在内部实现上,Point 模式使用了最近邻(nearest neighbor)滤波,在放大或缩小时,它的
采样像素数目通常只有一个,因此图像会看起来有种像素风格的效果。而Bilinear 滤波则使用了
线性滤波,对于每个目标像素,它会找到4 个邻近像素,然后对它们进行线性插值混合后得到最
终像素,因此图像看起来像被模糊了。而Trilinear 滤波几乎是和Bilinear 一样的,只是Trilinear
还会在多级渐远纹理之间进行混合。如果一张纹理没有使用多级渐远纹理技术,那么Trilinear 得

到的结果是和Bilinear 就一样的。通常,我们会选择Bilinear 滤波模式。需要注意的是,有时我们
不希望纹理看起来是模糊的,例如对于一些类似棋盘的纹理,我们希望它就是像素风的,这时我
们可能会选择Point 模式。
在这里插入图片描述
最后,我们来讲一下纹理的最大尺寸和纹理模式。当我们在为不同平台发布游戏时,需要考
虑目标平台的纹理尺寸和质量问题。Unity 允许我们为不同目标平
台选择不同的分辨率,如图7.10 所示。
如果导入的纹理大小超过了Max Texture Size 中的设置值,那
么Unity 将会把该纹理缩放为这个最大分辨率。理想情况下,导
入的纹理可以是非正方形的,但长宽的大小应该是2 的幂,例如
2、4、8、16、32、64 等。如果使用了非2 的幂大小(Non Power
of Two,NPOT)的纹理,那么这些纹理往往会占用更多的内存空
间,而且GPU 读取该纹理的速度也会有所下降。有一些平台甚至
不支持这种NPOT 纹理,这时Unity 在内部会把它缩放成最近的2
的幂大小。出于性能和空间的考虑,我们应该尽量使用2 的幂大
小的纹理。
而Format 决定了Unity 内部使用哪种格式来存储该纹理。如
果我们将Texture Type 设置为Advanced,那么会有更多的Format
供我们选择。这里不再依次介绍每种纹理模式,但需要知道的是,
使用的纹理格式精度越高(例如使用Truecolor),占用的内存空间
越大,但得到的效果也越好。我们可以从纹理导入面板的最下方看到存储该纹理需要占用的内存
空间(如果开启了多级渐远纹理技术,也会增加纹理的内存占用)。当游戏使用了大量Truecolor
类型的纹理时,内存可能会迅速增加,因此对于一些不需要使用很高精度的纹理(例如用于漫反
射颜色的纹理),我们应该尽量使用压缩格式。

参考

Unity Shader入门精要
冯乐乐

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity Shader入门精要第七章 基础纹理 单张纹理 的相关文章

  • 【Unity Shader】屏幕后处理1.0:调整亮度/饱和度/对比度

    1 Unity中实现屏幕特效的基本步骤 什么叫屏幕后处理 Screen post processing effects 渲染完整个场景得到屏幕图像后对图像进行一系列操作 实现各种屏幕特效 这一步我们可以添加很多例如景深 Depth of F
  • Unity单元测试流程

    文章目录 环境 流程 1 创建一个存放 单元测试程序集 的目录 2 打开 Test Runner 窗口 3 选择单元测试模式 4 创建单元测试程序集 5 创建测试脚本 6 运行测试 环境 Unity 2020 3 3f1 流程 1 创建一个
  • Unity中loading页加载的实现

    首先创建一个Global cs 使用单例用于存储场景的名字 便于后续脚本的调用 此脚本不必挂载在游戏物体上 using UnityEngine using System Collections public class Global Mon
  • Unity 安卓打包

    Unity打包的方式有很多种 自动打包和手动打包 今天小弟就鼓捣鼓捣unity手动打包 如果想动态打包的话 可以去看其他大佬的帖帖哈 unity打包先配置环境 下载unity的时候可以顺道把unity的安卓包下载下来 如果忘了也没事 可以从
  • unity网络资源导入

    1 找到需要导入的文件 这里导入fbx格式 2 打开unity界面 在Asset目录下创建文件夹FBX 将需要导入的fbx预制体或整个文件夹拖入创建的FBX文件夹下 3 选中需要的fbx预制体并拖至场景中 4 双击定位到当前物体 5 找到需
  • 1.17 从0开始学习Unity游戏开发--场景切换

    前面的所有文章我们都在一个固定的游戏场景内进行开发 在最开始介绍场景这个概念的时候就已经提及 这个场景可以是一张地图 或者是一个对战房间等等 所以显然这个场景可以有多个 并且可以从一个场景切换到另外一个场景 那么在Unity中如何进行场景切
  • Unity中级客户端开发工程师的进阶之路

    上期UWA技能成长系统之 Unity高级客户端开发工程师的进阶之路 得到了很多Unity开发者的肯定 通过系统的学习 可以掌握游戏性能瓶颈定位的方法和常见的CPU GPU 内存相关的性能优化方法 UWA技能成长系统是UWA根据学员的职业发展
  • Unity与Android的Back键冲突解决

    Unity与Android的Back键冲突解决 上一篇的最后留下了两个问题 Unity视图下横屏闪退 Unity视图下Android无法响应back返回上一activity 对于第一个问题 应该是Unity横屏下视图的某些设置跟Androi
  • GooglePlay提审警告(com.google.android.gms:play-services-safetynet:17.0.0)

    1 Goole在今年6月份出的新政策 不在使用safetynet 而使用Play Integrity API 2 项目本身没有使用过safetynet 3 使用了firebase 查阅资料 解决方案如下 implementation pla
  • Unity学习笔记(一)—— 基础知识

    一 基础知识 1 开发团队组成 2 unity特点 图形界面 所见即所得 入门简单 支持C 比OC C 更友好 js 国内外资源丰富 因为使用的人多 跨平台性好 PC端 移动端等 对VR AR的支持最完善 3 成功案例 游戏 炉石传说 神庙
  • unity后台加密时间锁

    前言 在做一些项目的时候 有些不良甲方在给完项目后会有不给尾款的情况 之前都是加一些水印啥的 感觉不是很方便 第一不美观 第二如果甲方给完尾款后还得重新打包去水印 然后又做过一个本地的时间锁 等到时间 程序直接退出 但是感觉还是不方便 有时
  • Unity打开工程时卡住的问题

    自从Unity升级了一个版本后 Unity打开工程卡住的问题越来越严重了 具体表现为 选择工程后 Unity窗口消失 但进程还在 有时候等个几分钟能出来 有时候等10分钟都不见得能出来 直观感受上看 似乎是Unity加载工程的时候某一步卡了
  • VLC for unity 插件如何使用

    VLC for unity 插件如何使用 先去下载一个VLC播放器 安装完成后 然后导入插件链接https download csdn net my 这个插件我的另一个上传资源里有 或者到商店去下载 这个插件链接下载完是一个txt文档 里面
  • Unity保存图片到相册

    Unity保存图片到Android相册 Java 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
  • unity实现鼠标右键控制视角

    主要实现的功能是相机跟随主角 鼠标右击移动后 相机的视角会旋转 思路 在主角里创建空的子物体 把相机绑在空物体上 通过旋转空物体来实现视角的旋转 要把相机调整到适当位置 代码如下 public float rotateSpeed 100 设
  • unity3d切换场景Application.LoadLevel(1)含义

    Application LoadLevel 1 场景ID
  • 【转载】【Unity】WebSocket通信

    1 前言 Unity客户端常用的与服务器通信的方式有socket http webSocket 本文主要实现一个简单的WebSocket通信案例 包含客户端 服务器 实现了两端的通信以及客户端向服务器发送关闭连接请求的功能 实现上没有使用U
  • 【Unity】运行时创建曲线(贝塞尔的运用)

    Unity 运行时创建线 贝塞尔的运用 1 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线 2 原理介绍 2 1 曲线的创建 unity建立网格曲线可以参考 Unity程序化网格体 的实现方法 主要分为顶点 三角面 U
  • Unity学习笔记

    一 旋转欧拉角 四元数 Vector3 rotate new Vector3 0 30 0 Quaternion quaternion Quaternion identity quaternion Quaternion Euler rota
  • 游戏开发常见操作系列之敌人系统的开发一(U3D)

    在开发游戏的过程中 我们常常会出现一些敌人攻击我们玩家 并且实现掉血以及死亡的现象 敌人还会源源不断地生成 这是怎么制作的呢 接下来为大家提供方法 其中使用了NGUI 后续会更新其它方法 敬请期待 使用HUDText实现扣血时显示文本 直接

随机推荐

  • 自动化测试高频面试题-90%可能会被问到

    Hello 你们的好朋友九九又又又来了 今天猜猜我给大家带来点啥干货呢 最近很多小伙伴出去面试的时候经常会被问到跟自动化测试相关的面试题 所以 今天九九特意给大家整理了一些经常被公司问到的自动化测试相关的面试题 停 咱先收藏起来好吗 别到时
  • js中过一段时间后终止while循环,防止死循环的方法

    今天发现了一个比较有趣的事 相信很多人遇到过写while循环时 在测试时很容易陷入死循环 导致要关闭页面再重启才能继续测试 那如果频繁调试 就每死循环一次就重启一次 很烦 所以想写一个到一定时间就终止循环的函数 刚开始用setTimeout
  • rhel8订阅注册激活

    先注册账号进行订阅 注册系统 https www howtoing com enable rhel subscription in rhel 8
  • JDK1.8的新特性(详细总结)

    目录 前言 一 jdk8简介 二 Lambda表达式语法 函数式接口 三 jdk8 内置四大核心函数接口 消费型接口 海王式接口 只知道索取 供给型接口 舔狗式接口 只知道付出 不索取回报的 函数型接口 双向奔赴 有输入有输出 断言型接口
  • C语言上机实验思路分享5

    实验内容 方法和步骤 1 编写一个函数 由实参传来一个整数n 将它各个位上的数字逆序输出 例如输入 123 输出为321 2 求方程ax 2 bx c O的根 用3个函数分别求当 b 2 4ac大于0 等于0和小于0时的根 并输出结果 从主
  • js使用AjaxFileupload插件实现文件上传

    最近做项目 需要上传表单元素中的文件POST到目标URL 并把得到的数据显示到本页面上 而不跳转到目标URL 那么 现在就要明确两件事 1 不能直接提交表单 因为一旦点击submit就会自动跳转到action界面 2 可以选择ajax进行异
  • Spring boot 整合 log4j2日志、程序异常,发送邮件通知

    官方文档 https logging apache org log4j 2 x 1 Maven修改如下
  • html 元素平滑滚动到某一位置

    在网上查了大半天 有人用高度算 然后setTimeout的 那个观感真的是差到家了 还有人说用 js动画库的 其实很简单 直接用window scrollTo 这个方法就完事了 回到顶部 window scrollTo top 0 beha
  • 【Java】5大排序算法总结(插入排序+希尔排序+选择排序+堆排序+冒泡排序)

    快速导航 1 稳定性 2 插入排序 3 希尔排序 4 选择排序 5 堆排序 6 冒泡排序 1 稳定性 两个相等的数据 如果经过排序后 排序算法能保证其相对位置不发生变化 则我们称该算法是具备稳定性的排序算法 图中排序后a仍然在b前面 此时这
  • Spring的两种代理方式:JDK动态代理和CGLIB动态代理

    代理模式 代理模式的英文叫做Proxy或Surrogate 中文都可译为 代理 所谓代理 就是一个人或者一个机构代表另一个人或者另一个机构采取行动 在一些情况下 一个客户不想或者不能够直接引用一个对象 而代理对象可以在客户端和目标对象之间起
  • Dalvik虚拟机简要介绍和学习计划

    通过修改 android framework base core jni AndroidRuntime cpp 中的 property get dalvik vm heapsize heapsizeOptsBuf 4 16m 来修改 dal
  • 电脑连接蓝牙耳机还是外放,输出设备只有扬声器怎么解决?

    1 问题描述 电脑连接蓝牙耳机耳机后 声音依然外放 输出设备只有扬声器 添加输出设备也找不到蓝牙耳机 2 排查问题 如果大家遇到的问题与我不同 还请查阅其他文章 右键计算机图标 gt 管理 gt 设备管理器 gt 声音 视频和游戏控制器 发
  • 神经网络应用: 手写数字识别(MNIST数据集)

    1 前言 本文使用 tensorflow 2 10 0 版本构建神经网络模型并进行训练 不同版本之间的 API 可能会有不同 请选择合适的版本学习 2 MNIST 数据集介绍 MNIST数据集 Mixed National Institut
  • 高性能计算(HPC)和智能计算理解

    1 现代终端设备一般都跟云端服务器相连 但只要可能 我们都希望计算可以在本地终端解决 这样做的好处是多方面的 既可以减小网络带宽的压力 又可以避免网络传输产生的时延 还可以让用户的数据更安全 现代终端设备一般用一个片上系统 SoC 做计算
  • Docker安装MinIO详细步骤

    本篇博客主要记录在Docker当中安装MinIO 目录 一 查看docker环境是否正常 二 下载minIO的镜像 三 创建minIO容器 四 访问地址 五 安装遇到问题 1 问题一 2 问题二 3 问题三 一 查看docker环境是否正常
  • Ubuntu18 04安装QQ

    Ubuntu18 04安装QQ Created time December 20 2022 5 12 PM Last edited time December 20 2022 6 15 PM Tags QQ Ubuntu18 04 截图工具
  • Flutter 第三方SDK集成(友盟统计,极光推送,百度地图)

    友盟统计 Flutter SDK集成 首先创建一个项目 接着去友盟工作台添加应用 添加成功后会得到AppKey 集成友盟 Flutter SDK 下载Demo Demo地址 https developer umeng com api sdk
  • Java实现多线程下载

    思路 1 基本思路是将文件分段切割 分段传输 分段保存 2 分段切割用到HttpUrlConnection对象的setRequestProperty Range bytes start end 方法 3 分段传输用到HttpUrlConne
  • 《面试准备》C++链表操作3(合并两个有序链表)

    include
  • Unity Shader入门精要第七章 基础纹理 单张纹理

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一 7 1单张纹理 参考 前言 纹理最初的目的就是使用一张图片来控制模型的外观 使用纹理映射 texture mapping 技 术 我们可以把一张图 黏 在模型表面 逐纹素