UnigineEditor
界面概述
资产工作流程
设置和首选项
项目开发
调整节点参数
Setting Up Materials
Setting Up Properties
照明
Landscape Tool
Sandworm (Experimental)
使用编辑器工具执行特定任务
Extending Editor Functionality
编程
基本原理
搭建开发环境
Usage Examples
UnigineScript
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine Tools
GUI
双精度坐标
应用程序接口
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes

可编写脚本的材料

A scriptable material is a base material with expressions (fragments of code written in UnigineScript) executed at certain stages of rendering sequence offering you an exceptional flexibility. For example, you can use them to create your own custom post effects such as DoF or Bloom.可编写脚本的材料是具有表达式(用 UnigineScript 编写的代码片段)的基础材料 渲染顺序为您提供了极大的灵活性。例如,您可以使用它们来创建自己的自定义后期效果,例如DoF或Bloom。

Scriptable materials represent an ideal instrument for fast prototyping of any custom effects, as they allow you to:可编写脚本的材料代表了快速定制任何特效的理想工具,因为它们使您能够:

  • write any logic in UnigineScript,用UnigineScript编写任何逻辑,
  • apply them globally or per-camera,全局或按摄像机应用它们,
  • have all necessary parameters added to UI automatically.将所有必需的参数自动添加到UI。

A single or multiple scriptable materials can be applied globally (via the Scriptable Materials section of the Settings window) or attached to a certain camera (via the Parameters window). Expressions assigned to a scriptable material are executed only if the material is enabled. The order of execution is defined by the material's number in the list of appllied scriptable materials (either global or camera-specific). The order can be changed if necessary.可以全局(通过Settings窗口的Scriptable Materials部分)应用单个或多个可编写脚本的材料,也可以将其附加到某个摄像机(通过Settings窗口)。仅在启用材质的情况下才执行分配给可脚本化材质的表达式。执行顺序由适用的可编写脚本的材料列表(全局或特定于摄像机)中的材料编号定义。必要时可以更改顺序。

注意
Scriptable materials applied globally have their expressions executed before the corresponding expressions of the ones that are applied per-camera.全局应用的可编写脚本的材质的表达式要在每个摄像机所应用的脚本的对应表达式之前执行。

Scriptable material lists are pretty much like the lists of components assigned to nodes, enabling you to adjust all available parameters and control which materials to apply.可编写脚本的材料列表与分配给节点的组件列表非常相似,使您可以调整所有可用参数并控制要应用的材料。

As base materials, scriptable ones are created and edited manually.作为基础材料,可手动编写和编辑可编写脚本的材料。

Creating a Scriptable Base Material with ULON使用ULON创建可编写脚本的基础材料#

The custom scriptable base material is the same as the default one: it is read-only, non-hierarchical, referred by the name and so on.可自定义脚本化的基础材料与默认材料相同:它是只读的,非分层的,由名称和引用引用。

Let’s write a material in the ULON file format.让我们以 ULON文件格式编写材料。

