OpenGL OSG :: Умножение текстур показывает только один цвет - PullRequest
0 голосов
/ 03 марта 2020

Моя цель - «умножить» два OSG :: Textures, где один - Light-Distribution (изображение RGBA), другой - черно-белый фильтр Image / Texture, который я генерирую сам. На данный момент оба Текстуры имеют одинаковый размер, хотя было бы неплохо, если бы это было возможно, что они этого не делают. Вы можете себе представить, что я пытаюсь удалить черные области на текстуре фильтра из светлой текстуры.

В настоящее время мой код работает так, чтобы весь экран был одним цветом, несмотря ни на что. Я думаю, что что-то вокруг gl_MultiTexCoord0 или gl_TexCoord[0] не правильно. Я просмотрел несколько онлайн-источников, но не смог заставить работать что-либо еще.

К сожалению, мне приходится использовать старую версию glew (2.1.0) [->? OpenGL #version 120] и OSG (3.0.1) из-за ограничений фреймворка.

Поскольку ничего не работает правильно, я пока попробую просто показать filterTexture (потому что, если я покажу lightTexture, все будет черный) ... Внутри init и update у меня есть несколько "checkError", чтобы увидеть, что происходит, но нет ошибок. Вот мои шейдеры:

// vertex shader
const char* shader_combine_vertex = "\n\
#version 120                                    \n\
                                                \n\
void main()                                     \n\
{                                               \n\
    // homogeneous vertex position              \n\
    gl_Position = ftransform();                 \n\
    //Texture coordinate of texture unit 0 and 1\n\
    gl_TexCoord[0] = gl_MultiTexCoord0;         \n\
    gl_TexCoord[1] = gl_MultiTexCoord1;         \n\
}                                               \n";


// fragment shader
const char* shader_combine_fragment = "                                     \n\
#version 120                                                                \n\
// input                                                                    \n\
uniform sampler2D lightTexture;                                             \n\
uniform sampler2D filterTexture;                                            \n\
//varying vec2 lightTexCoord;                                               \n\
//varying vec2 filterTexCoord;                                              \n\
                                                                            \n\
void main()                                                                 \n\
{                                                                           \n\
    gl_FragColor = texture2D(filterTexture, gl_TexCoord[1].st);             \n\
                                                                            \n\
    // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); //works and shows red       \n\
                                                                            \n\
    // gl_FragColor = texture2D(filterTexture, filterTexCoord);             \n\
                                                                            \n\
    // vec4 texel = texture2D(lightTexture, gl_TexCoord[0].st);             \n\
    // gl_FragColor = texel * texture2D(filterTexture, gl_TexCoord[1].st);  \n\
}\n";

И глобальные переменные и функции init и update с действительным контекстом OpenGL:

    /** textures for each lightSourceID **/
    std::map<int, GLuint> vp_ShaderCombine;
    std::map<int, GLuint> fp_ShaderCombine;
    /** Program linking shaders **/
    std::map<int, GLhandleARB> combineProgram;

    // TODO: maybe generate all texture IDs at once, but works for now
    std::map<int, unsigned int> g_uiSceneTex[2]; // for every sensor - 2 texture IDs (Light | Filter)

---------

bool initShaders(int id, int width, int height, char* texture)
{
    // Shaders compilation
    vp_ShaderCombine.insert(std::pair<int, GLuint>(id, glCreateShaderObjectARB(GL_VERTEX_SHADER)));
    fp_ShaderCombine.insert(std::pair<int, GLuint>(id, glCreateShaderObjectARB(GL_FRAGMENT_SHADER)));

    glShaderSource(vp_ShaderCombine.at(id), 1, &shader_combine_vertex, NULL);
    glShaderSource(fp_ShaderCombine.at(id), 1, &shader_combine_fragment, NULL);

    glCompileShader(vp_ShaderCombine.at(id));
    checkShaderCompileError(vp_ShaderCombine.at(id), "vertex");
    glCompileShader(fp_ShaderCombine.at(id));
    checkShaderCompileError(fp_ShaderCombine.at(id), "fragment");

    combineProgram[id] = glCreateProgram();
    glAttachShader(combineProgram[id], vp_ShaderCombine[id]);
    glAttachShader(combineProgram[id], fp_ShaderCombine[id]);

    glLinkProgram(combineProgram.at(id));
    glValidateProgram(combineProgram.at(id));

    // Check result and display errors if any
    ...
    return ...;
}

void update()
{
    for (... every light source id ...)
    {
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_LIGHTING);
        // ------------  NECESSARY? ----------------
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_CULL_FACE);
        glDisable(GL_BLEND);
        // ----------- LIGHT----------------
        // mainly the same as filter just on g_uiSceneTex[id][0]
        // ----------- FILTER ----------------
        glUseProgramObjectARB(combineProgram[id]); // call before each glActiveTexture (according to some SO post)
        glActiveTexture(GL_TEXTURE0 + 1);
        // TODO: maybe generate all texture IDs at once, but works for now
        glGenTextures(1, &g_uiSceneTex[id][1]); // generate texture names
        glBindTexture(GL_TEXTURE_2D, g_uiSceneTex[id][1]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, itSHM->myOsgImg->s(), itSHM->myOsgImg->t(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, itSHM->myOsgImg);

        GLint filterTexUnitLoc = glGetUniformLocation(combineProgram[id], "filterTexture");
        glUniform1i(filterTexUnitLoc, 0);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

        // render
        // draw QUAD
        glBegin(GL_QUADS);
        glTexCoord2f(0, 0);
        glVertex3f(0, 1, -1);
        glTexCoord2f(0, ScreenHeight);
        glVertex3f(0, 0, -1);
        glTexCoord2f(ScreenWidth, ScreenHeight);
        glVertex3f(1, 0, -1);
        glTexCoord2f(ScreenWidth, 0);
        glVertex3f(1, 1, -1);
        glEnd();

        // Disable Shaders
        glUseProgramObjectARB(0);

        glDisable(GL_TEXTURE_2D);
        // NECESSARY?
        myShmImages[0].myOsgImg->dirty();
        myPhotometries[0].myOSGTexture->dirtyTextureObject();
    }
}

