编写自定义 GLSL 着色器:纹理、透明度、照明和硬件选择示例

GLSL 着色语言规范不包含描述,该描述允许您将各种着色器片段及其关联的 UI 连接到单个效果文件中,而使用 CgFX 或 HLSL 则可以。

因此,提供了包裹器文件格式,允许您为各个着色阶段指定 GLSL 片段,以处理灯光和纹理绑定,并确定如何在“属性编辑器”(Attribute Editor)中显示参数。下面将介绍文件格式 .ogsfx

若要编写自定义 GLSL 着色器,请将它另存为 .ogsfx 文件。有关如何编写 GLSL 着色器的示例,请参见 Maya 安装的 ..\presets\GLSL\examples 文件夹中的 WaterSimulation.ogsfx 效果文件。

此示例演示以下内容:

要可视化此示例,请创建一个立方体,并通过 polyCube 节点“属性编辑器”(Attribute Editor)将其“细分宽度”(Subdivisions Width)“细分深度”(Subdvisions Depth)增至 100。对于着色的和带纹理的显示模式,按 6。

将 GLSL 着色器指定给立方体,并导航到 WaterSimulation.ogsfx 效果文件。有关详细信息,请参见创建和可视化 GLSL 着色器

示例着色器将创建可能对场景中的一个 Maya 灯光起反应的动画波浪。它将连接到高度和法线贴图,且可以显示透明度。

有关此着色器示例中使用的语义和注释的详细信息,请参见 Viewport 2.0 中的 dx11Shader 和 glslShader 插件支持的语义和注释以及 Viewport 2.0 支持的着色器语义

指定纹理文件

若要定义文件纹理,请按照以下示例执行操作:

uniform texture2D gHeightMap  <
    //Specify the texture file to be loaded by default
    string ResourceName = "SeaHeightMap.jpg";

    //Specify the type of texture
    string ResourceType = "2D";
    //Name of field in Attribute Editor
    string UIName = "Sea Height Map";
   
    int mipmaplevels = 0;
>;
uniform sampler2D gHeightMapSamp = sampler_state
{
    texture = <gHeightMap>;
};

采样在 gHeightMapSamp 上执行,并且文件纹理加载到 gHeightMap 中。sampler_state 允许将外部纹理关联到采样器。

使用 ResourceName 注释,您可以在加载着色器时,自动连接和加载指定的纹理文件。例如,在本例中,SeaHeightMap.jpg 文件已连接。否则,用户必须创建文件节点并将其连接到该属性。

在本例中,SeaHeightMap.jpg 文件与 WaterSimulation.ogsfx 文件位于同一目录中。如果纹理文件位于其他目录中,则必须指定其完整路径。

在 Maya 属性编辑器中创建属性

统一参数及其变量名称将自动显示在 Maya 的“属性编辑器”(Attribute Editor)中。若要为统一参数提供用户友好的名称,请使用 UIName 注释。

例如:

uniform texture2D gHeightMap  <
...
... 
  string UIName = "Sea Height Map";
...
>;

“海洋高度贴图”(Sea Height Map)显示为 GLSLShader 节点“属性编辑器”(Attribute Editor)中的一个属性,而不是显示为 gHeightMap。

如果不希望某个统一参数显示在“属性编辑器”(Attribute Editor)中,请使用以下注释:

string UIWidget = "None";

添加技术

一种可以包含一个或多个过程的技术,其中每个过程定义渲染对象的特定方式。如果具有多个顶点着色器和/或多个几何体着色器和/或像素着色器,则可以指定要用于每种技术/通道的着色器。

在此示例中,technique Main 包含一个通道,指定应该使用 PS_Wave 像素着色器。在 GLSLShader 节点属性编辑器中选择 Main 作为技术时,将在视口中渲染波浪。

同样,technique NormalView 包含一个通道,指定应该使用 PS_Normal 像素着色器。在属性编辑器中选择 NormalView 时,将在视口中显示波浪的法线贴图。

NormalView_Selection 技术包括 7 个通道,每个通道使用不同的顶点、几何体和像素着色器。此技术示范硬件选择。有关详细信息,请参见下面的选择和绘制置换组件

显示透明度

在指定技术时使用透明度技术注释,以便对象可以显示透明度。

在 GLSLShader 的“属性编辑器”(Attribute Editor)中选择“主”(Main)技术时,以下项允许对象显示为透明。

