Unity 3d Sprite Shader(如何在多个灯光照射下将最大亮度限制为 1)

2023-12-19

我正在 Unity 中创建一个视频游戏。每个精灵都使用具有 CornucopiaShader.shader 材质的精灵渲染器进行渲染。我遇到的问题是我想将精灵的最大亮度(或颜色)限制为精灵的正常图像,无论有多少点光源照射它的功率,灯光的强度,还有环境光在团结的场景中。当照射精灵的灯光强度低于最大亮度级别时,我希望它像正常点亮的精灵一样运行,如果没有灯光照射到它,则显示为黑色,如果照射到 0.5 的强度,则显示为半亮,等等,以及介于两者之间的一切都像平常一样。问题一:总之,如果三个强度为 5 的光照射到精灵上,我希望精灵看起来只是正常亮度 1,而不是被光冲出白色。

由于玩家可以像纸片马里奥一样旋转并切换侧面,因此当前的着色器代码会以这种方式运行,并且当前从背面照射的光线也应该像当前在着色器中一样照亮两侧。问题2:但我遇到的另一个问题,就像我所包含的四张图像中所看到的那样,当我翻转播放器时,强度会发生变化。

我连续三天试图解决这两个问题,但无法解决。

图片1 https://i.stack.imgur.com/85w2r.png

图2 https://i.stack.imgur.com/koyvc.png

图3 https://i.stack.imgur.com/bN30f.png

图4 https://i.stack.imgur.com/X5f3n.png

Shader "Custom/CornucopiaShader" {

Properties{
    _MainCol("Main Tint", Color) = (1,1,1,1)
    _MainTex("Main Texture", 2D) = "white" {}
    _Cutoff("Alpha cutoff", Range(0,0.5)) = 0.5
}

SubShader{
    Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"}
    Cull Off
    ZWrite Off
    LOD 200
    ColorMask RGB

    Blend SrcAlpha OneMinusSrcAlpha

    CGPROGRAM
    #pragma surface surf SimpleLambert alphatest:_Cutoff addshadow fullforwardshadows alpha:blend
    #pragma target 3.0

    #include "RetroAA.cginc"

    sampler2D _MainTex;
    float4 _MainTex_TexelSize;
    fixed4 _MainCol;

    half4 LightingSimpleLambert(SurfaceOutput s, half3 lightDir, half atten)
    {
        half4 c;

        c.rgb = s.Albedo * _MainCol.rgb * (atten)* _LightColor0.rgb;
        c.a = s.Alpha;

        return c;
    }

    struct Input {
        float2 uv_MainTex;
    };

    void surf(Input IN, inout SurfaceOutput o) {

        fixed4 c = RetroAA(_MainTex, IN.uv_MainTex, _MainTex_TexelSize);
        o.Albedo = lerp(c.rgb, c.rgb, c.a);
        o.Alpha = c.a;

    }
    ENDCG
}

Fallback "Transparent/Cutout/VertexLit"

}

#include "UnityCG.cginc"

#pragma target 3.0

fixed4 RetroAA(sampler2D tex, float2 uv, float4 texelSize){
    float2 texelCoord = uv*texelSize.zw;
    float2 hfw = 0.5*fwidth(texelCoord);
    float2 fl = floor(texelCoord - 0.5) + 0.5;
    float2 uvaa = (fl + smoothstep(0.5 - hfw, 0.5 + hfw, texelCoord -     fl))*texelSize.xy;

return tex2D(tex, uvaa);
}

您实际上无法使用表面着色器来做到这一点,但您可以使用顶点片段着色器非常有效地做到这一点。 Unity 将 4 个最近的点光源存储在一组向量中,用于每个顶点(不重要)的光源。幸运的是,这些也可以在片段着色器中访问,因此您可以使用它们一次对所有 4 个灯光进行着色!当您将所有灯光汇总在一起时,请确保它们的强度不能超过 1。这是我为您组合的一个快速着色器:

