Cg Programming/Unity/Nonlinear Deformations非线性变形

2024-03-11 09:08

本文主要是介绍Cg Programming/Unity/Nonlinear Deformations非线性变形,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本教程介绍顶点混合作为非线性变形的一个例子。主要的应用实际就是蒙皮网格的绘制。

虽然本教程不是基于其它任何指定的教程上的,对章节“顶点变换”的理解还是非常有用的。

在两个模型变换之间混合

这里写图片描述

大多数网格的变形不能用章节“顶点变换”中讨论的4×4矩阵的仿射变换来建模。虚构的变形场对空间的变形只是其中的一个例子。计算机图形中最重要的例子就是当连接点弯曲时网格的变形,比如肘或膝盖。

本教程介绍了实现其中一些变形的顶点混合。基本的想法是在顶点着色器中应用多重模型变换(在本教程中我们只使用两个模型变换)以及混合这些变换过的顶点,即用必须为每个顶点指定的权重计算它们的加权平均值。举例来说,在骨骼连接点附近处皮肤的变形主要是受两根骨骼交接处的位置和方向的影响。于是,这两根骨骼的位置和方向定义了两个仿射变换。皮肤上不同的点会受到这两根骨骼不同的影响:连接点处的点可能受到两根骨骼同样的影响,而在一根骨骼周围远离连接处的点会更多地受到这根骨骼的影响。通过使用这两个变换的加权平均值中的不同权重可以实现两根骨骼影响的不同强度。

为了本教程的目的,我们使用两个uniform变换float4x4 _Trafo0float4x4 _Trafo1,它们由用户指定。最后一个小型Java脚本(它应该被挂载到应该被变形有网格上去,比如默认的球体)允许我们指定其它两个游戏对象并且把它们的模型变换复制到着色器的uniform中。

@script ExecuteInEditMode()public var bone0 : GameObject;
public var bone1 : GameObject;function Update () 
{if (null != bone0){GetComponent(Renderer).sharedMaterial.SetMatrix("_Trafo0", bone0.GetComponent(Renderer).localToWorldMatrix);}if (null != bone1){GetComponent(Renderer).sharedMaterial.SetMatrix("_Trafo1", bone1.GetComponent(Renderer).localToWorldMatrix);}if (null != bone0 && null != bone1){transform.position = 0.5 * (bone0.transform.position + bone1.transform.position);transform.rotation = bone0.transform.rotation;}
}

在C#中,脚本(名字为”MyClass”)看起来是这样的:

using UnityEngine;
using System.Collections;[ExecuteInEditMode]
public class MyClass : MonoBehaviour
{public GameObject bone0;public GameObject bone1;void Update () {if (null != bone0){GetComponent<Renderer>().sharedMaterial.SetMatrix("_Trafo0", bone0.GetComponent<Renderer>().localToWorldMatrix);}if (null != bone1){GetComponent<Renderer>().sharedMaterial.SetMatrix("_Trafo1", bone1.GetComponent<Renderer>().localToWorldMatrix);} if (null != bone0 && null != bone1){transform.position = 0.5f * (bone0.transform.position + bone1.transform.position);transform.rotation = bone0.transform.rotation;}}
}

其它两个游戏对象可以是任何对象–我喜欢有一个内置半透明着色器的立方体,这样它们的位置和方向就是可见的但它们不会遮挡变形的网格。

在本教程中,用变换_Trafo0混合的权重被设置为input.vertex.z + 0.5

float weight0 = input.vertex.z + 0.5;

另一个权重就是1.0 - weight0。于是,input.vertex.z坐标正向的部分被_Trafo0影响,以及其它的部分被_Trafo1影响。一般来说,权重是依赖于应用的并且用户应该允许为每个顶点指定权重。

这两个变换的应用程序以及加权平均值可以这样写:

float4 blendedVertex = weight0 * mul(_Trafo0, input.vertex) + (1.0 - weight0) * mul(_Trafo1, input.vertex);

然后这个混合顶点必须被乘以观察矩阵和投影矩阵。这两个矩阵的乘积可以用UNITY_MATRIX_VP来表示:

output.pos = mul(UNITY_MATRIX_VP, blendedVertex);

为了说明这些不同的权重,我们用红色分量把weight0可视化,用绿色分量把1.0 - weight0可视化(它在片元着色器中设置):

output.col = float4(weight0, 1.0 - weight0, 0.0, 1.0);

对于一个实际的应用,我们应该通过这两个对应的逆转置模型变换对法向量进行变换,并且在片元着色器中执行逐像素光照。

完整的着色器代码