Implementing Material Logic实施材料逻辑#

  1. Create the post_sobel.basemat text file in the data/materials folder and open it in a plain text editor.data/materials文件夹中创建post_sobel.basemat文本文件,然后在纯文本编辑器中将其打开。
  2. Specify the name for the base material and attributes for it.
    源代码
    BaseMaterial post_sobel <options_hidden=1 preview_hidden=1 var_prefix=var texture_prefix=tex>
    {
    ...
    }
    指定基础材料的名称和属性。
    源代码
    BaseMaterial post_sobel <options_hidden=1 preview_hidden=1 var_prefix=var texture_prefix=tex>
    		{
    		...
    		}
  3. Describe material’s resources and parameters.
    源代码
    // specify an internal texture to be used
    Texture src_color <type=procedural internal=true>
    
    // define the material's states and parameters available in the Editor
    Group "Sobel operator"
    {
    	State multiply = false
    	Slider threshold = 1.0 <min=0.0 max=1.0>
    	Slider scale = 1.0 <min=0.0 max=1.0>
    }
    描述材料的资源和参数。
    源代码
    // specify an internal texture to be used
    Texture src_color <type=procedural internal=true>
    
    // define the material's states and parameters available in the Editor
    Group "Sobel operator"
    {
    	State multiply = false
    	Slider threshold = 1.0 <min=0.0 max=1.0>
    	Slider scale = 1.0 <min=0.0 max=1.0>
    }
  4. Write the fragment shader for the custom outline render pass.
    源代码
    // define the outline render pass
    Pass render_sobel_operator
    {
    	// write the fragment shader in UUSL or HLSL/GLSL
    	Fragment=
    	#{
    		#include <core/shaders/common/fragment.h>
    		
    		MAIN_BEGIN(FRAGMENT_OUT, FRAGMENT_IN)
    			// get the inverse resolution of the viewport (1.0 / width, 1.0 / height)
    			float2 offset = s_viewport.zw; 
    			
    			// take 3x3 samples
    			OUT_COLOR = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV);
    			
    			float3 c0 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 0)).rgb;
    			float3 c1 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, 1)).rgb;
    			float3 c2 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 1)).rgb;
    			float3 c3 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, -1)).rgb;
    			
    			float3 c4 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 0)).rgb;
    			float3 c5 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, -1)).rgb;
    			float3 c6 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, -1)).rgb;
    			float3 c7 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 1)).rgb;
    			
    			// find edge with Sobel filter
    			float3 sobel_x = c6 + c4 * 2.0f + c7 - c3 - c0 * 2.0f - c2;
    			float3 sobel_y = c6 + c5 * 2.0f + c3 - c7 - c1 * 2.0f - c2;
    			float3 sobel = sqrt(sobel_x * sobel_x + sobel_y * sobel_y);
    			
    			// apply threshold
    			float edge = saturate(1.0f - dot(sobel, to_float3(var_threshold)));
    			
    			// apply scale
    			float3 result = saturate(OUT_COLOR.rgb + var_scale) * edge;
    			
    			#ifdef STATE_MULTIPLY
    				OUT_COLOR.rgb *= result; // for colored result
    			#else
    				OUT_COLOR.rgb = result; // for black & white result
    			#endif
    		MAIN_END
    	#}
    }
    为自定义轮廓渲染过程编写片段着色器。
    源代码
    // define the outline render pass
    		Pass render_sobel_operator
    		{
    			// write the fragment shader in UUSL or HLSL/GLSL
    			Fragment=
    			#{
    				#include <core/shaders/common/fragment.h>
    				
    				MAIN_BEGIN(FRAGMENT_OUT, FRAGMENT_IN)
    					// get the inverse resolution of the viewport (1.0 / width, 1.0 / height)
    					float2 offset = s_viewport.zw; 
    					
    					// take 3x3 samples
    					OUT_COLOR = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV);
    					
    					float3 c0 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 0)).rgb;
    					float3 c1 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, 1)).rgb;
    					float3 c2 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 1)).rgb;
    					float3 c3 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, -1)).rgb;
    					
    					float3 c4 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 0)).rgb;
    					float3 c5 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, -1)).rgb;
    					float3 c6 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, -1)).rgb;
    					float3 c7 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 1)).rgb;
    					
    					// find edge with Sobel filter
    					float3 sobel_x = c6 + c4 * 2.0f + c7 - c3 - c0 * 2.0f - c2;
    					float3 sobel_y = c6 + c5 * 2.0f + c3 - c7 - c1 * 2.0f - c2;
    					float3 sobel = sqrt(sobel_x * sobel_x + sobel_y * sobel_y);
    					
    					// apply threshold
    					float edge = saturate(1.0f - dot(sobel, to_float3(var_threshold)));
    					
    					// apply scale
    					float3 result = saturate(OUT_COLOR.rgb + var_scale) * edge;
    					
    					#ifdef STATE_MULTIPLY
    						OUT_COLOR.rgb *= result; // for colored result
    					#else
    						OUT_COLOR.rgb = result; // for black & white result
    					#endif
    				MAIN_END
    			#}
    		}
  5. Write the Expression callback in Unigine Script to be called after the Post Materials stage (RENDER_CALLBACK_END_POST_MATERIALS) of the render sequence to perform outline render pass with Sobel filter.
    源代码 (UnigineScript)
    // the expression in Unigine Script defines a callback 
    Expression RENDER_CALLBACK_END_POST_MATERIALS = 
    #{
    	// declare the source texture from the screen frame
    	Texture source = engine.render.getTemporaryTexture(engine.render_state.getScreenColorTexture());
    	// define the source texture from the screen frame
    	source.copy(engine.render_state.getScreenColorTexture());
    	//set the color source texture to use it in the shader
    	setTexture("src_color", source);
    	// render the outline result texture to output it to the screen 
    	renderPassToTexture("render_sobel_operator", engine.render_state.getScreenColorTexture());
    	// release the temporaty texture
    	engine.render.releaseTemporaryTexture(source);
    #}
    在Unigine脚本中编写Expression回调,以便在Post Materials阶段(RENDER_CALLBACK_END_POST_MATERIALS)渲染序列,以使用Sobel滤镜执行轮廓渲染。
    源代码 (UnigineScript)
    // the expression in Unigine Script defines a callback 
    		Expression RENDER_CALLBACK_END_POST_MATERIALS = 
    		#{
    		// declare the source texture from the screen frame
    		Texture source = engine.render.getTemporaryTexture(engine.render_state.getScreenColorTexture());
    		// define the source texture from the screen frame
    		source.copy(engine.render_state.getScreenColorTexture());
    		//set the color source texture to use it in the shader
    		setTexture("src_color", source);
    		// render the outline result texture to output it to the screen 
    		renderPassToTexture("render_sobel_operator", engine.render_state.getScreenColorTexture());
    		// release the temporaty texture
    		engine.render.releaseTemporaryTexture(source);
    		#}
  6. The full source code for the material is given below. You can copy it to the post_sobel.basemat and save the file.
    源代码
    BaseMaterial post_sobel <options_hidden=1 preview_hidden=1 var_prefix=var texture_prefix=tex>
    {
    // specify an internal texture to be used
    Texture src_color <type=procedural internal=true>
    
    // define the material's states and parameters available in the Editor
    Group "Sobel operator"
    {
    	State multiply = false
    	Slider threshold = 1.0 <min=0.0 max=1.0>
    	Slider scale = 1.0 <min=0.0 max=1.0>
    }
    
    // define the outline render pass
    Pass render_sobel_operator
    {
    	// write the fragment shader in UUSL or HLSL/GLSL
    	Fragment=
    	#{
    		#include <core/shaders/common/fragment.h>
    		
    		MAIN_BEGIN(FRAGMENT_OUT, FRAGMENT_IN)
    			// get the inverse resolution of the viewport (1.0 / width, 1.0 / height)
    			float2 offset = s_viewport.zw; 
    			
    			// take 3x3 samples
    			OUT_COLOR = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV);
    			
    			float3 c0 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 0)).rgb;
    			float3 c1 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, 1)).rgb;
    			float3 c2 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 1)).rgb;
    			float3 c3 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, -1)).rgb;
    			
    			float3 c4 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 0)).rgb;
    			float3 c5 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, -1)).rgb;
    			float3 c6 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, -1)).rgb;
    			float3 c7 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 1)).rgb;
    			
    			// find edge with Sobel filter
    			float3 sobel_x = c6 + c4 * 2.0f + c7 - c3 - c0 * 2.0f - c2;
    			float3 sobel_y = c6 + c5 * 2.0f + c3 - c7 - c1 * 2.0f - c2;
    			float3 sobel = sqrt(sobel_x * sobel_x + sobel_y * sobel_y);
    			
    			// apply threshold
    			float edge = saturate(1.0f - dot(sobel, to_float3(var_threshold)));
    			
    			// apply scale
    			float3 result = saturate(OUT_COLOR.rgb + var_scale) * edge;
    			
    			#ifdef STATE_MULTIPLY
    				OUT_COLOR.rgb *= result; // for colored result
    			#else
    				OUT_COLOR.rgb = result; // for black & white result
    			#endif
    		MAIN_END
    	#}
    }
    
    // the expression in Unigine Script defines a callback 
    Expression RENDER_CALLBACK_END_POST_MATERIALS = 
    #{
    	// declare the source texture from the screen frame
    	Texture source = engine.render.getTemporaryTexture(engine.render_state.getScreenColorTexture());
    	// define the source texture from the screen frame
    	source.copy(engine.render_state.getScreenColorTexture());
    	//set the color source texture to use it in the shader
    	setTexture("src_color", source);
    	// render the outline result texture to output it to the screen 
    	renderPassToTexture("render_sobel_operator", engine.render_state.getScreenColorTexture());
    	// release the temporaty texture
    	engine.render.releaseTemporaryTexture(source);
    #}
    }
    该材料的完整源代码如下。 您可以将其复制到post_sobel.basemat并保存文件。
    源代码
    BaseMaterial post_sobel <options_hidden=1 preview_hidden=1 var_prefix=var texture_prefix=tex>
    		{
    		// specify an internal texture to be used
    		Texture src_color <type=procedural internal=true>
    
    		// define the material's states and parameters available in the Editor
    		Group "Sobel operator"
    		{
    			State multiply = false
    			Slider threshold = 1.0 <min=0.0 max=1.0>
    			Slider scale = 1.0 <min=0.0 max=1.0>
    		}
    
    		// define the outline render pass
    		Pass render_sobel_operator
    		{
    			// write the fragment shader in UUSL or HLSL/GLSL
    			Fragment=
    			#{
    				#include <core/shaders/common/fragment.h>
    				
    				MAIN_BEGIN(FRAGMENT_OUT, FRAGMENT_IN)
    					// get the inverse resolution of the viewport (1.0 / width, 1.0 / height)
    					float2 offset = s_viewport.zw; 
    					
    					// take 3x3 samples
    					OUT_COLOR = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV);
    					
    					float3 c0 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 0)).rgb;
    					float3 c1 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, 1)).rgb;
    					float3 c2 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, 1)).rgb;
    					float3 c3 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 1, -1)).rgb;
    					
    					float3 c4 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 0)).rgb;
    					float3 c5 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2( 0, -1)).rgb;
    					float3 c6 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, -1)).rgb;
    					float3 c7 = TEXTURE_BIAS_ZERO(tex_src_color, IN_UV + offset * float2(-1, 1)).rgb;
    					
    					// find edge with Sobel filter
    					float3 sobel_x = c6 + c4 * 2.0f + c7 - c3 - c0 * 2.0f - c2;
    					float3 sobel_y = c6 + c5 * 2.0f + c3 - c7 - c1 * 2.0f - c2;
    					float3 sobel = sqrt(sobel_x * sobel_x + sobel_y * sobel_y);
    					
    					// apply threshold
    					float edge = saturate(1.0f - dot(sobel, to_float3(var_threshold)));
    					
    					// apply scale
    					float3 result = saturate(OUT_COLOR.rgb + var_scale) * edge;
    					
    					#ifdef STATE_MULTIPLY
    						OUT_COLOR.rgb *= result; // for colored result
    					#else
    						OUT_COLOR.rgb = result; // for black & white result
    					#endif
    				MAIN_END
    			#}
    		}
    
    		// the expression in Unigine Script defines a callback 
    		Expression RENDER_CALLBACK_END_POST_MATERIALS = 
    		#{
    			// declare the source texture from the screen frame
    			Texture source = engine.render.getTemporaryTexture(engine.render_state.getScreenColorTexture());
    			// define the source texture from the screen frame
    			source.copy(engine.render_state.getScreenColorTexture());
    			//set the color source texture to use it in the shader
    			setTexture("src_color", source);
    			// render the outline result texture to output it to the screen 
    			renderPassToTexture("render_sobel_operator", engine.render_state.getScreenColorTexture());
    			// release the temporaty texture
    			engine.render.releaseTemporaryTexture(source);
    		#}
    		}

