在 WebGL 中只绘制网格的一部分
Only draw part of a mesh in WebGL
我有一个可以旋转和四处移动的网格。我只想画一部分。
例如:
在我的 WebGL 游戏中,我有一个轨道图网格,我只想显示红圈(左上角)中的部分,其余部分我不想绘制。
我应该考虑使用片段着色器吗?或者我能以某种方式告诉轨道图网格只绘制圆圈中的部分吗?
谢谢!
PS:如果我能在圆圈周围淡出轨道图,而不是仅仅切断它,那就太好了。 :-)
有几种方法可以实现这一点,对于简单的矩形切口,您可以像这样使用 scissor testing:
gl.enable(gl.SCISSOR_TEST);
gl.scissor(0,gl.canvas.clientHeight-256,256,256);
// draw track here
gl.disable(gl.SCISSOR_TEST);
对于圆形切口,您可以使用模板缓冲区,将磁盘绘制到模板缓冲区,启用模板并绘制轨道,但这需要您使用带有附加模板缓冲区的帧缓冲区来设置渲染管道,这可能有点压倒性,只给出一个锐利的切口。
使用自定义片段着色器并与上述剪刀矩形混合似乎是这里最明智的解决方案,如前所述设置剪刀,然后在片段着色器中:
void main(void) {
// do what you need to do to get the final color
gl_FragColor.rgb = finalColor;
gl_FragColor.a = smoothstep(128.,100.,length(min(vec2(gl_FragCoord.x,resolution.y-gl_FragCoord.y),256.)-128.));
}
我们在这里做的是计算当前像素到剪刀区域中心的距离(假设屏幕左上角为 256x256),然后在 100 到 128 之间进行线性淡出
结果是一个看起来像这样的掩码:
请注意,从技术上讲,我们不再需要剪刀测试,因为片段着色器中的遮罩会遮盖圆形区域之外的所有内容。然而,保留剪刀测试可确保我们只在需要的地方进行片段着色器工作。
由于您还想淡化圆形区域中的轨迹图,一个快速但肮脏的解决方案是使用片段着色器,其中圆形区域外的片段被丢弃,而圆形区域内的片段的 alpha 值沿线性插值到中心的距离。
片段着色器或多或少看起来像这样
precision mediump float;
varying vec3 Color;
uniform vec2 MapPos; //map's center position in screen pixels
//constant value to decide how big the red area is
const float circle_radius = 90.0;
const float falloff = 1.0;
void main()
{
float distance = length(FragCoord.xy - MapPos.xy);
if(distance > circle_radius) discard; //discarding fragments outside circle area
//alpha fades from 1 to 0, falloff decides how strong the fade is on the edge of the circle
float alpha = pow(1.0 - distance / 90.0, falloff);
gl_FragColor = vec4(Color, alpha);
}
请记住,这只是您可以用于解决此特定问题的众多解决方案之一。您可以通过丢弃圆形区域外的顶点或设置模板缓冲区来直接在顶点着色器中执行此操作,以实现完全相同的效果
我有一个可以旋转和四处移动的网格。我只想画一部分。
例如:
在我的 WebGL 游戏中,我有一个轨道图网格,我只想显示红圈(左上角)中的部分,其余部分我不想绘制。
我应该考虑使用片段着色器吗?或者我能以某种方式告诉轨道图网格只绘制圆圈中的部分吗?
谢谢!
PS:如果我能在圆圈周围淡出轨道图,而不是仅仅切断它,那就太好了。 :-)
有几种方法可以实现这一点,对于简单的矩形切口,您可以像这样使用 scissor testing:
gl.enable(gl.SCISSOR_TEST);
gl.scissor(0,gl.canvas.clientHeight-256,256,256);
// draw track here
gl.disable(gl.SCISSOR_TEST);
对于圆形切口,您可以使用模板缓冲区,将磁盘绘制到模板缓冲区,启用模板并绘制轨道,但这需要您使用带有附加模板缓冲区的帧缓冲区来设置渲染管道,这可能有点压倒性,只给出一个锐利的切口。
使用自定义片段着色器并与上述剪刀矩形混合似乎是这里最明智的解决方案,如前所述设置剪刀,然后在片段着色器中:
void main(void) {
// do what you need to do to get the final color
gl_FragColor.rgb = finalColor;
gl_FragColor.a = smoothstep(128.,100.,length(min(vec2(gl_FragCoord.x,resolution.y-gl_FragCoord.y),256.)-128.));
}
我们在这里做的是计算当前像素到剪刀区域中心的距离(假设屏幕左上角为 256x256),然后在 100 到 128 之间进行线性淡出 结果是一个看起来像这样的掩码:
请注意,从技术上讲,我们不再需要剪刀测试,因为片段着色器中的遮罩会遮盖圆形区域之外的所有内容。然而,保留剪刀测试可确保我们只在需要的地方进行片段着色器工作。
由于您还想淡化圆形区域中的轨迹图,一个快速但肮脏的解决方案是使用片段着色器,其中圆形区域外的片段被丢弃,而圆形区域内的片段的 alpha 值沿线性插值到中心的距离。
片段着色器或多或少看起来像这样
precision mediump float;
varying vec3 Color;
uniform vec2 MapPos; //map's center position in screen pixels
//constant value to decide how big the red area is
const float circle_radius = 90.0;
const float falloff = 1.0;
void main()
{
float distance = length(FragCoord.xy - MapPos.xy);
if(distance > circle_radius) discard; //discarding fragments outside circle area
//alpha fades from 1 to 0, falloff decides how strong the fade is on the edge of the circle
float alpha = pow(1.0 - distance / 90.0, falloff);
gl_FragColor = vec4(Color, alpha);
}
请记住,这只是您可以用于解决此特定问题的众多解决方案之一。您可以通过丢弃圆形区域外的顶点或设置模板缓冲区来直接在顶点着色器中执行此操作,以实现完全相同的效果