IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> unity gpu instancing -> 正文阅读

[游戏开发]unity gpu instancing

Unity gpu instancing

unity可以自动合并相同的material对象渲染

将对应shader enable instancing的选项勾上

本文说明一下直接调用unity api的方式,实现合并渲染

参考opengl gl_Instance

unity提供了一组api,向gpu批量提交渲染数据

以其中的一个为例Graphics.DrawMeshInstanced

参数为网格数据,shader,以及每个instance的变换矩阵

Material.SetBuffer可以向shader传递数组,在shader可以根据unity_InstanceID相访问对应的实例数据

本文的例子是在urp下实现的,使用了urp中shader的api

运行效果如下:

?

?

shader代码:

Shader "lsc/gpu_instancing"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            //启用gpu instancing
            #pragma multi_compile_instancing 

            //开启主灯光的阴影
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile_fragment _ _SHADOWS_SOFT
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            //自定义数组,保存每个实例的颜色
            StructuredBuffer<float4> _instancing_color;

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;

                float3 positionWS               : TEXCOORD2;
                float4 positionCS               : SV_POSITION;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                //给unity_InstanceID赋值,使urp的内部函数会自动调用unity_Builtins0数组中的属性
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_TRANSFER_INSTANCE_ID(v, o);

                //内部会自动取实例的变幻矩阵,在不同的位置画出实例
                VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
                o.positionCS = vertexInput.positionCS;
                o.positionWS = vertexInput.positionWS;
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(i);

                half4 col = tex2D(_MainTex, i.uv);
#ifdef UNITY_INSTANCING_ENABLED
                col.rgb = _instancing_color[unity_InstanceID];
#else
                col.rgb = half4(0, 1, 0, 1);
#endif

                //计算主光与阴影
                float4 shadow_coord = TransformWorldToShadowCoord(i.positionWS);
                Light mainLight = GetMainLight(shadow_coord);
                half3 light_col = mainLight.color * mainLight.shadowAttenuation;

                col.rgb = light_col * col.rgb;

                return col;
            }
            ENDHLSL
        }

        Pass //产生阴影
        {
            Name "ShadowCaster"
            Tags{"LightMode" = "ShadowCaster"}

            ZWrite On
            ZTest LEqual
            ColorMask 0
            Cull[_Cull]

            HLSLPROGRAM
            #pragma exclude_renderers gles gles3 glcore
            #pragma target 4.5

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local_fragment _ALPHATEST_ON
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #pragma vertex ShadowPassVertex
            #pragma fragment ShadowPassFragment

            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
            ENDHLSL
		}

        Pass //写入深度
        {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}

            ZWrite On
            ColorMask 0
            Cull[_Cull]

            HLSLPROGRAM
            #pragma exclude_renderers gles gles3 glcore
            #pragma target 4.5

            #pragma vertex DepthOnlyVertex
            #pragma fragment DepthOnlyFragment

            // -------------------------------------
            // Material Keywords
            #pragma shader_feature_local_fragment _ALPHATEST_ON
            #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

            //--------------------------------------
            // GPU Instancing
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
            ENDHLSL
        }
    }
}

对应的cs代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;

//此脚本挂在任意物体(空物体也可)
public class gpu_instancing : MonoBehaviour
{
    public int gobj_line_count_ = 20;
    public int gobj_count_perline_ = 20;
    
    //网格数据
    public Mesh instance_mesh_;
    //gpu instancing shader
    public Material mtrl_;

    ComputeBuffer cb_color_;
    List<float4> lst_color_;

    void Start()
    {
        cb_color_ = new ComputeBuffer(gobj_line_count_ * gobj_count_perline_, sizeof(float) * 4);
        lst_color_ = new List<float4>();
    }

    void Update()
    {
        //绘制gpu instancing 100个胶囊
        lst_color_.Clear();
        Vector3 pos = this.transform.position;
        var matrices = new Matrix4x4[gobj_line_count_ * gobj_count_perline_];
        for (int i = 0; i < gobj_line_count_; i++)
        {
            for (int j = 0; j < gobj_count_perline_; j++)
            {
                Vector3 tmppos = pos;
                tmppos.z = pos.z + i;
                tmppos.x = pos.x + j;

                var scale = new Vector3(0.5f, 0.5f, 0.5f);
                var matrix = Matrix4x4.TRS(tmppos, Quaternion.identity, scale);

                matrices[i * gobj_count_perline_ + j] = matrix;

                //每个实例颜色赋值
                lst_color_.Add(new float4((float)i/ gobj_line_count_, (float)j / gobj_count_perline_, 0.0f, 1.0f));
            }
        }

        cb_color_.SetData(lst_color_);
        //每个实例的颜色数组
        mtrl_.SetBuffer(Shader.PropertyToID("_instancing_color"), cb_color_);
        if (mtrl_)
            Graphics.DrawMeshInstanced(instance_mesh_, 0, mtrl_, matrices, gobj_line_count_ * gobj_count_perline_);//materices是变换矩阵
    }
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-09-26 10:31:04  更:2021-09-26 10:32:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 3:43:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码