编辑着色器

在 Kanzi Studio 项目中,着色器程序作为文件存储在计算机硬盘上。当您将着色器添加到 Kanzi Studio 项目的 <KanziWorkspace>/Projects/<ProjectName>/Shaders 目录时,Kanzi Studio 会自动在 Library > Resource Files > Shaders 中显示它们。

当您想要将所有堆栈材质类型从基于片段的着色器更改为基于顶点的着色器时,或者相反,则访问着色器文件非常有用。如果文件名相同,要执行此操作,请在文件系统中用正确的版本替换着色器文件。

要开始创建您自己的着色器,您可以将 Kanzi 材质库中合适的材质类型作为起点,然后修改着色器和材质属性。请参阅 使用材料类型。

要以可视化方式构建着色器而不是编写代码,请参阅 着色器图。

Kanzi Studio Shader Source Editor

您可以使用 Kanzi Studio Shader Source Editor 来编辑着色器源代码。 当使用 Kanzi Studio Shader Source Editor 时,请记住:

  • 编辑器会将更改保存到磁盘,这意味着当您关闭工程而不保存更改时,已保存到着色器文件中的更改仍会保留在硬盘上。

  • 要在 Kanzi Studio 代码编辑器中显示代码补全选项,请按 Ctrl Space。

    ../../_images/code-editor-code-completion.gif
  • 在 Kanzi Studio Shader Source Editor 中编辑着色器时,使用 Uniforms 和 Attributes 按钮在当前光标位置快速添加用于声明 uniform 和特性的代码片段。

    ../../_images/use-uniforms-in-shader-source-editor.png ../../_images/use-attributes-in-shader-source-editor.png
  • 状态栏显示有关编辑器状态的消息,例如保存代码的时间。

  • 当您保存一个着色器文件时,Kanzi Studio 会自动编译它。如果您遇到编译错误,您可以在 Log 中查看错误。在 Preview 中,包含无效着色器的材质的对象会以红色显示。

着色器特性

着色器程序的输入是顶点属性和统一变量。属性可以在每个顶点之间变化,并提供给顶点着色器。您可以将统一变量用作顶点或片段着色器的输入。

网格的顶点缓冲区也包含一组特性。这些顶点缓冲区特性用于将数据发送到顶点着色器。

Kanzi 可以自动将属性传递给着色器程序,但您也可以手动配置这些设置。

顶点特性总是具有这些语义之一,并且 Kanzi 会自动识别这些名称:

特性 (Attribute)

数据类型 (Data Type)

描述 (Description)

kzPosition

vec3

位置

kzNormal

vec3

正常 (Normal)

kzTangent

vec3

切线

kzWeight

vec4

权重 (Weight)

kzMatrixIndices

vec4

矩阵调色板

kzTextureCoordinate0

vec2

纹理坐标 0

kzTextureCoordinate1

vec2

纹理坐标 1

kzTextureCoordinate2

vec2

纹理坐标 2

kzTextureCoordinate3

vec2

纹理坐标 3

kzColor0

vec4

颜色 0

kzColor1

vec4

颜色 1

kzColor2

vec4

颜色 2

kzColor3

vec4

颜色 3

kzMorphTargetXPosition

vec3

变形目标位置 X,其中 X 是 0…8

kzMorphTargetXNormal

vec3

变形目标法线 X,其中 X 是 0…8

kzMorphTargetXTangent

vec3

变形目标切线 X,其中 X 是 0…8。

您还可以添加自定义特性。

如果着色器特性和顶点特性之间存在一对一的关系,则这些特性会自动互相映射。您可以手动配置映射,以便在网格数据中以不同方式工作。如果您使用的着色器特性名称不在默认列表中,则必须使用手动映射。

要查看和编辑材质类型的着色器属性的语义, 在 Library > Materials and Textures > Material Types 中,右键单击一个材质类型并选择 Open Shader Attributes Editor。

../../_images/open-shader-attributes-editor.png ../../_images/shader-attributes-editor.png

着色器 uniform

着色器 uniform 可以从以下数据源接收其数据:

  • Kanzi 默认 uniforms

  • 材质类型中定义的属性类型。

如果 uniform 名称与任何 Kanzi 默认 uniform 匹配,Kanzi Engine 会自动将它的值发送至着色器程序。以下 uniform 默认可用:

Uniform

数据类型 (Data Type)

描述 (Description)

ContentTexture

sampler2D

在渲染时由渲染节点提供的纹理,例如在 Image 节点中显示的图像。请参阅 应用自定义渲染到 2D 节点 和 应用自定义渲染到 Image 节点。

RenderOpacity

