Unity2D求承包 2023-10-09 16:00 采纳率: 40%
浏览 74
已结题

Unity2D动态阴影制作

我想在Unity2d的top-down 游戏中实现类似于《星之海》人物和建筑的阴影效果。
阴影可以随着光照的调整,在方向和形状上进行调整。

img

求有经验的同学给指点下怎么做。
AI我已经问过无数次,希望能讲讲详细怎么做,希望讲讲深度图怎么拿,拿来怎么用等等。或者用贴图阴影的话,怎么才能模拟出来那种光照变换,位置,角度,外形跟着变的效果!

如果有现成的可直接用的脚本/模块/插件就更好了,欢迎私信,如果需要经费也请私信!

img

img

img

  • 写回答

20条回答 默认 最新

  • bug菌¹ Java领域优质创作者 2023-10-16 17:47
    关注
    获得18.00元问题酬金

    该回答引用ChatGPT,希望对题主有所帮助,如有帮助,还望采纳。


    实现动态阴影效果,通常可以使用两种方法:使用实时渲染生成阴影贴图或者使用预渲染好的阴影贴图来实现。下面分别介绍这两种方法的实现。

    1. 基于实时渲染的动态阴影生成

    实时渲染动态阴影的实现一般需要用到渲染纹理、深度图等技术。具体实现步骤如下:

    1.1 生成深度图

    首先需要生成一个深度图,深度图可以通过将场景中所有需要产生阴影的物体渲染到一个特定的纹理中得到。具体来说,我们可以通过设置一个摄像机专门用于渲染深度图,并把深度渲染到一个 RenderTexture 上来实现。关于 RenderTexture 的使用可以参考 Unity 官方文档。

    在摄像机上添加 Depth Texture 选项后,可以使用以下代码获取深度图:

    Texture2D depthTexture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
    depthTexture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
    depthTexture.Apply();
    

    1.2 生成阴影贴图

    有了深度图之后,我们可以通过对深度图进行处理,得到阴影贴图。具体来说,我们需要将深度图中比当前像素深的像素对应的阴影贴图像素设为黑色,否则设置为白色。这个过程可以通过在 Shader 中编写代码实现,具体实现如下:

    Shader "Custom/ShadowCaster" {
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
    
                #define SHADOW_DISTANCE 5.0
                #define SHADOW_BIAS 0.01
                #define SHADOW_OPACITY 0.5
    
                struct appdata {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                    float4 worldPos : TEXCOORD1;
                };
    
                v2f vert (appdata v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = v.uv;
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                    return o;
                }
    
                sampler2D _CameraDepthTexture;
    
                float4 frag (v2f i) : SV_Target {
                    float4 depthColor = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
                    float4 depthPos = mul(UNITY_MATRIX_VP, i.worldPos);
                    depthPos.xyz /= depthPos.w;
                    depthPos.z -= SHADOW_BIAS;
                    float4 shadowPos = ComputeShadowCoord(depthPos);
    
                    float4 shadow = SAMPLE_SHADOW_TEXTURE(_CameraDepthTexture, shadowPos);
                    float4 worldPos = mul(unity_CameraToWorld, depthPos);
    
                    return shadow.r > 0 ? SHADOW_OPACITY : 1;
                }
                ENDCG
            }
        }
    }
    

    其中,SHADOW_DISTANCE 表示阴影最远的渲染距离,SHADOW_BIAS 表示偏移量,SHADOW_OPACITY 表示阴影的透明度。这个 Shader 上会接收渲染纹理 _CameraDepthTexture,用来获取深度信息。在 frag 函数中,我们先将深度转换到非线性空间,并通过 ComputeShadowCoord 计算当前像素在深度图上对应的位置,然后通过该位置获取阴影信息,最终决定当前像素是否要产生阴影。

    1.3 投射阴影

    有了阴影贴图之后,我们就可以将阴影贴图投射到场景中了。具体实现方式有很多种,可以使用贴图方式将阴影贴图贴在角色或场景上,也可以使用 Shader 在物体表面上生成阴影,或者使用 Projector 设备进行投影等等。下面介绍一种较为简单的方法:使用贴图投影。

    首先需要将阴影贴图赋给角色或场景的材质,然后将材质的 Shader 修改为接收阴影贴图的 Shader。接下来,我们还需要计算出阴影的位置和角度。这可以通过创建一个空 GameObject,将其位置和旋转与角色或场景相同,然后使用该 GameObject 的 Transform 计算出阴影的位置和旋转。再将阴影贴图通过贴图方式投射在场景中即可。

    1. 基于预渲染的动态阴影生成

    预渲染动态阴影的实现方式较为简单,但需要预先生成好阴影贴图。具体实现步骤如下:

    2.1 生成阴影贴图

    预渲染的动态阴影需要预先生成一个阴影贴图,这个过程较为复杂,具体实现可以使用一些工具或者手动制作。生成阴影贴图的过程主要分为以下几个步骤:

    • 创建场景和角色
    • 确定灯光的位置和角度
    • 将所有需要生成阴影的物体渲染到一个 RenderTexture 上
    • 将 RenderTexture 中比当前像素深的像素设为黑色,否则设置为白色
    • 将处理好的 RenderTexture 保存为阴影贴图

    2.2 投射阴影

    有了阴影贴图之后,我们就可以将阴影贴图投射到角色或场景上了。这个过程类似于实时渲染方式中的投影过程,具体实现方式可以参考上面的介绍。

    以上是两种实现动态阴影的方式,需要根据实际情况选择使用哪种方法。如果需要实时生成阴影,可以使用实时渲染的方式;如果阴影效果相对固定,可以使用预渲染的方式。

    评论

报告相同问题?

问题事件

  • 系统已结题 10月17日
  • 创建了问题 10月9日

悬赏问题

  • ¥15 Kylin-Desktop-V10-GFB-Release-JICAI_02- 2207-Build14-ARM64.iso有没有这个版本的系统啊
  • ¥15 能不能通过蓝牙将传感器数据传送到手机上
  • ¥20 100元python和数据科学实验项目
  • ¥15 根据时间在调用出列表
  • ¥15 FastReport.community 编辑,table只显示“每页”最顶部和底部横线
  • ¥15 R 包chipseeker 安装失败
  • ¥15 Veeam Backup & Replication 9.5 还原问题
  • ¥15 vue-print-nb
  • ¥15 winfrom的datagridview下拉框变成了黑色,渲染不成功
  • ¥20 利用ntfy实现短信推送