编辑着色器

在 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 和 attribute 的代码片段。

    ../../_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。

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 着色语言版本。

例如,要将着色器源文件设置为使用 OpenGL ES 3.0,请在文件的开头添加:

#version 300 es

如果您声明版本 100,并且 Kanzi 检测到您的着色器源文件中的代码需要 OpenGL ES 3,Kanzi 会自动将版本设置为 300。

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

要在材质类型中覆盖 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"
    
    ...
    

在 API 中使用着色器

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

另请参阅

属性类型

着色器最佳实践

优化网格