Unity URP 如何写基础的几何着色器

这是使用几何着色器在点中心生成一个点并根据这个点把原本的面片分成三个三角形的操作。

对于几何着色器构造相对简单,网上的信息也相对较多,需要注意的点就是需要提供一个新的数据结构供几何着色器输出,因为几何着色器在顶点之后,片元之前,所以结构体就需要模型输入的结构体、顶点输出的结构体、几何输出的结构体。

下面是完整代码

Shader "Kerzh/GeoShaderTest"
{
    Properties
    {
        _Length("Length",Float) = 1
    }
    SubShader
    {
        Tags {"LightMode" = "UniversalForward"}
        LOD 100

        Pass
        {
            Cull Off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma geometry geom

            #include "UnityCG.cginc"

            //cpu 传到 vs
            struct appdata
            {
                float4 posOS : POSITION;
                float2 uv : TEXCOORD0;
                float4 normalOS : NORMAL;
            };

            //vs 传到 gs
            struct v2g
            {
                float4 posOS    : TEXCOORD0;
                float2 uv       : TEXCOORD1;
                float3 normalOS : TEXCOORD2;
            };

            //gs 传到 fs
            struct g2f
            {
                float4 posCS    : SV_POSITION;
                float2 uv       : TEXCOORD0;
                float3 normalWS : TEXCOORD1;
                float3 posWS    : TEXCOORD2;
                float  dis      : TEXCOORD3;
            };
            
            float _Length;

            v2g vert (appdata input)
            {
                v2g output;
                output.uv = input.uv;
                output.normalOS = input.normalOS;
                output.posOS = input.posOS;
                return output;
            }

            //最大的顶点数,这里比如你要生成三个三角形面片,那么一个面片需要三个顶点,就是9个顶点
            [maxvertexcount(9)]
            void geom (triangle v2g input[3],inout TriangleStream<g2f> triStream)
            {
                g2f center;  //  中间那个点
                center.uv = (input[0].uv + input[1].uv + input[2].uv)/3.0;//  计算中间点的uv
                float3 centerNormalOS = (input[0].normalOS + input[1].normalOS + input[2].normalOS)/3.0;
                center.normalWS = UnityObjectToWorldNormal(centerNormalOS );//  计算中间点的法线
                float3 centerPosOS = (input[0].posOS + input[1].posOS + input[2].posOS)/3.0;//  计算中间点的位置
                centerPosOS = centerPosOS + centerNormalOS *_Length;//  沿着中心点法线根据噪声及系数位移中心点

                //中心点后期所需数据
                center.posWS = mul(unity_ObjectToWorld, centerPosOS);
                center.posCS = UnityObjectToClipPos(centerPosOS);
                center.dis = 1;
                
                g2f output[3];  //  这里是原样把输入三角形的三个点放到了这里面,只是为了下面取得方便
                for(int i=0;i<3;i++)
                {
                    g2f p0;
                    p0.uv = input[i].uv;
                    p0.normalWS = UnityObjectToWorldNormal( input[i].normalOS);
                    p0.posWS = mul(unity_ObjectToWorld, input[i].posOS);
                    p0.posCS = UnityObjectToClipPos(input[i].posOS );
                    p0.dis = 0;
                    output[i] = p0;
                }

                //  根据这三个点分别和中心点制造三角形输出
                triStream.RestartStrip(); //  重新开始一个新的三角形
                triStream.Append(output[1]);
                triStream.Append(center);
                triStream.Append(output[0]);

                triStream.RestartStrip();  //  重新开始一个新的三角形
                triStream.Append(output[2]);
                triStream.Append(center);
                triStream.Append(output[1]);
                
                triStream.RestartStrip(); //  重新开始一个新的三角形
                triStream.Append(output[0]);
                triStream.Append(center);
                triStream.Append(output[2]);
            }
            
            float4 frag (g2f i) : SV_Target
            {
                return i.dis;
                return float4(i.uv,0,0);
            }
            ENDCG
        }
    }
}

关于其中几何着色器的部分

