unity shader 较完整光照(含有多光源阴影)

在Unity引擎中,开发者可以使用Shader编写自定义着色器,来实现对游戏场景中的模型、材质进行更加高级的渲染。其中,光照是Shader编写中十分重要的一个环节,一个较完整的光照着色器需要包括基础光照、多光源、阴影等要素。下面介绍一些实现这些功能的方法:

1. 基础光照

在Unity中,使用Built-in Shader中的“Surface Shader”或“Unlit Shader”都提供基础光照的功能。如果需要自定义光照模型,则需要使用ShaderLab来手动编写对应的光照部分。

在ShaderLab代码中,可以使用光照计算的内置函数,如Lightinglighthalf4 AmbientLight等。通过计算每个像素点的法线、反射光、漫反射光等参数,可以模拟光照的效果。

以下是一个简单的基础光照示例:

Shader "Custom/LightingExampleShader" {
    Properties {
        _MainTex("Texture", 2D) = "white" {}
    }

    SubShader {
        Tags {
            "RenderType"="Opaque"
        }

        CGPROGRAM
        #pragma surface surf Standard

        struct Input {
            float2 uv_MainTex;
        };

        sampler2D _MainTex;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
            o.Metallic = 0.5;
            o.Smoothness = 0.5;
            o.Normal = float3(0,0,1);
        }

        ENDCG
    }

    FallBack "Diffuse"
}

2. 多光源

Unity内置提供了多种光源类型,例如:点光源、方向光,聚光灯等。使用Shader编写的时候,可以通过内置的_LightColor0_LightColor1等Uniform来获取不同光源的颜色。同时也可以自定义Uniform变量,来获取光源的位置、方向、光照范围等属性。

以下是一个简单的多光源示例,在渲染过程中,使用了两个点光源和一个方向光:

Shader "Custom/MultiLightExampleShader" {
    Properties {
        _MainTex("Texture", 2D) = "white" {}
    }

    SubShader {
        Tags {
            "RenderType"="Opaque"
        }

        CGPROGRAM
        #pragma surface surf Standard

        struct Input {
            float2 uv_MainTex;
        };

        sampler2D _MainTex;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            float3 lightingColor = float3(0,0,0);

            // Point Light 1
            float3 pointLight1Dir = _WorldSpaceLightPos0.xyz - UnityObjectToWorldPos(float3(0,0,0));
            float3 pointLight1Color = _LightColor0.rgb;
            float3 pointLight1Attenuation = UnityInverseSquaredDistance(UnityObjectToWorldPos(float3(0,0,0)), _WorldSpaceLightPos0);

            lightingColor += pointLight1Color * pointLight1Attenuation * max(dot(normalize(IN.worldNormal), normalize(pointLight1Dir)), 0);

            // Point Light 2
            float3 pointLight2Dir = _WorldSpaceLightPos1.xyz - UnityObjectToWorldPos(float3(0,0,0));
            float3 pointLight2Color = _LightColor1.rgb;
            float3 pointLight2Attenuation = UnityInverseSquaredDistance(UnityObjectToWorldPos(float3(0,0,0)), _WorldSpaceLightPos1);

            lightingColor += pointLight2Color * pointLight2Attenuation * max(dot(normalize(IN.worldNormal), normalize(pointLight2Dir)), 0);

            // Directional Light
            float3 directionalLightDir = _WorldSpaceLightPos2.xyz;
            float3 directionalLightColor = _LightColor2.rgb;

            lightingColor += directionalLightColor * max(dot(normalize(IN.worldNormal), normalize(directionalLightDir)), 0);

            o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
            o.Metallic = 0.5;
            o.Smoothness = 0.5;
            o.Normal = float3(0,0,1);
            o.Emission = lightingColor;
        }

        ENDCG
    }

    FallBack "Diffuse"
}

3. 阴影

Unity的光照计算支持实时阴影。使用Shader绘制的物体在有灯光照射下,会产生阴影效果。Unity提供了内置的ShadowMap,可以通过内置的函数来获取阴影采样。

以下是一个简单的实时阴影示例:

Shader "Custom/ShadowExampleShader" {
    Properties {
        _MainTex("Texture", 2D) = "white" {}
    }

    SubShader {
        Tags {
            "RenderType"="Opaque"
        }

        CGPROGRAM
        #pragma surface surf Standard

        struct Input {
            float2 uv_MainTex;
            float3 worldPos;
            float3 worldNormal;
        };

        sampler2D _MainTex;
        float4x4 _WorldToShadow;
        sampler2D _ShadowMapTexture;
        float4 _ShadowMapTexture_ST;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            float4 shadowUV = UnityShadowCoord(IN.worldPos);
            shadowUV.z += 0.0001;
            float shadowValue = tex2D(_ShadowMapTexture, shadowUV.xy).r;

            float3 lightingColor = float3(0,0,0);

            float3 pointLightDir = _WorldSpaceLightPos0.xyz - IN.worldPos;
            float3 pointLightColor = _LightColor0.rgb;
            float3 pointLightAttenuation = UnityInverseSquaredDistance(IN.worldPos, _WorldSpaceLightPos0);

            lightingColor += pointLightColor * pointLightAttenuation * max(dot(normalize(IN.worldNormal), normalize(pointLightDir)), 0) * shadowValue;

            o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
            o.Metallic = 0.5;
            o.Smoothness = 0.5;
            o.Normal = float3(0,0,1);
            o.Emission = lightingColor;
        }

        ENDCG
    }

    FallBack "Diffuse"
}

