文章目录

  • ddx, ddy 说明
    • DirectX - ddx, ddy
    • OpenGL - dFdx, dFdy
    • 伪代码表示
  • 可用它来做什么
    • 简单的边缘突出应用
      • Shader
      • 边缘突出-锐化-增加差值
      • 边缘突出-增加亮度
    • 高度生成法线应用
      • 准备一张高度图
      • Shader
      • 整体运行效果
    • Flat Shading 应用
      • Shader
      • 运行效果
  • 用于优化
  • Project
  • References

ddx, ddy 说明

这两条指令用于对指定的寄存器,求其值在临近像素上的变化率,因为纹理坐标的梯度可以用来确定纹理当前被缩放的程度,可用该值来计算Mip层,另外它也可以用来计算Texel的跨越Size,由此求得正确的过滤宽度,从而纠正通常的线性过滤在远处由于过滤宽度错误而产生的失真。


DirectX - ddx, ddy

参考:hlsl函数 ddx ddy

  • HLSL叫:HLSL ddx、HLSL ddy - 这部分文档没有详细的将,会让人一头雾水
  • 想要更好了解 ddx, ddy 的原理,可以查看,dxbc 中的
    • deriv_rtx (sm4 - asm)
    • deriv_rty (sm4 - asm)

下面是以 ddx 的 : derive_rtx 的 dxbc api 文档说明为例(derive_rty 基本上是一样的说明)

ddx(x), ddy(y)
// 其中x,y都是screen space x,y

OpenGL - dFdx, dFdy

GLSL叫:

dFdx(x), dFdy(y)

参考:An introduction to shader derivative functions - 有讲到 ddx, ddy 的计算原理,下面引用的是原文

Derivatives computation
During triangles rasterization, GPUs run many instances of a fragment shader at a time organizing them in blocks of 2×2 pixels. Derivatives are calculated by taking differences between the pixel values in a block; dFdx subtracts the values of the pixels on the left side of the block from the values on the right side, and dFdy subtracts the values of the bottom pixels from the top ones. See the image below where the grid represents the rendered screen pixels and dFdx, dFdy expressions are provided for the generic value p evaluated by the fragment shader instance at (x, y) screen coordinates and belonging to the 2×2 block highlighted in red.

翻译成中文就是:

偏导计算
在三角形光栅化是,GPU 都是以 2x2 的 block 片段来计算光栅化的。偏导计算于是由这block之间的片段的值来计算的;dFdx 计算并返回的是右边的片段减去左边的片段的值,而 dFdy 是有上减去下的值。查看下图的格式显示的就是 红色高亮的 2x2 block 中对应的 (x, y) 屏幕坐标上的片段。

(虽然这里说的是 2x2 block 的 fragment 来渲染,但,如果我们的几何体比较小、或是离镜头很远,那么光栅化是得出的片段很小的话,小到什么程度,刚好就是 1 pixel,就一个像素(一个片段),那这种算法来处理的话肯定是没法计算 ddx, ddy 的内容的,除非说,使用类似 AA(Anti Aliasing 坑锯齿方式)x2 的方式,实际渲染数据的分辨率大小是原来的 宽高的一赔,那么光栅出来的原本一个 片段,那么 AA x2之后,原本 1 pixel 大小的片段就变成了 2x2 大小的栅格块,那么就可以计算 ddx, ddy 了,如果小于 2x2 的就不用渲染下去了,因为AA x2之后的片段都不足以 2x2 block pixels 的话,那么正常(就是不AA情况下)情况下,可能连一个像素的大小都没有,所以可以直接跳过不处理,这应该是渲染管线中几何应用阶段后,光栅化阶段前的剔除过滤了)

要注意的是,不论HLSL还是GLSL中,偏导函数都只能在fragment shader阶段处理,因为它是求不同 fragment 的 val 差值


伪代码表示

