a.漫反射公式:
diff=C*max(0,cos<L,N>);//C是颜色和强度_LightColor0.rgb
代码: diff=max(0,dot(i.normal,i.lightDir))//i的单位向量and单位法向量
c=tex2D(tex,i.uv)_LightColor0diff//_LightColor0表示的是场景中平行光的颜色和强度
b.高光反射公式:
Spec=pow(max(0,cos(R,V),gloss))//R 单位反射向量reflect(ray,normal)函数获取,V视线单位方向向量 ,gloss光色度
代码: Spec=pow(max(0),dot(reflect(-i.lightDir,i.normal),32))
c=c**_LightColor0*(diff+Spec)
纹理 uv坐标是顶点存储了图片上的坐标
_MainTex (“Main Tex”, 2D) = “white” {}
sampler2D _MainTex;
float4 _MainTex_ST;//Unity中 纹理_ST来默认声明该纹理的属性_MainTex_ST.xy表示Scale, Till缩放,_MainTex_ST.zw表示Transform 偏移
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);//vs输入纹理坐标和纹理值输出UV,ps对uv进行纹理采样和计算。UV通常在0-1范围,等于o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;//反射率
法线贴图:
xyz映射存成rgb值。一般存在切线空间,z轴法线方向,x轴切线方向,y轴副(法)切线方向
TANGENT_SPACE_ROTATION;//Unity来获取rotation矩阵,从模型空间到切线空间变换的矩阵。仅存在旋转和平移时,一个矩阵的转置矩阵等于他的逆矩阵。
自己实现:
float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w; //切线空间的w分量用来存储负法线向内还是向外
float3x3 rotation = float3x3(v.tangent.xyz, binormal, v.normal);//float3x3是按行存储
float3 tangentNormal = UnpackNormal(packedNormal);Unity将法线贴图纹理坐标0,1映射到正常法线坐标-1,1,返回切线空间下的法线方向。法线贴图要设置成Normal格式。该设置unity有优化 rgb值不再是法线xyz的映射了,如果不设置的话要自己算 该公式不能用。
自己实现:
tangentNormal.xy = (packedNormal.xy * 2 - 1) * _BumpScale;//坐标反映射,自己计算的方法
tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));//通过xy计算z
屏幕后处理:
void OnRenderImage(RenderTexture src, RenderTexture dest){}//全部渲染完后将调用,屏幕纹理存在src上,用来计算后通过dest返回,添加[ImageEffectOpaque]属性,可使不透明物体(AlphaTest)被渲染完后立即调用.
Graphics.Blit(src, dest);//直接copy纹理。src是屏幕当前或上一步渲染的纹理,dest是目标纹理
Graphics.Blit(src, dest, material,pass=-1);//将把src传到shader的material的_MainTex纹理。经过material(shader)的处理后输出到dest渲染到屏幕.pass默认是-1会调用所有pass,否则只调用给定顺序的pass。指定pass渲染很重要。
基于颜色变化的边缘检测:Sobel卷积算法,对边缘点进行采样计算 和特定矩阵卷积相乘。
高斯模糊:多次采样纹理混合 消耗较大
Bloom效果:把较亮区域提取出来进行高斯模糊 模拟扩散效果,然后再与原纹理混合。
运动模糊:将上一帧的屏幕图像存到renderTexture中,然后执行Graphics.Blit(src, renderTexture, material),shader将开启混合Blend SrcAlpha OneMinusSrcAlpha把src纹理和目标缓冲纹理renderTexture进行混合,然后再Blit输出到dst进行渲染。就得到了运动模糊效果。
深度和法线纹理:
float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth));
_CameraDepthNormalsTexture //unity中调用camera.depthTextureMode=DepthTextureMode.Depth/DepthNormal;这句话后可以通过该变量访问深度纹理或者深度和法线纹理,project空间
float depth=SAMPLE_DEPTH_TEXTURE(tex,uv)//对深度纹理进行采样,返回project空间下非线性深度值。和tex2D类似 只是封装了平台。自动将NDC坐标下的深度映射(0,1)需要转换到(-1,1)veiw空间去计算
LinearEyeDepth(depth)负责把深度纹理的采样结果转换到视角view空间下的线性深度值
Linear01Depth(depth)则会返回一个范围在0,1的线性深度值
half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv);
half2 centerNormal = DecodeViewNormalStereo(sample1);//center.xy存的法线的映射值
float centerDepth = DecodeFloatRG(center.zw);//zw深度
DecodeDepthNormal(sample1,out centerNormal,out centerDepth)//获取采样的法线和深度
Camera.worldToCameraMatrix //世界转相机矩阵 world2view
Camera.cameraToWorldMatrix //相机转世界矩阵
Camera.projectionMatrix //get投影矩阵viewToproject 视角空间到2维投影空间矩阵,set自定义的投影矩阵。如果你改变这个矩阵,相机的渲染不再基于它的fieldOfView更新,直到调用ResetProjectionMatrix
默认把view2project矩阵叫成project矩阵,默认把World2view矩阵叫做view矩阵。比如ViewProject就是world 2 project矩阵
全局雾效
深度雾效:通过每个顶点的深度值计算出该点到摄像机的距离d,然后把距离d进行参与公式计算得到雾效图(远的雾浓 rgb值大,近的雾淡 rgb值小),再把原图和雾效图进行混合。一般用线性,指数,指数平方公式,ds采用指数平方。
地面雾效:通过深度值和摄像机的方向向量计算该点到摄像机的偏移量,再加上摄像机的位置得到该顶点在世界空间中的坐标,然后把该坐标的y值参与雾效计算。如果用坐标z参与计算和深度雾类似。
#pragma multi_compile_fog
基于法线的边缘检测:防止阴影等信息干扰检测,判断临近的4个点的法线和深度值是否是近似,如果差距过大则是边缘roberts算法。(屏幕后处理)
渲染轮廓线:第一个pass对顶点进行法线方向扩散渲染,第二个pass用真实渲染实际光照,覆盖第一次,对扩散的顶点未被覆盖的像素就产生了轮廓效果。(模型轮廓)
噪声:
消融效果:怪物消失渐散的效果,把某个像素值小于阈值的裁剪掉,阈值附近的值用burncolor进行混合。阴影的pass里边算阴影时也把该项给clip掉,这样阴影就动态变化了//clip(burn.r - _BurnAmount);
水面扰动效果:用时间去控制偏移距离,然后对该顶点的uv偏移两点的法线平均值来代替该点的法线值。水面=反射+折射+绕动
float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);
/ Get the normal in tangent space
fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;
fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;
fixed3 bump = normalize(bump1 + bump2);
全局(动态)雾效:通过时间控制噪声纹理的偏移距离,然后根据噪声颜色值来参与计算雾效浓度,然后计算雾效,就有了流动和淡浓的效果。
来源:CSDN
作者:洛初_Rakuui
链接:https://blog.csdn.net/weixin_44279708/article/details/103539685