HLSL着色器原理:(三)高级着色器

  3.2 游戏引擎技术
  • 我创建了一个游戏制作交流群:637959304 进群密码:(CSGO的拆包密码)欢迎各位大佬一起学习交流,不限于任何平台(U3D、UE、COCO2dx、GamesMaker等),以及欢迎编程,美术,音乐等游戏相关的任何人员一起进群学习交流。

视差贴图

  • 增加法线信息细节,增添深度信息细节,通过营造高度差来模拟深度细节。
  • 缺点:数值设置过大会造成图片拉伸效果,摄像机视角如果与贴图法线角度接近90度则看不出效果。
image 76 - HLSL着色器原理:(三)高级着色器
offset hight = 0
image 77 - HLSL着色器原理:(三)高级着色器
offset hight = 0.06
  • 前置条件:高度贴图(Height Map),可以存入到法线贴图的alpha通道中
//自定义Offset Height变量
v2f v(a2v In,uniform float4 lightPosition)
{
//在v2f中定义t_eyeVec,代表切线空间下的观察向量
        float3x3 objTangentXf = //ObjectToTangentSpaceTransform,类似于mvp矩阵
        objTangentXf[0] = In.binoraml.xyz;
        objTangentXf[0] = -In.tangent.xyz;
        objTangentXf[0] = In.normal.xyz;

        float4 objSpaceEyePos = mul(Viewinverse[3] , worldI);//摄像机坐标物体空间,worldI为定义的Inverse矩阵
        float3 objEyeVec = objSpaceEyePos.xyz - In.position.xyz;//观察向量

        Out.t_eyeVec = mul(objEyeVec,objTangentXf);.//切线空间下观察向量
}

float4 f(v2f In,uniform float4 lightColor) : COLOR
{
//计算出能够跟随观察向量和高度贴图移动的UV坐标
        float2 t_eyeVec = normalize(In.t_eyeVec).xy;
        t_eyeVec.y = -t_eyeVec.y;//这里是视频里适配3DS MAX的UV坐标才这么写的
        float heightAlpha = tex2D(normalMapSampler,In.texCoord).a * 2 - 1;
        float2  nevTextCoords = (heightAlpha * t_eyeVec * OffsetHeight) + In.texCoord.xy;
//之后把新的nevTextCoords在ColorTexture、SpecularTexture、noraml中替换原来的In.texCoord.xy
}

反射贴图(镜面反射)

  • 反射贴图(Reflection Mapping),依靠反射贴图实现实时反(Realtime)射计算,实现环境光的效果
  • (现在可以直接使用光追,NVIDIA yes!)
  • 前置条件:立方贴图
  • 数据结构
//自定义反射贴图材质(texture reflectMap)以及反射贴图采样器(samplerCUBE reflectMapSampler)
float4 f(v2f In,uniform float4 lightColor) : COLOR
{
//计算反射向量,解决贴图旋转问题
        float3 refvector = reflect(V,N);
        refvector.yz = -refvector.zy;//同3DS的问题
        float4 ref = texCUBE(reflectMapSampler, refvector);
        return ref * 5;//该系数根据贴图亮度进行调整即可
}

制作金属材质

  • 设置反射模糊度(模拟不光滑、锈蚀等的金属表面)
//自定义采样层数reflectionBlur
float4 f(v2f In,uniform float4 lightColor) : COLOR
{
//texCUB->texCUBElod从更模糊的贴图中进行采样 LOD->level of detail
//此处ColorTexture.a为模糊贴图的设置,导入模糊贴图后可以让指定区域展示不同的模糊效果
        float4 ref = texCUBElod(reflectMapSampler, float4(refvector,reflectionBlur * ColorTexture.a));

//将反射混合进原有光装模型当中
         Diffuse = lerp(Diffuse,ref,colorTexture.a);//lerp允许按照权重混合两个颜色
}
  • Tip:因为导入图片是黑白贴图,所以在作乘法运算时,黑色区域的值为0,0乘以任何值都为0,所以无论如何提高模糊度该表面区域都是光滑的。
image 78 - HLSL着色器原理:(三)高级着色器
reflectionBlur = 6的效果
image 79 - HLSL着色器原理:(三)高级着色器
导入了黑白格子的模糊贴图后效果
image 80 - HLSL着色器原理:(三)高级着色器
进行反射混合之后的效果

折射效果(Reflection)

image 81 - HLSL着色器原理:(三)高级着色器
//水晶、透明等类似材质的折射效果
//自定义函数refractionIndex代表曝光率

float4 f(v2f In,uniform float4 lightColor) : COLOR
{
//计算折射向量
//refract用于计算折射的函数,第一介质折射率除以第二介质折射率,此时第一介质为空气,第二介质为水。绝对折射率分别为函数内填入数据
//把1.330替换为refractionIndex,可让用户自定义材质折射率
        float3 refractvector = refract(V,-N,1.000293/1.330).xyz;
        refractvector = -refractvector.xzy;
        refractvector.z = -refractvector.z;

        refractedColor = texCUBE(reflectMapSampler,refractvector ) * 5;//系数5用来提高贴图亮度

}
image 82 - HLSL着色器原理:(三)高级着色器
折射效果贴图
image 83 - HLSL着色器原理:(三)高级着色器
材质折射率=1.0时情况

