从渲染管线学 GLES2.0(四)----图元装配

本来这一节应该讲的是裁剪,但是裁剪的时候,根据不同的图元类型处理裁剪的方式也是不一样的,所以在裁剪之前先来说一下图元装配。

1、图元装配

图元装配发生在顶点着色之后,根据我们在调用 glDrawArrays 或者 glDrawElements 时设置的图元类型,将顶点着色输出的顶点组合成指定的图元形状,OpenGL ES 2.0 一共支持 7 种不同的图元类型,经过图元装配之后,图元的类型就只有三种了,分别是点、线、三角形。

2、图元类型

图元枚举值和对应图元类型如下表所示

枚举值

图元类型

GL_POINT

GL_LINES

线

GL_LINE_STRIP

条带线

GL_LINE_LOOP

循环线

GL_TRIANGLES

三角形

GL_TRIANGL_STRIP

条带三角形

GL_TRIANGLE_FAN

扇面三角形

点可以通过单一的顶点来表示,一个点也就是一个四维的其次坐标值。默认的点大小是 1.0,因此当我们渲染点的时候,每个顶点实际上都是屏幕上的一个像素,如果点的大小增加,那么每个点的顶点都会占据超过 1 个像素的值。

点精灵

当点大小是 1 的时候,看起来就是屏幕上的一个像素,当点大小超过 1 的时候,比如设置为 4,那么就是屏幕上的 4x4 大小的一个块,在这个 4x4 块里面的像素除了正常的像素坐标以外,还有一个点精灵坐标,它的范围是 [0, 1],左上角的坐标是 (0, 0),右下角的坐标是 (1, 1),OpenGL 在片段着色器里面提供了一个内置变量来表示这个坐标,它叫做 gl_PointCoord,它的值只对点渲染有效,我们可以使用这个坐标将一个方形的点绘制成一个圆形的点,也可以将 gl_PointCoord 作为输入的纹理坐标使用,那么就可以使用纹理颜色来替代方块的颜色。

使用点精灵绘制圆形的点(片段着色器)

precision mediump float;
void main() {
    vec2 temp = gl_PointCoord - vec2(0.5);
    float dis = dot(temp, temp);
    if(dis > 0.25) {
        discard;
    }
    gl_FragColor = vec4(1.0, 0.9, 0.3, 1.0);
}

绘制效果 

使用点精灵作为纹理坐标(片段着色器)

precision mediump float;
uniform sampler2D vTexture;
void main() {
    gl_FragColor = texture2D(vTexture, gl_PointCoord);
}

绘制效果

线、条带线、循环线

线

两个点表示一条线

条带线

每两个点表示一条线,但是下一条线段的起点是上一条线的结束点

循环线

和条带类似,但是最后一条线段是尾和首相连,形成一个闭环

三角形、条带三角形、扇面三角形

三角形

三个点构成一个三角形

条带三角形

和线的条带有点类似,区别是一个三角形前两个点是上一个三角形的后两个点

扇面三角形

当绘制扇面的时候,第一个顶点会作为一个共享点存在,也是后面每一个三角形的第一个点,然后每一个三角形的最后一个点作为下一个三角形的第二个点存在

这里要特别注意的是 GL_TRIANGL_STRIP 也就是条带三角形,比如我们输入的顶点顺序是 {1,2,3,4,5,6},然后设置图元类型为 GL_TRIANGL_STRIP,那么它的组合方式如下

三角形编号

顶点组成

1

1,2,3

2

3,2,4

3

3,4,5

4

5,4,6

这里需要注意的是第二个和第四个三角形的顶点顺序,顶点顺序不一样计算出来的前后面也是不同的,那么这里就可以写成下面这样

n 为奇数三角形顺序为 n,n+1,n+2 n 为偶数三角形顺序为 n+1,n,n+2

那么对应的代码实现就像下面这样

struct Point {
    float x;
    float y;
};
Point traingles[3];
int index = 0;
bool flip = true;
// 顶点是按照顺序下发的,不是一次性所有的顶点都会到图元装配模块
void PushData(Point point) {
    traingles[index++] = point;
    if (index == 3) {
        std::cout << traingles[0] << " " << traingles[1] << " " << traingles[2] << std::endl;
        if (flip) {
            traingles[0] = traingles[2];
        } else {
            traingles[1] = traingles[2];
        }
        flip = !flip;
        index = 2;
    }
}

3、C++ 代码实现

下面使用一段完整的 C++ 代码来实现图元装配的功能

#define GL_POINTS                         0x0000
#define GL_LINES                          0x0001
#define GL_LINE_LOOP                      0x0002
#define GL_LINE_STRIP                     0x0003
#define GL_TRIANGLES                      0x0004
#define GL_TRIANGLE_STRIP                 0x0005
#define GL_TRIANGLE_FAN                   0x0006

struct Point {
    float x{};
    float y{};
    Point(float x = 0, float y = 0) {
        this->x = x;
        this->y = y;
    }
};

class PrimitiveAssembly {
public:
    PrimitiveAssembly() {}
    ~PrimitiveAssembly() {}

    void SetPrimitiveType(int type) {
        if (primitive_type_ != type) {
            primitive_type_ = type;
        }
    }

    void PushData(const Point& point, bool is_end) {
        if (primitive_type_ == GL_POINTS) {
            std::cout << point.x << " " << point.y << std::endl;
            return;
        }
        recv_point_count_++;
        points_[recv_point_count_ - 1] = point;
        if (primitive_type_ == GL_LINES || primitive_type_ == GL_LINE_STRIP || primitive_type_ == GL_LINE_LOOP) {
            if (recv_point_count_ == 2) {
                HandleLine(is_end);
            }
        } else {
            if (recv_point_count_ == 3) {
                HandleTriangle(is_end);
            }
        }
        if (is_end) {
            recv_point_count_ = 0;
            triangle_strip_flip_ = true;
        }
    }