technique Main
<
//tell Maya to support transparency for this technique
string Transparency = "Transparent";
>

将场景中的灯光指定给着色器

示例效果文件的 Light 0 Group 部分演示如何将场景中的一个灯光指定给 GLSL 着色器,以及灯光参数应该如何影响着色器。

若要在着色器计算中包括多个灯光,请在效果着色器中创建其他的 Light 1、Light 2(依此类推)部分。您还将需要为灯光如何彼此交互制定计划。

有三种方法可以用于向着色器添加灯光。可以执行下列操作:

如果您选择前两个选项之一,则在绑定灯光后无法在 GLSLShader 的“属性编辑器”(Attribute Editor)中更改灯光参数。相反,您必须从灯光“属性编辑器”(Attribute Editor)进行更改。

若要查看场景灯光的效果,请在 Maya 视口面板菜单中选择“照明 > 使用所有灯光”(Lighting > Use All Lights)

注: 在此示例中,照明仅在 PS_Wave 像素着色器中定义,其仅在“主”(Main)技术中使用。因此,只有选择“主”(Main)作为技术,才能在 Viewport 2.0 中查看照明效果。

禁用合并

将技术注释 handlesConsolidatedGeometry 设置为 false,可在要应用 GLSL 着色器的几何体上禁用“合并世界”(Consolidate World)功能。

string handlesConsolidatedGeometry = "false";

如果通过技术绘制其计算涉及对象的对象空间坐标(例如,使用世界变换矩阵)的置换,则此注释非常有用。由于“合并世界”(Consolidate World)会将多个对象的顶点移到一个新的共享对象空间中,因此可能会导致插件着色器渲染错误。在这种情况下,您可能需要禁用“合并世界”(Consolidate World)

选择和绘制置换组件

NormalView_Selection 技术演示了如何对置换组件执行硬件选择,以及在相应置换位置渲染非材质项目(例如线框和所选边/顶点)。

硬件选择允许选择细分的几何体。此外,线框和组件在视口中绘图时使用同一轮廓作为着色材质。此技术有 7 个不同的通道。

在定义技术之前,使用 #include 指令加载四个着色器,如下所示。#include 指令允许在不同的应用程序之间共享相同的 GLSL 片段,并保持单独的着色器代码文件,而不必将它们合并到一个 .ogsfx 文件中。

GS_FatLine.ogsfh:这是一个几何体着色器,可将线转化为矩形,因此允许将渲染线绘制得较大(例如,红色预先选择亮显边绘制得比休眠边大)。

GS_FatPoint.ogsfh:这是一个几何体着色器,可将点转化为四边形,因此允许将渲染点绘制得较大(例如,将顶点渲染为方形,而不是单个像素)。

PS_SolidColor.ogsfh:这是一个像素着色器,用于使用纯色进行绘制。

PS_HWSelection.ogsfh:这是一个像素着色器,用于在硬件选择过程中渲染组件,其中每个组件按照使用对象或组件 ID 计算的不同纯色进行渲染。

前 4 个通道用于在视口中绘制;因此使用了 PS_Normal 和 PS_SolidColor 像素着色器。

最后 3 个通道用于在硬件选择期间渲染组件,因此使用 PS_HWSelection 像素着色器。未使用 PS_SolidColor 像素着色器,因为这些通道不用于在视口中进行绘制。

基本体 ID(如顶点 ID)用于生成一种颜色来标识拾取的对象。屏幕外缓冲区用于存储这些计算的颜色,以便 Maya 知道鼠标拾取的内容。

技术和通道注释

overridesNonMaterialItems 技术注释指定此技术可用于渲染非材质项目,例如线框以及边或顶点等组件。

string overridesNonMaterialItems = "true";

通道注释用于告知插件将哪些通道用于哪些渲染项目。

例如:

pass pNonMaterialItemsFatLine
<
// This pass will be used to render non material items as fat lines
string drawContext = "nonMaterialItemsPass";
string primitiveFilter = "fatLine";
>

因此,如果渲染项目属于非材质项目,而基本体类型属于粗线,则使用 pNonMaterialItemsFatLine 通道。

有关这些通道注释的信息,请参见支持的通道注释

有关 OverrideNonMaterialItems 的详细信息,请参见 Maya 开发人员帮助中的 MRenderItem::RenderItemType