Applying Material and Adjusting Parameters施加材料和调整参数#

  1. Launch the UnigineEditor via the SDK Browser. In the Materials tab you will find the imported post_sobel material in the list of base materials.
    通过SDK浏览器启动UnigineEditor。在``材料''选项卡中,您可以在基础材料列表中找到导入的post_sobel材料。
  2. To apply the material globally go to Windows -> Settings and in the Scriptable Materials section click Add New Scriptable Material. Assign the post_sobel material by dragging it to the field or by specifying the name of the material. 要全局应用材质,请转到Windows -> Settings,然后在Scriptable Materials部分中单击Add New Scriptable Material。通过将post_sobel材质拖到字段或指定材质名称来分配它。
  3. Click create a child material to be able to specify states and parameters of the material. The new child material of the post_sobel will be created and assigned here.
    单击create a child material可以指定材料的状态和参数。 post_sobel的新子材料将在此处创建和分配。
  4. Check Multiply to make a colorful final image. Adjust the Threshold and Scale values to customize the effect.
    The applied post process outline effect.The applied post process outline effect.
    The applied post process outline effect.
    选中Multiply以制作彩色的最终图像。调整ThresholdScale值以自定义效果。
    The applied post process outline effect.应用的后期处理轮廓效果。


That’s it! You have just created a scriptable material for all of the application’s cameras. To apply the post process effect only to a specific camera, go to the Parameters tab of the corresponding Player node and assign the material to it.


就是这样!您刚刚为应用程序的所有摄像机创建了可编写脚本的材料。要将后期处理效果仅应用于特定相机,请转到相应Player节点的Parameters选项卡并为其分配材质。

最新更新: 2020-11-21