以上就是一个较完整的光照Shader的几个要点,开发者可以根据自己的需求来进行进一步的改良。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:unity shader 较完整光照(含有多光源阴影) - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • C#实现根据图片的链接地址获取图片的后缀名

    当我们给很多图片命名时,我们通常会使用图片的结尾部分作为图片的后缀名。因此,获取图片的后缀名是一项非常常见的任务。在C#中,我们可以通过一定的代码实现获取图片的后缀名。 首先,我们需要明确一下目标:根据图片的链接地址获取图片的后缀名。这个目标可以分解为以下几个步骤: 从链接地址中获取图片的文件名; 将文件名转换成小写形式; 从文件名中获取后缀名。 以下是详细…

    C# 2023年6月1日
    00
  • WinForm中DefWndProc、WndProc与IMessageFilter的区别

    WinForm是Windows Forms的缩写,是基于Windows的用户界面框架,提供了一个可视化的设计工具。在WinForm中,程序的窗口消息都是通过消息循环和窗口过程来处理的。其中DefWndProc、WndProc和IMessageFilter都是处理窗口消息的重要概念。接下来我将针对这三个概念进行详细讲解: DefWndProc DefWndPr…

    C# 2023年6月7日
    00
  • C#使用对象序列化类库MessasgePack

    下面就为您详细讲解一下 C# 使用对象序列化类库 MessasgePack 的完整攻略。 MessagePack 简介 MessagePack 是一种高效的二进制序列化格式,它比 JSON、XML 等其他格式更节省存储空间、更快的数据序列化和反序列化速度。它具有跨语言、轻量级、易于使用、可扩展等特点,广泛应用于 Web 应用、移动应用、游戏开发等领域。 为什…

    C# 2023年5月31日
    00
  • 在.NET Core类库中使用EF Core迁移数据库到SQL Server的方法

    在 .NET Core 类库中使用 EF Core 迁移数据库到 SQL Server 的方法 在 .NET Core 类库中使用 EF Core 迁移数据库到 SQL Server 是一种常见的操作。本攻略将介绍如何在 .NET Core 类库中使用 EF Core 迁移数据库到 SQL Server。 步骤 以下是在 .NET Core 类库中使用 EF…

    C# 2023年5月17日
    00
  • 利用C#实现分割GIF图片

    这里是使用C#实现分割GIF动态图的完整攻略。我们将会使用ImageMagick这一第三方库在C#代码中实现分割GIF的功能。 准备工作 下载和安装ImageMagick。(注意:在安装期间,勾选“Install development headers and libraries for C and C++”选项。) 创建一个C#控制台应用程序工程。 将GI…

    C# 2023年6月3日
    00
  • c# 在Emit代码中如何await一个异步方法

    在 C# 中,可以通过使用 Emit 代码来动态生成 IL 字节码,实现类似于代码生成器或者 AOP 的功能。当我们需要在 Emit 代码中调用异步方法并且等待其完成时,需要按照以下步骤进行: Step 1: 定义异步委托 在 Emit 代码中调用异步方法,需要定义一个委托类型来表示异步方法的调用方式和返回值类型。例如,如果异步方法的返回值类型是 Task&…

    C# 2023年6月1日
    00
  • asp.net 身份验证机制实例代码

    ASP.NET身份验证是一种灵活的机制,用于验证用户身份、授权访问和管理会话对象。实现身份验证需要使用ASP.NET提供的一些特定的类和方法,本文将带你通过实例代码学习如何使用ASP.NET身份验证机制。 步骤一:启用ASP.NET身份验证 首先,你需要在Web.config文件中启用ASP.NET身份验证。在标签下添加如下配置: <system.we…

    C# 2023年5月31日
    00
  • C#单例模式Singleton的实现详解

    C#单例模式Singleton的实现详解 单例模式是什么? 单例模式是一种创建型设计模式,其主题为确保一个类只有一个实例,并提供全局访问点。 实现单例模式 1. 延迟初始化 实现单例模式的一种简单方法是在实例化对象之前先执行一些操作。 假如我们只需要在调用该对象时才创建该对象,那么我们可以使用以下方式来实现: public class Singleton {…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部