《OpenGL 超级宝典(Super Bible)第七版》 有关 PBO 的 Example

简介: 《OpenGL 超级宝典(Super Bible)第七版》 有关 PBO 的 Example

该代码除了使用了 PBO 还是加入了 OpenMP

 

代码及关键注释如下:

 

/*
 * Copyright ?2012-2015 Graham Sellers
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <sb7.h>
#include <shader.h>
#include <object.h>
#include <vmath.h>
#include <sb7textoverlay.h>
#include <sb7ktx.h>
#include <math.h>
#include <omp.h>
class pmbfractal_app : public sb7::application
{
public:
    pmbfractal_app()
    {
    }
    void init();
    void startup();
    void render(double currentTime);
    void onKey(int key, int action);
    void shutdown(void);
protected:
    sb7::text_overlay   overlay;
    void updateOverlay();
    void update_fractal();
    enum
    {
        // Use a super-low resolution fractal in debug builds to
        // make the application useable.
#ifdef _DEBUG
        FRACTAL_WIDTH   = 128,
        FRACTAL_HEIGHT  = 128,
#else
        FRACTAL_WIDTH   = 512,
        FRACTAL_HEIGHT  = 512,
#endif
        BUFFER_SIZE     = (FRACTAL_WIDTH * FRACTAL_HEIGHT)
    };
    GLuint              vao;
    GLuint              program;
    GLuint              buffer;
    GLuint              texture;
    unsigned char *     mapped_buffer;
    float               fps;
    struct
    {
        vmath::vec2 C;
        vmath::vec2 offset;
        float       zoom;
    } fractparams;
};
void pmbfractal_app::init()
{
    static const char title[] = "OpenGL SuperBible - Persistent Mapped Fractal";
    sb7::application::init();
    memcpy(info.title, title, sizeof(title));
}
void pmbfractal_app::startup()
{
  // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  // 创建用于输出到纹理的 PBO
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
    glBufferStorage(GL_PIXEL_UNPACK_BUFFER,
                    BUFFER_SIZE,
                    nullptr,
                    GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
    mapped_buffer = (unsigned char*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER,
                                   0,
                                   BUFFER_SIZE,
                                   GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
    GLuint shaders[2] =
    {
        sb7::shader::load("media/shaders/fsq/fsq.vs.glsl", GL_VERTEX_SHADER),
        sb7::shader::load("media/shaders/fsq/fsq.fs.glsl", GL_FRAGMENT_SHADER)
    };
    program = sb7::program::link_from_shaders(shaders, 2, true);
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, FRACTAL_WIDTH, FRACTAL_HEIGHT);
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    overlay.init(128, 50);
    int maxThreads = omp_get_max_threads();
    omp_set_num_threads(maxThreads);
}
void pmbfractal_app::update_fractal()
{
    const vmath::vec2 C = fractparams.C; // (0.03f, -0.2f);
    const float thresh_squared = 256.0f;
    const float zoom = fractparams.zoom;
    const vmath::vec2 offset = fractparams.offset;
  // 动态调度,当有空闲线程则为其分配16次迭代,来写 mapped_buffer
#pragma omp parallel for schedule (dynamic, 16)
    for (int y = 0; y < FRACTAL_HEIGHT; y++)
    {
        for (int x = 0; x < FRACTAL_WIDTH; x++)
        {
            vmath::vec2 Z;
            Z[0] = zoom * (float(x) / float(FRACTAL_WIDTH) - 0.5f) + offset[0];
            Z[1] = zoom * (float(y) / float(FRACTAL_HEIGHT) - 0.5f) + offset[1];
            unsigned char * ptr = mapped_buffer + y * FRACTAL_WIDTH + x;  // ☆
            int it;
            for (it = 0; it < 256; it++)
            {
                vmath::vec2 Z_squared;
                Z_squared[0] = Z[0] * Z[0] - Z[1] * Z[1];
                Z_squared[1] = 2.0f * Z[0] * Z[1];
                Z = Z_squared + C;
                if ((Z[0] * Z[0] + Z[1] * Z[1]) > thresh_squared)
                    break;
            }
            *ptr = it;
        }
    }
}
void pmbfractal_app::render(double currentTime)
{
    static float lastTime = 0.0f;
    static int frames = 0;
    float nowTime = float(currentTime);
    fractparams.C = vmath::vec2(1.5f - cosf(nowTime * 0.4f) * 0.5f,
                                1.5f + cosf(nowTime * 0.5f) * 0.5f) * 0.3f;
    fractparams.offset = vmath::vec2(cosf(nowTime * 0.14f),
                                     cosf(nowTime * 0.25f)) * 0.25f;
    fractparams.zoom = (sinf(nowTime) + 1.3f) * 0.7f;
    update_fractal();
    glViewport(0, 0, info.windowWidth, info.windowHeight);
    glUseProgram(program);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
  // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  // 将 PBO 的数据输出到纹理中
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, FRACTAL_WIDTH, FRACTAL_HEIGHT, GL_RED, GL_UNSIGNED_BYTE, nullptr);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    if (nowTime > (lastTime + 0.25f))
    {
        fps = float(frames) / (nowTime - lastTime);
        frames = 0;
        lastTime = nowTime;
    }
    updateOverlay();
    frames++;
}
void pmbfractal_app::shutdown(void)
{ 
    glDeleteProgram(program);
    glDeleteBuffers(1, &buffer);
}
void pmbfractal_app::updateOverlay()
{
    char buffer[256];
    overlay.clear();
    sprintf(buffer, "%2.2fms / frame (%4.2f FPS)", 1000.0f / fps, fps);
    overlay.drawText(buffer, 0, 0);
    overlay.draw();
}
void pmbfractal_app::onKey(int key, int action)
{
    if (action)
    {
        switch (key)
        {
            case 'M':
                break;
        }
    }
}
DECLARE_MAIN(pmbfractal_app)

运行结果如下:

image.png

相关阅读:

《OpenGL 超级宝典(Super Bible)第五版》 有关 PBO 的 Example

OpenGL深入探索——像素缓冲区对象 (PBO)

OpenMP并行构造的schedule子句详解

 

目录
相关文章
|
Android开发 数据安全/隐私保护 C++
Opengl ES之PBO
Opengl ES连载系列
203 0
《OpenGL 超级宝典(Super Bible)第五版》 有关 PBO 的 Example
《OpenGL 超级宝典(Super Bible)第五版》 有关 PBO 的 Example
230 0
《OpenGL 超级宝典(Super Bible)第五版》 有关 PBO 的 Example
|
存储 缓存 异构计算
NDK OpenGL ES 3.0 开发(二十二):PBO
OpenGL PBO(Pixel Buffer Object),被称为像素缓冲区对象,主要被用于异步像素传输操作。PBO 仅用于执行像素传输,不连接到纹理,且与 FBO (帧缓冲区对象)无关。
616 0
NDK OpenGL ES 3.0 开发(二十二):PBO
|
存储 openCL C++
A Simple OpenGL Shader Example II
A Simple OpenGL Shader Example II eryar@163.com Abstract. The OpenGL Shading Language syntax comes from the C family of programming languages.
1241 0
|
缓存 程序员 异构计算
A Simple OpenGL Shader Example
A Simple OpenGL Shader Example eryar@163.com Abstract. OpenGL Shading Language, the high-level programming language defined to allow application writ...
1575 0
|
6月前
|
XML 小程序 Java
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
124 0
|
缓存 C++
Opengl ES之FBO
Opengl ES连载系列
151 0
|
存储 编解码 算法
Opengl ES之LUT滤镜(上)
Opengl ES之连载系列
458 0
|
数据安全/隐私保护 开发者
OpenGL ES 多目标渲染(MRT)
Opengl ES连载系列
319 0
|
数据安全/隐私保护 索引
Opengl ES之纹理数组
Opengl ES连载系列
257 0