本文转载自http://blog.csdn.net/puppet_master/article/details/70199330?locationNum=2&fps=1

简介

千等万等终于等到了《耻辱2》打折,本以为可以爽一发了,然而各种出问题,先是steam下载速度奇慢无比,下了三天晚上好不容易下完的游戏,第一次打开给弹了个3D11CreateDeviceAndSwapChain Failed,折腾半天装了个补丁算是能打开游戏了,然而过完新手教学显卡驱动就崩了,崩了!崩了,连崩三回,差点想把坑爹的A卡从机箱掏出来顺着窗户扔出去,后来想想,为了楼下同学的生命安全,我还是忍了。好在AMD有专门为《耻辱2》R9380崩溃打了个补丁,算是拯救我于水火之中了。《耻辱2》用了ID Tech5衍生的Void引擎,看起来画面比《耻辱1》用的虚幻3好了不少。先来张帅帅哒截图,最近每天沉迷于杀杀杀,感觉自己好颓废:
一时间差点忘了自己是个程序员,差点变成游戏鉴赏博客,尴尬…下面步入正题,今天打游戏的时候路过了一个火炉,看到了火炉旁边的热空气扭曲的效果,感觉做的还是蛮逼真的,今天打算自己实现一发玩一玩:

实现原理

扭曲效果是游戏里面经常有的一个效果,说道扭曲效果,一般就是当前的画面发生了扭曲,在现实世界中一般是折射导致的,但是在图形学中,我们要模拟这种效果,原理就大不一样了。首先,我们并不会真正影响光线的传播,只是用uv的偏移来模拟扭曲的效果。有一种全屏的扭曲效果,这种是基于屏幕后处理的,可以参考前面的一篇文章屏幕水波纹效果,但是,往往我们并不希望全屏幕都发生扭曲,而是只希望某些地方发生了扭曲,比如上面的火炉的做法,拼关的同学肯定是希望在火炉的上方放一个特效片,就能够出扭曲的效果。那么,我们的这个片就需要是一个可以显示后面所有物体的片,换句话说,我们需要在这个面片上渲染面片后面所有的东西,这样,面片看起来就是透明的了。然后我们在采样uv的时候将uv进行偏移,就能够得到扭曲的效果了。恩,听起来很简单的样子,但是我们要怎么得到面片后面的所有东西呢?其实Unity已经为我们提供了这样的一个功能,GrabPass。下面看一下Grabpass的使用。

GrabPass

