赞
踩
本文出发点在于,从shader可视化工具制作的shader导出的表面着色器,需要进行重写!
从编辑器中导出的着色器,很多事表面着色器,表面着色器是unity提供的一种更高层的封装,虽然降低了shader入门的难度,但是这种shader,会包含大量的变体,里面的逻辑由于封装而无法被开发者控制,所以,需要将表面着色器转换为顶点片元着色器;前提:需要在一定程度上了解表面着色器,如果不了解,推荐可以简单看一下官方文档,或《Unity Shader入门精要》- 17章;
可以选择直接重写,但有时,如果想要完整复现导出的surface着色器,可以通过先将其转换为顶点片元着色器,然后移除不必要的代码,再根据其顶点片元着色器来理解它究竟真正做了什么工作;
随便新建一个表面着色器,然后转换为顶点片元着色器,及时是一个简单的lamber模型,我们可以看到会生成上千行代码,并带来很多变体;
我们的剔除工作就是根据不必要的变体关键字来去除,首先是移除不必要的pass,可以搜索pass关键字,然后将第一个pass之后的全部移除,他们通常是不必要的;然后只关心一个pass,可以看到它根据不同的宏定义了不同的结构体和片元着色器,根据ifdef和ifndef等可以去除;最后得到一个只有一个顶点和片元着色器的pass,去尝试着理解这个pass里做了什么;当然,剔除的时候要关注材质效果是否发生了变化,如果发生了变化,那说明删除的代码是受到影响的;
最终可以得到一个简易版本,如下是一个简单的lambert模型:
- // Upgrade NOTE: replaced 'defined FOG_COMBINED_WITH_WORLD_POS' with 'defined (FOG_COMBINED_WITH_WORLD_POS)'
-
- Shader "SurfaceTest/Surf2Vert" {
- Properties {
- _MainTex ("Texture", 2D) = "white" {}
- _Color ("Main Color", Color) = (1,1,1,1)
- }
- SubShader {
- Tags { "RenderType" = "Opaque" }
-
- // ------------------------------------------------------------
- // Surface shader code generated out of a CGPROGRAM block:
-
-
- // ---- forward rendering base pass:
- Pass {
- Name "FORWARD"
- Tags { "LightMode" = "ForwardBase" }
-
- CGPROGRAM
- // compile directives
- #pragma vertex vert_surf
- #pragma fragment frag_surf
- #pragma multi_compile_instancing
- #pragma multi_compile_fog
- #pragma multi_compile_fwdbase
- #include "HLSLSupport.cginc"
- #define UNITY_INSTANCED_LOD_FADE
- #define UNITY_INSTANCED_SH
- #define UNITY_INSTANCED_LIGHTMAPSTS
- #include "UnityShaderVariables.cginc"
- #include "UnityShaderUtilities.cginc"
- // -------- variant for: <when no other keywords are defined>
- #if !defined(INSTANCING_ON)
-
- #include "UnityCG.cginc"
- #include "Lighting.cginc"
- #include "AutoLight.cginc"
-
- #define INTERNAL_DATA
- #define WorldReflectionVector(data,normal) data.worldRefl
- #define WorldNormalVector(data,normal) normal
-
-
- half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
- half NdotL = dot (s.Normal, lightDir);
- half4 c;
- c.rgb = s.Albedo * _LightColor0.rgb * max(0, NdotL);
- c.a = s.Alpha;
- return c;
- // return fixed4(0,0,0,1);
- }
-
- struct Input {
- float2 uv_MainTex;
- };
-
- sampler2D _MainTex;
- fixed4 _Color;
-
- void surf (Input IN, inout SurfaceOutput o) {
- o.Albedo = tex2D(_MainTex, IN.uv_MainTex) * _Color;
- // o.Albedo = fixed4(0,1,0,1);
- }
-
- // high-precision fragment shader registers:
- #ifndef UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS
- struct v2f_surf {
- UNITY_POSITION(pos);
- float2 pack0 : TEXCOORD0; // _MainTex
- float3 worldNormal : TEXCOORD1;
- float3 worldPos : TEXCOORD2;
- fixed3 vlight : TEXCOORD3; // ambient/SH/vertexlights
- UNITY_FOG_COORDS(4)
- UNITY_SHADOW_COORDS(5)
- #if SHADER_TARGET >= 30
- float4 lmap : TEXCOORD6;
- #endif
- UNITY_VERTEX_INPUT_INSTANCE_ID
- UNITY_VERTEX_OUTPUT_STEREO
- };
- #endif
- // with lightmaps:
-
- float4 _MainTex_ST;
-
- // vertex shader
- v2f_surf vert_surf (appdata_full v) {
- // UNITY_SETUP_INSTANCE_ID(v);
- v2f_surf o;
- // UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
- // UNITY_TRANSFER_INSTANCE_ID(v,o);
- // UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
- o.pos = UnityObjectToClipPos(v.vertex);
- o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
- float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
- float3 worldNormal = UnityObjectToWorldNormal(v.normal);
- o.worldPos.xyz = worldPos;
- o.worldNormal = worldNormal;
-
- // SH/ambient and vertex lights
- #ifndef LIGHTMAP_ON
- #if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
- float3 shlight = ShadeSH9 (float4(worldNormal,1.0));
- o.vlight = shlight;
- #else
- o.vlight = 0.0;
- #endif
- #endif // !LIGHTMAP_ON
-
- // UNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy); // pass shadow and, possibly, light cookie coordinates to pixel shader
- // #ifdef FOG_COMBINED_WITH_TSPACE
- // UNITY_TRANSFER_FOG_COMBINED_WITH_TSPACE(o,o.pos); // pass fog coordinates to pixel shader
- // #elif defined (FOG_COMBINED_WITH_WORLD_POS)
- // UNITY_TRANSFER_FOG_COMBINED_WITH_WORLD_POS(o,o.pos); // pass fog coordinates to pixel shader
- // #else
- // UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader
- // #endif
- return o;
- }
-
- // fragment shader
- fixed4 frag_surf (v2f_surf IN) : SV_Target {
- UNITY_SETUP_INSTANCE_ID(IN);
- // prepare and unpack data
- Input surfIN;
- UNITY_INITIALIZE_OUTPUT(Input,surfIN);
- surfIN.uv_MainTex.x = 1.0;
- surfIN.uv_MainTex = IN.pack0.xy;
- float3 worldPos = IN.worldPos.xyz;
- #ifndef USING_DIRECTIONAL_LIGHT
- fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
- #else
- fixed3 lightDir = _WorldSpaceLightPos0.xyz;
- #endif
- #ifdef UNITY_COMPILER_HLSL
- SurfaceOutput o = (SurfaceOutput)0;
- #else
- SurfaceOutput o;
- #endif
- o.Albedo = 0.0;
- o.Emission = 0.0;
- o.Specular = 0.0;
- o.Alpha = 0.0;
- o.Gloss = 0.0;
- fixed3 normalWorldVertex = fixed3(0,0,1);
- // return fixed4(0.5* normalize(IN.worldNormal)+0.5, 1);
- o.Normal = IN.worldNormal;
- normalWorldVertex = IN.worldNormal;
-
- surf (surfIN, o);
-
- UNITY_LIGHT_ATTENUATION(atten, IN, worldPos)
- fixed4 c = 0;
-
- #ifndef LIGHTMAP_ON
- c.rgb += o.Albedo * IN.vlight;
- #endif
-
- #ifndef LIGHTMAP_ON
- c += LightingSimpleLambert (o, lightDir, atten);
- // return c;
- #else
- c.a = o.Alpha;
- #endif
-
- UNITY_APPLY_FOG(_unity_fogCoord, c); // apply fog
- UNITY_OPAQUE_ALPHA(c.a);
- return c;
- }
- #endif
-
- ENDCG
-
- }
-
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。