    void HandleLine(bool is_end) {
        for (int i = 0; i < 2; ++i) {
            std::cout << points_[i].x << " " << points_[i].y << std::endl;
        }
        if (primitive_type_ == GL_LINES) {
            recv_point_count_ = 0;
            return;
        }
        if (primitive_type_ == GL_LINE_LOOP) {
            if (is_end && !line_loop_first_) {
                std::cout << points_[1].x << " " << points_[1].y << std::endl;
                std::cout << tmp_point_.x << " " << tmp_point_.y << std::endl;
                line_loop_first_ = true;
            }
            if (line_loop_first_) {
                tmp_point_ = points_[0];
                line_loop_first_ = false;
            }
        }
        points_[0] = points_[1];
        recv_point_count_ = 1;
    }

    void HandleTriangle(bool is_end) {
        for (int i = 0; i < 3; ++i) {
            std::cout << points_[i].x << " " << points_[i].y << std::endl;
        }
        if (primitive_type_ == GL_TRIANGLES) {
            recv_point_count_ = 0;
            return;
        }
        if (primitive_type_ == GL_TRIANGLE_STRIP) {
            if (triangle_strip_flip_) {
                points_[0] = points_[2];
            } else {
                points_[1] = points_[2];
            }
            triangle_strip_flip_ = !triangle_strip_flip_;
        } else {
            points_[1] = points_[2];
        }
        recv_point_count_ = 2;
    }

private:
    int primitive_type_{};
    int recv_point_count_{};
    Point points_[3];
    Point tmp_point_{};
    bool triangle_strip_flip_{ true };
    bool line_loop_first_{ true };
};

### 回答1: gles2-gears是一个基于OpenGL ES 2.0的图形渲染示例程序。该程序主要用于演示OpenGL ES 2.0中的基本图形渲染功能和性能。它由几个齿轮组成,每个齿轮由多个三角形组成,通过旋转和平移操作,可以观察到各个齿轮之间的相互作用和渲染效果。 通过使用OpenGL ES 2.0gles2-gears可以利用硬件加速图形渲染,提供高性能的图形处理能力。它支持通过着色器程序来实现各种渲染效果,如光照、阴影和纹理等。同时,该示例程序也提供了用户交互接口,用户可以通过触摸或鼠标操作来改变齿轮的旋转速度和方向,从而观察不同的视觉效果。 gles2-gears不仅是一个OpenGL ES 2.0的示例程序,也是一个性能测试工具。通过改变齿轮数量和分辨率等参数,可以测试设备对于大规模场景和高分辨率渲染的性能表现。这对于开发者来说是非常有价值的,可以帮助他们评估设备的图形处理能力,并根据测试结果进行相应的优化。 总而言之,gles2-gears是一个基于OpenGL ES 2.0的演示和性能测试程序,可以帮助开发者习和评估设备的图形处理能力。它充分利用硬件加速,通过渲染齿轮的旋转和交互操作,展示了OpenGL ES 2.0的高性能实时图形渲染能力。 ### 回答2: gles2-gears是一个基于OpenGL ES 2.0的开源项目,它展示了使用OpenGL ES 2.0绘制的齿轮模型。它是一个典型的图形示例,用于演示OpenGL ES 2.0的功能和特性。 在gles2-gears中,通过使用OpenGL ES 2.0的着色器语言GLSL,实现了光照、纹理贴图等高级渲染技术。整个场景由齿轮模型组成,通过旋转、缩放等操作,可以观察到齿轮之间的互动效果。 gles2-gears的源代码可用于OpenGL ES 2.0编程,了解图形渲染的基本原理和技术。通过阅读和理解其代码结构和逻辑,可以了解OpenGL ES 2.0的编程模式和渲染流程。 此外,gles2-gears还可以用作性能测试工具,用于测试硬件设备的图形渲染性能。通过调整渲染分辨率、齿轮数量等参数,可以评估设备的图形处理能力,并进行性能对比。 总的来说,gles2-gears是一个教育和性能测试的工具,用于展示和验证OpenGL ES 2.0的功能和性能。无论是初者还是专业开发者,都可以使用它来习和优化图形渲染技术。 ### 回答3: gles2-gears是一个使用OpenGL ES 2.0图形库编写的一个开源项目,它展示了三个互动的齿轮,用于测试和演示OpenGL ES 2.0的性能和功能。 在它的实现过程中,作者使用了OpenGL ES 2.0的着色器语言GLSL来处理图形渲染。齿轮之间的转动是通过在每个齿轮上应用旋转变换来实现的,通过修改齿轮的旋转角度和速度,可以调整和控制齿轮之间的相对运动。此外,作者还为齿轮和整个场景设计了适当的材质、光照和阴影效果,以增强视觉效果。 这个项目最初是为了展示OpenGL ES 2.0在移动设备上的性能和功能而创建的,但它也可以在其他支持OpenGL ES 2.0的平台上运行。用户可以通过触摸或鼠标交互来控制和改变齿轮的旋转和速度,从而创建不同的视觉效果和交互体验。 值得一提的是,该项目的源代码开放,并经常作为一种教工具,帮助人们习和理解OpenGL ES 2.0的基本概念和应用技巧。许多人使用和修改这个项目,以满足不同的需求和目标。 总的来说,gles2-gears是一个展示和测试OpenGL ES 2.0在三维图形渲染中的性能和功能的开源项目。它不仅仅是一个演示程序,还可以作为习和教工具来帮助人们更好地理解和应用OpenGL ES 2.0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值