shader入门精要2

在看shader入门精要。

第五章 shader学习之旅

如何使用属性

Shader "Book/Chapter 5/Simple Shader" {
    Properties {
        _Color ("Color Tint", Color) = (1.0,1.0,1.0,1.0)
    }
    SubShader {
        Pass {
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            
            //定义一个与属性名称和类型都匹配的变量
            fixed4 _Color; // 前面要加uniform?
            
            struct a2v {...};
            
            struct v2f{...};
            
            v2f vert(a2v v) : SV_POSITION {
            ...
            }
            
            fixed4 frag(v2f i) : SV_Target {
                fixed3 c = i.color;
                c *= _Color.rgb;
                return fixed4(c, 1.0);
            }
            
            ENDCG
        }
    }
}

强大的援手:Unity提供的内置文件和变量

内置包含文件

CGPROGRAM
#include "UnityCG.cginc"
ENDCG

可以在 http://unity3d.com/cn/get-unity/download/archive

unity程序目录下,CGIncludes 也包含了相关文件。

Unity提供的CG/HLSL语义

更具体内容看DirectX相关文档。

从应用阶段传递模型数据给顶点着色器时Unity支持的常用语义

POSITION模型空间中顶点位置,通常是float4类型
NORMAL顶点法线,float3
TANGENT顶点切线,float4
TEXCOORDn该顶点的纹理坐标,float2 or float4
COLOR顶点颜色,fixed4 or float4

从顶点着色器阶段到片元着色器阶段的语义

SV_POSITION裁剪空间中的顶点坐标,
COLOR0顶点颜色
COLOR1顶点颜色
TEXCOORD0~7纹理坐标

Debug

使用假彩色

Visual Studio

帧调试器

第六章 Unity中的基础光照

省略的具体公式,具体看书啦。

光源

自发光,环境光

辐照度(irradiance) 对于平行光,它的辐照度是垂直于光的单位面积上单位时间内穿过的能量。

吸收和散射

折射、透射、反射

高光反射(specular)

漫反射(diffuse)

着色(shading)

BRDF(Bidirectional Reflectance Distribution Function)光照模型

大多使用一个数学公式表示,并且提供了一些参数来调整光照能量分布。它可以给出在某个出射方向上的光照能量分布。

标准光照模型

把进入摄像机的光线分为4个部分,每个部分使用一种方法来计算它的贡献度。

  • 自发光(emissive)部分。往往不会照亮周围物体。

  • 高光反射(specular)部分。

  • 漫反射(diffuse)。

  • 环境光(ambient)。unity shader可以通过UNITY_LIGHTMODEL_AMBIENT得到环境光的颜色和强度信息。

基于基本的光照模型的数学公式。可以选择:在片元着色器中计算,也叫逐像素光照(per-pixel lighting);在顶点着色器中计算,也叫逐顶点光照(per-vertex lighting)。

在UnityShader中实现漫反射光照模型

逐顶点光照

SubShader {
    Pass {
        Tags {"LightMode"="ForwardBase"}

LightMode标签是Pass标签中的一种,它用于定义该Pass在Unity的光照流水线中的角色,通过这个操作,我们才能得到一些Unity的内置光照变量。

实践:逐顶点光照

v2f vert(a2v v) {
    v2f o;
    // transform the vertex from object space to projection space
    o.pos = mul (UNITY_MATRI_MVP, v.vertex);
    // get ambient term
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    //transform the normal from object space to world space
    fixed3 worldNormal = normalize(mul(v.normal, (float3x3)_World2Object));
    //get the light direction in world space
    fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
    //compute diffuse term
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
    o.color = ambient + diffuse;
    return o;
}

顶点着色器最基本任务是把顶点位置从模型空间转换到裁剪空间中,因此我们需要使用Unity内置的模型 * 世界 * 投影矩阵 UNITY_MATRIX_MVP 来完成这样的坐标变换。通过Unity的内置变量UINTY_LIGHTMODEL_AMBIENT得到环境光部分。

_Diffuse 材质的漫反射颜色

v.normal顶点法线

内置变量_LightColor0,该Pass处理的光源的颜色和强度信息(注意,需要定义合适的LightMode标签)

_WorldSpaceLightPos0光源方向

实践:逐像素光照

//顶点着色器的输出结构体
struct v2f {
    float4 pos : SV_POSITION;
    float3 worldNormal : TEXCOORD0;
}
//顶点着色器不需要计算光照模型,只需要把世界空间下的法线传递给片元着色器
v2f vert(a2v v) {
    //transform the vertex from object space to projection space
    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    //transform the normal from object space to world space
    o.worldNormal = mul(v.normal, (float3x3)_World2Object);
    return o;
}
//片元着色器需要计算漫反射光照模型
fixed4 frag(v2f i) : SV_Target {
    // get ambient term
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    //get the normal in world space
    fixed3 worldNormal = normalize(i.worldNormal);
    fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
    //compute diffuse term
    fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));
    fixed3 color = ambient + diffuse;
    return fixed4(color,1.0);
}

目前,逐像素漫反射光照的问题是,在光照无法到达的区域,模型的外观通常是全黑的,没有任何明暗变化。改善技术,下面的。

半兰伯特模型(Half Lambert)

高光反射光照模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FatherOfCodingMan

如果觉得有用的话,可以赏点饭钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值