// jave.lin 2021/11/30 - 后续补充的伪代码说明
// 在 fragment block (2x2) 光栅化后,得到的 fragment(片段)后的 shader 计算过程中的对应 寄存器 的值的差值
// ddx(val) = frag(x+1,y).val - frag(x,y).val; // 从右减左
// ddy(val) = frag(x,y-1).val - frag(x,y).val; // 从上减下// =================
// jave.lin :
// 下面只是伪代码,只是意思意思的表达,真正的实现不一定是这样的
// 有可能还真的就是标记某个 fragment shader 的方法体对应的指令集
// 打个标记,然后将这个带上标记的数据在:2x2 block 的 frags 中做差值
// =================// data type
const int INT_T_1       = 1;
const int FLOAT_T_1     = 2;
const int INT_T_2       = 3;
const int FLOAT_T_2     = 4;
const int INT_T_3       = 5;
const int FLOAT_T_3     = 6;
const int INT_T_4       = 7;
const int FLOAT_T_4     = 8;// addValT 是 偏导采样数据记录
struct ddValT
{int type; // 对应上面的 data type 常量枚举char* data;
};// 单个片段的数据
struct FragInfo
{vector<ddValT*> ddValDatas;short sx, sy; // screen x, y
} frags;// 所有片段的二维数据
FragInfo[][] frags;// 当前 片段的数据
FragInfo* curFrag;// FragShader
struct FragShader
{// 当前 上下文记录的 ddx, ddy 的索引int _curDDX_IDX;int _curDDY_IDY;void* __Func_Address__;void Reset(){_curDDX_IDX = 0;_curDDY_IDY = 0;}void Run(FragInfo* frag){__Func_Address(frag);}
};void DrawCall()
{...// 当前使用的 fragment shaderauto& fragShader = ...;for (auto& frag : frags){// 在上下文执行之前,先清除 ddx, ddy 的数据frag.ddValDatas.clear();fragShader.Reset();fragShader.Run(frag);}...
}// RetT : 返回的数据类型
// ArgT : 参数的数据类型
// curFrag : 当前上下文片段信息类型
// frags: 当前上下文中所有片段的二维集合
RetT ddx(ArgT* val)
{FragShader& __context_cur_frag = ...;int dd_idx = __context_cur_frag._curDDX_IDX++;rightFrag.ddValDatas[dd_idx] = val;barrier(); // 先等所有的 ddx, ddy 都同步添加到 ddValDatasint rx = curFrag.x + 1, ry = curFrag.y;FragInfo* rightFrag = frags[rx][ry];ddValT* dd_data = rightFrag.ddValDatas[dd_idx];switch (dd_data->type){case INT_T_1:{int* rval = (int*)dd_data->data;return *rval - *(int*)(val);}case FLOAT_T_1:{float* rval = (float*)dd_data->data;return *rval - *(float*)(val);}case INT_T_2:{int2* rval = (int2*)dd_data->data;return *rval - *(int2*)(val);}case FLOAT_T_2:{float2* rval = (float2*)dd_data->data;return *rval - *(float2*)(val);}case INT_T_3:{int3* rval = (int3*)dd_data->data;return *rval - *(int3*)(val);}case FLOAT_T_3:{float3* rval = (float3*)dd_data->data;return *rval - *(float3*)(val);}case INT_T_4:{int4* rval = (int4*)dd_data->data;return *rval - *(int4*)(val);}case FLOAT_T_4:{float4* rval = (float4*)dd_data->data;return *rval - *(float4*)(val);}default:throw Error("xxx");}
}// ddy 类似上面,就不写了

可用它来做什么


简单的边缘突出应用

在下面Project提供的源Unity工程的 Sharpen.unity 场景


Shader

