Mask的艺术Word格式文档下载.docx
- 文档编号:17843123
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:4
- 大小:20.12KB
Mask的艺术Word格式文档下载.docx
《Mask的艺术Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《Mask的艺术Word格式文档下载.docx(4页珍藏版)》请在冰豆网上搜索。
UV贴图也有分布梯度,脚部需要分配的UV面积应该最小而头部\躯干上部分配的贴图面积最大。
眼睛应该是一个独立的UV在规划整张贴图上的各区域时,在各区域之间不会过于密集的前提下,尽可能减少各部分贴图之间的浪费空间。
各分块之间确保留下约5~10像素的距离(一些引擎在会在某些情况下压缩贴图,导致贴图分块区域间未留出足够空间的情况产生接缝)把颜色相似的分块排布在贴图中接近的区域,有助于加载较小版本纹理时保持颜色。
对于mask贴图,是存在两张mask贴图的rgba通道里面的,减少采样次数。
然而官方给的贴图都是分开的(为了好理解?
)。
写Shader基础Shader由于并不是正真的pbr,所以基础的还是原始的Blinn-Phong模型,然后慢慢的加上tricks。
下面来一点点搞个最基本的Blinn-Phong模型的diffuse+normal+specularshader,那jugg的模型为例。
只绘制albedo贴图带上normalmap和diffuse加最后加上油腻的高光可以加个wrapdiffuse不要那么黑基础shader的代码Shader'
Custom/DotaHero'
{Properties{_MainColor('
MainColor'
Color)=(0.5,0.5,0.5,0.5)_MainTex('
MainColorTexture'
2D)='
white'
{}_Wrap('
LightWrap'
float)=0.25_NormalMap('
NormalMap'
bump'
{}_BumpDepth('
BumpDepth'
Range(0.1,4.0))=1}SubShader{Pass{Tags{'
LightMode'
='
ForwardBase'
}CGPROGRAM#pragmavertexvert#pragmafragmentfrag#pragmatarget3.0#pragmamulti_compile_fwdadd_fullshadows#include'
UnityCG.cginc'
#include'
AutoLight.cginc'
//userdefineduniformsampler2D_MainTex;
uniformsampler2D_NormalMap;
uniformfloat4_MainTex_ST;
uniformfloat4_NormalMap_ST;
uniformfloat4_MainColor;
uniformfloat_Wrap;
uniformfloat_BumpDepth;
//unitydefineduniformfloat4_LightColor0;
//baseinputstructstructvertexInput{float4vertex:
POSITION;
float3normal:
NORMAL;
float4texcoord:
TEXCOORD0;
float4tangent:
TANGENT;
};
structvertexOutput{float4pos:
SV_POSITION;
float4tex:
float4posWorld:
TEXCOORD1;
float3normalWorld:
TEXCOORD2;
float3tangentWorld:
TEXCOORD3;
float3binormalWorld:
TEXCOORD4;
LIGHTING_COORDS(5,6)};
//vertexfunctionvertexOutputvert(vertexInputv){vertexOutputo;
float4x4modelMatrix=_Object2World;
float4x4modelMatrixInverse=_World2Object;
o.normalWorld=normalize(mul(float4(v.normal,0.0),_World2Object).xyz);
o.tangentWorld=normalize(mul(_Object2World,half4(half3(v.tangent.xyz),0)));
o.binormalWorld=normalize(cross(o.normalWorld,o.tangentWorld)*v.tangent.w);
o.posWorld=mul(_Object2World,v.vertex);
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.tex=v.texcoord;
TRANSFER_VERTEX_TO_FRAGMENT(o);
//forshadowsreturno;
}//takea-1to1rangeandfitit0to1floatclamp01(floattoBeNormalized){returntoBeNormalized*0.5+0.5;
}float3calculateAmbientReflection(float3rsrm,floattexM){floatmask=(rsrm.x+rsrm.y+rsrm.z)*0.33;
float3amb=UNITY_LIGHTMODEL_AMBIENT.xyz;
returnfloat3(1.5*rsrm*amb+amb*0.5*texM);
}//fragmentfunctionfloat4frag(vertexOutputi):
COLOR{floatshadAtten=LIGHT_ATTENUATION(i);
float4tex=tex2D(_MainTex,i.tex.xy*_MainTex_ST.xy+_MainTex_ST.zw);
//tex=tex*_MainColor;
float4texN=tex2D(_NormalMap,i.tex.xy*_NormalMap_ST.xy+_NormalMap_ST.zw);
floatnDepth=8/(_BumpDepth*8);
//UnpackNormalhalf3localCoords=half3(2.0*texN.ag-float2(1.0,1.0),0.0);
localCoords.z=nDepth;
//normaltransposematrixfloat3x3local2WorldTranspose=float3x3(i.tangentWorld,i.binormalWorld,i.normalWorld);
//Calculatenormaldirectionfloat3normalDir=normalize(mul(localCoords,local2WorldTranspose));
float3N=normalize(normalDir);
float3V=normalize(_WorldSpaceCameraPos.xyz-i.posWorld.xyz);
float3fragmentToLight=_WorldSpaceLightPos0.xyz-i.posWorld.xyz;
floatdistanceToLight=length(fragmentToLight);
floatatten=pow(2,-0.1*distanceToLight*distanceToLight)*_WorldSpaceLightPos0.w+1-_WorldSpaceLightPos0.w;
//(-0.1x^2)^2forpointlights1fordirlightsfloat3L=(normalize(fragmentToLight))*_WorldSpaceLightPos0.w+normalize(_WorldSpaceLightPos0.xyz)*(1-_WorldSpaceLightPos0.w);
float3H=normalize(V+L);
float3worldReflect=reflect(V,N);
//lightingfloatNdotL=dot(N,L);
floatNdotV=1-max(0.0,dot(N,V));
floatNdotH=clamp(dot(N,H),0,1);
floatVdotL=clamp01(dot(V,L));
floatwrap=clamp(_Wrap,-0.25,1.0);
float4texdesat=dot(tex.rgb,float3(0.3,0.59,0.11));
float3difftex=tex.xyz;
VdotL=pow(VdotL,0.85);
floatbellclamp=(1/(1+pow(0.65*acos(dot(N,L)),16)));
float3spec=NdotH;
spec=pow(spec,32.0);
float3diff=max(0,(pow(max(0,(NdotL*(1-wrap)+wrap)),(2*wrap+1))));
diff*=lerp(shadAtten,1,wrap)*atten*difftex.xyz*_LightColor0.rgb;
returnfloat4(atan(clamp(spec+diff,0,2)),1);
//thisisusedtoroundoffvaluesaboveoneandgivebettercolorreproductioninbrightscenes}ENDCG}}Fallback'
Diffuse'
}
虽说直接用unity的builtinshader拖两下也能得到一样的效果,但是自己用vertex+fragment搞一边就没那么简单了,需要去了解tagentspace,需要去了解forward渲染内部的各个pass…虽然比较基础,但是有不明白的最好还是google搞清楚。
后面的内容都是基于上面的情况进行修改。
AlphamaskDota2中用一张贴图来决定皮肤上某个像素是可见的还是不可见的,这样贴图是黑白的,没有灰度
比如下面是大圣的披风,没有mask的话是这样Mask是这样的
而且披风为了实现双面的cutoff,是有两个mesh的
这里为了简单就直接用discard来处理了(discard在移动端貌似性能貌似不佳,最好用alphablend来实现,但是这个时候又要注意渲染次序了)。
float4texTransparency=tex2D(_TransparencyTex,i.tex.xy*_TransparencyTex_ST.xy+_TransparencyTex_ST.zw);
if(texTransparency.r
结果还有头发这里Jugg的模型里面没有需要做透明处理的部分。
SpecularMask有了SpecularMask就不会所有地方都油腻腻了。
比如剑圣面具,上边是albedo,下边是specularmask
floattexSpecular=tex2D(_SpecularMask,i.tex.xy*_SpecularMask_ST.xy+_SpecularMask_ST.zw);
texSpecular*=_SpecularPower;
算specular的时候
float3spec=NdotH;
spec=pow(spec,32.0)*texSpecular;
皮带的部分就比较明显了SpecularExponent贴图SpecularExponent值用来控制表面specular高光的的大小,越黑表示表面越粗糙,越白表示表面越光滑,对于不同的材质金属:
高specular,中Exponent羽毛:
中specular,高Exponent木头:
低specular,超低Exponent如下图所示这个值其实就是Unity中standardshader中的Smoothness,不过这里是用一张贴图来控制。
比如剑圣的身上的肌肉
加了贴图控制之后,可以看到胸肌部分是“比较Spec“的。
MatalnessMask这个mask和specularmask类似,在Unity的standardshader中,Matalness和specular是作为两种不同的处理方案,在Dota2中,两种贴图都用到了。
MetalnessMask的作用是用来模拟真实世界的金属效果,主要做的就是让diffuse和rimlight更黑一些。
金箍棒的Albedo和Metalness如下
采样的时候这样处理一下floattexMatal=tex2D(_MetalnessMask,i.tex.xy*_MetalnessMask_ST.xy+_MetalnessMask_ST.zw);
texMatal=min(texMatal+_MetalnessPower,1.0);
在算diffuse和rim的时候把texMatal乘进去就可以了。
对比一下Diffuse+specular+rim+Matalness
SelfIlluminationMask自发光贴图用来控制颜色由albedo贴图决定的程度,比如jugg的面具,白色的部分即使在很暗的灯光下也会很亮。
原理就是标记的地方不受光照影响,直接使用albedo贴图采样出来的颜色。
首先是采贴图floattexEmmision=tex2D(_EmissionMask,i.tex.xy*_EmissionMask_ST.xy+_EmissionMask_ST.zw);
texEmmision*=_EmissionIntensity;
然后在算diffuse的时候把emmision加上去float3diff=max(0,(pow(max(0,(NdotL*(1-wrap)+wrap)),(2*wrap+1))));
diff*=lerp(shadAtten,1,wrap)*atten*difftex.xyz*_LightColor0.rgb*2*_LightColor0.rgb*difftex.xyz;
diff+=difftex.xyz*texEmmision;
在光照强度很暗的情况下,有emmision和没emmsion还是区别很大的RimlightRimlight是用来给角色轮廓光的,可以让角色在复杂环境中很容易辨识出来最简单的rim//RimtermfloatrimPower=1;
float3rim=rimPower*saturate(1-saturate(dot(N,V))*1.8);
Rimmask用来精细地控制rim的强度,越黑的地方rim越强Jugg的面部的rimmask如下对比有没有mask和有mask的情况最后的结果BaseTintMask
BaseTintMask用来控制受speccularlight影响的地方specular的颜色,比如黄金的spec的颜色就是黄色的白银的spec的颜色就是白色,用于模拟光穿透物质表面然后反射出来物质的颜色,可以让表面表现得更加丰满。
越黑的地方表示albedo贴图对spec影响得越多。
之前的specular的颜色是这样的float3specColor=_LightColor0.rgb;
现在要这样算float3specColor=(1-texSpecularTint)*_LightColor0.rgb+texSpecularTint*difftex.xyz;
对比下
基于Cubemap的reflection通过读一张cubemap来作为反射部分。
反射和metalness还有smoothness都有关。
Cubemap贴图要设定一下
采样非常简单float3reflection=texCUBE(_ReflectionMap,worldReflect);
单纯输出reflection
将roughness加入,通过采样不同的mipmap的cubemap来达到roughness的效果,
调用的采样接口是texCUBElod:
Samplesacubetexturewithmipmaps.ThemipmapLODisspecifiedint.w.采样lod8的效果如下完成之后要将relection和之前的合在一起,按照近似的经验公式,就是直接和diffuselerp一下。
多谢@易恺铭的提示。
float3reflection=texCUBElod(_ReflectionMap,float4(worldReflect,roughness*8))*texSpecular;
…//calculatediffusediff=lerp(diff,reflection,matalValue*_Reflectance).xyz;
MaskedCombined加上之前的部分,一起调整一下
Wrapdiffusemask这个在TF2的那篇论文中有提到过。
最简单的wrapdiffuse就是halflambert,halfdiffuse=dot(normal,lightDir)*wrapAmount+(1-wrapAmount);
如果用一张一维的Wrapdiffuse贴图来处理的话,diffuse值就是从texture1DrampTex;
floatDiffuseCoeff(infloat3pos,infloat3normal,infloat3lightPos){float3lightDir=lightPos-pos;
lightDir.normalize();
//Mapvaluefrom[-1,1]to[0,1]floatrampCoord=Dot(lightDir,normal)*0.5+0.5;
returntex1D(rampTex,rampCoord);
}Dota2中rampTex变成了一张二维的图
通过不同的mask来控制采样的位置。
加上自阴影,最后调一个炫酷的剑圣
小结利用家里蹲的这段时间把这篇文章给写出来了,撒花.PBR有待更加深入的学习。
还有很多可以深入学习的地方,比如各种trick的性能profile,比如放到移动端会是怎样,怎么在低端机上也能跑。
再次感谢恺大和申屠小羊同学。
参考在Unity中复刻基于PBS的Dota2着色器//UnitySkinShaderOptimized//Dota2Workshop-ItemShaderMasks//【OpenGL】Dota2Shader分析
(1)//GameShadersVolume1-Dota2[Released]//ExtensiontoEnergy-ConservingWrappedDiffuse//Dota2Workshop-CharacterArtGuide//HowtoExploreUnity5'
sShaderSystemCode-IV-GlobalIlluminationcodeoverview//翻译Tri-Ace:
在Shader里近似渲染公式//CodingLabs:
:
PhysicallyBasedRendering//Physically-inspiredShader//TechnicalGraphicDirector//Rendering8,Reflections,aUnityC#Tutorial//Dota2ShaderMaskGuide//BlenderGLSLviewportshader//WhatisRampShadingorLighting?
//Guideoncreating/modifyingStatusEffects(withTemplate)//GPUGEM4PracticalPlanarReflectionsUsingCubemapsandImageProxies//
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Mask 艺术