【发布时间】:2019-12-26 03:09:30
【问题描述】:
我有一个简单的片段着色器,可以绘制测试网格图案。
我真的没有问题 - 但我注意到一种奇怪的行为,这对我来说是莫名其妙的。不要介意奇怪的常量——它们在编译之前的着色器组装过程中被填充。另外,vertexPosition 是世界空间中实际计算的位置,因此我可以在网格本身移动时移动着色器纹理。
这是我的着色器的代码:
#version 300 es
precision highp float;
in highp vec3 vertexPosition;
out mediump vec4 fragColor;
const float squareSize = __CONSTANT_SQUARE_SIZE;
const vec3 color_base = __CONSTANT_COLOR_BASE;
const vec3 color_l1 = __CONSTANT_COLOR_L1;
float minWidthX;
float minWidthY;
vec3 color_green = vec3(0.0,1.0,0.0);
void main()
{
// calculate l1 border positions
float dimention = squareSize;
int roundX = int(vertexPosition.x / dimention);
int roundY = int(vertexPosition.z / dimention);
float remainderX = vertexPosition.x - float(roundX)*dimention;
float remainderY = vertexPosition.z - float(roundY)*dimention;
vec3 dyX = dFdy(vec3(vertexPosition.x, vertexPosition.y, 0));
vec3 dxX = dFdx(vec3(vertexPosition.x, vertexPosition.y, 0));
minWidthX = max(length(dxX),length(dyX));
vec3 dyY = dFdy(vec3(0, vertexPosition.y, vertexPosition.z));
vec3 dxY = dFdx(vec3(0, vertexPosition.y, vertexPosition.z));
minWidthY = max(length(dxY),length(dyY));
//Fill l1 suqares
if (remainderX <= minWidthX)
{
fragColor = vec4(color_l1, 1.0);
return;
}
if (remainderY <= minWidthY)
{
fragColor = vec4(color_l1, 1.0);
return;
}
// fill base color
fragColor = vec4(color_base, 1.0);
return;
}
因此,使用此代码一切正常。 然后我想通过在绘制垂直线之后移动仅涉及水平线的计算来对其进行一点优化。因为如果垂直线检查为真,这些计算将毫无用处。像这样:
#version 300 es
precision highp float;
in highp vec3 vertexPosition;
out mediump vec4 fragColor;
const float squareSize = __CONSTANT_SQUARE_SIZE;
const vec3 color_base = __CONSTANT_COLOR_BASE;
const vec3 color_l1 = __CONSTANT_COLOR_L1;
float minWidthX;
float minWidthY;
vec3 color_green = vec3(0.0,1.0,0.0);
void main()
{
// calculate l1 border positions
float dimention = squareSize;
int roundX = int(vertexPosition.x / dimention);
int roundY = int(vertexPosition.z / dimention);
float remainderX = vertexPosition.x - float(roundX)*dimention;
float remainderY = vertexPosition.z - float(roundY)*dimention;
vec3 dyX = dFdy(vec3(vertexPosition.x, vertexPosition.y, 0));
vec3 dxX = dFdx(vec3(vertexPosition.x, vertexPosition.y, 0));
minWidthX = max(length(dxX),length(dyX));
//Fill l1 suqares
if (remainderX <= minWidthX)
{
fragColor = vec4(color_l1, 1.0);
return;
}
vec3 dyY = dFdy(vec3(0, vertexPosition.y, vertexPosition.z));
vec3 dxY = dFdx(vec3(0, vertexPosition.y, vertexPosition.z));
minWidthY = max(length(dxY),length(dyY));
if (remainderY <= minWidthY)
{
fragColor = vec4(color_l1, 1.0);
return;
}
// fill base color
fragColor = vec4(color_base, 1.0);
return;
}
但即使看起来这不应该影响结果 - 它确实。差一点。 下面是两张截图。第一个是原始代码,第二个是“优化”的。哪个效果不好。
原版:
优化版(看起来差很多):
请注意线条是如何变得“模糊”的,即使看起来根本没有数字应该改变。
注意:这不是因为 minwidthX/Y 是全局的。我最初通过使它们本地化来进行优化。 我最初也将RoundY和remainderY的计算移到了X检查的下方,结果是一样的。
注意 2:我尝试专门为每个计算添加 highp 关键字,但这并没有改变任何东西(不是我期望的那样,但我还是尝试了)
谁能解释一下为什么会这样?我想知道我未来的着色器,实际上我也想优化这个。我想在这里了解精度损失背后的原理,因为它对我来说没有任何意义。
【问题讨论】:
标签: opengl-es glsl shader precision fragment-shader