Vex language refrence语言基础语法

您所在的位置:网站首页 r语言nls函数语法 Vex language refrence语言基础语法

Vex language refrence语言基础语法

2023-04-06 23:41| 来源: 网络整理| 查看: 265

这里上下文函数的参数(如果有参数的话)会成为程序的用户界面,例如引用vex程序的shader节点参数。

如果几何属性的contex函数与之前有重名,那么她会覆盖之前的函数。

surface

noise_surf(vector clr = {1,1,1}; float frequency = 1;

export vector nml = {0,0,0})

{

Cf = clr * (float(noise(frequency * P)) + 0.5) * diffuse(normalize(N));

nml = normalize(N)*0.5 + 0.5;

}

这里有一点需要注意的是,参数在vex中使用一种特殊的方法去处理。除非使用的是集合属性里一些存在的值,其他的情况中参数在着色器范围内被认为是const的。也就是在这里任何对参数的修改都是非法的。如果实在哟组合中需求,需要使用 export关键字来标记改参数。

User interface pragmas 自定义UI界面

houdini生成的UI界面是按照最小生成来做的,基本上只会显示变量名和类型。如果你想要定让 frequency显示为滑动条并且有区间值,颜色的显示应该是一个颜色的选择界面,你可以使用 houdini的 自定义UI功能

#pragma opname noise_surf

#pragma oplabel "Noisy Surface"

#pragma label clr "Color"

#pragma label frequency "Frequency"

#pragma hint clr color

#pragma range frequency 0.1 10

surface noise_surf(vector clr = {1,1,1}; float frequency = 1;

export vector nml = {0,0,0})

{

Cf = clr * (float(noise(frequency * P)) + 0.5) * diffuse(normalize(N));

nml = normalize(N)*0.5 + 0.5;

}

Operators 运算符

VEX有c优先级的c标准运算符,但是有以下不同点:

乘法实在两个向量或者点之间定义的,执行逐元素相乘,不是点乘或者叉乘。有许多运算符视为非标量类型定义的(例如 vector * matrix = matrix, 标量类型:是一种具有加法运算符内置功能而没有重载(算数、指针、成员指针、枚举 std:nullptr_t) *)在模棱两可的情况下当你计算两种不同类型的参数时,他的返回值回类型是第二个参数的类型。(右边的类型),如 int + vector = vector

Dot operator 点运算符

可以通过点运算符去获取vector matrix里的具体数据。 具体索引看下表

vector2vector3vector4(x,y)(x,y,z)(x,y,z,w)(u,v)(r,g,b)(r,g,b,a)

这里的集中索引方式都是等效的,即使是一个point也可以通过rgba来索引,他们和 [idx]的索引方式是等效的,如

vector2 v = {1,2};

printf(" %d %d %d \n", v.v, v.y, v[1]); // u,v x,y

vector v1 = {1,2,3};

printf(" %d %d %d \n", v1.z, v1.b, v1[2]); // x,y,z r,g,b

vector4 v2 = {1,2,3,4};

printf(" %d %d %d \n", v2.w, v2.a, v2[3]); // x,y,z,w r,g,b,a

他的输出结果为

2 2 2 3 3 3 4 4 4

对于矩阵来说,和上面的索引方式大致相似 这里你可以使用一对字母,例如

.xx [0][0].zz [2][2].ax [3][0] 此外,点运算符可以被用于 将各个索引的值混合为一个vectorv.zyx set(v.z, v.y, v.x) set(v[2], v[1], v[0])v4.bgab set(v4.b, v4.g, v4.a, v4.b) set(v4[2], v4[1], v4[0], v4[2]) 注意这里是只读的,只能通过它赋值给别的vector不能通过这样去给向量赋值 (不可以 v.xyz = b)

Comparisons 逻辑运算符,比较运算符

比较运算符 (==, !=, =) 只能在左右两侧值类型相同并且类型为 int float string 时可以使用,返回结果为int类型 字符串匹配屯算符 (~=) 只能在两边都是 string是可以调用,他相当于调用了字符串比较函数 match 逻辑运算符 (&&, ||, and !) 和位运算符 (& |, ^, and ~) 只能用于int类型。

运算符优先级表

优先级运算符结合方式简介15()LtRFunction call, expression grouping, structure member13!LtRLogical negation13~LtROne’s complement13+LtRUnary plus (for example, +5)13-LtRUnary minus (for example, -5)13++LtRIncrement (for exmaple, x++)13--LtRDecrememt (for example, x--)13(type)LtRType cast (for example, (int)x).12*LtRMultiplication12/LtRDivision12%LtRModulus11+LtRAddition11-LtRSubtraction10LtRGreater than10=LtRGreater than or equal9==LtREqual9!=LtRNOT Equal9~=LtRString matches8&LtRBitwise AND7^LtRBitwise XOR6|LtRBitwise OR5&&LtRLogical AND4IILtRLogical OR3?:LtRTernary conditional (for example, x ? "true" : "false")2= += -= *= /= %= &= |= ^=RtLVariable assignment1,LtRArgument separatorOperator type interactions 不同类型参数运算交互