float

渲染的2D节点的不透明度。请参阅 应用自定义渲染到 2D 节点 和 应用自定义渲染到 Image 节点。

kzWorldMatrix

mat4

将点或矩阵从局部空间转换到世界空间的矩阵。

kzCameraMatrix

mat4

将点或矩阵从世界空间转换为视图(相机)空间的矩阵。

kzCameraWorldMatrix

mat4

将点或矩阵从局部空间转换到视图(相机)空间的矩阵。

这是预乘矩阵 kzCameraMatrix * kzWorldMatrix。

kzProjectionCameraWorldMatrix

mat4

将点或矩阵从局部空间转换到屏幕空间的矩阵。

这是预乘矩阵 kzProjectionMatrix * kzCameraMatrix * kzWorldMatrix。

kzPreviousProjectionCameraWorldMatrix

mat4

上一帧的投影 * 摄像机 * 世界矩阵。

使用此 uniform 计算逐像素的屏幕空间速度,用于运动模糊和时间抗锯齿 (TAA) 等效果。速度在顶点着色器中计算,即当前裁剪空间位置与上一帧裁剪空间位置之差:

vec4 pos = kzProjectionCameraWorldMatrix * vec4(position, 1.0);
vec4 prevPos = kzPreviousProjectionCameraWorldMatrix * vec4(position, 1.0);
velocity = ((pos.xy / pos.w) - (prevPos.xy / prevPos.w)) * 0.5;

要为材质 (Material) 启用速度缓冲区输出,请在 PBR 材质的预处理器定义中将 KANZI_SHADER_OUTPUT_VELOCITY 设置为 1。然后将 KANZI_SHADER_OUTPUT_VELOCITY_INDEX 的值设置为您要使用的纹理坐标的语义索引 (Semantic Index)。或者,使用 Smart PBR 材质类型 (Material type),当 Prism Graph 需要时,该材质类型会自动启用此预处理器定义。

    • kzProjectionCameraMatrix

    • mat4

    • 将点或矩阵从世界空间转换为屏幕空间的矩阵。

      这是预乘矩阵 kzProjectionMatrix * kzCameraMatrix。

    • kzProjectionMatrix

    • mat4

    • 将点或矩阵从视图(相机)空间转换为屏幕空间的矩阵。

    • kzNormalMatrix

    • mat4

    • 将对象法线从局部空间转换为世界空间的矩阵。

    • kzCameraNormalMatrix

    • mat4

    • 将对象法线从局部空间转换为视图(相机)空间的矩阵。

      这是预乘矩阵 kzCameraMatrix * kzNormalMatrix。

    • kzCameraPosition

    • vec3

    • 世界空间中的相机位置。

    • kzViewPosition

    • vec4

    • 用于计算视图方向的齐次位置:positionWorld.xyz * kzViewPosition.w - kzViewPosition.xyz。

    • kzTime

    • float

    • 调试计时器,1.0f = 1000 毫秒。

    • kzTexture

    • sampler2D

    • 应用到笔刷或材质的纹理。

    • kzTextureSize0

    • vec2

    • 着色器中第一个纹理的 (width, height) 形式的尺寸。

    • kzTextureSize1

    • vec2

    • 着色器中第二个纹理的 (width, height) 形式的尺寸。

    • kzTextureSize2

    • vec2

    • 着色器中第三个纹理的 (width, height) 形式的尺寸。

    • kzTextureSize3

    • vec2

    • 着色器中第四个纹理的 (width, height) 形式的尺寸。

    • kzMatrixPalette

    • vec4

    • 一个 4x3 矩阵数组,Kanzi 在顶点蒙皮中使用。每个矩阵的形式为:

      [ m00 m01 m02 translate_x]

      [ m10 m11 m12 translate_y]

      [ m20 m21 m22 translate_z]

    • kzCameraNearFarPlane

    • vec2

    • 从相机到近平面和远平面的距离。

    • kzMorphWeights[8]

    • float

    • Kanzi 在变形中使用的网格权重数组。

    • kzViewport

    • vec4

    • (x, y, width, height) 形式的向量,表示 Kanzi 当前渲染到的视口:

      • x 和 y 定义了视口矩形的左下角,以像素为单位。

      • width 和 height 定义了视口的宽度和高度。

      默认情况下,kzViewport 映射到应用程序的 Screen 节点:

      • x 和 y 等于 0。

      • width 和 height 等于屏幕的宽度和高度。

      当 Kanzi 渲染到合成目标或伴随较大区域的子矩形的 3D 场景时,kzViewport 代表该目标区域。

    • kzWindowSize

    • vec2

    • 应用程序的 Screen 节点的尺寸 (width, height)。