菲涅尔效应

  • 利用菲涅尔效应(Fresnel)来结合反射和折射的效果。也可以用该思路制作边缘光效果,制作厨房表面,
  • 菲涅尔效应(第二集里有详细链接):物体边缘或光线入射角较大的部位,比入射角小的部分体现出了更强烈的反射性质。
float4 f(v2f In,uniform float4 lightColor) : COLOR
{
        float fresnelTerm = pow(1 - dot(V,N),fresnelPower)* fresnelBrightness;//边缘白色中间黑色,直接是dot为边缘黑色中间白色,fresnelPower,fresnelBrightness为自定义变量
        float4 reflectionAndRefraction = lerp(refractedColor,ref,fresnelTerm);
}
image 85 - HLSL着色器原理:(三)高级着色器
dot(V,N)
image 84 - HLSL着色器原理:(三)高级着色器
1 – dot(V,N)
image 87 - HLSL着色器原理:(三)高级着色器
pow(1 – dot(V,N),4)
image 86 - HLSL着色器原理:(三)高级着色器
反射折射混合后效果
image 88 - HLSL着色器原理:(三)高级着色器
pow(1 – dot(V,N),4)* 3

细节法线贴图

  • 细节法线贴图(Detail Normal Mapping):允许放大观察后的图片拥有更多的细节。
//自定义参数:detailnormalmap 自定义采样器:detailNoramlMapSampler
float4 f(v2f In,uniform float4 lightColor) : COLOR
{
//自定义参数detailSize,detialHeight
        float3 detailNormal = tex2D(detailNoramlMapSampler,In.textCoord * detailSize).xyz * 2.0 -1.0 t;
        
        normal = float3((normal.x + detailNormal.x* detialHeigh),(normal.y + detailNormal.y* detialHeigh),normal.z);
}

image 89 654x1024 - HLSL着色器原理:(三)高级着色器

顶点颜色

  • 利用顶点颜色和不同明度编写着色器。具体教程请看视频3.7章节。
  • 用处举例:有两张漫反射贴图,通过顶点色决定哪些地方显示第一张,哪些地方显示第二张。

顶点动画

  • 改变渲染位置
image 90 - HLSL着色器原理:(三)高级着色器
v2f v(a2v In,uniform float4 lightPosition)
{
        float4 ObjectSpacePosition = In.position;
        ObjectSpacePosition.z += 50;//这里的单位为cm,在3dsmax中
}
  • 通过引入时间变量来制作各种动画
  • 波动效果(动画)
float time : TIME;

float wave(float value,float frequency,float speed,float amplitude)
{
        return sin(value * frequency + speed) * amplitude;
}

v2f v(a2v In,uniform float4 lightPosition)
{
        float4 ObjectSpacePosition = In.position;
        ObjectSpacePosition.z += wave(ObjectSpacePosition.x,0.1,time,8) ;
}
image 91 - HLSL着色器原理:(三)高级着色器
波动效果
  • 跷跷板效果(沿着中轴线旋转移动)
float2 teetertotter(float2 Textcoords,float2 center,float maxAngle,float time)
{
        float theta = maxAngle * sin(time);
        float2 sc;
        sincos(theta,sc.x,sc.y);
        float2 uv = Texcoords - center;
        float2 rotateduv;
        rotateduv.x = dot(uv,float2(sc.y-sc.x));
        rotateduv.y = dot(uv,sc.xy);
        rotateduv += center;
        return rotateduv;
}

v2f v(a2v In,uniform float4 lightPosition)
{
        float4 ObjectSpacePosition = In.position;
        ObjectSpacePosition.yz += teetertotter(ObjectSpacePosition.yz,float2(0,0),1,time) ;
}
  • 旋转效果(和跷跷板差不多具体可以看视频)

溶解特效

image 92 1024x986 - HLSL着色器原理:(三)高级着色器
technique regular
{
        pass one
        {
                AlphaTTestEnable = true;//开启透明度测试,根据透明度选择是否剔除片元
                AlphaRef = 128;//用于定义透明度分界线。透明度低于128分为一组视为完全透明,高于128视为完全不透明
        }
}

//自定义参数brightnessAmount,contrastAmount
float4 f(v2f In,uniform float4 lightColor) : COLOR
{
        float4 OutColor = (Ambient + Diffuse + Specular) * lightColor;
        Outcolor.a = ColorTexture.a + brightnessAmount;
        Outcolor.a = contrastAmount * (Outcolor.a - 0.5) + 0.5;//对比度调整公式
        if(Outcolor.a <= 0.55) OutColor.rgb = float3(1.0,0.5,0.0);//因为在AlphaRef中规定了小于128的颜色会完全透明,所以实际上是在0.5-0.55的区间段内进行颜色的渲染

        return OutColor;
}

  • WELL DONE!

LEAVE A COMMENT