网站设计需要考虑的基本原则,广东企业网站模板定制,网站建设河南公司,医疗营销网站建设方案素描风格渲染#xff08;Hatching Style Rendering#xff09;#xff0c;是一种非真实感渲染#xff08;NPR#xff09;#xff0c;主要目的是使3D模型看起来像 手绘素描的视觉效果。这种风格的渲染常用于游戏、动画和电影中#xff0c;用来创造一种独特的艺术风格 1、…素描风格渲染Hatching Style Rendering是一种非真实感渲染NPR主要目的是使3D模型看起来像 手绘素描的视觉效果。这种风格的渲染常用于游戏、动画和电影中用来创造一种独特的艺术风格 1、基本原理
用漫反射系数决定采样权重在多张具有不同密度和方向的素描纹理中进行采样并将采样结果进行叠加得到最终效果 关键点
多张具有不同密度和方向的素描纹理
美术需要提供多张素描纹理我们之后会根据不同位置的光照强度决定从哪种纹理中进行采样 漫反射系数决定采样权重
通过兰伯特光照模型中的
max0, 标准化后物体表面法线向量· 标准化后光源方向向量* 素描纹理数 1 将漫反射光照强度 0~1 扩充到 0~N 如果是6张素描纹理那么就是 0 ~ 7 根据不同顶点的不同光照决定在哪一张纹理中进行采样的权重更大该权重决定最后的颜色叠加 6~7不在素描纹理中采样; 5~6第1张素描纹理中采样; 4~5第1、2素描张纹理中采样; 3~4第2、3张纹理中采样; 2~3第3、4张纹理中采样; 1~2第4、5张纹理中采样; 0~1第5、6张纹理中采样;
采样结果进行叠加
根据之前的权重计算越亮的地方、越趋近于白色或使用的素描纹理中线条更少更稀疏 而越暗的地方使用的素描纹理中线条更密集。 因此只需要使用之前的权重值和纹理采样结果相乘最后将纹理颜色进行叠加即可
2、实现
Version 1:
Shader ShaderProj/20/Sketch
{Properties{_Color (Color, Color) (1,1,1,1)_TileFactor (TileFactor, Float) 1_Sketch0 (Sketch0, 2D) {}_Sketch1 (Sketch1, 2D) {}_Sketch2 (Sketch2, 2D) {}_Sketch3 (Sketch3, 2D) {}_Sketch4 (Sketch4, 2D) {}_Sketch5 (Sketch5, 2D) {}}SubShader{Tags { RenderTypeOpaque }Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include UnityCG.cgincstruct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;// x,y,z 分别代表第 123张素描纹理的权重fixed3 sketchWeight0 : TEXCOORD1;// x,y,z 分别代表第 456张素描纹理的权重fixed3 sketchWeight1 : TEXCOORD2;};fixed4 _Color;float _TileFactor;sampler2D _Sketch0;sampler2D _Sketch1;sampler2D _Sketch2;sampler2D _Sketch3;sampler2D _Sketch4;sampler2D _Sketch5;v2f vert (appdata_base v){v2f o;o.vertex UnityObjectToClipPos(v.vertex);// uv 坐标平铺缩放值越大细节越多o.uv v.texcoord.xy * _TileFactor;fixed3 worldLightDir normalize(WorldSpaceLightDir(v.vertex));fixed3 worldNormal normalize(UnityObjectToWorldNormal(v.normal));fixed diffFac max(0, dot(worldLightDir, worldNormal)) * 7.0;o.sketchWeight0 fixed3(0, 0, 0);o.sketchWeight1 fixed3(0, 0, 0);if (diffFac 6.0){}// 最亮的部分不从纹理中采样else if(diffFac 5.0) // 从第1张图中采样{o.sketchWeight0.x diffFac - 5.0;}else if(diffFac 4.0) // 从第2张图中采样{o.sketchWeight0.y diffFac - 4.0;}else if (diffFac 3.0) // 从第3张图中采样{ o.sketchWeight0.z diffFac - 3.0;} else if (diffFac 2.0) // 从第4张图中采样{ o.sketchWeight1.x diffFac - 2.0;}else if (diffFac 1.0) // 从第5张图中采样{o.sketchWeight1.y diffFac - 1.0;}else // 从第6张图中采样{o.sketchWeight1.z diffFac;}return o;}fixed4 frag (v2f i) : SV_Target{fixed4 sketchColor0 tex2D(_Sketch0, i.uv) * i.sketchWeight0.x;fixed4 sketchColor1 tex2D(_Sketch1, i.uv) * i.sketchWeight0.y;fixed4 sketchColor2 tex2D(_Sketch2, i.uv) * i.sketchWeight0.z;fixed4 sketchColor3 tex2D(_Sketch3, i.uv) * i.sketchWeight1.x;fixed4 sketchColor4 tex2D(_Sketch4, i.uv) * i.sketchWeight1.y;fixed4 sketchColor5 tex2D(_Sketch5, i.uv) * i.sketchWeight1.z;// 最亮的部分白色fixed4 whiteColor fixed4(1,1,1,1) * (1 - i.sketchWeight0.x - i.sketchWeight0.y - i.sketchWeight0.z - i.sketchWeight1.x - i.sketchWeight1.y - i.sketchWeight1.z);fixed4 sketchColor whiteColor sketchColor0 sketchColor1 sketchColor2 sketchColor3 sketchColor4 sketchColor5;return fixed4(sketchColor.rgb, 1);}ENDCG}}
}现在是有问题的可以看到材质球最暗的部分显示的是白色同时有黑色的部分会有白色的条纹这分别是因为
当跑到 【o.sketchWeight1.z diffFac】 的分支时值是很小的趋近于0 因此最终计算的 whiteColor 基本为白色当跑到【o.sketchWeight0.x diffFac - 5.0】的分支时如果 diffFac 趋近于 5那么权重也几近于 0因此在该分支的边缘部分会变成白色
为了解决这个问题可以每个分支用两张纹理进行采样采样权重用【1- weight】这样就可以在计算 whiteColor 的时候减少白色的填充除了最亮的地方因为本来就是白色
Shader ShaderProj/20/Sketch
{Properties{_Color (Color, Color) (1,1,1,1)_TileFactor (TileFactor, Float) 1_Sketch0 (Sketch0, 2D) {}_Sketch1 (Sketch1, 2D) {}_Sketch2 (Sketch2, 2D) {}_Sketch3 (Sketch3, 2D) {}_Sketch4 (Sketch4, 2D) {}_Sketch5 (Sketch5, 2D) {}_OutLineColor (OutLineColor, Color) (1,1,1,1)_OutLineWidth (OutLineWidth, Range(0,0.1)) 0.04}SubShader{Tags { RenderTypeOpaque }UsePass ShaderProj/19/Kartoon/OUTLINEPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include UnityCG.cginc#include Lighting.cginc#include AutoLight.cgincstruct v2f{float2 uv : TEXCOORD0;float4 pos : SV_POSITION;// x,y,z 分别代表第 123张素描纹理的权重fixed3 sketchWeight0 : TEXCOORD1;// x,y,z 分别代表第 456张素描纹理的权重fixed3 sketchWeight1 : TEXCOORD2;float3 worldPos: TEXCOORD3;SHADOW_COORDS(4)};fixed4 _Color;float _TileFactor;sampler2D _Sketch0;sampler2D _Sketch1;sampler2D _Sketch2;sampler2D _Sketch3;sampler2D _Sketch4;sampler2D _Sketch5;v2f vert (appdata_base v){v2f o;o.pos UnityObjectToClipPos(v.vertex);// uv 坐标平铺缩放值越大细节越多o.uv v.texcoord.xy * _TileFactor;o.worldPos mul(unity_ObjectToWorld, v.vertex).xyz;TRANSFER_SHADOW(o);fixed3 worldLightDir normalize(WorldSpaceLightDir(v.vertex));fixed3 worldNormal normalize(UnityObjectToWorldNormal(v.normal));fixed diffFac max(0, dot(worldLightDir, worldNormal)) * 7.0;o.sketchWeight0 fixed3(0, 0, 0);o.sketchWeight1 fixed3(0, 0, 0);if (diffFac 6.0){}// 最亮的部分不从纹理中采样else if(diffFac 5.0) // 从第1张图中采样{o.sketchWeight0.x diffFac - 5.0;}else if(diffFac 4.0) // 从第1, 2张图中采样{o.sketchWeight0.x diffFac - 4.0;o.sketchWeight0.y 1- o.sketchWeight0.x;}else if (diffFac 3.0) // 从第2, 3张图中采样{ o.sketchWeight0.y diffFac - 3.0;o.sketchWeight0.z 1 - o.sketchWeight0.y;} else if (diffFac 2.0) // 从第3, 4张图中采样{ o.sketchWeight0.z diffFac - 2.0;o.sketchWeight1.x 1 - o.sketchWeight0.z;}else if (diffFac 1.0) // 从第4, 5张图中采样{o.sketchWeight1.x diffFac - 1.0;o.sketchWeight1.y 1 - o.sketchWeight1.x;}else // 从第5, 6张图中采样{o.sketchWeight1.y diffFac;o.sketchWeight1.z 1 - o.sketchWeight1.y;}return o;}fixed4 frag (v2f i) : SV_Target{fixed4 sketchColor0 tex2D(_Sketch0, i.uv) * i.sketchWeight0.x;fixed4 sketchColor1 tex2D(_Sketch1, i.uv) * i.sketchWeight0.y;fixed4 sketchColor2 tex2D(_Sketch2, i.uv) * i.sketchWeight0.z;fixed4 sketchColor3 tex2D(_Sketch3, i.uv) * i.sketchWeight1.x;fixed4 sketchColor4 tex2D(_Sketch4, i.uv) * i.sketchWeight1.y;fixed4 sketchColor5 tex2D(_Sketch5, i.uv) * i.sketchWeight1.z;// 最亮的部分白色fixed4 whiteColor fixed4(1,1,1,1) * (1 - i.sketchWeight0.x - i.sketchWeight0.y - i.sketchWeight0.z - i.sketchWeight1.x - i.sketchWeight1.y - i.sketchWeight1.z);fixed4 sketchColor whiteColor sketchColor0 sketchColor1 sketchColor2 sketchColor3 sketchColor4 sketchColor5;UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);return fixed4(sketchColor.rgb * atten * _Color.rgb, 1);}ENDCG}}Fallback Diffuse
}