当你对一个 float 和 int 类型的值进行运算时,结果的类型是运算符左边的类型。 float * int = float , int * float = int如果对向量和 一个 int or flaot 进行加减乘除,返回值类型是向量的类型,结果为向量各元素加减乘除标量 {1.0, 2.0, 3.0} * 2.0 == {2.0, 4.0, 6.0} 如果你对不同长度的向量进行 加减乘除时,返回值的类型是更长的那个。 这里有一点需要注意的是,缺失的数据会用 {0.0, 0.0, 0.0, 1.0}来补全(齐次后的0向量) {1.0, 2.0, 3.0} * {2.0, 3.0, 4.0, 5.0} == {2.0, 6.0, 12.0, 5.0}

如果不清楚此规则的话可能会造成意外的结果如

{1.0, 2.0} + {1.0, 2.0, 3.0, 4.0} == {2.0, 4.0, 3.0, 5.0}推荐当年需要对不同维度向量进行加减乘除的运算时尽量还是转换到同维度的向量去进行运算。

Data types 数据类型

默认情况下 vex使用32位int类型,如果使用AttribCast SOP讲激活的属性转换为64位这时在vex中操作该属性时 vex会舍弃额外的位数

vex引擎在32位64位模式下均可以运行,在32模式下所有的 float vectors int占用32bit。64位模式下是64bit。这里没有double 或者 long 类型。 这里可以使用下划线 _ 来拆分过长的数数字

TypeDefinitionExampleintInteger values21, -3, 0x31(16进制), 0b1001(2进制), 0212(8进制), 1_000_000(1000000 只是太长用_隔开了)flaotFloating point scalar values21.3, -3.2, 1.0, 0.000_000_1vector2Two floating point values. You might use this to represent texture coordinates (though usually Houdini uses vectors) or complex numbers{0,0}, {0.3,0.5}vectorThree floating point values. You can use this to represent positions, directions, normals or colors (RGB or HSV){0,0,0}, {0.3,0.5,-0.5}vector4Four floating point values. You can use this to represent positions in homogeneous coordinates, or color with alpha (RGBA). It is often used to represent a quaternion. Quaternions in VEX are laid out in x/y/z/w order, not w/x/y/z. This applies both to both quaternions and positions with homogeneous coordinates.{0,0,0,1}, {0.3,0.5,-0.5,0.2}arrayA list of values. See arrays for more information.{ 1, 2, 3, 4, 5, 6, 7, 8 }structA fixed set of named values. See structs for more information.matrix2Four floating point values representing a 2D rotation matrix{ {1,0}, {0,1} }matrix3Nine floating point values representing a 3D rotation matrix or a 2D transformation matrix{ {1,0,0}, {0,1,0}, {0,0,1} }matrixSixteen floating point values representing a 3D transformation matrix{ {1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1} }stringA string of characters. See strings for more information"hello world"dictA dictionary mapping strings to other VEX data types. See dicts for more information.bsdfA bidirectional scattering distribution function. See writing PBR shaders for information on BSDFs.Structs 结构体

从houdini12开始,可以通过struct关键字来定义结构体。和c++11类似,可以对结构体内的变量赋初始值。 每个结构体会生成两个构造函数,一个是无参的构造函数,每个值都按照定义时的初始值去分配。一个是含有所有值的构造函数,按照生命的顺序分配。

#include

struct basis {

vector i, j, k;

}

struct bases {

basis m, n, o;

string description;

}

struct values {

int uninitialized; // Uninitialized member data

int ival = 3;

float fval = 3.14;

float aval[] = { 1, 2, 3, 4.5 };

}

basis rotate(basis b; vector axis; float amount) {

matrix m = 1;

rotate(m, amount, axis);

basis result = b;

result.i *= m;

result.j *= m;

result.k *= m;

return result;

}

// Declare struct variables

basis b0; // Initialize using default values (i.e. 0 in this case)

basis b1 = basis({1,0,0}, {0,1,0}, {0,0,1}); // Initialize using constructor

basis b2 = { {1,0,0}, {0,1,0}, {0,0,1} }; // Initialize as explicit struct

b1 = rotate(b1, {0,0,1}, M_PI/6);

