对于引擎开发者¶
代码样式¶
这款引擎采用结构化程序。该代码由模块组织。没有用OOP方法都,没有定义的类,不进行继承等。
使用 K&R风格 除了对于一个组合操作的括号开口被放置在同一行上,例如:
function foo_bar() {
// ...
}
if (a > b) {
// ...
}
4个空格用于缩进(不允许tab)。
例子¶
下划线符号在函数和变量名称中使用:
var foo_bar = 123; // correct
var fooBar = 123; // wrong
所有的全局变量以下划线开头:
var _foo_bar = null;
这些常量用大写字母表示,从不以下划线开头:
var FOO_BAR = 100;
外部API方法和属性的名称均在点之后写的。为了避免混淆他们必须用 @ cc_externs
标签字段:
exports.FOO_BAR = 123;
exports.foo_bar = function() {
}
/**
* Set properties.
* @method module:properties.set_props
* @param {Object} foo Foo object
* @cc_externs props_1 props_2
* @cc_externs props_3 props_4
*/
exports.set_props = function(foo) {
var bar_1 = foo.props_1;
var bar_2 = foo.props_2;
var bar_3 = foo.props_3;
var bar_4 = foo.props_4;
...
}
注释仅用英语。注释风格 - JSDoc。
构建引擎¶
构建之前,请确保您的系统已安装所有需要的依赖关系(参见 table).
要编译引擎,并纳入SDK,请执行以下命令(在SDK根目录)的应用程序:
make compile
完整的构建,包括将资源(纹理,声音和视频),编辑和转换的文档,可以用下面的命令执行:
make build
构建发布档案:
make dist
所有上述操作可以用一个命令来执行:
make all
构建插件¶
二进制的Blend4Web插件版本是可用于以下平台:Linux的X32 / 64,macOS的 x64,Windows X32 / 64。同时用户可以自行编译插件。
要做到这一点,Python 3.X(如果它是跟blender相同的版本更好)和C编译器是必需的。在Linux下,只需安装python3-dev 和 build-essential 的程序包。
- 路径相对于库根:
构建脚本:
csrc/b4w_bin/build.py
Blend4Web插件:
addons/blend4web/
该构建过程开始于以下方式:
python3 ./csrc/b4w_bin/build.py
由于构建的结果,你会得到一个名为二进制文件:
b4w_bin_[PLATFORM]_[ARCHITECTURE].[STANDARD_EXTENSION]
,
和插件位于同一目录中。例如:b4w_bin_Linux_64.so
。在此之后,插件已经准备好这个平台下使用。
依赖¶
所有依赖于下表中列出的重要性顺序递减。
名称 |
Ubuntu的16.04包 |
用途 |
---|---|---|
Bash | 默认情况下包含 |
脚本解释器 |
Python 3 | 默认情况下包含 |
脚本解释器 |
NodeJS | nodejs | 着色器编译 |
Java | 默认的JRE |
编译和混淆引擎模块 |
ImageMagick | imagemagick | 转换纹理 |
NVIDIA纹理工具 |
libnvtt-bin | 转换纹理 |
Libav | libav-tools | 转换资源 |
NVIDIA CG工具包 |
NVIDIA-CG-工具包 |
着色器的调试 |
OptiPNG | optipng | 优化 PNG 文件 |
Emscripten | 构建Uranium |
|
Gnuplot | gnuplot | 偵錯 |
Graphviz | graphviz | 偵錯 |
xsel | xsel | 偵錯 |
Sphinx | python3-sphinx | 构建手册 |
sphinx-intl | 使用 PIP v3 安装(pip3 install sphinx-intl) |
构建手册(国际) |
TeX Live | texlive texlive-latex-extra texlive-lang-cyrillic texlive-lang-chinese texlive-xetex | 构建说明书(PDF版) |
JSDoc 3 | 使用 NPM 进行安装 (npm install -g jsdoc) |
构建API文档 |
PEG.js | 着色器预处理 |
命名函数和变量¶
当创建新的函数和变量,建议使用以下前缀和后缀。
- init_
创建抽象物体
- create_
创建实际的物体
- update_
更新现有物体的状态
- attach_/detach_
添加/删除临时物体属性
- append_/remove_
添加/删除临时属性同类的现有属性
- insert_/pop_
添加/删除数组元素(按索引访问)
- switch_
切换标志的二进制值
- apply_/clear_
操作标志,二进制值或任意参数的操作
- set_/get_
设置/获取属性/变量值
- _tmp
全局变量 - 缓存在一个简单的物体的形式(数组,向量)
- _cache
全局变量 - 缓存在一个复杂的物体的形式
调试中¶
引擎调试在 debug.js
模块方法进行。
当前的渲染图的结构可以用 b4w.debug.scenegraph_to_dot()
调用,例如,在浏览器的控制台被保存在DOT格式。调用此方法后,保存控制台输出与.gv扩展名的文件。为了得到在视觉形式图表中的 graphviz的 是必需的工具。转换为SVG格式是使用命令执行:
> dot -Tsvg graph.gv -o graph.svg
其中,graph.gv
是保存的图形文件的名称。
着色器编译¶
在引擎中使用的所有着色器由编译器处理。编译器执行以下三个主要步骤:
shader代码的验证,
它的混淆处理,
优化
为了编译运行,在SDK根处键入以下命令执行:
> make compile_shaders
> make verify_shaders
make compile_shaders - 执行验证,混淆,优化和最后,编译着色器的导出,
make verify_shaders - 只执行验证,混淆和优化。
在编译期间首先进行着色文本的语法分析(解析)。相应的解析器自动创建基于语法,使用 PEG.js 引擎。然后将由着色器验证,混淆和优化根据解析器数据,之后该着色器中抽象语法树(AST),用于在引擎直接装载的形式输出。
资源库中的主要文件的位置:
初步的语法 - glsl_utils / pegjs / glsl_parser.pegjs
解析器生成脚本 - glsl_utils / pegjs / gen_nodejs.sh
解析器 - glsl_utils /编译器/ glsl_parser.js
优化¶
优化构成以下程序:
除去大括号,不能在除了创建本地作用域任何方式有用(这一功能是用于处理节点/灯指示),
内部功能的优化 - 创建共享局部变量,以取代原来由程序员创建的。
删除未使用大括号的一个例子:替换下面的代码
void function(){
int a;
{
a = 1;
}
}
与这些代码
void function(){
int a;
a = 1;
}
临时局部变量的低数量是由在不同情况下重复使用它们来实现的。例如,下面的代码
int function(){
int a = 1;
int b = a + 3;
return b;
}
Blender内置渲染引擎的纹理绘图类型已被其它三个模块所取代:
int function(){
int _int_tmp0 = 1;
_int_tmp0 = _int_tmp0 + 3;
return _int_tmp0;
}
注解
对于结构和数组的局部变量未优化这种方式。
导入/导出指令¶
导入/导出指令用于组织,结构和增加着色器代码的可读性中包含文件。它们在文件的开头指定,应该看起来大约是这样的:
#import u_frame_factor u_quatsb u_quatsa u_transb u_transa a_influence
#import qrot
#export skin
在 #import
指令定义了一组声明的包含文件之外,但可以从里面被访问的ID。这里有一个限制,但:这样的id必然是上述地方,其中包括文件链接的地方声明。
在 #export
指令定义了一组可以从该文件外部访问的ID。这样的id必然在这个文件中声明。
因此,它使用的着色器包含文件必须拥有所有必要的连接位置之前,进口的声明,以后它可以使用导出的标识。
IDS既可以是变量名和函数名。如果没有导入/导出命令中,它在默认情况下认为,包括文件不使用外部声明和内部的人的使用不允许。
建议和限制¶
由于以下几个原因:预处理,处理多个着色器和包括文件和由于编译器的功能的需要 - 其可能保证只有当一些规则和限制方面的着色源推崇的输出代码的工作码:
为了描述这是由引擎在运行中定义的常量,有必要使用``#var``特殊指令。例如:
#var AU_QUALIFIER uniform
AU_QUALIFIER float a;
这里的语法是类似的#define指令。所述#var指令的一点是,它定义了值允许解析初始着色。它是不相关的这将是什么(在上面的例子如“制服”或“属性”),因为在这个水平上它是未知反正。不过,最好是指定一个或多或少适当的描述,不是随心所欲。
注解
该#var指令没有必要不是在着色的代码,但在预处理器表达式中使用的常数。
在需要的时候使用导入/导出指令。
内置的功能,不能超载 - 只有用户的。
变量不应与的内置函数名称,或者主要(即使它不导致错误)中声明。
的#var和#define指令不能被用于以这样运营商更换单个符号:“ ”,“ - ”,“* =”,“/ =”,“ =”,“ - =” ,“==”,“<=”,“> =”,“!=”,“&&”,“||”,“^^”。
例如:
#var EQUAL =
...
a *EQUAL b;
...
#include指令的使用不应该包含文件的混淆中产生歧义。当多个着色器纳入相同的文件,上面定义的指令(如#var或者将#define)可以对任何人的影响,可能发生这种情况。此外,最好不要使用未声明的函数和变量中包含文件。
多级包括或相同的多个纳入到包括不支持相同的着色器。
着色器的故障也可以通过使用非平凡的预处理,例如,创建一个无效的GLSL代码引起的:
#if TYPE
void function1() {
#else
void function1(int i) {
#endif
...
}
不要声明与这样的名字变量
node_ [NODE_NAME] _var_ [IN_OUT_NODE]
,其中NODE_NAME
—一些节点的名称,IN_OUT_NODE
—输入或输出的名称节点。重复使用
#nodes_main
,#nodes_global
或#lamps_main
指令是不是一个单一的着色器内禁止。在
#nodes_main
,#nodes_global
和#lamps_main
指令,建议在该文件中使用,包含这些着色器节点的说明,例如,在同一个包含文件。这是必要的正确的着色器验证。
编译错误¶
在发生错误时,编译器会在控制台输出相应的消息。
可能发生的错误的表:
错误信息 |
原因 |
---|---|
错误!含糊不清的包含文件“FILE_NAME”。 |
在“FILE_NAME”含糊不清包含文件。 |
错误!扩展名是在混淆器不支持。文件:“FILE_NAME”。 |
在FILE_NAME文件中使用的名称WebGL的扩展不被混淆器支持。 |
错误!包括“FILE_NAME找不到。 |
该FILE_NAME包含文件找不到。 |
Error! Undeclared TYPE: ‘NAME’. File: ‘FILE_NAME’. | FILE_NAME文件中错误。类型TYPE(变量,函数,结构等)的未声明标识符名称。 |
Error! Undeclared TYPE: ‘NAME’. Importing data missed. File: ‘FILE_NAME’. | 类型TYPE(变量,函数,结构等)的未声明标识符名称。声明中缺少在FILE_NAME所需的标识符包括根据``#import``指令文件。 |
Error! Undeclared TYPE: ‘NAME’. Possibly exporting needed in include file ‘INCLUDE_NAME’. File: ‘FILE_NAME’. | 在FILE_NAME文件有错误。类型TYPE(变量,函数,结构等)的未声明标识符名称。可能出口到INCLUDE_NAME include文件应该被允许。 |
Error! Undeclared TYPE: ‘NAME’. Possibly importing needed. File: ‘FILE_NAME’. | 类型TYPE(变量,函数,结构等)的未声明标识符名称。也许应指定为FILE_NAME进口包含文件。 |
Error! Unused export token ‘NAME’ in include file ‘FILE_NAME’. | 未声明的标识符名称是允许在出口FILE_NAME包含文件。 |
Error! Using reserved word in TYPE ‘NAME’. File: ‘FILE_NAME’. | 错误FILE_NAME文件。的预留ID用于声明类型TYPE(变量,函数,结构等)的标识符名称。 |
Error! ‘all’ extension cannot have BEHAVIOR_TYPE behavior. File: ‘FILE_NAME’. | 对于指定的 |
Syntax Error. ERROR_MESSAGE. File: FILE_NAME, line: LINE_NUMBER, column: COL_NUMBER. | 解析FILE_NAME着色器在线路LINE_NUMBER列COL_NUMBER语法错误。最初的错误描述在ERROR_MESSAGE是引用。代码清单来自各地的相应线路连接到邮件采取的(注意哪些指定哪个才是真正的错误后,一点点就行pegjs解析器的特点。 |
Warning! Function ‘NAME’ is declared in [include ]file FILE_NAME, but never used. | 未使用的函数名在FILE_NAME文件中声明。 |
Warning! Include file ‘FILE_NAME’ not used in any shader, would be omitted! | 该FILE_NAME包含文件未在任何着色器的使用,所以它会从模糊版本被排除在外。 |
Warning! Unused import token ‘NAME’ in include file ‘FILE_NAME’. | 未使用的ID名称在FILE_NAME导入包含文件。 |
Warning! Variable ‘NAME’ is declared in include file FILE_NAME, but never used. | 未使用的变量名称在FILE_NAME文件中声明。 |