Android如何在Custom Node里面使用高精度float

我们使用UE4.26 在opengles3_1下 想给材质蓝图里的某些运算提高精度,但是发现我们就算使用custom node 声明float变量,编译后的glsl代码也不会添加highp关键字。初步怀疑是因为custom node的返回值是MateriaFloat ,在android下会换成half,导致在词法分析阶段认为变量类型并不是GLSL_TYPE_FLOAT。请问有什么好的解决方案吗?

Hi,

custom node里的运算如果是申明float,应该是float,但是我怀疑是custom node的输入以及输出还是用Material Float,所以导致结果不符合你们的需求。

UE5的版本里支持只把Material Float都转成float的功能,不影响shader里half的写法,不知道这个功能是否能满足你们的需求?其他改法看起来目前没有特别好的办法。

您好,我改了源码 目前已经可以让custom返回值都是float了。例如生成的hlsl代码

// Uniform material expressions.

float3 CustomExpression0(FMaterialPixelParameters Parameters,float input)

{

float3 test = input * 0.354;

return test;

}

在CalcPixelMaterialInputs函数中的使用

// Now the rest of the inputs

float3 Local0 \= CustomExpression0(Parameters,Material.ScalarExpressions\[0].x);

float3 Local1 \= lerp(Local0,Material.VectorExpressions\[1].rgb,MaterialFloat(Material.ScalarExpressions\[0].y));



PixelMaterialInputs.EmissiveColor \= Local1;

但是对应生成glsl代码依然没有highp关键字

void main()

{

vec4 v0;

vec3 v1;

highp float f2;

f2 = pc1_m[0].x;

vec3 v3;

v3.xyz = vec3((f2*3.540000e-01));

v1.xyz = max(v3,vec3(0.000000e+00,0.000000e+00,0.000000e+00));

Custom Node返回的变量是 “vec3 v3”,但是前面没有 highp 关键字。

请问是词法分析出的问题吗?有什么地方能改吗?或者有办法能让我在custom节点里写glsl代码吗?

材质很简单,如下:​

[Image Removed]对应的shader代码:

[HLSL]

...
    // Now the rest of the inputs
    float3 Local0 = CustomExpression0(Parameters,Material.ScalarExpressions[0].x);
    float3 Local1 = lerp(Local0,Material.VectorExpressions[1].rgb,MaterialFloat(Material.ScalarExpressions[0].y));
 
    PixelMaterialInputs.EmissiveColor = Local1;
    PixelMaterialInputs.Opacity = 1.00000000;
    PixelMaterialInputs.OpacityMask = 1.00000000;
    PixelMaterialInputs.BaseColor = MaterialFloat3(0.00000000,0.00000000,0.00000000);
    PixelMaterialInputs.Metallic = 0.00000000;
    PixelMaterialInputs.Specular = 0.50000000;
    PixelMaterialInputs.Roughness = 0.50000000;
    PixelMaterialInputs.Anisotropy = 0.00000000;
    PixelMaterialInputs.Tangent = MaterialFloat3(1.00000000,0.00000000,0.00000000);
    PixelMaterialInputs.Subsurface = 0;
    PixelMaterialInputs.AmbientOcclusion = 1.00000000;
    PixelMaterialInputs.Refraction = 0;
    PixelMaterialInputs.PixelDepthOffset = 0.00000000;
    PixelMaterialInputs.ShadingModel = 0;
...
// Uniform material expressions.
float3 CustomExpression0(FMaterialPixelParameters Parameters,float TestInput)
{
float3 result = TestInput * 0.34;
return result;
}
...

​[GLSL]

#version 310 es
// end extensions
precision mediump float;
precision highp int;
 
 
void compiler_internal_AdjustInputSemantic(inout vec4 TempVariable)
{
//#if HLSLCC_DX11ClipSpace
	TempVariable.y = -TempVariable.y;
	TempVariable.z = ( TempVariable.z + TempVariable.w ) / 2.0;
//#endif
}
 
void compiler_internal_AdjustOutputSemantic(inout vec4 Src)
{
//#if HLSLCC_DX11ClipSpace
	Src.y = -Src.y;
	Src.z = ( 2.0 * Src.z ) - Src.w;
//#endif
}
 
bool compiler_internal_AdjustIsFrontFacing(bool isFrontFacing)
{
//#if HLSLCC_DX11ClipSpace
	return !isFrontFacing;
//#else
//	return isFrontFacing;
//#endif
}
uniform highp vec4 pc0_h[4];
uniform vec4 pc1_m[1];
layout(location=3) in vec4 in_TEXCOORD7;
layout(location=0) out vec4 out_Target0;
void main()
{
	vec4 v0;
	vec3 v1;
	highp float f2;
	f2 = pc1_m[0].x;
	vec3 v3;
	v3.xyz = vec3((f2*3.400000e-01));
	v1.xyz = max(v3,vec3(0.000000e+00,0.000000e+00,0.000000e+00));
	highp float f4;
	f4 = ((v1.x+v1.y)+v1.z);
	highp vec3 v5;
	v5.xyz = v1;
	vec3 v6;
	v6.xyz = mix(v5,vec3((f4*pc0_h[1].x)),pc0_h[2].xxx);
	v0.xyz = ((v6*in_TEXCOORD7.www)+in_TEXCOORD7.xyz);
	v0.w = 1.000000e+00;
	float h7;
	h7 = (gl_FragCoord.z*pc0_h[3].x);
	v0.w = h7;
	float h8;
	h8 = pc0_h[0].x;
	v0.xyz = (v0.xyz*vec3(h8));
	vec3 v9;
	v9.xyz = max(v0.xyz,vec3(1.000000e-05,1.000000e-05,1.000000e-05));
	v0.xyz = v9;
	v0.xyz = min(vec3(1.000000e+02,1.000000e+02,1.000000e+02),v9);
	out_Target0.xyzw = v0;
}
 
/** 
 
 * Parameters calculated from the pixel material inputs.
 
 */
 
struct FPixelMaterialInputs
 
{
 
    float3 EmissiveColor;
 
    MaterialFloat Opacity;
 
    MaterialFloat OpacityMask;
 
    float3 BaseColor;
 
    MaterialFloat Metallic;
 
    MaterialFloat Specular;
 
    MaterialFloat Roughness;
 
    MaterialFloat Anisotropy;
 
    float3 Normal;
 
    float3 Tangent;
 
    MaterialFloat4 Subsurface;
 
    MaterialFloat AmbientOcclusion;
 
    MaterialFloat2 Refraction;
 
    MaterialFloat PixelDepthOffset;
 
    uint ShadingModel;
 
 
 
}; 

是float 但是 GetMaterialEmissive函数的返回值是half3 。我可以试试看float用来当作uv采样 然后给emissive,是不是会是float。

原来是测试的shader太短,编译器直接转half3了,Custom Node里面代码多点就好了,:slight_smile:

[Image Removed]

Hi,

理论上GLSLbacked.cpp里ir_gen_glsl_visitor.GetPrecisionModifier函数根据类型是否是float来添加highp,你能看一下除了customnode,其余地方的写法是否正常吗?另外你方便把hlsl和glsl文件发上来我看一下吗?

你看一下HLSL里PixelMaterialInputs.EmissiveColor是half,还是float?

应该跟GetMaterialEmissive是half3也有关系,可以改成float3测试一下。

感谢反馈,问题解决就好。