//最大的顶点数,这里比如你要生成三个三角形面片,那么一个面片需要三个顶点,就是9个顶点
            [maxvertexcount(9)]
            void geom (triangle v2g input[3],inout TriangleStream<g2f> triStream)
            {
                g2f center;  //  中间那个点
                center.uv = (input[0].uv + input[1].uv + input[2].uv)/3.0;//  计算中间点的uv
                float3 centerNormalOS = (input[0].normalOS + input[1].normalOS + input[2].normalOS)/3.0;
                center.normalWS = UnityObjectToWorldNormal(centerNormalOS );//  计算中间点的法线
                float3 centerPosOS = (input[0].posOS + input[1].posOS + input[2].posOS)/3.0;//  计算中间点的位置
                centerPosOS = centerPosOS + centerNormalOS *_Length;//  沿着中心点法线根据噪声及系数位移中心点

                //中心点后期所需数据
                center.posWS = mul(unity_ObjectToWorld, centerPosOS);
                center.posCS = UnityObjectToClipPos(centerPosOS);
                center.dis = 1;
                
                g2f output[3];  //  这里是原样把输入三角形的三个点放到了这里面,只是为了下面取得方便
                for(int i=0;i<3;i++)
                {
                    g2f p0;
                    p0.uv = input[i].uv;
                    p0.normalWS = UnityObjectToWorldNormal( input[i].normalOS);
                    p0.posWS = mul(unity_ObjectToWorld, input[i].posOS);
                    p0.posCS = UnityObjectToClipPos(input[i].posOS );
                    p0.dis = 0;
                    output[i] = p0;
                }

                //  根据这三个点分别和中心点制造三角形输出
                triStream.RestartStrip(); //  重新开始一个新的三角形
                triStream.Append(output[1]);
                triStream.Append(center);
                triStream.Append(output[0]);

                triStream.RestartStrip();  //  重新开始一个新的三角形
                triStream.Append(output[2]);
                triStream.Append(center);
                triStream.Append(output[1]);
                
                triStream.RestartStrip(); //  重新开始一个新的三角形
                triStream.Append(output[0]);
                triStream.Append(center);
                triStream.Append(output[2]);
            }

大部分在注释中描述的相对明确,但要注意这些操作

center.uv = (input[0].uv + input[1].uv + input[2].uv)/3.0;//  计算中间点的uv
center.normalWS = UnityObjectToWorldNormal(centerNormalOS );//  计算中间点的法线
//中心点后期所需数据
center.posWS = mul(unity_ObjectToWorld, centerPosOS);
center.posCS = UnityObjectToClipPos(centerPosOS);
center.dis = noise;

根据一定的计算规则,给中心点赋予详细的顶点信息,这样他就和模型上初始存在的顶点无异,数据填充完毕后和原顶点一起组成片元,组成一个片元的操作如下。

triStream.RestartStrip(); //  重新开始一个新的三角形
triStream.Append(output[1]);
triStream.Append(center);
triStream.Append(output[0]);

通过这样的操作确立一个三角形片元中的三个点。

而这些点在像素着色器中调用时,因为是对每个像素调用,所以会根据这些点取插值,

 这里的像素着色器是这么写的

float4 frag (g2f i) : SV_Target
{
    return i.dis;
}

所以对于一个片元中的像素,根据片元三个顶点的信息

struct g2f
{
    float4 posCS    : SV_POSITION;
    float2 uv       : TEXCOORD0;
    float3 normalWS : TEXCOORD1;
    float3 posWS    : TEXCOORD2;
    float  dis      : TEXCOORD3;
};

插值到对应像素,dis也就会呈现出一种渐变感。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/451986.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

properties文件和yml文件的区别以及文件优先级

properties文件和yml文件的区别 yml是按照缩进关系&#xff0c;而properties用"."来表示关系springboot默认生成的是properties文件当properties文件和yml文件都存在时&#xff0c;properties文件的优先级更高。 properties文件的样式 yml文件的样式 文件优先级 r…