Shader "Unlit/ToonTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Name "FORWARD"
        Tags { "LightMode" = "ForwardBase" "RenderType" = "TransparentCutout" "Queue"="AlphaTest"}
        Cull Off
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #pragma multi_compile_fwdbase

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                half3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD1;
                float3 ambient : TEXCOORD2;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.ambient = ShadeSH9(mul(unity_ObjectToWorld, float4(v.normal, 0.0 ))); // Ambient from spherical harmonics
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            float3 Shade4Lights (    
                float4 lightPosX, float4 lightPosY, float4 lightPosZ,
                float3 lightColor0, float3 lightColor1, float3 lightColor2, float3 lightColor3,
                float4 lightAttenSq,
                float3 pos)
            {
                // to light vectors
                float4 toLightX = lightPosX - pos.x;
                float4 toLightY = lightPosY - pos.y;
                float4 toLightZ = lightPosZ - pos.z;
                // squared lengths
                float4 lengthSq = 0;
                lengthSq += toLightX * toLightX;
                lengthSq += toLightY * toLightY;
                lengthSq += toLightZ * toLightZ;
                // don't produce NaNs if some vertex position overlaps with the light
                lengthSq = max(lengthSq, 0.000001);

                // attenuation
                float4 atten = 1.0 / (1.0 + lengthSq * lightAttenSq);
                float4 diff = atten; //ndotl * atten;
                // final color
                float3 col = 0;
                col += lightColor0 * diff.x;
                col += lightColor1 * diff.y;
                col += lightColor2 * diff.z;
                col += lightColor3 * diff.w;
                return col;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                half3 intensity = Shade4Lights(unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, unity_LightColor[0], unity_LightColor[1], unity_LightColor[2], unity_LightColor[3], unity_4LightAtten0, i.worldPos);
                intensity = min((half3)1, i.ambient + intensity);

                col.rgb *= intensity;

                clip(col.a - 0.5);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

“Shade4Lights”函数是 Unity 的“Shade4PointLights”的修改版本,删除了漫射朗伯照明(仅衰减)。您还必须将 RetroAA 函数添加到纹理采样中。您的截止值是“剪辑”功能内的“- 0.5” - 如果需要,您可以公开它。如果您需要为此着色器进行阴影投射,您可以从 Unity 的标准着色器复制/粘贴阴影通道(您可以从其页面下载源代码)。对于阴影接收,您需要向着色器添加几行 - 再次检查源代码。

您可以在此处阅读有关内置着色器变量的更多信息:

https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity 3d Sprite Shader(如何在多个灯光照射下将最大亮度限制为 1) 的相关文章

随机推荐

  • 是否有“全包同级”CSS 选择器之类的东西?

    My HTML p Doggies p p class green guys Froggies p p Cupcakes p p Piggies p 一个全包兄弟选择器 正如我希望的那样 当用于选择 green guys 的兄弟姐妹时 将选
  • Firebase 和 React 的 useEffect 清理功能

    我有一个问题 我的 useEffect 导致以下警告 无法对已卸载的组件执行 React 状态更新 这是一个空操作 但它表明应用程序中存在内存泄漏 要修复此问题 请取消 useEffect 清理函数中的所有订阅和异步任务 仅当从该组件处于活
  • 如何在 Qt 项目中包含 OpenSSL

    我是 Qt 的新手 我已经做了一些谷歌搜索 但找不到足够详细的答案 我需要在基于 qmake 的 Qt 项目中使用 OpenSSL 我如何下载 安装 链接它 以便我可以执行包含语句并在我的代码中使用它的功能 假设使用 Windows 您可以
  • 通过引用传递 std::string 数组

    我想创建一个不通过引用传递 std string 进行修改的函数 void changeStr std string str str Hello World 而是一个完整的 固定大小的 std strings 数组 该函数将执行完全相同的操
  • AngularJS - 当另一个范围内的键为 true 时更改范围值

    我有一个像这样的 ng repeat li p car model p span span span X span li 基于此 scope cars scope cars model Ford check true model Honda
  • 使用本机登录页面的登录凭据实施 Oauth2

    我正在尝试实现基于 Oauth2 的 Web 服务 我有 clientID clientSecret 授权端点 令牌端点和回调 Url 自定义架构指向 android 本机页面 当我检查其他基于 Oauth2 的 API 时 它有登录 Ur
  • 为乒乓球游戏的神经网络寻找正确的参数

    我在 Pong 游戏中实现深度神经网络时遇到了一些麻烦 因为无论我更改哪些参数 我的网络总是发散 我玩了一个 Pong Game 并实现了一个基于 theano lasagne 的深度 q 学习算法 该算法基于 Google Deepmin
  • 找不到存储过程,但可以执行它

    我是 SQL Server 新手 创建了我的第一个存储过程 它执行得很好 我可以在 可编程性 存储过程 下找到它 因此我弹出一个新查询并输入以下语句 use name of database exec name of stored proc
  • 如何对甘特条进行聚类而不重叠?

    使用 create gantt 我有重叠的开始日期和结束日期 import plotly plotly as py import plotly figure factory as ff import plotly df dict Task
  • 获取应用服务器下的真实(虚拟)主机名

    我有一个在 Jetty 下运行的应用程序 我希望该应用程序返回自引用绝对 URL 生成 RSS 提要时 因此客户端必须能够在没有 当前 URL 上下文的情况下工作 问题是我事先不知道应用程序将部署在哪个主机名下 而且很可能它将部署在多个主机
  • 通过 Powershell 为另一个用户设置环境变量

    我正在尝试从管理员用户 ABC 的 powershell 设置用户 XYZ 的环境变量 我正在使用 Start Process 启动用户 XYZ 的 powershell 但我无法捕获输出 所有这些过程都需要用Java来完成 有人可以帮我吗
  • 将对象实例添加到 gradle 插件扩展

    我有类似下面的插件 其中有一个外部命名空间 其中有一个 具体 实例 mother 一个对象加上另一个集合 children family mother firstname John lastname Cleese children son
  • Spring bean 的标准命名

    有人知道应用程序上下文中 Spring bean 的标准命名吗 我使用了驼峰命名法 但我不确定是否存在一种标准 我在网上搜索了相关内容 但没有找到任何东西 Bean 命名约定 Spring 框架参考第 1 3 1 节 https docs
  • 使用Excel作为Access数据库的前端(使用VBA)

    我正在为朋友构建一个小型应用程序 他们希望能够使用 Excel 作为前端 UI 基本上是 Excel 中的用户表单 他们在 Excel 中有一堆数据 他们希望能够查询这些数据 但我不想使用 Excel 作为数据库 因为我认为它不适合该目的
  • JBoss 6.4.20 补丁中允许使用哪些版本的 Jackson?

    我正在尝试更新我的 Jackson 版本6 4 20 JBoss补丁 https www redhat com archives rhsa announce 2018 May msg00028 html 我在用着org codehause
  • 匹配 bool 与 const void* 重载的函数的地址

    我正在阅读使用随机数生成器作为 C 中的函数出现意外值 https stackoverflow com questions 27225614 unexpected value using random number generator as
  • MTOM 是如何工作的?

    MTOM 是 W3C 消息传输优化机制 是一种高效地向 Web 服务发送二进制数据或从 Web 服务发送二进制数据的方法 它一般如何运作 这一切都始于 SOAP 的事实XML 当您发送文本以外的任何内容 例如图像 时 必须将其转换为 XML
  • Java 未经检查的操作转换为泛型

    我想知道为什么以下内容会发出有关不安全 未经检查的操作的警告 Map
  • 使用 Puppeteer 将鼠标悬停在 Node.js 中的元素上并获取计算样式?

    我想将鼠标悬停在某个元素上 比如说document getElementById abc 并找到它的悬停计算样式 我应该如何使用 Puppeteer 在 Node js 中执行此操作 您可以使用以下解决方案来迭代并将鼠标悬停在某些元素上以获
  • Unity 3d Sprite Shader(如何在多个灯光照射下将最大亮度限制为 1)

    我正在 Unity 中创建一个视频游戏 每个精灵都使用具有 CornucopiaShader shader 材质的精灵渲染器进行渲染 我遇到的问题是我想将精灵的最大亮度 或颜色 限制为精灵的正常图像 无论有多少点光源照射它的功率 灯光的强度