Shader "Cg shader for vertex blending" {SubShader {Pass {   CGPROGRAM#pragma vertex vert  #pragma fragment frag #include "UnityCG.cginc"// Uniforms set by a scriptuniform float4x4 _Trafo0; // model transformation of bone0uniform float4x4 _Trafo1; // model transformation of bone1struct vertexInput {float4 vertex : POSITION;};struct vertexOutput {float4 pos : SV_POSITION;float4 col : COLOR;};vertexOutput vert(vertexInput input) {vertexOutput output;float weight0 = input.vertex.z + 0.5; // depends on the meshfloat4 blendedVertex = weight0 * mul(_Trafo0, input.vertex) + (1.0 - weight0) * mul(_Trafo1, input.vertex);output.pos = mul(UNITY_MATRIX_VP, blendedVertex);output.col = float4(weight0, 1.0 - weight0, 0.0, 1.0); // visualize weight0 as red and weight1 as greenreturn output;}float4 frag(vertexOutput input) : COLOR{return input.col;}ENDCG}}
}

当然,这个只是这个概念的一个说明,但是它已经可以被用在一些有趣的非线性变形中了,比如围绕着z轴的扭动。

对于骨骼动画中的蒙皮网格,更多的骨骼(即模型变换)是必须的,每个顶点必须指定哪一根骨骼(例如使用索引)对加权平均值的哪个权重有贡献。但是,Unity会在软件中计算顶点的混合;这样,这个话题就跟Unity程序员无关了。

总结

恭喜,你又完成了一章的学习。我们看到了:

  • 如何混合被两个模型矩阵变换的顶点。
  • 该技术是如何被应用到非线性变换和蒙皮网格上的。

这篇关于Cg Programming/Unity/Nonlinear Deformations非线性变形的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/797364

相关文章

csu(背包的变形题)

题目链接 这是一道背包的变形题目。好题呀 题意:给n个怪物,m个人,每个人的魔法消耗和魔法伤害不同,求打死所有怪物所需的魔法 #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>//#include<u>#include<map

hdu3389(阶梯博弈变形)

题意:有n个盒子,编号1----n,每个盒子内有一些小球(可以为空),选择一个盒子A,将A中的若干个球移到B中,满足条件B  < A;(A+B)%2=1;(A+B)%3=0 这是阶梯博弈的变形。 先介绍下阶梯博弈: 在一个阶梯有若干层,每层上放着一些小球,两名选手轮流选择一层上的若干(不能为0)小球从上往下移动,最后一次移动的胜出(最终状态小球都在地面上) 如上图所示,小球数目依次为

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

Unity Post Process Unity后处理学习日志

Unity Post Process Unity后处理学习日志 在现代游戏开发中,后处理(Post Processing)技术已经成为提升游戏画面质量的关键工具。Unity的后处理栈(Post Processing Stack)是一个强大的插件,它允许开发者为游戏场景添加各种视觉效果,如景深、色彩校正、辉光、模糊等。这些效果不仅能够增强游戏的视觉吸引力,还能帮助传达特定的情感和氛围。 文档

Unity协程搭配队列开发Tips弹窗模块

概述 在Unity游戏开发过程中,提示系统是提升用户体验的重要组成部分。一个设计良好的提示窗口不仅能及时传达信息给玩家,还应当做到不干扰游戏流程。本文将探讨如何使用Unity的协程(Coroutine)配合队列(Queue)数据结构来构建一个高效且可扩展的Tips弹窗模块。 技术模块介绍 1. Unity协程(Coroutines) 协程是Unity中的一种特殊函数类型,允许异步操作的实现

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光 一,前言二,资源包内容三,免费获取资源包 一,前言 在创意的世界里,每一个细节都能决定一个项目的独特魅力。今天,要向大家介绍一款令人惊艳的粒子效果包 ——Super Confetti FX。 二,资源包内容 💥充满活力与动态,是 Super Confetti FX 最显著的标签。它宛如一位

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(4)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)-CSDN博客  这节就是真正的存储数据了   理清一下思路: 1.存储路径并检查 //2进制文件类存储private static string Data_Binary_Pa

Unity Adressables 使用说明(一)概述

使用 Adressables 组织管理 Asset Addressables 包基于 Unity 的 AssetBundles 系统,并提供了一个用户界面来管理您的 AssetBundles。当您使一个资源可寻址(Addressable)时,您可以使用该资源的地址从任何地方加载它。无论资源是在本地应用程序中可用还是存储在远程内容分发网络上,Addressable 系统都会定位并返回该资源。 您

Unity Adressables 使用说明(六)加载(Load) Addressable Assets

【概述】Load Addressable Assets Addressables类提供了加载 Addressable assets 的方法。你可以一次加载一个资源或批量加载资源。为了识别要加载的资源,你需要向加载方法传递一个键或键列表。键可以是以下对象之一: Address:包含你分配给资源的地址的字符串。Label:包含分配给一个或多个资源的标签的字符串。AssetReference Obj

在Unity环境中使用UTF-8编码

为什么要讨论这个问题         为了避免乱码和更好的跨平台         我刚开始开发时是使用VS开发,Unity自身默认使用UTF-8 without BOM格式,但是在Unity中创建一个脚本,使用VS打开,VS自身默认使用GB2312(它应该是对应了你电脑的window版本默认选取了国标编码,或者是因为一些其他的原因)读取脚本,默认是看不到在VS中的编码格式,下面我介绍一种简单快