注意:结构体必须先生命并定义后使用。

# Struct functions 结构体内方法

可以通过在结构体内定义方法来进行有限的面向对象编程。

在结构体内方法中,可以使用 this 函数来引用结构体的实例。在结构体内部,可以用名称去引用结构体的字段。(例如 basis 是 this.basis 的简写)对于结构体的实例来说,可以通过 ->来调用函数,例如 sampler->sample(),在结构体内部想要调用结构体内部的其他函数可以通过 this->method()来调用。

struct randsampler {

// Fields

int seed;

// Methods

float sample()

{

// Struct functions can refer to fields by name

return random(seed++);

}

}

cvex shader()

{

randsampler sampler = randsampler(11);

for (int i = 0; i < 10; i++)

{

// Use -> to call methods on struct instances

printf("%f\n", sampler->sample());

}

}

Mantra Specific Types, Mantra预定义类型

Mantra有一些预定义的结构体类型,用于一些特性的着色方法

\\light只在 matra shading context中定义,这是一个持有光源的结构体,提供了这些方法

illuminate(…) 将光源绑定到 vex surface shader的 vm_illumshader属性material只在mantra shading context中定义。这是个对外部不透明的结构体,表示分配给一个obj的材质。lpeaccumulator只在 mantra shading context中定义。这是代表光线路径累加器的表达式。有以下方法

begin() 构建并初始化累加器

end() 结束并销毁

move(string eventtype; string scattertype; string tag, string bsdflabel) 根据当前传入的事件类型修改内部状态,如果传入的事件类型为空则被认为修改所有的。

pushstate() 吧当前的状态入栈。

popstate()将当前状态出栈。使用 pushstate方法来取消移动。

accum(vector color, …) 将输入的颜色累积到缓存区(buffer)。接受可选的全追字符串,与 LPE image平面生命的前缀进行比较,需要前缀匹配才能累积到缓存区。

flush(vector multiplier) 讲缓存区(buffer)中的值乘以成熟,然后添加到image上。中间缓存区的存在是为了允许FXAA (一种高效的抗锯齿的方案)(即乘数将是1/number_of_samples)。

int getid() 返回分配给lpeaccumulator的int id

lpeaccumulator getlpeaccumulator(int id) 根据 id 返回 lpeaccumulator 配合 getid 方法使用可以跨shader传递 lpeaccumulatorType casting 类型转换

# Variable casting 变量类型转换

vex中的类型转换和c++ java中的类似。你可以讲一个变量的类型变为另一个(如 int -> float),这个操作很多时候是必要的,如

int a, b;

float c;

c = a / b;

在这个例子中,等号右侧的两个变量进行的是整数的除法,返回的也是整数。例如如果 a = 1,b = 2 则c = 0所以需要转换成一下方法

int a, b;

float c;

c = (float)a / (float)b;

这里转换完之后进行浮点除法,结果为 0.5。需要注意的是这里进行了强制类型转换,会让代码产生性能敏感。

Function casting 函数转换(函数重载)

vex重载函数时不仅仅依靠参数的类型(像c++或者java那样),而且也可以依靠函数的返回值类型去重载函数。例如 noise函数有返回值类型为float 和 vector的两种重载,如下

float n;

n = noise(noise(P));

vex回去自动调用对应的函数,如果想强制转换调用的函数,可以用类型来约束。这里相当于进行了一次函数转换 Function casting。这里其实不会产生任何的性能问题,因为他只是选择了一个函数来调用。

n = noise( vector( noise(P) ) ); //vector 约束返回值的类型

这里有一点是这里并不会产生额外的性能开销,他只是消除了函数调用时的歧义。当你直接调用函数直接分配给指定类型的变量时,他其实就已经隐含了上面的转换。

vector n = vector( noise(P) ); // 不必要的函数转换

vector n = noise(P);

当vex无法确定想要调用的函数时,会产生报错。这时候需要使用显示的函数转换来约定对应的函数。 由于函数转换不会产生任何的开销(他只是简单的从重载的函数中挑选了一个去调用),也不包含任何的类型转换。一个好的习惯是尽可能的使用函数转换。只有当需要显示的转换的时候再使用变量类型转换。

Comments 注释

vex的注释格式使用c++风格的注释格式:

一行内的注释使用 //多行的注释使用 /* xxxxxx */ 包裹Reserved Keywords 保留的关键字

break, bsdf, char, color, const, continue, do, dict, else, export, false, float, for, forpoints, foreach, gather, hpoint, if, illuminance, import, int, integer, matrix, matrix2, matrix3, normal, point, return, string, struct, true, typedef, union, vector, vector2, vector4, void, while返回搜狐,查看更多



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3