材质 uniform

如果 uniform 的名称与着色器的材质类型中定义的任何属性类型匹配,则使用属性提供值。在运行时,属性的值从渲染的材质和与材质类型中定义的光属性匹配的灯光中收集,并可能进行属性覆盖。

uniform 的名称和数据类型必须与材质类型中的属性类型的名称和数据类型匹配。请注意,属性类型的显示名称可能与在此上下文中使用的实际名称不同。请参阅 属性类型。例如,如果材质类型具有颜色属性类型 Diffuse,则着色器代码必须具有以下定义:

uniform mediump vec4 Diffuse;

名称中的字母和大小写必须匹配。这些是从属性数据类型到着色器统一数据类型的兼容数据类型:

属性数据类型

着色器 uniform 数据类型

float

float

Vector 2D

vec2

Vector 3D

vec3

颜色

vec4

向量 4D

vec4

矩阵 2D

mat2

Matrix 3D

mat3

矩阵 4D

mat4

纹理 (Texture)

  • sampler1D

  • sampler2D

  • sampler3D

  • sampler1DShadow

  • sampler2DShadow

  • samplerCube

  • samplerCubeShadow

光源属性类型的 uniform 数组

光属性类型支持统一数组。这使您可以使用多个相同类型的灯光。例如,如果一个着色器程序使用两个方向光,您必须在该材质类型的着色器中添加一个数组属性类型:

uniform mediump vec4 DirectionalLightColor[2];
uniform mediump vec3 DirectionalLightDirection[2];

以下属性类型支持 uniform 数组:

  • DirectionalLightColor

  • DirectionalLightDirection

  • PointLightColor

  • PointLightAttenuation

  • PointLightPosition

  • PointLightRadius

  • SpotLightColor

  • SpotLightPosition

  • SpotLightDirection

  • SpotLightAttenuation

  • SpotLightCutoffAngle

  • SpotLightConeParameters

  • SpotLightExponent

  • SpotLightRadius

设置 OpenGL ES 版本

在着色器源文件中,使用 #version 指令声明着色器代码所使用的 OpenGL ES 着色语言版本。

对于嵌入式目标,Kanzi 要求 GLSL ES 3.1 或更高版本;对于桌面目标,要求桌面 GLSL 1.40 或更高版本。不接受 #version 100 或 #version 300 es 等较早版本。

例如,要将着色器源文件设置为使用嵌入式目标所需的最低版本,请将以下内容添加为文件的第一行:

#version 310 es

对于材质类型,您可以覆盖在该材质类型的着色器源文件中声明的版本。

要在材质类型中覆盖 OpenGL ES 版本:

  1. 在 Library > Materials and Textures > Material Types 中,选择要为其设置 OpenGL ES 版本的材质类型。

    ../../_images/library-physically-based-material-type.png
  2. 在 Properties 中,添加 Input > Shader Version 属性,并将其设置为您希望该材质类型使用的 OpenGL ES 版本。

    ../../_images/properties-shader-version.png

重用着色器代码

您可以将要在多个着色器中使用的功能放入单独的着色器中,从而重用着色器代码。例如,这样您就可以在着色器中包含在多个着色器中使用的辅助函数。

要重用着色器代码:

  1. 在 Library > Resource Files 按 Alt 并右键单击 Shaders 中,选择 Shader Source File,并命名着色器文件。

    例如,将着色器文件命名为 MyHelperShader。

    ../../_images/create-shader-source-file.png ../../_images/myhelpershader-in-library.png
  2. 双击您创建的着色器文件,并在 Shader Source Editor 中添加实现您想在另一个着色器文件中包含的功能的代码。

    例如,添加一个将 RGB 颜色值转换为灰度的函数:

    float colorToLuma(vec3 col)
    {
        return col.r * 0.2126 + col.g * 0.7152 + col.b * 0.0722;
    }
    
  3. 在 Library > Resource Files > Shaders 中双击您要包含另一个着色器的着色器文件,并在 Shader Source Editor 中添加 #include 指令,后跟一个着色器文件名。

    Kanzi 用着色器的内容替换您添加 #include 指令的那一行。

    例如,要包含着色器 MyHelperShader.glsl:

    ...
    
    #include "MyHelperShader.glsl"
    
    ...
    

要在工程之间共享着色器代码而无需复制文件,请使用 Kanzi 着色器包含库。请参阅 使用着色器包含库。

在 API 中使用着色器

有关详细信息,请参阅 ShaderProgram 类。

另请参阅

属性类型

使用着色器包含库

着色器最佳实践

优化网格