Теперь у меня возникает несколько вопросов:

  1. Что не так с шейдерами, что они показывают только один цвет? Я думаю, что они когда-либо оценивают только один пиксель.
  2. Какая разница между использованием этих функций gl по сравнению с использованием собственных функций OSG для создания шейдера? Есть ли ограничения или возможна моя настройка? Это "проще"? Какое-нибудь хорошее чтение по этой теме c, я не нашел ни одного?
  3. Код обновления выглядит очень длинным и ненужным, нужно ли мне генерировать / создавать текстуру каждый раз при обновлении, или я могу только инициировать ее? один раз?
  4. В настоящее время текстура отображается в полноэкранном режиме, но я хочу отобразить ее в позиции Light в дереве OSG. У меня есть видимость распределения света, поэтому я думаю, что мне просто нужно «отобразить» новую отфильтрованную текстуру, используя этот вид / камеру / усеченный ...

1 Ответ

1 голос
/ 03 марта 2020

Вы вообще не вводите gl_Multitexcoord1:

    glBegin(GL_QUADS);
    glTexCoord2f(0, 0);
    glVertex3f(0, 1, -1);
    [...]
    glEnd();

Этот код предоставляет данные только для gl_MultiTexCoord0. Если вам действительно нужны разные текстовые корды для каждой текстуры, то вам нужно предоставить их для каждой вершины через glMultiTexCoord:

    glBegin(GL_QUADS);
    glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
    glMultiTexCoord2f(GL_TEXTURE1, ..., ...);
    glVertex3f(0, 1, -1);
    [...]
    glEnd();

Однако вы также можете использовать один набор текстурных координат для обеих текстур, если вам действительно не нужны разные значения (что не ясно из вашего вопроса).

Обратите внимание, что ваш код ужасно устарел и не рекомендуется в GL с 2008 года . Даже если вы ограничены GL2.x (в качестве цели для ваших шейдеров), вы должны никогда использовать встроенные атрибуты, такие как gl_MultiTexCoord* et c. Используйте обобщенные атрибуты вершин c и предоставляйте свои данные в виде массивов вершин в объектах буфера вершин.

...