仅在WebGL中绘制网格的一部分

时间:2017-01-08 13:09:12

标签: javascript webgl mesh fragment-shader

我有一个旋转并移动的网格。我想只画一部分。

例如:

GameImage

在我的WebGL游戏中,我有一个轨迹贴图网格,我只想显示红色圆圈中的部分(左上角),其余的我不想绘制。

我应该考虑使用片段着色器吗?或者我可以告诉轨迹图网格只绘制圆圈​​中的部分吗?

谢谢!

PS:如果我可以在圆圈周围淡出轨道地图而不是仅仅将其切掉,那将会很棒。 : - )

2 个答案:

答案 0 :(得分:6)

有几种方法可以达到这个目的,对于一个简单的矩形切口,你可以像这样使用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之间进行线性淡出 结果是一个看起来像这样的面具:

result

请注意,从技术上讲,我们不再需要剪刀测试,因为片段着色器中的蒙版会遮盖圆形区域之外的所有内容。然而,保持剪刀测试确保我们只在我们需要的地方进行片段着色器工作。

答案 1 :(得分:3)

由于你还希望淡化圆形区域中的轨迹图,一个快速而肮脏的解决方案是使用片段着色器,其中圆形区域外的片段被丢弃,而内部的片段沿着距离线性插值其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);
}

请记住,这只是您可以针对此特定问题使用的众多解决方案之一。您可以通过丢弃圆形区域外的顶点或设置模板缓冲区来直接在顶点着色器内部执行此操作