Unity着色器基础

本文介绍了Unity中的着色器基础知识,包括删除默认设置以简化场景、从对象到图像的渲染过程,以及创建第一个着色器。内容涉及顶点和片段着色器、着色器属性、纹理使用和设置,帮助初学者理解Unity中的渲染原理和着色器编程。
摘要由CSDN通过智能技术生成

本文翻译自catlikecoding


1 默认场景

当你在Unity中创建一个新场景时,你会得到一个默认的camera和directional light.通过GameObject/ 3D Object/ Sphere创建一个简单的球体,把它放在原点,然后把camera放在它前面。
这里写图片描述

虽然这是很简单的场景,但已经可以进行复杂的渲染操作。为了更好地了解渲染的过程,删掉一些东西会很有帮助。

1删除

通过 Window / Lighting /Setting, 我们来看一下场景的光照设置。
这里写图片描述

我们可以在Environtment lighting中选择skybox。skybox现在被当做场景的背景使用。把skybox设为none来关闭它。

当你这么做了的时候,你也可以关闭Precomputed Realtime GI和 Baked GI,我们这次不会用到它们。

取消skybox之后,背景自动被设置成了灰蓝色。

你可能会猜测背景的颜色来自哪里。

这里写图片描述

每个camera都会定义背景,camera默认渲染skybox,但是没有skybox也会渲染默认的颜色。

这里写图片描述

为了进一步简化渲染,删掉directional light object.这样场景中不再存在光线。球体会显示阴影。

这里写图片描述

2从Object到Image

这个简单的场景通过两步渲染。首先,图片填充了camera的背景颜色。接下来球体的阴影被画在背景颜色上。

Unity是怎么知道它需要画一个球体的呢?我们有一个球体对象,并这个对象有一个mesh renderer组件。如果这个对象在camera的视野里,那么它就会被渲染。Unity通过检查对象的包围盒是否和相机视野的平截锥体相交来确认是否需要渲染。

1第一个着色器

通过Assets/ Cteate / Shader / Unlit Shader并命名,比如你可以命名My First Shader
Your first shader.

打开着色器文件,删掉它的内容,这样我们可以从0开始。

一个着色器通过Shader关键字定义。紧跟Shader关键字的时描述着色器的字符串,你可以在着色器选择菜单选择这个着色器。命名不需要和文件名相同。

Shader "Custom/My First Shader" {

}

保存文件,再把着色器赋值给一个material.使用我们自己的material改变我们的球体。球体会变成紫红色。这发生在Unity使用了一个有错误的着色器的时候,Unity使用这个颜色来告诉我们这里出问题了。

这里写图片描述

我们需要添加sub-shaders来消除这个问题,我们可以使用不同的sub-shader渲染不同的平来或者是不同等级的细节。举个例子,你可以为pc使用一个sub-shader,为手机使用另一个。这里我们只需要一个sub-shader.

Shader "Custom/My First Shader" {

    SubShader {

    }
}

一个sub-shader至少有一个pass.一个shader pass 是一个对象被渲染的地方。我们使用一个pass,但使用多个pass是可能的。使用多个pass意味着这个对象被渲染多次。

Shader "Custom/My First Shader" {

    SubShader {

        Pass {

        }
    }
}

这时球体会变成白色,因为我们使用了空白的empty的默认行为。这时我们也不再有任何的错误。

A white sphere.

2着色器程序

是时候编写我们自己的着色器程序了。我们使用Unity的着色语言来编写,Unity的着色语言是HLSL和CG渲染语言的变种。我们必须用CGPROGRAM关键字开始我们的代码,用关键字ENDCG结束。

Pass {
        CGPROGRAM

        ENDCG
}

着色器现在抱怨没有vertex program和fragment programs。每个Shader都由两个programs组成。vertex program负责处理mesh的顶点。这包括从object space到display space的转换。fragment program负责每个位于mesh三角形中像素的染色。

Vertex and fragment program.

我们需要通过pragma 指令告诉编译器使用哪个程序。

CGPROGRAM

            #pragma vertex MyVertexProgram
            #pragma fragment MyFragmentProgram

            void MyVertexProgram () {

            }

            void MyFragmentProgram () {

            }
ENDCG

3着色器合集

Unity着色器编译器根据目标平台,将我们的代码转化成其他的程序。不同的平台需要不同的解决方案。举个例子,Windows下是Direct3D,,Macs 是OpenGL,手机是OpenGL ES。

在编辑器中选择着色器,在inspector窗口中观察。它展示了一些着色器的信息,包括编译错误。你也可以点击Compile and show code 按钮,Uity会编译着色器,并在你的编辑器中输出结果,这样你可以观察生成的代码。

Shader inspector, with errors for all platforms.

4包含其他文件

为了生成有用的着色器,你需要很多模版代码, 那些定义了常用变量,函数还有其他东西的代码。如果这是C#语言,我们可以把代码放到其他类里面,但是着色器没有类。那些代码就全部扔在一个大文件里,没有类或者命名空间。

幸运的是,我们可以把代码分成多个文件。你可以使用#include指令加载不同文件的内容。一个需要包含的经典文件是 UnityCG.cginc

        CGPROGRAM

            #pragma vertex MyVertexProgram
            #pragma fragment MyFragmentProgram

            #include "UnityCG.cginc"

            void MyVertexProgram () {

            }

            void MyFragmentProgram () {

            }

            ENDCG

UnityCG.cginc是绑定到Unity我们会经常使用的包含文件。它包含了一些其他的重要文件,和一些通用的函数。

Include file hierarchy, starting at UnityCG.

UnityShaderVariables.cgnic定义了大量在渲染中必须的着色器变量,比如transformation, camera, 还有light data.如果需要的话,这些全部由Unity设置。

HLSLSupport.cginc让你的代码能够跨平台,这样你就无需担心平台指定的数据类型。

UnityInstancing.cginc专门用来instancing support。instancing support是用来降低draw调用的渲染技术。虽然UnityCG没有直接包含这个文件,但它被包含在UnityShaderVariables中。

5产生输出

为了渲染一些东西,我们的着色器程序需要产生一些输出。Vertex Program 必须返回一个顶点最后的坐标。坐标有几个参数?4个。因为我们使用的是4 X 4变换矩阵。

将函数的返回值从void改成float4,float4就是4个浮点数的集合。现在我们只需要返回0。


float4 MyVertexProgram () {
return 0;
}

现在我们会得到一个“语义缺失(missing semantics)”的错误。编译器知道了我们返回float4,但它不知道这个返回值代表什么。所以它不知道GPU会怎么处理它。我们程序的输出必须变得具

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值