使用 Jenkins 和 Spinnaker 构建 Kubernetes CI/CD

无论您是新手还是持续集成和持续交付以及容器化领域的经验丰富&#xff0c;本文都将为您提供设置 Spinnaker 以满足您的软件应用程序交付需求的基本知识。 了解 Jenkins、Spinnaker 和 Kubernetes Kubernetes 和 Jenkins 是两个强大的工具&#xff0c;它们相互配合&#xff0…

新加坡大带宽服务器托管优势

在数字化快速发展的今天&#xff0c;服务器托管成为企业拓展业务、提高服务质量的关键环节。而新加坡作为一个国际性的金融、贸易和科技创新中心&#xff0c;其大带宽服务器托管服务在全球范围内享有盛誉。本文将为您科普新加坡大带宽服务器托管的诸多优势。 首先&#xff0c;新…

第十五届蓝桥杯(Web 应用开发)模拟赛 3 期-大学组(被题目描述坑惨了)

目录 1.创意广告牌 2.原子化css 3.神秘咒语 4.朋友圈 5.美食蛋白揭秘 6.营业状态变更 7.小说阅读器 8.冰岛人 9.这是一个”浏览器“ 10.趣味加密解密 总结 1.创意广告牌 这个题目不多说了&#xff0c;只要知道这些css应该都能写出来&#xff0c;不会的平时多查查文…

Docker部署ChatGLM3、One API、FastGPT

创建并运行chatglm3容器 docker run --name chatglm3 -p 8000:8000 registry.cn-hangzhou.aliyuncs.com/ryyan/chatglm.cpp:chatglm3-q5_1 创建并运行one-api容器 (其中挂载路径 D:\one-api 可以选择你自己喜欢的目录) docker run --name oneapi -d -p 3000:3000 -e TZAsia…

k8s基本使用(namespace,pod增删查)-持续更新中

目录 1. 查看Namespace 2. 创建Namespace 2.1 使用纯命令行创建 2.2 编写yaml文件创建 3. 删除Namespace 3.1 使用纯命令行删除 3.2 使用yaml文件删除 二、Pod 1. 查看pod 1.1 查看默认空间的pod 1.2 查看指定空间的pod 1.3 查看全部pod 1.4 查看pod更多信息 1…

HUAWEI 华为交换机 配置 MAC 地址漂移检测示例

组网需求 如 图 2-17 所示&#xff0c;网络中两台 LSW 间网线误接形成了网络环路&#xff0c;引起 MAC 地址发生漂 移、MAC 地址表震荡。 为了能够及时检测网络中出现的环路&#xff0c;可以在 Switch 上配置 MAC 地址漂移检测功能&#xff0c; 通过检测是否发生MAC 地址漂移…

Python in Visual Studio Code 2024年3月发布

排版&#xff1a;Alan Wang 我们很高兴地宣布 2024 年 3 月发布适用于 Visual Studio Code 的 Python 和 Jupyter 扩展&#xff01; 此版本包括以下公告&#xff1a; 新的“Add Imports”代码操作设置调试 Django 或 Flask 应用时自动启动浏览器Python REPL 的 Shell 集成对本…

Python学习:基本数据类型

Python3 命令行参数 Python 提供了 getopt 模块来获取命令行参数。 %> python test.py arg1 arg2 arg3Python 中也可以所用 sys 的 sys.argv 来获取命令行参数&#xff1a; sys.argv 是命令行参数列表。 len(sys.argv) 计算命令行参数个数。 sys.argv[0] 表示脚本名。tes…

docker ENTRYPOINT [“sh“,“-c“,“java“,“-jar“,“Hello.jar“] 启动失败问题分析

因为没系统的学过linux语法&#xff0c;所以才会产生如下疑问。大佬请跳过。 问题&#xff1a;当在dockerfile里面配置 ENTRYPOINT ["sh","-c","java","-jar","Hello.jar"] &#xff0c;启动对应容器时会无法正常运行&…

剑指offer经典题目整理(四)

