C
自定义材质参考
本页将解释如何编写自定义材质。
概述
材质规范允许编写自定义材质并将其连接到工作室照明系统。必须为材质编写片元着色器,该着色器必须实现工作室用于计算着色颜色的所有函数。材质系统还提供现成的函数来帮助实现材质。这些函数可以通过着色器使用 #include
指令(带函数名称)来访问。
材质系统支持介质和透明材质、点光源、区域光、环境遮蔽、阴影、双面多边形、折射率和片元截止(蒙蔽)。
也可以在不使用占位符代码的情况下编写自定义材质,在这种情况下,必须在着色器中实现主函数。
有关 XML 格式的更多信息,请参阅自定义材质和效果和效果参考。
注意:在着色器代码中使用的某些字符(如 '<')会破坏 XML 解析。建议将任何着色器代码包裹在 <![CDATA[]]> 中,以启用使用此类字符。示例用法
<FragmentShader><![CDATA[ void main() { } ]]></FragmentShader>
必需的函数
每个片元着色器都必须实现这些函数。
bool evalTwoSided()
此函数控制双面光照。返回 true 启用双面光照,返回 false 禁用双面光照。当禁用双面光照时,仅调用面向前方的材质函数。
float computeIOR()
调用此函数以计算材质的折射率。返回材质折射率。
float evalCutout()
在评估片元截止(蒙蔽)值时调用此函数。如果此函数返回的值小于等于零,将丢弃片元。
vec3 computeNormal()
此函数用于计算片元的法线。返回片元的法线。
void computeTemporaries()
调用此函数允许材质计算它需要的任何临时值。它在其他任何函数之前调用。
void initializeLayerVariables()
调用此函数允许材质初始化层参数。用户应在 computeFrontLayerColor、computeFrontAreaColor、computeFrontLayerEnvironment、computeBackLayerColor、computeBackAreaColor 和 computeBackLayerEnvironment 中初始化存储要计算的照明值的变量。
void initializeLayerVariablesWithLightmap()
调用此函数允许材质初始化层参数。
注意:此函数是可选的,并且只有在材质使用光照贴图时才会调用。
vec3 computeFrontMaterialEmissive()
在计算面向前方多边形的材质的辐射组件时调用此函数。返回 RGB 发射值 vec3。
vec3 computeBackMaterialEmissive()
在计算面向背面的多边形的材质的辐射组件时调用此函数。返回 RGB 发射值 vec3。
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, in float aoFactor )
为每个面向前方多边形的亮光(不包括区域光)调用此函数。材质可以编写自己的光照模型或使用提供的函数。可用的函数有 microfacetBSDF、physGlossyBSDF 和 simpleGlossyBSDF。normal 是片元法线。lightDir 是从片段到灯光的世界空间中的归一化向量。
void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
为每个面向前方多边形的面光源调用此函数。
void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, in float aoFactor )
仅调用一次以计算面向前方多边形的环照光。
void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, in float aoFactor )
此函数对于背面多边形的每个非区域光源都会被调用。材质可以编写自己的照明模型或使用提供的功能。可用的函数有 microfacetBSDF、physGlossyBSDF 和 simpleGlossyBSDF。其中,normal 是片段的法线,而 lightDir 是从片段到光在世界空间中的归一化向量。
void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
此函数对于背面多边形的每个区域光源都会被调用。
void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, in float aoFactor )
此函数仅调用一次,用于计算背面多边形的环境光。
vec4 computeLayerWeights( in float alpha )
此函数在处理完所有照明后调用,用于计算片段的最终照明值。
vec4 computeGlass( in vec3 normal, in float materialIOR, in float alpha, in vec4 color )
仅在调用 computeLayerWeights 后材质透明且非透射的情况下,此函数会被调用。
注意:此函数是可选的,仅当材质是透明且非透射时才会调用。
vec4 computeOpacity( in vec4 color )
仅在调用 computeLayerWeights 后材质是透射的情况下,此函数会被调用。
注意:此函数是可选的,仅当材质是透射时才会调用。
强制包含
#include "vertexFragmentBase.glsllib" #include "SSAOCustomMaterial.glsllib" #include "sampleLight.glsllib" #include "sampleProbe.glsllib" #include "sampleArea.glsllib"
这是所有材质所需的基本包含。
全局变量
这些变量可供材质使用,但不应被写入。
vec3 normal; vec3 surfNormal; vec3 texCoord0; vec3 tangent; vec3 binormal; vec3 viewDir;
这些是片段着色器输入变量,只能读取。
vec3 varTexCoord0; vec3 varTexCoord1; vec3 varNormal; vec3 varTangent; vec3 varBinormal; vec3 varObjTangent; vec3 varObjBinormal; vec3 varWorldPos; vec3 varObjPos;
配置标志
这些是配置标志,可用于为材质启用某些功能。
#define QT3DS_ENABLE_UV0 1/0 #define QT3DS_ENABLE_WORLD_POSITION 1/0 #define QT3DS_ENABLE_TEXTAN 1/0 #define QT3DS_ENABLE_BINORMAL 1/0
- QT3DS_ENABLE_UV0 标志启用纹理坐标 0 变量。
- QT3DS_ENABLE_WORLD_POSITION 标志启用世界位置变量。
- QT3DS_ENABLE_TEXTAN 标志启用切线变量。
- QT3DS_ENABLE_BINORMAL 标志启用副法线变量。
配置功能
这些标志可以在材质编译时由材质系统条件性地启用。自定义着色器可以使用它们来启用不同的编译代码路径。
#define QT3DS_ENABLE_CG_LIGHTING #define QT3DS_ENABLE_LIGHT_PROBE #define QT3DS_ENABLE_SSAO #define QT3DS_ENABLE_SSDO #define QT3DS_ENABLE_SSM #define QT3DS_ENABLE_RNM
- QT3DS_ENABLE_CG_LIGHTING 标志在启用照明时启用。
- QT3DS_ENABLE_LIGHT_PROBE 标志在启用光探针时启用。
- QT3DS_ENABLE_SSAO 标志在启用屏幕空间环境遮挡时启用。
- QT3DS_ENABLE_SSDO 标志在启用屏幕空间直接遮挡时启用。
- QT3DS_ENABLE_SSM 标志在启用阴影映射时启用。
- QT3DS_ENABLE_RNM 标志在启用法线贴图辐射度时启用。
注意:法线贴图辐射度目前不受支持。
使用包含从着色器库添加功能
材质可以使用 #include
指令从着色器库中导入功能。某些功能需要用户定义该功能的常量和结构。例如,要使用 blendColorLayers 函数,用户必须在使用之前指定 mono_xxx 常量和 texture_return 和 color_layer 结构(至少一次)。
#define mono_alpha 0 #define mono_average 1 #define mono_luminance 2 #define mono_maximum 3 struct texture_return { vec3 tint; float mono; }; struct color_layer { vec3 layer_color; float weight; int mode; }; #include "blendColorLayers.glsllib" texture_return blendColorLayers( in color_layer colorLayer[1], in vec3 base, in int monoSource );
某些包含需要额外的包含才能正确工作。例如,fileBumpTexture 需要以下额外的包含和定义
#include "luminance.glsllib" #include "monoChannel.glsllib" #define wrap_clamp 0 #define wrap_repeat 1 #define wrap_mirrored_repeat 2 #include "rotationTranslationScale.glsllib" #include "transformCoordinate.glsllib"
可包含函数
microfacetBSDF
#define scatter_reflect 0 #define scatter_transmit 1 #define scatter_reflect_transmit 2 #include "calculateRoughness.glsllib" #include "microfacetBSDF.glsllib" vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior, in float roughnessU, in float roughnessV, in int mode )
此函数使用微面元BSDF光照模型计算粗糙表面的光值。tanFrame参数是片元的切空间矩阵,L和V分别是光照向量和视图向量,lightSpecular是光照镜面反射值,ior指定了表面的折射率,roughnessU和roughnessV是相对于纹理U和V坐标的粗糙度因子,mode参数指定了如何计算散射。返回值是4个分量的rgba向量。
vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, in int mode )
此函数依据环境图使用微面元BSDF光照模型计算粗糙表面的光值。环境图由uEnvironmentMap属性指定。tanFrame参数是片元的切空间矩阵,viewDir是视图向量,roughnessU和roughnessV是相对于纹理U和V坐标的粗糙度因子,mode参数指定了如何计算散射。返回值是4个分量的rgba向量。
physGlossyBSDF
#define scatter_reflect 0 #define scatter_transmit 1 #define scatter_reflect_transmit 2 #include "physGlossyBSDF.glsllib" vec4 kggxGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior, in float roughnessU, in float roughnessV, in int mode )
此函数使用GGX BSDF计算镜面表面的光值。tanFrame参数是片元的切空间矩阵,L和V分别是光照向量和视图向量,lightSpecular是光照镜面反射值,ior指定了表面的折射率,roughnessU和roughnessV是相对于纹理U和V坐标的粗糙度因子,mode参数指定了如何计算散射。返回值是4个分量的rgba向量。
vec4 wardGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior, in float roughnessU, in float roughnessV, in int mode )
此函数使用Ward BSDF计算镜面表面的光值。tanFrame参数是片元的切空间矩阵,L和V分别是光照向量和视图向量,lightSpecular是光照镜面反射值,ior指定了表面的折射率,roughnessU和roughnessV是相对于纹理U和V坐标的粗糙度因子,mode参数指定了如何计算散射。返回值是4个分量的rgba向量。
simpleGlossyBSDF
#define scatter_reflect 0 #define scatter_transmit 1 #define scatter_reflect_transmit 2 #include "calculateRoughness.glsllib" #include "simpleGlossyBSDF.glsllib" vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecular, in float ior, in float roughnessU, in float roughnessV, in int mode )
此函数使用简单BSDF计算镜面表面的光值。tanFrame参数是片元的切空间矩阵,L和V分别是光照向量和视图向量,lightSpecular是光照镜面反射值,ior指定了表面的折射率,roughnessU和roughnessV是相对于纹理U和V坐标的粗糙度因子,mode参数指定了如何计算散射。返回值是4个分量的rgba向量。
vec4 simpleGlossyBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, in int mode )
此函数使用基于环境图的简单BSDF光照模型计算镜面表面的光值。环境图由uEnvironmentMap属性指定。tanFrame参数是片元的切空间矩阵,viewDir是视图向量,roughnessU和roughnessV是相对于纹理U和V坐标的粗糙度因子,mode参数指定了如何计算散射。返回值是4个分量的rgba向量。
sampleProbe
#include "sampleProbe.glsllib" vec4 sampleGlossyAniso( mat3 tanFrame, vec3 viewDir, float roughnessU, float roughnessV )
为光探针计算镜面采样。tanFrame参数是片元的切空间矩阵,viewDir是视图向量,roughnessU和roughnessV是相对于纹理U和V坐标的粗糙度因子。
注意:必须启用QT3DS_ENABLE_LIGHT PROBE才能使用此函数。
vec4 sampleDiffuse( mat3 tanFrame )
为光探针计算漫反射采样。tanFrame参数是片元的切空间矩阵。
注意:必须启用QT3DS_ENABLE_LIGHT PROBE才能使用此函数。
sampleArea
#include "sampleArea.glsllib" vec4 sampleAreaGlossy( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec3 viewDir, in float roughnessU, in float roughnessV )
计算区域光源的反射采样。参数 tanFrame 是片段的切线空间矩阵,pos 是片段世界的位置,lightIdx 是光源的索引,viewDir 是视图向量,而 roughnessU 和 roughnessV 是关于纹理 U 和 V 坐标的粗糙度因子。
vec4 sampleAreaDiffuse( in mat3 tanFrame, in vec3 pos, in int lightIdx )
计算区域光源的漫反射采样。参数 tanFrame 是片段的切线空间矩阵,pos 是片段世界的位置,和 lightIdx 是光源的索引。
具有主函数的自定义材料
在没有其余材质系统的情况下,也可以编写自定义材料。在这种情况下,不需要编写上述所有函数。每个片段仅需要包含主函数。
out vec4 fragColor; void main() { fragColor = ... }
注意:前版本中提到不应将闭合括号添加到主函数中。现在情况已改变,主函数应添加闭合括号。
使用图像变换访问纹理
生成自定义材料时,还会生成图像变换的统一变量,以及获取变换坐标和纹理采样的访问函数。
对于名为 "basecolor" 的纹理,生成的统一变量和函数是
uniform vec3 basecolorTransformU; uniform vec3 basecolorTransformV; vec3 texcoordTransformed_basecolor(vec3 texcoord); vec4 sampleTransformed_basecolor(vec3 texcoord);
简单自定义材料示例
<Material name="simplecustom" version="1.0"> <MetaData > <Property formalName="Red" name="red_weight" type="Float" default="1.0" min="0" max="1.0" category="Material"/> <Property formalName="Green" name="green_weight" type="Float" default="1.0" min="0" max="1.0" category="Material"/> <Property formalName="Blue" name="blue_weight" type="Float" default="1.0" min="0" max="1.0" category="Material"/> <Property formalName="Base Color" name="basecolor" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" category="Material"/> </MetaData> <Shaders type="GLSL" version="330"> <Shader> <Shared></Shared> <VertexShader> </VertexShader> <FragmentShader><![CDATA[ #define UIC_ENABLE_UV0 1 #define UIC_ENABLE_WORLD_POSITION 1 #define UIC_ENABLE_TEXTAN 0 #define UIC_ENABLE_BINORMAL 0 #include "vertexFragmentBase.glsllib" #include "SSAOCustomMaterial.glsllib" #include "sampleLight.glsllib" #include "sampleProbe.glsllib" #include "sampleArea.glsllib" // Set shader output. out vec4 fragColor; void main() { vec4 c = texture(basecolor, varTexCoord0.xy); c.rgb *= vec3(red_weight, green_weight, blue_weight); fragColor = c; } ]]></FragmentShader> </Shader> </Shaders> <Passes > <ShaderKey value="7"/> <LayerKey count="1"/> <Pass > </Pass> </Passes> </Material>
ShaderKey
ShaderKey-元素是一个指定的材质如何编译的魔数字符。值是材质需要启用的属性的总和。支持属性包括
常量 | 描述 |
---|---|
1 | 介电体 |
2 | 镜面反射 |
4 | 亚光 |
8 | 剪影 |
16 | 折射 |
32 | 透明 |
256 | 透射 |
LayerKey-element 指定材质的层数。这目前被忽略。
在一些 Qt 许可证下可用。
了解更多信息。