» cn.Tutorial Effects - Multiple Textures
This site relies heavily on Javascript. You should enable it if you want the full experience. Learn more.

cn.Tutorial Effects - Multiple Textures

English | Italian | Japanese

TOC: Of Effects and Shaders
Back: Neighbouring Pixels
Next: Multiple Passes


材质和取样

已经在texture coordinates这一章中提到过,材质总是和取样一起。实际上,材质自己在effect中没有多大的用处,总是需要通过采样来使用。下面几行代码使我们的取样:

  1. texture Tex <string uiname="Texture";>;
  2. sampler Samp = sampler_state    //sampler for doing the texture-lookup
  3. {
  4.     Texture   = (Tex);          //apply a texture to the sampler
  5.     MipFilter = LINEAR;         //sampler states
  6.     MinFilter = LINEAR;
  7.     MagFilter = LINEAR;
  8. };

在第二行指定一个命名为Textexture变量类型。annotation角形括号指定对应材质引脚显示在effect节点上Texture。下面是取样器模块指定一个名叫Samp取样器并且和材质Tex关联正像第5行显示的那样。
下面是取样状态。其它的可能取样状态参见 Effect States (Direct3D 9)

多材质引脚

在着色器上的材质引脚不能够以原来在一个引脚里获取多片材质方式被铺展。如果你需要在一个像素着色器获取过个材质你需要指定多个texture变量并分别取样。因此对于每一你需要用到而另外加入的材质你都要拷贝一遍上面描绘的程序块同时指定不同材质名称和取样器变量、注释同时为每个取样器指定单独的材质。由于硬件的限制你最多只能在一个effect上加入16个材质。

两个材质间的淡入淡出

在一个像素着色中使用多个材质的典型例子就是在两个材质间的淡入淡出。像上面所描述的那样复制材质和取样器,材质混合的代码如下:

float Fade = 0.5;
float4 PS(vs2ps In): COLOR
{
    float4 colA = tex2D(SampA, In.TexCd);
    float4 colB = tex2D(SampB, In.TexCd);
 
    return lerp(colA, colB, Fade);
}

这里 lerp() 函数做了一个线性的插值:

 colB * Fade + colA * (1 - Fade)

用遮罩控制两个材质的混合

另外一种通常的情况是你有两个材质和一个遮罩,这个遮罩一灰度图的形式决定了两张材质混合方式。对于遮罩中每一个像素的颜色如果是白色你希望看到对应的是A材质,遮罩黑色的地方你想看到对应的是B材质,遮罩是灰色的地方你想看到的是材质A与B的混合。

那么定义第三个材质命名为 Mask,指定给他一个 SampMask的名称像素着色器如下:

float4 PS(vs2ps In): COLOR
{
    float4 colA = tex2D(SampA, In.TexCd);
    float4 colB = tex2D(SampB, In.TexCd);
    float4 mask = tex2D(SampMask, In.TexCd);
 
    return lerp(colA, colB, mask.r);
}

假设遮罩材质是一个灰度图,你可以获取它颜色元素作为渐变值(例如用红色的元素通过.r)。注意你怎样简单的使用 lerp()函数,和原来不同它的第三个参数根据每一个像素可以是一个不同的值,原来 Fade是使用一个常量的值作用于整个材质。

用另一个材质控制当前材质的置换

在关于texture coordinates中的部分内容已经讲过怎样通过编程的方式在像素取样之前修改给定材质的坐标来实现各种各样的置换效果。

在像素着色器中如果不用生成的偏移值,你同样能够使用材质上颜色值作为另一个材质坐标的偏移值。像这样你能用更加直观的方式在patch中创建材质的偏移值。下面是怎样在你的材质上做一个水平的毛刺效果:

float4 PS(vs2ps In): COLOR
{
    float4 offset = tex2D(SampOff, In.TexCd) - 0.5;
    float4 col = tex2D(SampA, float2(In.TexCd.x + offset.r, In.TexCd.y));
    return col;
}

对于这个例子你创建了一个新的材质把它指定到一个命名为SampOff取样器。正如代码显示这个偏移的取样器先被取样,然后(假定我们希望偏移在偏移材质的红色的元素中被编码)offset.r的值(范围是0到1)被用作输入材质坐标x元素的偏移值。-0.5是为了使在0到1之间偏移值以0为中心在正负两个方向上对称偏移。

在patch中把DynamicTexture (EX9.Texture Value)Width引脚设置为1,Height引脚设置成我们希望具有毛刺效果的材质。这个确保效果确实作用于linewise。连接一个随机数的铺展到DynamicTexture (EX9.Texture Value)节点的Red引脚,你现在就能直观的设置linewise的偏移了。

材质滤镜

现在你不想要这么精细的效果,仅仅想定义10个偏移,设置DynamicTexture (EX9.Texture Value)节点的Height引脚到10同时也至填入10个随机数。结果会看起来很奇怪:

现在的情况是偏移仅仅发生在10个像素高度的范围内,这样的偏移被重复了512次。对10个值进行512次取样需要采用一些插值/重采样的算法,目的是定义10个值中那些值对应另外一个材质中512个哪个像素。这个算法可以通过使用取样器MagFilter状态来设置。把它设置成POINT然后看发生了什么变化。

texture Off <string uiname="Offset Texture";>;
sampler SampOff = sampler_state    //sampler for doing the texture-lookup
{
    Texture   = (Off);          //apply a texture to the sampler
    MipFilter = LINEAR;         //sampler states
    MinFilter = LINEAR;
    MagFilter = POINT;
};

Next: Multiple Passes
Back: Neighbouring Pixels
TOC: Of Effects and Shaders

anonymous user login

Shoutbox

~3d ago

skyliner: the vcard page is assembled by personal settings + user page

~3d ago

lasal: thank you guys but this is to edit the user data, i don't find how to edit the vcard

~3d ago

CeeYaa: @lasal - haha nice - I think it's funny - you should keep it ;) to change - HOME-SETTINGS - PERSONAL SETTINGS

~3d ago

skyliner: @lasal: here?

~3d ago

lasal: who knows how to edit the vcard?

~3d ago

joreg: get started with #vl with this first part of a series of "vl for vvvv users" tutorial: https://discourse.vvvv.org/t/vl-for-vvvv-users-key-differences-1-5/15919 #vvvv

~3d ago

joreg: speak japanese? this looks like a great resource for #vvvv tipsntricks: https://qiita.com/advent-calendar/2017/vvvv