openGL - рисование сетки квадов и их ручная роспись - PullRequest
2 голосов
/ 15 марта 2019

Я делаю простое приложение для обработки изображений с использованием OpenGL и C ++. Однако есть одна особенность, которую я не знаю, как это сделать, а именно:

Мне нужно, чтобы мой пользователь нарисовал график гистограммы. Я подумал об этом, создав сетку из четырех квадратов для каждой пиксельной интенсивности моего изображения. Пример: если изображение 8-битное, мне понадобится 256х256 квадов в моей сетке. После рисования сетки я хочу, чтобы пользователь вручную нарисовал квадраты квантованным способом (каждый квад) так, чтобы он мог «нарисовать» гистограмму. Проблема в том, что я не знаю, как сделать что-то из этого ... Кто-нибудь подскажет, как нарисовать сетку и как сделать рисунок для рисования.

Если вы не понимаете, как нарисовать гистограмму, просто подумайте, что это обычный график.

1 Ответ

3 голосов
/ 16 марта 2019

Вам не нужно рисовать сетку четырехугольников. Достаточно одного квадратора, а затем используйте шейдер для выборки из гистограммы, хранящейся в 1d-текстуре. Вот что я получаю:

enter image description here

Вершинный шейдер:

#version 450 core
layout(std140, binding = 0) uniform view_block {
    vec2 scale, offset;
} VIEW;

layout(std140, binding = 1) uniform draw_block {
    vec4 position;
    float max_value;
} DRAW;

out gl_PerVertex {
    vec4 gl_Position;
};

void main()
{
    ivec2 id = ivec2(gl_VertexID&1, gl_VertexID>>1);
    vec2 position = vec2(DRAW.position[id.x<<1], DRAW.position[(id.y<<1) + 1]);
    gl_Position = vec4(fma(position, VIEW.scale, VIEW.offset), 0, 1);
}

Фрагмент шейдера:

#version 450 core
layout(std140, binding = 1) uniform draw_block {
    vec4 position;
    float max_value;
} DRAW;
layout(binding = 0) uniform sampler1D hist;
layout(location = 0) out vec4 OUT;

void main()
{
    const vec2 extent = DRAW.position.zw - DRAW.position.xy;
    vec2 texcoord = (gl_FragCoord.xy - DRAW.position.xy)/(DRAW.position.zw - DRAW.position.xy);
    OUT.rgb = vec3(lessThan(texcoord.yyy*DRAW.max_value, texture(hist, texcoord.x).rgb));
    OUT.a = 1;
}

Создание текстуры гистограммы:

image hist(256, 1, 3, type_float);
// ... calculate the histogram ...

tex.reset(glCreateTextureSN(GL_TEXTURE_1D));
glTextureStorage1D(tex.get(), 1, GL_RGB32F, hist.w);
glTextureSubImage1D(tex.get(), 0, 0, hist.w, GL_RGB, GL_FLOAT, hist.c[0]);
glTextureParameteri(tex.get(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);

Процедура рендеринга:

const vec2i vs = { glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT) };
glViewport(0, 0, vs[0], vs[1]);
glClear(GL_COLOR_BUFFER_BIT);

struct view_block {
    vec2f scale, offset;
} VIEW = {
    vec2f(2)/vec2f(vs), -vec2f(1)
};
GLbuffer view_buf(glCreateBufferStorageSN(sizeof(VIEW), &VIEW, 0));
glBindBufferBase(GL_UNIFORM_BUFFER, 0, view_buf.get());

struct draw_block {
    box2f position;
    float max_value;
} DRAW = {
    box2f(0, 0, vs[0], vs[1]),
    max_value
};
GLbuffer draw_buf(glCreateBufferStorageSN(sizeof(DRAW), &DRAW, 0));
glBindBufferBase(GL_UNIFORM_BUFFER, 1, draw_buf.get());

bind_textures(tex.get());
glBindProgramPipeline(pp.get());
glBindVertexArray(0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glutSwapBuffers();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...