一、树的子结构 1.链接 树的子结构_牛客题霸_牛客网 (nowcoder.com) 2.描述 给两颗二叉树A B&#xff0c;判断B是不是A的子结构 3.思路 将问题拆解开来&#xff0c;首先是找到a树中子结构的位置&#xff0c;然后是判断是否相同&#xff0c;也就是说&#xff0c;我们需要去…

【小白学机器学习8】统计里的自由度

目录 1 自由度 /degree of freedom / df 1.1 物理学的自由度&#xff08;摘自网上 ^&#xff09; 1.2 数学里的自由度 1.2.2 统计里的自由度 1.2.3 需要补充线性代数的&#xff0c;用线性代数来理解自由度 1.3 统计学里自由度的定义 1.4 自由度的公式 1.5 线性回归公式…

stm32使用时钟生成PWM时调用__HAL_TIM_SetAutoreload导致PWM消失处理

stm32使用时钟生成PWM时调用__HAL_TIM_SetAutoreload导致PWM消失处理 这一个是配置的时候没有使用影子寄存器导致的, 如果加载的Autoreload的值比原来的这一个值小, 这是会出现一个问题, 如果计数器里面的值记为Count, 如果改变的时候New_Autoreload < Count < Old_Auto…

结构体的增删查改

结构体&#xff0c;是为了解决生活中的一些不方便利用c语言自带数据类型来表示的问题。例如表示一个学生&#xff0c;那么学生这个个体假如用c语言自带数据类型怎么表示呢。可以使用名字&#xff0c;也就是字符数组&#xff1b;也可以使用学号&#xff0c;也就是int类型。但是这…

Hadoop学习2:完全分布集群搭建

文章目录 Fully-Distributed Operation&#xff08;完全分布模式&#xff09; 重点机器环境同步集群规划配置文件修改以及同步步骤0&#xff1a;下面其他步骤涉及修改配置以这里为准&#xff08;要不然部署使用过程会有很多问题&#xff09;通用配置&#xff08;三台节点机器&a…

工具-百度云盘服务-身份认证

目标 通过百度网盘API的方式去获取网盘中的文件&#xff0c;要实现这的第一步就是需要获取网盘的权限。资料(参考) 如果期望应用访问用户的网盘文件&#xff0c;则需要经过用户同意&#xff0c;这个流程被称为“授权”。百度网盘开放平台基于 OAuth2.0 接入授权。OAuth2.0 是…

配置中心概述

目录 一、配置中心的定义 二、配置中心的工作 三、配置中心的作用 四、SpringBoot中的配置文件 一、配置中心的定义 配置中心就是用来管理项目当中所有配置的系统&#xff0c;也是微服务系统当中不可或缺的一部分。 nacos是一个更易于构建云原生应用的动态服务发现、配置管理…

服务器被大流量攻击怎么办?如何防御攻击?

随着网络的发展&#xff0c;我们所遇到的安全挑战也越来越多。尤其是近年来&#xff0c;网络攻击频发&#xff0c;许多互联网企业深受其扰。为了不影响自身业务的稳定运行&#xff0c;许多企业都在想方设法的寻求解决方案&#xff0c;防止服务器被攻击而影响业务发展。下面我们…

跨境电商选品实战——Ownips静态ip代理+Python爬虫轻松搞定Lazada电商选品

文章目录 一、引言二、Lazada电商平台爬虫实战2.1、分析Lazada电商平台的商品列表接口2.2、定位商品列表计算逻辑2.3、封装IP代理2.4、运行爬虫 三、数据处理及选品分析四、Ownips——企业级全球静态IP代理 一、引言 互联网与外贸的结合&#xff0c;催生了蓬勃兴起的跨境电子商…

el-Switch 开关二次确认

前言 最近在做毕设&#xff0c;有个需求是点击按钮控制用户的状态是否禁用&#xff0c;就看到element有个switch组件可以改造一下&#xff0c;就上网看了一下&#xff0c;结果为了这个效果忙活了很久。。。所以说记录一下&#xff0c;让大家少踩坑。 前置条件 先看完我的需求再…