找回密码
 立即注册
查看: 592|回复: 0

[简易教程] 【译】Ronja的Unity Shader教程(二)

[复制链接]
发表于 2020-12-5 07:44 | 显示全部楼层 |阅读模式
Summary

第二节,我将解释要使Unity Shader显示图形,必须执行哪些操作。最终会得到一个只有一种颜色的对象,但可以稍后再添加一些效果。如果您发现理解所有内容都有困难,我建议您阅读:【译】Ronja的Shader入门教程(一)
Shaderlab 框架

当在Unity中编写Shader时,我们首先必须告诉Unity它应该如何使用我们的Shader。这就是为什么我们首先用着色器的名称定义“Shader”部分,然后在“SubShader”部分内部定义。我们可以为每个Shader定义多个SubShader,并告诉Unity何时使用哪个SubShader,但大多数情况下,我们希望在任何地方都使用相同的SUbShader。
Shader "Tutorial/02_Simple"{
    Subshader{

    }
}在该SubShader中,我们将写Shader pass。渲染SubShader时,所有过程都是连续绘制的,但目前我们只需要一个pass。在该pass中,我们添加一些Tags来告诉Unity我们希望它如何处理该pass。对于此Shader,我们希望渲染的对象是Opaque,完全不透明的,并且希望它与其他不透明对象一起渲染。
Shader "Tutorial/02_Simple"{
    Subshader{
        Pass{
            Tags{
                "RenderType"="Opaque"
                "Queue"="Geometry"
            }

        }
    }
}HLSL Code

现在我们可以开始编写Shader的HLSL部分。了解数据在Shader中的处理方式非常重要。首先,3D模型中的信息被提供给顶点Shader(vertex shader),使其相对于屏幕,然后结果通过光栅化器(Rasterizer),将点和三角形转换为可以在屏幕上绘制的像素。但此时Shader还不知道每个像素具有哪种颜色,因此对于对象的每个像素,都会调用片段Shader(fragment shader)。它接收顶点shader的输出,顶点之间带有插补值。然后,片段shader返回在屏幕上绘制的颜色。
Rasterizer:光栅化器
为了让Unity知道我们在这里编写HLSL代码,我们从CGPROGRAM开始,以ENDCG结束。为了使用unity提供给我们的实用函数,我们需要包含“UnityCG.cginc”文件。
Shader "Tutorial/02_Simple"{
    Subshader{
        Pass{
            Tags{
                "RenderType"="Opaque"
                "Queue"="Geometry"
            }

            CGPROGRAM
            #include "unityCG.cginc"

            ENDCG
        }
    }
}我们首先为输入数据添加一个结构。它通常被称为“appdata”,目前我们只获取对象的顶点位置。
struct appdata{
    float4 vertex : POSITION;
}然后我们编写一个结构,顶点shader将返回该结构。现在我们只需要顶点相对于屏幕的位置。为了让unity知道这就是变量中的数据,我们用SV_POSITION属性标记它。
struct v2f{
    float4 position : SV_POSITION;
}接下来是顶点Shader,它将顶点返回到片段结构,并获取appdata中的对象信息。首先,我们初始化结构的新实例,然后用顶点的屏幕坐标填充它,并将其返回给光栅化器处理。UnityObjectToClipPos函数位于UnityCG.cginc文件中,帮我们解决了坐标转换的矩阵乘法。
v2f vert(appdata v){
    v2f o;
    o.position = UnityObjectToClipPos(v.vertex);
    return o;
}最后,编写片段Shader。现在我们只返回红色,后面的教程会加入更多东西。我们必须将函数标记为SV_TARGET,以便Unity知道此函数的结果将在屏幕上绘制。
fixed4 frag(v2f i) : SV_TARGET{
    return fixed4(0.5, 0, 0, 1);
}在编写了我们的数据类型和函数之后,我们必须告诉unity哪个函数是用来做什么的,这是通过 #scrima shaderFunction 来完成的,所以我们用#pragma vertex vert 告诉Unity我们的顶点shader,用 #pragma fragment frag 告诉Unity我们的片段着shader。
Shader "Tutorial/01_Basic"{
        SubShader{
                Tags{
                                "RenderType"="Opaque"
                                "Queue"="Geometry"
                        }
                Pass{
                       

                        CGPROGRAM
                        #include "UnityCG.cginc"

                        #pragma vertex vert
                        #pragma fragment frag

                        struct appdata{
                                float4 vertex : POSITION;
                        };

                        struct v2f{
                                float4 position : SV_POSITION;
                        };

                        v2f vert(appdata v){
                                v2f o;
                                o.position = UnityObjectToClipPos(v.vertex);
                                return o;
                        }

                        fixed4 frag(v2f i) : SV_TARGET{
                                return fixed4(0.5, 0, 0, 1);
                        }

                        ENDCG
                }
        }
}下图展示了如何将编写好的shader指定给材质并渲染物体。


源码repo地址:
You can find the source code of the shader here: https://github.com/ronja-tutorials/ShaderTutorials/blob/master/Assets/002_basic/basic_color.shader
作者本人信息:
You can also find me on twitter at @totallyRonja. If you liked my tutorial and want to support me you can do that on Patreon (patreon.com/RonjaTutorials) or Ko-Fi (ko-fi.com/RonjaTutorials).

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-23 10:32 , Processed in 0.091653 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表