GrabPass是Unity为我们提供的一个很方便的功能,可以直接将当前屏幕内容渲染到一张贴图上,我们可以直接在shader中使用这张贴图而不用自己去实现渲染到贴图这样的一个过程,大大的方便了我们的shader编写。GrabPass的使用非常简单,我们在写vertex fragment shader的时候都需要写一个pass,GrabPass也是一个pass,只不过是Unity为我们实现好的一个pass。我们只需要在我们正常的Pass前面加一个GrabPass{}就可以了。
官方文档上有两种GrabPass的写法,第一种是直接GrabPass{}的写法,这种写法抓屏的图片就直接存到_GrabTexture这个系统预定义的贴图变量中了,我们可以直接访问该贴图,但是这种写法会导致每个使用GrabPass的物体进行一次这种旷日持久的抓屏操作!如果用这种shader的物体多了的话,想想就很可怕。另一种是GrabPass{"TextureName"}的写法,其中TextureName是我们自定义的一个贴图名称,这种写法,Unity每帧只会为第一个使用了该名称的物体进行抓屏操作,之后的就可以复用这张贴图了。所以,我们还是使用第二种方式更好一点。下面附上一份最简单的抓屏代码:
//Grabpass shader
//by: puppet_master
//2017.4.23
Shader "ApcShader/GrabPass"
{SubShader{ZWrite Off//GrabPassGrabPass{//此处给出一个抓屏贴图的名称,抓屏的贴图就可以通过这张贴图来获取,而且每一帧不管有多个物体使用了该shader,只会有一个进行抓屏操作//如果此处为空,则默认抓屏到_GrabTexture中,但是据说每个用了这个shader的都会进行一次抓屏!"_GrabTempTex"}Pass{Tags{ "RenderType" = "Transparent""Queue" = "Transparent+1"}CGPROGRAMsampler2D _GrabTempTex;float4 _GrabTempTex_ST;#include "UnityCG.cginc"struct v2f{float4 pos : SV_POSITION;float4 grabPos : TEXCOORD0;};v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);//计算抓屏的位置,其中主要是将坐标从(-1,1)转化到(0,1)空间并处理DX和GL纹理反向的问题o.grabPos = ComputeGrabScreenPos(o.pos);return o;}fixed4 frag(v2f i) : SV_Target{//根据抓屏位置采样Grab贴图,tex2Dproj等同于tex2D(grabPos.xy / grabPos.w)fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);return 1 - color;}#pragma vertex vert#pragma fragment fragENDCG}}
}

我们找个面片,附上这个shader的材质。为了更方便的看一下效果,我们就参照官网的写法,直接将最终输出的颜色反向,也就是1-原颜色作为输出(这个颜色不禁让我想起了宇智波鼬的月读……..)

看一下这个shader用到的几个函数,第一个是ComputeGrabScreenPos这个函数,我们从UnityCG.cginc中可以找到这个函数的实现:
inline float4 ComputeGrabScreenPos (float4 pos) { #if UNITY_UV_STARTS_AT_TOP float scale = -1.0; #else float scale = 1.0; #endif float4 o = pos * 0.5f; o.xy = float2(o.x, o.y*scale) + o.w;

#ifdef UNITY_SINGLE_PASS_STEREO o.xy = TransformStereoScreenSpaceTex(o.xy, pos.w); #endif o.zw = pos.zw; return o; }我们传递进来的参数是经过mvp变换后的顶点坐标,传入之后这个函数主要做了两件事情,第一个是处理DX和OpenGL纹理坐标差异导致的问题,这个 之前的文章有记录过。第二件事主要就是将转化到标准裁剪空间(-1,1)区间的顶点转化到(0,1)区间。按照Unity的写法,本人推测,这个GrabPass获取的屏幕贴图应该是基于视空间的,而在这个信息传递到fragment shader后,用了tex2Dproj函数进行采样,tex2Dproj(i.xy)应该等同于tex2D(i.xy/i.w),也就是说这个采样点坐标进行了一次投影变换。

扭曲效果的实现

准备工作完成,下面步入正题,来看看扭曲效果的实现。首先,要扭曲,就肯定要动,这个shader还是得需要Time系列的变量进行驱动。不过这只是其中一个条件,由于shader是高度并行化的计算,我们没有办法区分每个像素到底需要偏移多少。在屏幕水波纹效果中,我们是通过计算当前像素点到屏幕中心位置的距离作为偏移值的,对于后处理这样做可能比较方便,但是对于普通物体上使用的shader就没有那么简单了。比如,我们同样是让采样坐标按照sin值进行偏移:
fixed4 frag(v2f i) : SV_Target{i.grabPos.x += _DistortStrength * sin(_Time.y * 10);i.grabPos.y += _DistortStrength * sin(_Time.y);fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);return 1 - color;}

那么所有的顶点就都会按照一致的方向进行偏移:

为了让偏移变得随机,我们就要引入一个能够随机化输出的东东,也就是噪声图。比如我们找到了一张这个样子的噪声图:
然后,只需要用一个连续变化的值去采这个噪声图,就可以得到不连续的随机输出偏移值。下面附上扭曲效果的实现:
//Distort shader
//by: puppet_master
//2017.4.24
Shader "ApcShader/Distort"
{Properties{_DistortStrength("DistortStrength", Range(0,1)) = 0.2_DistortTimeFactor("DistortTimeFactor", Range(0,1)) = 1_NoiseTex("NoiseTexture", 2D) = "white" {}}SubShader{ZWrite OffCull Off//GrabPassGrabPass{//此处给出一个抓屏贴图的名称,抓屏的贴图就可以通过这张贴图来获取,而且每一帧不管有多个物体使用了该shader,只会有一个进行抓屏操作//如果此处为空,则默认抓屏到_GrabTexture中,但是据说每个用了这个shader的都会进行一次抓屏!"_GrabTempTex"}Pass{Tags{ "RenderType" = "Transparent""Queue" = "Transparent + 100"}CGPROGRAMsampler2D _GrabTempTex;float4 _GrabTempTex_ST;sampler2D _NoiseTex;float4 _NoiseTex_ST;float _DistortStrength;float _DistortTimeFactor;#include "UnityCG.cginc"struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float4 grabPos : TEXCOORD1;};v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.grabPos = ComputeGrabScreenPos(o.pos);o.uv = TRANSFORM_TEX(v.texcoord, _NoiseTex);return o;}fixed4 frag(v2f i) : SV_Target{//首先采样噪声图,采样的uv值随着时间连续变换,而输出一个噪声图中的随机值,乘以一个扭曲快慢系数float4 offset = tex2D(_NoiseTex, i.uv - _Time.xy * _DistortTimeFactor);//用采样的噪声图输出作为下次采样Grab图的偏移值,此处乘以一个扭曲力度的系数i.grabPos.xy -= offset.xy * _DistortStrength;//uv偏移后去采样贴图即可得到扭曲的效果fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);return color;}#pragma vertex vert#pragma fragment fragENDCG}}
}
为了更加应景,我搜刮了一下我的资源库,找到了一个火把,2333:
然后在火把附近放一个面片,用上我们的扭曲shader:
最终效果如下图所示:

基于后处理的优化效果

GrabPass非常耗时,在安卓平台也会有问题,虽然对于安卓机的性能,用shader lod直接干掉扭曲效果也是一个不错的选择,不过这个毕竟是下策,首先还是要解决这个问题。正常渲染是往frame buffer中渲染,但是grabpass应该是从当前的frame buffer中将内容再读出来,从显存往内存中拷贝,应该是一个阻塞的过程,我记得之前一帧渲染过3000ms,简直可怕。PS:这种情况在两个(或多个)相机渲染,后面的相机没有Clear并且在后面的相机上挂了后处理的时候也会出现这种情况,猜测原因也是因为在后面的相机进行后处理时需要上一个相机的内容,然而这个东东已经在frame buffer中了,所以后处理如果要在上层相机运用,最好还是慎重考虑一下。关于用后处理卡的问题,这篇文章解释得很好。文章中给了几种解决方案,一种是关抗锯齿,一个是用GL3.0,最后一个是直接改为用渲染到纹理。记得以前还看过一个帖子,不过忘记链接了,这个做法比较极端,就是最终渲染的结果都不走frame buffer,而是都渲染到一个纹理上。然后所有的后处理都在这个纹理上进行,完全绕开了OnRenderImage。额,不小心扯远了,只是希望能给和我遇到一样问题的倒霉蛋一点参考,下面进行正题。
既然GrabPass比较费,那么最简单的,我们可能会想直接用另外一个相机去渲染这个场景到一个RenderTarget上,然后用这个RenderTarget代替我们上面用的GrabTexture。不过这种做法会导致DrawCall翻倍,如果我们的场景中内容较少,比较适合用这种方法。或者我们可以设置另一个相机的层级,使之只渲染某些内容,这样也可以降低一些开销。不过这里就不用这种方式了。之前看到了一篇文章,作者给了这样的一个思路,感觉非常巧妙。简而言之,这个方法作扭曲的部分是用全屏后处理进行的,但是全屏都扭曲了,我们其实只需要扭曲一部分地方,所以我们需要一个Mask图来控制,而这张Mask图我们就可以直接用另一个相机渲染出来,其实就是我们上面用到的特效片,渲染到一个RT上就可以了。相比于用另一个摄像机把场景中的东西都渲染一遍,这种方式只是需要额外渲染一个片外加一次全屏后处理操作,两者各有千秋,视具体情况而定。
我们先写一个全屏扭曲的shader,首先,需要后处理,我们继承这个已经用了无数次的PostEffectBase类,实现后处理的C#部分代码:
/********************************************************************FileName: DistortEffect.csDescription: 屏幕扭曲效果Created: 2017/04/27by: puppet_master
*********************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DistortEffect : PostEffectBase {//扭曲的时间系数[Range(0.0f, 1.0f)]public float DistortTimeFactor = 0.15f;//扭曲的强度[Range(0.0f, 0.2f)]public float DistortStrength = 0.01f;//噪声图public Texture NoiseTexture = null;public void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){_Material.SetTexture("_NoiseTex", NoiseTexture);_Material.SetFloat("_DistortTimeFactor", DistortTimeFactor);_Material.SetFloat("_DistortStrength", DistortStrength);Graphics.Blit(source, destination, _Material);}else{Graphics.Blit(source, destination);}}
}

然后shader部分,扭曲的原理与上面一样,只是处理的对象变了一下,直接处理OnRenderImage传来的MainTex即可:

//全屏幕扭曲Shader
//by:puppet_master
//2017.4.28Shader "Custom/DistortPostEffect"
{Properties{_MainTex("Base (RGB)", 2D) = "white" {}_NoiseTex("Base (RGB)", 2D) = "black" {}//默认给黑色,也就是不会偏移}CGINCLUDE#include "UnityCG.cginc"uniform sampler2D _MainTex;uniform sampler2D _NoiseTex;uniform float _DistortTimeFactor;uniform float _DistortStrength;fixed4 frag(v2f_img i) : SV_Target{//根据时间改变采样噪声图获得随机的输出float4 noise = tex2D(_NoiseTex, i.uv - _Time.xy * _DistortTimeFactor);//以随机的输出*控制系数得到偏移值float2 offset = noise.xy * _DistortStrength;//像素采样时偏移offsetfloat2 uv = offset + i.uv;return tex2D(_MainTex, uv);}ENDCGSubShader{Pass{ZTest AlwaysCull OffZWrite OffFog{ Mode off }CGPROGRAM#pragma vertex vert_img#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest ENDCG}}Fallback off
}
这样,整个屏幕就都扭曲了,动图如下(赶脚好像来到了沙漠一样…..):
这里我把扭曲的强度设置得高一些,感觉也可以直接当一些全屏后处理的样子,比如扭曲,水幕效果:
我们有了全屏的扭曲效果之后,下面我们考虑要怎么把需要扭曲的部分抠出来。那么,第一个想到的就是Mask图,我们可以给一个Mask图,作为权重,白色为需要偏移的权重,黑色为无偏移的权重,这样,我们就可以控制哪个地方需要扭曲。但是,这里,我们的Mask图需要是一个动态的Mask图,因为相机会移动,所以,我们需要实时地生成这张Mask图。在描边效果这篇文章中,我们用过类似的方法。这里,我们故技重施,将需要扭曲的部分,也就是上面我们用的面片渲染到一张RenderTarget上,首先,我们还是创建一个新的摄像机,然后通过在OnPreRender函数中用RenderWithShader,将面片渲染到一张RT上(这个RT可以多降低一些分辨率),渲染的shader就用一个纯白色的shader就可以了。比如下面的这个Shader:
//Mask图生成shader
//by:puppet_master
//2017.5.3Shader "ApcShader/MaskObjPrepass"
{//子着色器  SubShader{Pass{   Cull OffCGPROGRAM#include "UnityCG.cginc"struct v2f{float4 pos : SV_POSITION;};v2f vert(appdata_full v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);return o;}fixed4 frag(v2f i) : SV_Target{//这个Pass直接输出颜色return fixed4(1,1,1,1);}//使用vert函数和frag函数#pragma vertex vert#pragma fragment fragENDCG}}
}

下面附上扭曲效果的C#脚本:
/********************************************************************FileName: DistortEffect.csDescription: 屏幕扭曲效果Created: 2017/04/27by: puppet_master
*********************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DistortEffect : PostEffectBase {//扭曲的时间系数[Range(0.0f, 1.0f)]public float DistortTimeFactor = 0.15f;//扭曲的强度[Range(0.0f, 0.2f)]public float DistortStrength = 0.01f;//噪声图public Texture NoiseTexture = null;//渲染Mask图所用的shaderpublic Shader maskObjShader = null;//降采样系数public int downSample = 4;private Camera mainCam = null;private Camera additionalCam = null;private RenderTexture renderTexture = null;public void OnRenderImage(RenderTexture source, RenderTexture destination){if (_Material){_Material.SetTexture("_NoiseTex", NoiseTexture);_Material.SetFloat("_DistortTimeFactor", DistortTimeFactor);_Material.SetFloat("_DistortStrength", DistortStrength);_Material.SetTexture("_MaskTex", renderTexture);Graphics.Blit(source, destination, _Material);}else{Graphics.Blit(source, destination);}}void Awake(){//创建一个和当前相机一致的相机InitAdditionalCam();}private void InitAdditionalCam(){mainCam = GetComponent<Camera>();if (mainCam == null)return;Transform addCamTransform = transform.FindChild("additionalDistortCam");if (addCamTransform != null)DestroyImmediate(addCamTransform.gameObject);GameObject additionalCamObj = new GameObject("additionalDistortCam");additionalCam = additionalCamObj.AddComponent<Camera>();SetAdditionalCam();}private void SetAdditionalCam(){if (additionalCam){additionalCam.transform.parent = mainCam.transform;additionalCam.transform.localPosition = Vector3.zero;additionalCam.transform.localRotation = Quaternion.identity;additionalCam.transform.localScale = Vector3.one;additionalCam.farClipPlane = mainCam.farClipPlane;additionalCam.nearClipPlane = mainCam.nearClipPlane;additionalCam.fieldOfView = mainCam.fieldOfView;additionalCam.backgroundColor = Color.clear;additionalCam.clearFlags = CameraClearFlags.Color;additionalCam.cullingMask = 1 << LayerMask.NameToLayer("Distort");additionalCam.depth = -999;//分辨率可以低一些if (renderTexture == null)renderTexture = RenderTexture.GetTemporary(Screen.width >> downSample, Screen.height >> downSample, 0);}}void OnEnable(){SetAdditionalCam();additionalCam.enabled = true;}void OnDisable(){additionalCam.enabled = false;}void OnDestroy(){if (renderTexture){RenderTexture.ReleaseTemporary(renderTexture);}DestroyImmediate(additionalCam.gameObject);}//在真正渲染前的回调,此处渲染Mask遮罩图void OnPreRender(){//maskObjShader进行渲染if (additionalCam.enabled){additionalCam.targetTexture = renderTexture;additionalCam.RenderWithShader(maskObjShader, "");}}
}

还是上面的测试场景,我们将面片改为Distort层级,然后可以直接给这个面片设置一个透明的材质,比如最简单的粒子的shader,让它正常渲染不可见即可:

通过上面的脚本,我们临时将这个Mask图输出到屏幕上(为了性能好一些,降采样比较多,已经有锯齿了,不过在正式使用的时候是看不出来的):
有了Mask图,我们就可以根据Mask图的权重进行修改了,白色的地方是需要扭曲的,黑色的地方不需要扭曲,我们将上面的shader中的offest用这个mask采样图进行修正就能够得到最终的扭曲效果了。后处理版本的shader如下:
//全屏幕扭曲Shader
//by:puppet_master
//2017.5.3Shader "Custom/DistortPostEffect"
{Properties{_MainTex("Base (RGB)", 2D) = "white" {}_NoiseTex("Noise", 2D) = "black" {}//默认给黑色,也就是不会偏移_MaskTex("Mask", 2D) = "black" {}//默认给黑色,权重为0}CGINCLUDE#include "UnityCG.cginc"uniform sampler2D _MainTex;uniform sampler2D _NoiseTex;uniform sampler2D _MaskTex;uniform float _DistortTimeFactor;uniform float _DistortStrength;fixed4 frag(v2f_img i) : SV_Target{//根据时间改变采样噪声图获得随机的输出float4 noise = tex2D(_NoiseTex, i.uv - _Time.xy * _DistortTimeFactor);//以随机的输出*控制系数得到偏移值float2 offset = noise.xy * _DistortStrength;//采样Mask图获得权重信息fixed4 factor = tex2D(_MaskTex, i.uv);//像素采样时偏移offset,用Mask权重进行修改float2 uv = offset * factor.r + i.uv;return tex2D(_MainTex, uv);}ENDCGSubShader{Pass{ZTest AlwaysCull OffZWrite OffFog{ Mode off }CGPROGRAM#pragma vertex vert_img#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest ENDCG}}Fallback off
}

扭曲效果动态图如下:

通过后处理制作的热空气扭曲效果与GrabPass的效果大致相同,虽然多了全屏后处理操作,但是能够避免安卓机上GrabPass读帧缓存卡死的问题,而且也不需要DrawCall翻倍,对于复杂的场景来说相对效率更高一些。如果场景比较简单,也可以使用另一个相机渲染场景到RT上的方法进行制作。

unityShader热空气扭曲效果相关推荐

  1. 10.热空气扭曲效果

    Shader "Study/10_Distortion" {Properties{_NoiseTex("絮乱图", 2D) = "white" ...

  2. Unity Shader-热空气扭曲效果(多种实现方案,包括移动平台)

    原文地址:https://blog.csdn.net/puppet_master/article/details/70199330 简介 千等万等终于等到了<耻辱2>打折,本以为可以爽一发 ...

  3. [UnityShader3]热扭曲效果

    参考链接:http://blog.sina.com.cn/s/blog_89d90b7c0102vaqy.html 1.首先回顾一下透明度混合的实现.在片段着色器输出源颜色后,经过Blend后与目标颜 ...

  4. Python实现PS滤镜Fish lens图像扭曲效果示例

    Python实现PS滤镜Fish lens图像扭曲效果 这篇文章主要介绍了Python实现PS滤镜Fish lens图像扭曲效果,结合实例形式分析了Python实现PS滤镜的图像扭曲效果相关操作技巧 ...

  5. android 下拉窗帘,Android 窗帘(Curtain)效果二之波浪式动态扭曲效果

    上一篇文章已经实现了如何把一张图片扭曲成波浪效果,那么这一篇文章我们介绍如何动态调整系数,去改变波浪图片的皱褶成度.我们自一次观察下图morning routine的效果: 仔细观察我们发现,当往右滑 ...

  6. python 艺术照片滤镜_Python实现PS滤镜Fish lens图像扭曲效果示例

    本文实例讲述了Python实现PS滤镜Fish lens图像扭曲效果.分享给大家供大家参考,具体如下: 这里实现 PS 滤镜中的一种几何变换– Fish lens, 对图像做扭曲,感觉就像通过一个凸镜 ...

  7. psql屏幕输出全部结果_CommandBuffer实现Distort屏幕扭曲效果

    现在的游戏中很多特效都喜欢用到扭曲效果,常见的实现方案都是在Shader中使用GrabPass,来获取屏幕的画面然后去做计算.关于获取屏幕画面的几种方案的性能分析可以参考我上篇文章. idleworm ...

  8. 扭曲效果 效率优化 GrapPass,CommandBuffer对比

    屏幕图像捕捉: Shader的GrabPass GrabPass可以很方便地捕获当前渲染时刻的FrameBuffer中的图像. 其原理就是从当前FrameBuffer中copy一份纹理,通过SetTe ...

  9. python 画三角形matli_Python实现PS滤镜特效Marble Filter玻璃条纹扭曲效果示例

    本文实例讲述了Python实现PS滤镜特效Marble Filter玻璃条纹扭曲效果.分享给大家供大家参考,具体如下: 这里用 Python 实现 PS 滤镜特效,Marble Filter, 这种滤 ...

最新文章

  1. MVP模式在Android实际项目中的应用和优化
  2. 如何做618数据复盘?你需要掌握这8大思路
  3. tensowflow 训练 远程提交_深度解析AutoML工具——NNI:带上超参一起训练
  4. 【树莓派】树莓派SD卡系统镜像系统备份方法
  5. 【Spring】Spring第一天 - 环境搭建、IoC 详解、DI 详解等
  6. MySQL查询数据字典_存储过程_函数_视图元数据_表元数据_触发器
  7. 如何使用Elasticsearch,Logstash和Kibana实时可视化Python中的日志
  8. 国外著名java技术资料网站
  9. Aspose.Cells Smart markers 基于模板导出Excel
  10. 英特尔预计第12代酷睿H系列处理器将有超过100款设备采用
  11. 在JAVA中把JSON数据格式化输出到控制台
  12. 中国开源激荡 20 年:IT 江湖,谁主沉浮?
  13. leetcode(二)—— Add Two Numbers(Python/C++)
  14. 20135337——信息安全设计基础第十四周学习笔记
  15. Cap01_信息化和信息系统
  16. 吴恩达机器学习课程笔记
  17. 皮克公式(格点多边形内点的个数)
  18. 海栎创原厂HAA9806和HAA9806-R连续10W输出功率的单声道音频功率放大器
  19. Android eclipse常见错误开发总结
  20. Vivado使用技巧(1):综合策略与设置的选择

热门文章

  1. 大漠沙盘sandboxie游戏多开易语言大漠后台绑定的实现
  2. Alcohol 120%刻录教程:制作镜像文件
  3. 论VI设计的基础部分和应用部分
  4. 斌酱归档---C语言实现Linux cp命令
  5. python科学计算库numpy和绘图库PIL的结合,素描图片(原创)
  6. mysql 无限层级传销_直销几个层级是传销
  7. 淘宝店铺如何找关键词、如何筛选关键词
  8. 看懂数据分析图表的十个基本方法(上)
  9. Springboot项目自动打包部署插件 (wagon-maven-plugin)
  10. vue路由无痕浏览nodeJS环境搭建ElementUI简介