UE自定义Shader(HLSL)
本文用的是UE4.27,其实UE5或者UE4低版本也是ok的
新建一个项目
2.3 HLSL常用函数介绍 - 知乎 (zhihu.com)
1:配置自定义节点到虚幻中
在根目录下新建一个Shader目录,并VSCode中在这个目录下创建一个g.ush文件。
新建一个材质,添加一个Custom
自定义材质节点,并对这个自定义的节点附上代码为刚才的gg.ush,如图
#include "D:/GameProject/studyProject/AddamShader/Shader/g.ush"
return 0;
输出类型和u.ush输出类型要保持一致,比如输出的是float,那这里就写浮点1,要是是vec3,那就是浮点3
至此配置完毕
2:基本运算
HLSL基本浮点数数值定义有以下三种
- float:高精度类型,32位,通常用于世界坐标下的位置,纹理UV,或涉及复杂函数的标量计算,如三角函数、幂运算等
- half:中精度类型,16位,数值范围为[-60000,+60000],通常用于本地坐标下的位置、方向向量、HDR颜色等
- fixed:低精度类型,11位,数值范围为[-2,+2],通常用于常规的颜色与贴图,以及低精度间的一些运算变量等
并且输出支持debug节点直接显示数值,比如输出是浮点1,那么就用DebugScalarValues
,效果如下
加减乘除
float a = A;
float b = B;
// 加
// float c = a + b;
// 减
// float c = a - b;
// 乘
// float c = a * b;
// 除
float c = a / b;
return c;
最大/最小值
float a = A;
float b = B;
// 最小值
// float c = min(a, b);
// 最大值
float c = max(a, b);
return c;
绝对值 abs
语法 | 描述 |
---|---|
abs(x) | 返回x的绝对值。对x的每个元素都会独立计算一次。Absolute value (per component). |
代码
float a = A;
// 绝对值
float c = abs(a);
return c;
取余 fmod
语法 | 描述 |
---|---|
fmod(x,y) | 返回xy的浮点部分(取余的余数部分) |
代码
float a = A;
float b = B;
// 取余
float c = fmod(a, b);
return c;
指数 pow
语法 | 描述 |
---|---|
pow(x,y) | x的y次方 |
exp(x) | 返回以e为底的指数函数,e的x次方 |
exp2(x) | 返回以2为底,x为指数的幂 |
代码
float a = A;
float b = B;
// 次方
float c = pow(a, b);
return c;
平方根 rsqrt
语法 | 描述 |
---|---|
sqrt(x) | 返回x的平方根,根号x |
rsqrt(x) | 返回x的平方根的倒数,根号x分之1 |
代码
float a = A;
// 返回平方根
// float c = rsqrt(a);
// 返回1/平方根
float c = rsqrt(a);
return c;
弧度和角度互转
语法 | 描述 |
---|---|
degrees(x) | 将x(弧度)转换到角度。 |
radians(x) | 将x(角度)转换到弧度。 |
float a = A;
// 将x(弧度)转换到角度
// float c = degrees(a);
// 将x(角度)转换到弧度
float c = radians(a);
return c;
生成随机数
语法 | 描述 |
---|---|
noise(x) | 使用Perlin-noise算法生成随机值,传入二维坐标,返回[0, 1]随机值 |
代码
float3 a = A;
// 随机数
float3 c = noise(a);
return c;
对数函数
语法 | 描述 |
---|---|
log(x) | 返回以e为底的对数 |
log2(x) | 返回以2为底的对数 |
log10(x) | 返回以10为底的对数 |
代码
float a = A;
// 返回以e为底的对数
// float c = log(a);
// 返回以e为底的对数
// float c = log2(a);
// 返回以e为底的对数
float c = log10(a);
return c;
三角函数
三角函数
语法 | 描述 |
---|---|
sin(x) | 求正弦,x为弧度 |
cons(x) | 求余弦,x为弧度 |
tan(x) | 求正切,x为弧度 |
反三角函数
语法 | 描述 |
---|---|
asin(x) | 求输入的反正弦 |
acos(x) | 求输入的反余弦 |
atan(x) | 求输入的反正切 |
atan2(x, y) | 求的y / x的反正切 |
双曲线函数
语法 | 描述 |
---|---|
sinh(x) | 返回x的双曲正弦值 |
cosh(x) | 返回x的双曲余弦值 |
tanh(x) | 返回x的双曲正切值 |
y = sinh x
y = cosh x
y = tanh x
数据处理函数
向上 \下取整
语法 | 描述 |
---|---|
ceil | 返回大于等于x的最小整数 |
float | 返回小于等于x的最大整数 |
代码
float a = A;
// 大于等于a的最小整数
// float c = ceil(a);
// 小于等于a的最大整数
float c = floor(a);
return c;
smoothstep插值
语法 | 描述 |
---|---|
smoothstep(min, max, x) | 如果x的范围是[min, max],则返回一个介于0和1之间的Hermite插值。可以使用smoothstep在两个值直接创建平滑过渡 |
代码
0~0.2的部分会被插值,0.2之外就直接返回1了
float3 a = A;
float3 c = smoothstep(0, 0.2, a);
return c;
效果如下
范围截取函数 clamp
语法 | 描述 |
---|---|
clamp(x, min, max) | 将x截取在[min, max]范围内。 |
saturate(x) | 把x截取在[0, 1]之间。 |
代码
float a = A;
// float c = saturate(a);
float c = clamp(1, 10, a);
return c;
判断大小 step
语法 | 描述 |
---|---|
step(a, x) | 返回 (x >= a) ? 1 : 0 。 |
代码
float3 a = A;
float3 b = B;
float3 c = step(b, a);
return c;
效果
lerp插值函数
语法 | 描述 |
---|---|
lerp(x, y, s) | 按照s对x、y进行插值计算。即为return x*(1-x) + s*y 。 |
代码
float3 a = A;
float3 b = B;
float3 c = C;
float3 d = lerp(a, b, c);
return d;
效果
输出小数 frac
语法 | 描述 |
---|---|
frac(x) | 返回输入x的小数部分 |
代码
float a = A;
float d = frac(a);
return d;
类型判断类
-
all(x) 确定指定量的所有分量是否均为非零,均非零则返回true,否则返回false(处理由浮点型、整型、布尔型数据定义的标量、向量或者矩阵)
-
clip(x) 如果输入值小于零,则丢弃当前像素 常用于判定范围(不仅仅针对0,返回值为void)
-
- 常用于测试alpha,如果每个分量代表到平面的距离,还可以用来模拟剪切平面
-
sign(x) 返回x的正负性 如果x小于零返回-1,如果x等于零返回0,如果x大于零返回1
-
isinf(x) 如果x参数为+ INF或-INF(无穷+无穷仍无穷,0x3f3f3f3f),返回true,否则返回False
-
isfinite(x) 判断x参数是有限,即有界的,与isinf(x)相反
-
isnan(x) 如果x参数为NAN(非数字),返回true,否则返回false
向量与矩阵类
求向量的长度 length
语法 | 描述 |
---|---|
length(x) | 返回向量x的长度(返回值为标量) |
代码
float3 a = A;
float3 d = length(a);
return d;
效果
比如(3, 4, 0)的向量输出的是5
求向量距离 distance
语法 | 描述 |
---|---|
distance(x, y) | 返回x、y之间的距离(向量各分量之差的平方和) |
代码
float3 a = A;
float3 b = B;
float3 c = distance(a, b);
return c;
效果如下:
归一化函数 normalize
语法 | 描述 |
---|---|
normalize(x) | 向量归一化,x/length(x) |
代码
float3 a = A;
float3 c = normalize(a);
return c;
矩阵相乘 mul
语法 | 描述 |
---|---|
mul(a, b) | 两变量相乘,多用于矩阵运算 |
代码
float3 a = A;
float2 b = B;
float3 c = mul(a, b);
return c;
效果如下
输出点积 dot
语法 | 描述 |
---|---|
dot(a, b) | 输出a和b的点积 |
代码
float3 a = A;
float2 b = B;
float3 c = dot(a, b);
return c;
效果
输出叉积 cross
语法 | 描述 |
---|---|
cross(a,b) | 输出叉积 |
语法 | 描述 |
---|---|
determinant(x) | 返回指定浮点矩阵的按行列式方式计算的值 |
转置矩阵
语法 | 描述 |
---|---|
transpose(x) | 返回矩阵x的转置矩阵 |
Bool类
语法 | 描述 |
---|---|
clip(x) | 如果输出值小于0,丢弃该像素,不进行渲染(像素为负->没有颜色) |
sign(x) | 返回x的正负,若x<0返回-1,x=0返回0,x>0返回1 |
all(x) | 可以传入矢量,所有分量均为非0则返回true,否则返回false |
any(x) | 可以传入矢量,有任一分量非0返回true,否则返回false |
自定义函数
用结构体创建局部函数
代码
struct function
{
float add(float a, float b)
{
float c = a + b;
return c;
}
};
function t;
float a = A;
float b = B;
float y = t.add(a, b);
return y;
效果
创建全局函数
修改引擎目录下的common.ush文件,感觉好麻烦就不演示了,还是局部函数好用
虚幻内置变量
View调用的内置变量
例如代码如下
float time = View.RealTime;
float h = sin(time);
return h;
变量如下
- GameTime //游戏时间
- RealTime //时间
- DeltaTime //增量时间
- AtmosphereLightDirection//大气照明方向
- Random //随机值
- FrameNumber //帧数
- GlobalClippingPlane //全局裁剪屏幕
- ViewWideAngles //查看广角
- PrevFieldOfViewWideAngles //上一个视野广角
- ViewSizeAndInvSize //视图大小和inv大小
- ViewRectMinAndSize //视图矩形最小值和大小
- LightProbeSizeRatioAndInvSizeRatio //灯光测试
- BufferSizeAndInvSize //缓冲区大小
- BufferBilinearUVMinMax //缓冲线UV最大最小
- ScreenToViewSpace //屏幕到视图空间
- BufferToSceneTextureScale //缓冲区到场景文本比例
- ResolutionFractionAndInv //分辨率分数和库存
- NumSceneColorMSAASamples //NumSceneColorMSAA示例
- SeparateWaterMainDirLightLuminance //分隔水主指示灯亮度
- PreExposure //预暴露
- OneOverPreExposure //一次过度预暴露
- PrevFrameGameTime //上一帧游戏时间
- PrevFrameRealTime //上一帧实时
- WorldCameraMovementSinceLastFrame //自上一帧以来的世界相机移动
- CullingSign //消隐符号
- MaterialTextureMipBias //材料纹理MipBias
- MaterialTextureDerivativeMultiply //材料纹理衍生乘法
- StateFrameIndexMod8 //帧数状态索引mod8
- StateFrameIndex //帧数状态索引
- DebugViewModeMask //调试视图模式掩码
- TemporalAAParams //临时AA参数
- CircleDOFParams //圆形DOF参数
- DepthOfFieldSensorWidth //景深传感器宽度
- DepthOfFieldFocalDistance //景深焦距深度
- DepthOfFieldScale //字段比例深度
- DepthOfFieldFocalLength //字段焦点长度深度
- DepthOfFieldFocalRegion //字段焦点区域深度
- DepthOfFieldNearTransitionRegion //字段最近转换区域的深度
- DepthOfFieldFarTransitionRegion //字段深度转换区域
- MotionBlurNormalizedToPixel //单一化bulr到像素
- GeneralPurposeTweak //一般目的调整
- GeneralPurposeTweak2 //一般目的调整2
- DecalDepthBias //贴花深度偏移
- IndirectLightingColorScale //间接照明颜色比例
- PrecomputedIndirectLightingColorScale //预计算间接照明色阶
- PrecomputedIndirectSpecularColorScale //预计算间接规格颜色比例
- AtmosphereLightIlluminanceOnGroundPostTransmittance//大气光照度地面后透射率
- AtmosphereLightIlluminanceOuterSpace//大气照明室外空间
- AtmosphereLightDiscLuminance//大气发光二极管亮度
- AtmosphereLightDiscCosHalfApexAngle_PPTrans//大气光光盘
- SkyViewLutSizeAndInvSize //天空视图
- SkyCameraTranslatedWorldOrigin //天空相机变换世界原点
- SkyPlanetTranslatedWorldCenterAndViewHeight //开始深度Km
- SkyViewLutReferential //透视体积深度分辨率
- SkyAtmosphereSkyLuminanceFactor //透视体积深度切片长度Km
- SkyAtmospherePresentInScene //透视体积深度切片长度KmInv
- SkyAtmosphereHeightFogContribution //天空大气应用相机空中透视体积
- SkyAtmosphereBottomRadiusKm //正常曲率到粗糙度刻度偏差
- SkyAtmosphereTopRadiusKm //渲染反射捕获遮罩
- SkyAtmosphereCameraAerialPerspectiveVolumeSizeAndInvSize
- SkyAtmosphereAerialPerspectiveStartDepthKm
- SkyAtmosphereCameraAerialPerspectiveVolumeDepthResolution
- SkyAtmosphereCameraAerialPerspectiveVolumeDepthResolutionInv
- SkyAtmosphereCameraAerialPerspectiveVolumeDepthSliceLengthKm
- SkyAtmosphereCameraAerialPerspectiveVolumeDepthSliceLengthKmInv
- SkyAtmosphereApplyCameraAerialPerspectiveVolume
- NormalCurvatureToRoughnessScaleBias
- RenderingReflectionCaptureMask
- RealTimeReflectionCapture
- RealTimeReflectionCapturePreExposure
- AmbientCubemapTint
- AmbientCubemapIntensity
- SkyLightApplyPrecomputedBentNormalShadowingFlag
- SkyLightAffectReflectionFlag
- SkyLightAffectGlobalIlluminationFlag
- FLinearColor, SkyLightColor
- MobilePreviewMode
- HMDEyePaddingOffset
- ShowDecalsMask
- uDistanceFieldAOSpecularOcclusionMode
- IndirectCapsuleSelfShadowingIntensity
- ReflectionEnvironmentRoughnessMixingScaleBiasAndLargestWeight
- StereoPassIndex
- GlobalVolumeCenterAndExtent
- GlobalVolumeWorldToUVAddAndMul
- GlobalDistanceFieldMipWorldToUVScale
- GlobalDistanceFieldMipWorldToUVBias
- GlobalDistanceFieldMipFactor
- GlobalDistanceFieldMipTransition
- GlobalDistanceFieldClipmapSizeInPages
- GlobalDistanceFieldInvPageAtlasSize
- GlobalDistanceFieldInvCoverageAtlasSize
- GlobalVolumeDimension
- GlobalVolumeTexelSize
- MaxGlobalDFAOConeDistance
- uNumGlobalSDFClipmaps
- CoveredExpandSurfaceScale
- NotCoveredExpandSurfaceScale
- NotCoveredMinStepScale
- DitheredTransparencyStepThreshold
- DitheredTransparencyTraceThreshold
- FIntPo CursorPosition
- bCheckerboardSubsurfaceProfileRendering
- VolumetricFogInvGridSize
- VolumetricFogGridZParams
- FVector2f, VolumetricFogSVPosToVolumeUV
- VolumetricFogMaxDistance
- VolumetricLightmapWorldToUVScale
- VolumetricLightmapWorldToUVAdd
- VolumetricLightmapIndirectionTextureSize
- VolumetricLightmapBrickSize
- VolumetricLightmapBrickTexelSize
- IndirectLightingCacheShowFlag
- EyeToPixelSpreadAngle
- _ARRAY XRPassthroughCameraUVs, [2]
- GlobalVirtualTextureMipBias
- uVirtualTextureFeedbackShift
- uVirtualTextureFeedbackMask
- uVirtualTextureFeedbackStride
- uVirtualTextureFeedbackJitterOffset
- uVirtualTextureFeedbackSampleOffset
- RuntimeVirtualTextureMipLevel
- FVector2f, RuntimeVirtualTexturePackHeight
- RuntimeVirtualTextureDebugParams
- OverrideLandscapeLOD
- FarShadowStaticMeshLODBias
- MinRoughness
- HairRenderInfo
- uEnableSkyLight
- uHairRenderInfoBits
- uHairComponents
- bSubsurfacePostprocessEnabled
- SSProfilesTextureSizeAndInvSize
- SSProfilesPreIntegratedTextureSizeAndInvSize
- PhysicsFieldClipmapCenter
- PhysicsFieldClipmapDistance
- PhysicsFieldClipmapResolution
- PhysicsFieldClipmapExponent
- PhysicsFieldClipmapCount
- PhysicsFieldTargetCount
- PhysicsFieldTargets
- uInstanceSceneDataSOAStride
- uGPUSceneViewId
- ViewResolutionFraction
- SubSurfaceColorAsTransmittanceAtDistanceInMeters
Parameters调用的内置变量
基础调用
Parameters.VertexColor //获取方向颜色
Parameters.WorldTangent //获取世界切线
Parameters.ReflectionVector //获取反射向量
Parameters.CameraVector //获取相机向量
Parameters.LightVector //获取灯光向量(用于灯光函数)
Parameters.SvPosition //获取全局位置
Parameters.ScreenPosition //获取场景位置
Parameters.WorldNormal //获取世界法线
Parameters.ViewBufferUV //
Parameters.AbsoluteWorldPosition //获取世界绝对位置
Parameters.WorldPosition_CamRelative //世界位置 相机相对位置
Parameters.WorldPosition_NoOffsets_CamRelative //世界相机(没有编译)
Parameters.LightingPositionOffset //灯光位置偏移
使用案例
float4 h = Parameters.AbsoluteWorldPosition;
return h;
虚幻后处理函数
SceneTextureLookup
函数
SceneTextureLookup(GetDefaultSceneTextureUV(Parameters, 1), 1, false);
对应参数数字;
SceneColor 0 //场景颜色
SceneDepth 1 //场景深度
DiffuseColor 2 //漫反射颜色
SpecularColor 3 //高光颜色
SubsurfaceColor 4 //次表面颜色
BaseColor 5 //底色(针对光照)
Specular 6 //高光(针对光照)
Metallic 7 //金属
WorldNormal 8 //场景法线
SeparateTranslucency 9 //分隔半透明
Opacity 10 //不透明度
Roughness 11 //粗糙度
MaterialAO 12 //材质AO
CustomDepth 13 // 自定义深度
PostProcessInput0 14 //后期处理输入0
PostProcessInput1 15 //后期处理输入1
PostProcessInput2 16 //后期处理输入2
PostProcessInput3 17 //后期处理输入3
PostProcessInput4 18 后期处理输入4
PostProcessInput5 19 //后期处理输入5
PostProcessInput6 20 //后期处理输入6
DecalMask 21 //贴花遮罩
ShadingModelColor 22 //着色器颜色
ShadingModelID 23 // 着色器ID
AmbientOcclusion 24 //环境光遮蔽
CustomStencil 25 //自定义模板值
StoredBaseColor 26 //底色
StoredSpecular 27 //高光
Velocity 28 //速度
WorldTangent 29 //场景切线
Anisotropy 30//各向异性
/一下是函数可以直接用
GetTranslatedWorldPosition //获取世界变换世界位置
GetScreenPosition //获取场景位置
GetDefaultSceneTextureUV //获取默认场景UV
GetPixelDepth //获取像素深度
GetSceneTextureUV //获取场景UV
GetPixelPosition //获取像素位置
GetViewportUV //获取视口portUV
GetWaterWaveParamIndex
GetSceneTextureViewSize //获取场景视口大小
GetSceneTextureUVMinMax
GetActorWorldPosition //获取actor世界位置
GetObjectOrientation //获取物体
GetLocalToWorld
GetPrevLocalToWorld
TransformLocalPositionToWorld
GetObjectWorldPosition //获取物体位置
案例
构建一个旋转的黑白圈
代码
float2 uv = uv2;
float time = time2;
float r;
float rr = length(uv);
r = (rr + time + atan2(uv.x, uv.y) * 0.2);
r = sin(r*80);
r = smoothstep(-0.4, 0.4, r);
return float4(r, r, r, 1.0);
效果如下
构建一个球
代码
float y = 0;
for(int i = 0; i < 9999; i++) {
float d = distance(world, object) - R;
if(d < 1) {
return float4(1, 1, 1, 1);
} else {
world -= camera;
}
}
return y;
效果
口大小
GetSceneTextureUVMinMax
GetActorWorldPosition //获取actor世界位置
GetObjectOrientation //获取物体
GetLocalToWorld
GetPrevLocalToWorld
TransformLocalPositionToWorld
GetObjectWorldPosition //获取物体位置
案例
构建一个旋转的黑白圈
代码
float2 uv = uv2;
float time = time2;
float r;
float rr = length(uv);
r = (rr + time + atan2(uv.x, uv.y) * 0.2);
r = sin(r*80);
r = smoothstep(-0.4, 0.4, r);
return float4(r, r, r, 1.0);
效果如下
构建一个球
代码
float y = 0;
for(int i = 0; i < 9999; i++) {
float d = distance(world, object) - R;
if(d < 1) {
return float4(1, 1, 1, 1);
} else {
world -= camera;
}
}
return y;
效果
#define mix lerp
#define fract frac
#define vec float
#define vec2 float2
#define vec3 float3
#define vec4 float4
#define iTime View.RealTime
struct function {
float opSmoothUnion( float d1, float d2, float k ) {
float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
return mix( d2, d1, h ) - k*h*(1.0-h);
}
float sdSphere( vec3 p, float s ) {
return length(p)-s;
}
float map(vec3 p) {
float d = 2.0;
for (int i = 0; i < 16; i++) {
float fi = float(i);
float time = iTime * (fract(fi * 412.531 + 0.513) - 0.5) * 2.0;
d = opSmoothUnion(
sdSphere(p + sin(time + fi * vec3(52.5126, 64.62744, 632.25)) * vec3(2.0, 2.0, 0.8), mix(0.5, 1.0, fract(fi * 412.531 + 0.5124))),
d,
0.4
);
}
return d;
}
vec3 calcNormal( in vec3 p ) {
const float h = 1e-5; // or some other value
const vec2 k = vec2(1,-1);
return normalize( k.xyy*map( p + k.xyy*h ) +
k.yyx*map( p + k.yyx*h ) +
k.yxy*map( p + k.yxy*h ) +
k.xxx*map( p + k.xxx*h ) );
}
};
function t;
vec2 uv = uv2;
// screen size is 6m x 6m
vec3 rayOri = vec3((uv - 0.5) * vec2(daxiao, 1.0) * 6.0, 3.0);
vec3 rayDir = vec3(0.0, 0.0, -1.0);
float depth = 0.0;
vec3 p;
for(int i = 0; i < 64; i++) {
p = rayOri + rayDir * depth;
float dist = t.map(p);
depth += dist;
if (dist < 1e-6) {
break;
}
}
depth = min(6.0, depth);
vec3 n = t.calcNormal(p);
float b = max(0.0, dot(n, vec3(0.577, 0.577, 0.577)));
vec3 col = (0.5 + 0.5 * cos((b + iTime * 3.0) + uv.xyx * 2.0 + vec3(0,2,4))) * (0.85 + b * 0.35);
col *= exp( -depth * 0.15 );
// maximum thickness is 2m in alpha channel
return vec4(col, 1.0 - (depth - 0.5) / 2.0);