您的位置:首页 > 运维架构

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

2016-11-21 11:18 567 查看
该代码除了使用了 PBO 还是加入了 OpenMX

代码及关键注释如下:

/*
* 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)

运行结果如下:



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

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

OpenMP并行构造的schedule子句详解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opengl