// jave.lin 2019.07.02
Shader "Test/TestDDX&Tex"
{Properties{[KeywordEnum(IncreaseEdgeAdj, BrightEdgeAdj)] _EADJ("Edge Adj type", Float) = 0_Tex("Tex", 2D) = "white" {}_Intensity("Intensity", Range(0, 20)) = 2}SubShader{Pass{Tags { "RenderType"="Opaque" }Cull offBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile _EADJ_INCREASEEDGEADJ _EADJ_BRIGHTEDGEADJ#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _Tex;float4 _Tex_ST;float _Intensity;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _Tex);return o;}fixed4 frag (v2f i, float f : VFACE) : SV_Target{fixed a = 1;if (f < 0) a = 0.5;fixed3 c = tex2D(_Tex, i.uv).rgb;#if _EADJ_INCREASEEDGEADJ // 边缘调整:增加边缘差异调整// 类似两个3x3的卷积核处理/*one:| 0| 0| 0|| 0|-1| 1|| 0| 0| 0|two:| 0| 0| 0|| 0|-1| 0|| 0| 1| 0|*///使用(ddx(c) + ddy(c)),没有绝对值,会然边缘的像素亮度差异变大,即:加强边缘突出c += (ddx(c) + ddy(c)) * _Intensity;#else //_EADJ_BRIGHTEDGEADJ // 边缘调整:增加边缘亮度调整//c += abs(ddx(c)) + abs(ddy(c)) *_Intensity;c += fwidth(c) * _Intensity; // fwidth(c) ==> abs(ddx(c)) + abs(ddy(c))//使用fwidth函数,可以看出,会是边缘变亮,突出边缘// fwidth func in HLSL: https://docs.microsoft.com/zh-cn/windows/desktop/direct3dhlsl/dx-graphics-hlsl-fwidth#endif // end _EADJ_INCREASEEDGEADJreturn fixed4(c, a);}ENDCG}}
}

在shader中,可以看到有两种方法,对应材质Inspector中的两个选项

IncreaseEdgeAdj=边缘突出-锐化-增加差值;BrightEdgeAdj=边缘突出-增加亮度

边缘突出-锐化-增加差值


使用(ddx(c ) + ddy(c )),没有绝对值,会然边缘的像素亮度差异变大,即:加强边缘突出

边缘突出-增加亮度


fwidth(c ) ==> abs(ddx(c )) + abs(ddy(c ))
使用fwidth函数,可以看出,会是边缘变亮,突出边缘


高度生成法线应用

高度图,法线图,都是属于凹凸图的其一

在下面Project提供的源Unity工程的 HeightMap.unity 场景


准备一张高度图

高度图博文

用PS或是GIMP随便画一个黑白的高度图就好了,注意我们的画笔需要设置成软笔刷,这样才会有渐变过渡,不然笔刷太硬,没啥过渡的灰度,那么shader渲染出来的法线角度太陡,就不太容易观察法线对光影的影响。

图片导出jpg就好了,不需要alpha,因为我们shader只要一个通道的值就好R通道。

如下图,我们用GIMP制图

导出到Unity中,再设置一下不需要alpha source,如下图

在导出来的jpg我们可以看到只有黑白

黑色表示没有越是接近黑色,说明高度越低,全黑,说明完全没有高度值影响
反之,白色说明就是有高度。

我们调整表面法线就就是用这些相邻像素的高度差异作为影响当前法线的水平、垂直(法线:xy)的因数,即可调整法线。

如果调整法线,如下图:


Shader

// jave.lin 2019.07.02
Shader "Test/TestDDX&HeightMap"
{Properties{[KeywordEnum(LMRTMB,CMRCML,NAVDDXPOSDDY)] _S ("Sample Type", Float) = 0_Color("Main Color", Color) = (1,1,1,1)_MainTex("Main Tex", 2D) = "white" {}_HightMap("Hight Map", 2D) = "white" {}_Intensity("Intensity", Range(0, 20)) = 5_SpecuarlIntensity("Specular Intensity", Range(0, 100)) = 80_SpecuarlStrengthen("Specular Strengthen", Range(0, 1)) = 0.5}SubShader{Tags { "Queue"="Transparent" }Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile _S_LMRTMB _S_CMRCML _S_NAVDDXPOSDDY#include "UnityCG.cginc"#include "Lighting.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;float4 tangent : TANGENT;};struct v2f{float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float3 lightDir : TEXCOORD1;float3 viewDir : TEXCOORD2;float3 normal : TEXCOORD3;};fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;sampler2D _HightMap;float4 _HightMap_TexelSize; // 1/w, 1/h, w, hfloat _Intensity;float _SpecuarlIntensity;float _SpecuarlStrengthen;inline float3x3 getTBN (inout float3 normal, float4 tangent) {float3 wNormal = UnityObjectToWorldNormal(normal);           // 将法线从对象空间转换到世界空间float3 wTangent = UnityObjectToWorldDir(tangent.xyz);        // 将切线从对象空间转换到世界空间float3 wBitangent = normalize(cross(wNormal, wTangent)); // 根据世界空间下的法线,切线,叉乘算出世界空间下的副切线normal = wNormal;return float3x3(wTangent, wBitangent, wNormal);               // 根据世界空间下的法线,切线,副切线,组合成TBN,可将切线空间下的法线转换到世界空间下}v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);float3x3 tbn = getTBN(v.normal, v.tangent);// w2t or t2w可以参考我之前写的:Unity Shader - 切线空间的法线贴图应用(T2W & W2T)// https://blog.csdn.net/linjf520/article/details/94165872o.lightDir = mul(tbn, normalize(_WorldSpaceLightPos0.xyz)); // w2t : world to tangent spaceo.viewDir = mul(tbn, normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex))); // w2t : world to tangent spaceo.normal = mul(tbn, v.normal); // w2t : world to tangent spacereturn o;}fixed4 frag (v2f i) : SV_Target{fixed4 c = tex2D(_MainTex, i.uv);// 三种采样方式:本质方法是一样的,类似两个3x3的卷积核处理#if _S_LMRTMB/*one:| 0| 0| 0||-1| 0| 1|| 0| 0| 0|two:| 0|-1| 0|| 0| 0| 0|| 0| 1| 0|*/// 这种方式是参考:Unity Shader-法线贴图(Normal)及其原理// https://blog.csdn.net/puppet_master/article/details/53591167float offsetU = tex2D(_HightMap, i.uv + _HightMap_TexelSize * float2(-1, 0)).r - tex2D(_HightMap, i.uv + _HightMap_TexelSize * float2(1, 0)).r;float offsetV = tex2D(_HightMap, i.uv + _HightMap_TexelSize * float2(0, 1)).r - tex2D(_HightMap, i.uv + _HightMap_TexelSize * float2(0, -1)).r;#elif _S_CMRCML/*one:| 0| 0| 0|| 0| 1|-1|| 0| 0| 0|two:| 0|-1| 0|| 0| 1| 0|| 0| 0| 0|*/fixed cr = tex2D(_HightMap, i.uv).r;float offsetU = (cr - tex2D(_HightMap, i.uv + _HightMap_TexelSize * float2(1, 0)).r) * _Intensity;float offsetV = (cr - tex2D(_HightMap, i.uv + _HightMap_TexelSize * float2(0, -1)).r) * _Intensity;#else // _S_NAVDDXPOSDDY/*one:| 0| 0| 0|| 0|-1| 1|| 0| 0| 0|two:| 0| 0| 0|| 0|-1| 0|| 0| 1| 0|*/fixed h = tex2D(_HightMap, i.uv).r;float offsetU = -ddx(h); // 右边像素采样 - 当前像素采样 = U的斜率,这里我们取反向,因为我们需要的是当前-右边的值,而ddx是固定的right-cur,所以我们只能取反float offsetV = ddy(h); // 下边像素采样 - 当前像素采样 = V的斜率,这里我们不用取反向,斜率方向刚刚好是我们需要的#endif // end _S_LMRTMB// 调整tangent space normalfloat3 n = normalize(i.normal.xyz + float3(offsetU, offsetV, 0) * _Intensity);// 为了测试法线,添加了diffuse与specular的光照因数// diffusefloat ldn = dot(i.lightDir, n) * 0.5 + 0.5;fixed3 diffuse = _LightColor0.rgb * _Color * ldn * c.rgb * tex2D(_MainTex, i.uv);// specularfloat3 halfAngle = normalize(i.lightDir + i.viewDir);float3 hdn = max(0, dot(halfAngle, n));fixed3 specular = _LightColor0.rgb * _Color * pow(hdn, 100 - _SpecuarlIntensity) * _SpecuarlStrengthen;fixed3 combined = diffuse + specular;return fixed4(combined, 1);}ENDCG}}
}

其中有三种算法方式,前两种基本一样,支持采样坐标不太一样,最后一种就是使用偏导函数DDX,DDY来处理的


整体运行效果

还有三种不同算法的使用

采样质量从高到底(对应选项从上到下),最后一种就是DDX,DDY

无论用的是那种方式,我们都是采用高度图中相邻像素的灰度值(这里我们用R通道当灰度值,因为只有黑白,无所谓)相减,得到的差值我们当做是:当前像素就临近像素的高度斜率,然后用这个斜率调整对应水平、垂直的,法线:xy值。


Flat Shading 应用

在下面Project提供的源Unity工程的 ShowTBN.unity 场景


Shader

// jave.lin 2019.07.02
Shader "Test/TestDDX&TBN"
{Properties{_HightMap("Hight Map", 2D) = "white" {}}SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f{float4 positionCS : SV_POSITION;float3 positionWS : TEXCOORD0;};sampler2D _HightMap;float4 _HightMap_TexelSize; // 1/w, 1/h, w, hv2f vert (float4 positionOS : POSITION){v2f o = (v2f)0;o.positionCS = UnityObjectToClipPos(positionOS);o.positionWS = mul(unity_ObjectToWorld, positionOS);return o;}float4 frag (v2f i) : SV_Target{// jave.lin 2021/11/30 修改了代码,优化了写法,可能会与 Project 中的代码不带一样// 但是主要理解意思就够了float3 T = ddy(i.positionWS); // jave.lin : world space tangent = ddy(val) = 上片元.val - 下片元.valfloat3 B = ddx(i.positionWS); // jave.lin : world space bitangent = ddx(val) = 右片元.val - 左片元.valfloat3 N = normalize(cross(T, B)); // jave.lin : world space normal = 求法线//类似flat shader//平坦着色,没有插值,因为偏导函数只能在同一三角面内处理,没有插值的//return fixed4(N, 1);float3  L = normalize(UnityWorldSpaceLightDir(_WorldSpaceLightPos0.xyz)); // jave.lin : world space light dirfloat halfLambert = dot(L, N) * 0.5 + 0.5;return float4(halfLambert.xxx, 1);}ENDCG}}
}

主要看我们的法线如果求得

float3 T = ddy(i.positionWS); // jave.lin : world space tangent = ddy(val) = 上片元.val - 下片元.val
float3 B = ddx(i.positionWS); // jave.lin : world space bitangent = ddx(val) = 右片元.val - 左片元.val
float3 N = normalize(cross(T, B)); // jave.lin : world space normal = 求法线

就算在app to shader阶段没有 NORMAL 传入,我们也可以通过偏导函数来求得N 世界空间的法线

关于上面的 cross 叉乘,可以查看我之前写的一篇:Unity Shader - Billboard 广告板/广告牌 - BB树,BB投影 - 查看 向量叉乘的顺序 部分的内容,之前我写了一个 -ddx(val) 的写法是为了构建左手坐标的

然后添加了 diffuse 光照

但要注意,我们在像素阶段用ddx求出来的tbn是相对整个三角面的,所以没有插值,效果就如同Flat shader一样,没有对法线插值。

关于叉乘可以参考这篇:Basis Orientations in 3ds Max, Unity 3D and Unreal Engine

下面引用博主的两张图:

Basis orientations in 3ds Max, Unity 3D and Unreal Engine (right and left hand rules are shown) - 在3ds Max, Unity 3D 和 Unreal 引擎 的基本朝向(左右手坐标的规则显示)

  • 3ds Max – right handed, z-up - 右手坐标,z 向上
  • Unity 3D – left handed, y-up - 左手坐标,y 向上
  • Unreal Engine – left handed, z-up - 左手坐标,y 向上


右手坐标的 叉乘规则


运行效果


用于优化

如下,我在优化一篇高度雾的时候,使用的优化技巧:

#ifdef _HIGH_QUALITY_ON// jave.lin : method1:float2 xz1 = noise_wp.xz + fixed2(_DerivativeSampleGaps, 0);float2 xz2 = noise_wp.xz + fixed2(0, _DerivativeSampleGaps);float h = GetNoise(noise_wp.xz);//return h;float h1 = GetNoise(xz1);//return h1;float h2 = GetNoise(xz2);//return h2;float3 pos = float3(noise_wp.x, h, noise_wp.z);float3 posU = float3(xz1.x, h1, xz1.y);float3 posV = float3(xz2.x, h2, xz2.y);float3 N = normalize(cross(posV - pos, posU - pos));
#else// jave.lin : optimize method2:float h = GetNoise(noise_wp.xz);//return h2;float3 pos = float3(noise_wp.x, h, noise_wp.z);float3 N = normalize(cross(ddy(pos), ddx(pos)));
#endif

Project

TestDerivativeFunc 提取码: 7jur


References

  • An introduction to shader derivative functions
  • shader中ddx/ddy偏导数的原理和简单应用
  • 关于ddx/ddy重建法线在edge边沿上的artifacts问题
  • 凹凸贴图(Bump Map)
  • hlsl函数 ddx ddy

Unity Shader - ddx/ddy偏导函数测试,实现:锐化、高度图、Flat shading应用、高度生成法线相关推荐

  1. 《Unity Shader入门精要》学习笔记

    简单说明 为控制渲染过程提供一层抽象,避免许多繁琐配置:用ShaderLab编写,使用一些嵌套在{}的语义: 定义了要显示材质所需的全部,不仅仅是着色器代码 Unity Shader != Shade ...

  2. unity shader学习---透明度测试,透明度混合

    unity实现透明效果 效果图 理论 Alpha Test Alpha Blend 改进 开启深度写入的半透明效果 双面渲染的透明效果 代码部分 效果图 Alpha Test Alpha Test W ...

  3. 【Unity Shader】实现透明度测试和透明度混合

    本篇开始将进行<入门精要>初级篇最后一部分的学习,完成透明效果的学习. 1 Unity中实现透明效果的方法 一个像素的RGBA参数中的最后一项A指的就是透明度Alpha.在之前的实践中,一 ...

  4. C for Graphic:ddx/ddy

    最近有被群里好友问ddx/ddy的问题,本着帮助他人且提升自己的初衷,来一篇博客. ddx(a):returns approximate partial derivative with respect ...

  5. Unity Shader - 水体交互

    水体交互 水体交互效果在游戏中是一个很常见的需求,这里简单实现一个可交互的水体. 本篇文章主要是介绍水体交互的实现思路,水体的渲染这里就不再详细介绍,网上很多关于水体的渲染方法很多,可以自己百度.Go ...

  6. unity Shader Lab(cg hlsl glsl)着色器入门教程 以及 vs2019 支持unity shader语法(更新中2019.9.5)

    前言: 如果你对cg glsl hlsl 顶点着色器 片段着色器 表面着色器 固定渲染管线 等等有所疑惑,或是想学会unity的渲染,看这一篇就足够了.另外我博客的shader分类中还有很多shade ...

  7. Unity Shader 数学函数

    CG标准函数库的函数只要分为这几类:数学函数,几何函数,纹理映射函数,偏导数函数: 1:数学函数  数学函数用于执行数学上的常用计算,包括:三角函数,幂函数,向量和矩阵的操作函数.这些函数都被重载,以 ...

  8. HLSL 偏导数 ddx / ddy

    [HLSL ddx / ddy] 在光栅化的时刻,GPUs会在同一时刻并行运行很多Fragment Shader,但是并不是一个pixel一个pixel去执行的,而是将其组织在2x2的一组pixels ...

  9. Unity Shader 之 透明效果

    本文引用 Unity Shader入门精要 开启透明混合后,一个物体被渲染到屏幕上时,每个片元除了颜色值和深度值外,还有--透明度.透明度为1,则完全不透明,透明度为0,则完全不会显示. 在Unity ...

最新文章

  1. python(pil)图像处理(等比例压缩、裁剪压缩) 缩略(水印)图
  2. GNU make manual 翻译(六十九)
  3. flask之url_for()函数解析
  4. 【星球知识卡片】图像风格化与翻译都有哪些核心技术,如何对其长期深入学习...
  5. NXP I.MX6ULL 交叉编译工具链下载地址?
  6. js抽奖概率随机取出数据(简单示例)
  7. python中深拷贝和浅拷贝
  8. 微信无法连接服务器1-502,只有一部iphone x手机,在微信公众号中选择菜单,出现bad gateway 502错误,原因?...
  9. 较为周全的Asp.net提交验证方案 (下)
  10. 诗与远方:无题(三十二)- 曾经写给妹子的一首诗
  11. mini2440 uboot使用nfs方式引导内核,文件系统
  12. 架构 BitTorrent BT服务器
  13. 爬虫Selenium+Chrome 控制浏览器,打开百度网页,输入搜索关键词,点击回车,截取搜索页面
  14. R语言在逻辑回归中求R square R方
  15. Java技术进阶推荐书单
  16. 动作捕捉技术对演员的演技诉求
  17. ji计算机内存不足怎么回事,Win7提示内存不足的原因及应对措施
  18. Android中一个app启动另一个app|从浏览器打开app
  19. 系统集成项目管理(软考中级)第一章信息化知识
  20. tyvj p1004 滑雪

热门文章

  1. 影院电影售票管理系统
  2. 【C语言】结构体-求出学生的平均成绩放在成员ave中
  3. ACL2021 | 关键词生成任务新范式 - 把关键词生成看成集合预测问题
  4. PHP面向对象基础七
  5. Unix平台下iostat与vmstst说明
  6. LPF与HPF是什么意思?
  7. v5行为验证使用介绍(三)- 程序接入流程
  8. 毕业设计 单片机火灾报警系统设计与实现 - stm32 嵌入式
  9. #2002 SIGSEGV(SEGV_MAPERR)
  10. PowerDesigner如何导出表到word的方法