1

我目前正在用 Python 编写一个基于 glumpy 的渲染器。

我正在使用 glumpys OpenGL 功能来渲染一堆点和线。我的点实际上是一张图,所以线是边,多条边可以有一个共享点。

我实现了一个选择器,它使我能够绘制一个特定的子图。

我在每个顶点的缓冲区中存储了一个 alpha 值。当我单击时,alpha 值会发生变化,因此只有选定子图的点以 alpha = 1 绘制。着色器被调用两次:

# Draw Points
self.program_points.draw(gl.GL_POINTS)

# Draw Lines
self.program_points.draw(gl.GL_LINES, self.edge_buffer)

我的问题是: alpha 值设置正确,两个点 alpha = 1 的边缘也正确渲染,但一个点 alpha = 1 和一个点 alpha = 0 的边缘淡出。

我根本不想给褪色的边缘上色。有没有办法检查边缘的两个节点并始终选择较低的 alpha 值或同样有用的东西。

我的顶点着色器:

uniform vec2 resolution;

attribute vec3 position;
attribute float radius;

attribute float  color;
attribute float color_alpha;
attribute float id;

// for AA
varying vec4 v_position;
varying float v_radius;
varying float v_color_alpha;


varying vec4  v_id;
varying float  v_color;

void main (void)
{
    // this is for the picker!
    v_id = vec4 (mod(floor(id / (256*256)), 256) / 255.0,
             mod(floor(id /     (256)), 256) / 255.0,
             mod(floor(id /       (1)), 256) / 255.0,
             1.0 );
    // values to the fragment shader
    v_color         = color;
    v_color_alpha   = color_alpha;
    v_radius        = radius;

    //two pixel for AA
    gl_PointSize = 2.0+ ceil(2.0*radius);

    // hook for the Cameramovement
    v_position = <transform(position)>;
    gl_Position = v_position;
} ```
4

1 回答 1

1

好吧,基本上,有两种选择:

  • 变量的值在整个基元中插值
  • flat通过使用插值限定符,对于基元来说,varying 的值是恒定的。它的基元不仅仅是一个点,这意味着数据只能来自一个顶点,这被称为proviking vertex。对于GL_LINES,这通常是每行的第一个顶点。

在一般情况下,这两种模式都不能解决您的问题。考虑以下两个连接边的情况,AB分别BC带有附加的 alpha 值1和:10

A      B      C 
|------+------|
1      1      0

您真正想要的是从不透明到完全透明的急剧过渡,而标准解决方案是实际分割顶点:

A     B D     C 
|-----+++-----|
1     1 0     0

现在BD具有相同的位置,但不同的 alpha 值 - 这就是 GPU 的顶点模型的真正含义:一组属性 - 不仅仅是位置 - 如果单个属性不同,它在技术上是不同的顶点。

对于您的用例,您可能可以完全删除元素缓冲区,并始终每行保留两个不同的顶点。

有没有办法检查边缘的两个节点并始终选择较低的 alpha 值或同样有用的东西。

不是直接的。有一些非标准的 GL 扩展可以让您访问每个顶点的相关数据,例如AMD_shader_explicit_vertex_parameteror NV_fragment_shader_barycentric,但这些扩展通常不受支持,而且它也远高于您在此处使用的 GL 版本。

但是,对于您的用例,您可以执行一些简单的片段着色器技巧,例如:

gl_FragColor.a = step(0.99999, v_color_alpha);

如果它低于 0.99999,它将基本上将 alpha 设置为 0.0,因此它将删除大部分过渡。请注意,alpha=0 的片段可能仍会写入深度和模板缓冲区,因此您可能需要一个条件discard来代替。

于 2020-04-27T14:54:30.270 回答