openGL - не удалось отобразить изображения - PullRequest
1 голос
/ 16 апреля 2019

Обучение отображению изображений с помощью QOpenGLWidget.Однако я столкнулся с некоторыми проблемами.

  1. Как я могу передать переменную GLuint texture (фактическую текстуру, загруженную из изображения) в скрипты шейдера?Например, как связать GLuint texture с uniform sampler2D texture?Может быть, я просто не понимаю, что уже сделал это.
  2. В чем разница между attribute vec4 vertexColorIn и uniform sampler2D texture?Я думаю, что цвет исходит от текстуры.
  3. Могу ли я использовать glTexCoord2f() и glVertex2f() вместо glVertexAttribPointer() и glVertexAttribPointer()?Это потому, что они кажутся мне лучше.

Мне все еще неясно, как openGL отображает изображение, хотя я провел много исследований.Я не совсем уверен, что я делаю неправильно.Отображается NOT .

MyGLWiget.cpp

шейдеров:

#define STR(x) #x
#define VS_LOCATION 0
#define FS_LOCATION 1

const char* vertextShader = STR(
    attribute vec4 position;
    attribute vec4 vertexColorIn;
    varying vec4 vertexColorOut;
    void main(void)
    {
        gl_Position = position;
        vertexColorOut = vertexColorIn;
    }
);

const char* fragmentShader = STR(
    varying vec4 vertexColorOut;
    uniform sampler2D texture;
    void main(void)
    {
        ??? = texture2D(???, textureOut).r // no clue how to use it
        gl_FragColor = vertexColorOut;
    }   
);

загрузка текстуры изображения:

void MyGLWiget::loadTexture(const char* file_path)
{
    img_data = SOIL_load_image(file_path, &width, &height, &channels, SOIL_LOAD_RGB);

    glEnable(GL_TEXTURE_2D);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data);

    SOIL_free_image_data(img_data);
}

инициализация:

void MyGLWiget::initializeGL()
{
    initializeOpenGLFunctions();

    program.addShaderFromSourceCode(QGLShader::Vertex, vertextShader);
    program.bindAttributeLocation("position", VS_LOCATION);

    program.addShaderFromSourceCode(QGLShader::Fragment, fragmentShader);
    program.bindAttributeLocation("vertexColorIn", FS_LOCATION);

    program.link();
    program.bind();


    static const GLfloat ver[] = {
        -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f
    };

    static const GLfloat  tex[] = {
        0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
    };

    glVertexAttribPointer(VS_LOCATION, 2, GL_FLOAT, 0, 0, ver);
    glEnableVertexAttribArray(VS_LOCATION);

    glVertexAttribPointer(FS_LOCATION, 2, GL_FLOAT, 0, 0, tex);
    glEnableVertexAttribArray(FS_LOCATION);

    program.setUniformValue("texture", texture); 
    //texture = program.uniformLocation("texture");
}

paintGL:

Я действительно запутался в этой части.Я понятия не имею, что я должен использовать, чтобы нарисовать изображение.

void MyGLWiget::paintGL()
{
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, img_data);
    glUniform1i(texture, 0);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 1);
}

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Как передать переменную текстуры GLuint (фактическую текстуру, загруженную из изображения) в скрипты шейдеров?Например, как связать текстуру GLuint с однородной текстурой sampler2D?Может быть, я просто не понимаю, что я уже сделал это.

Это привязывает текстуру к единице текстуры 0:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

Это недопустимо, потому что texture не является единым местоположением, поэтому удалите эту строку:

glUniform1i(texture, 0); // <-- invalid

Это также недопустимо, потому что униформа texture должна быть установлена ​​на номер единицы текстуры:

program.setUniformValue("texture", texture); // <-- invalid

Поэтому замените ее на:

program.setUniformValue("texture", 0); // <-- sampler2D texture uses GL_TEXTURE0

Примечание: здесь я предполагаю, что setUniformValue работает правильно.


В чем разница между атрибутом vec4 vertexColorIn и однородной текстурой sampler2D?Я думаю, что цвет исходит от текстуры.

vertexColorIn исходит из VAO и отличается для каждой вершины.texture - это сэмплер, который выбирает текстуру, привязанную к единице текстуры, которую вы установили выше.

В вашем коде вам не нужен цвет вершины, но вам нужны координаты текстуры.Таким образом, ваши шейдеры должны выглядеть так:

const char* vertextShader = STR(
    attribute vec4 position;
    attribute vec4 texcoordIn;
    varying vec4 texcoordOut;
    void main(void)
    {
        gl_Position = position;
        texcoordOut = texcoordIn;
    }
);

const char* fragmentShader = STR(
    varying vec4 texcoordOut;
    uniform sampler2D texture;
    void main(void)
    {
        gl_FragColor = texture2D(texture, texcoordOut);
    }   
);

Могу ли я использовать glTexCoord2f () и glVertex2f () вместо glVertexAttribPointer () и glVertexAttribPointer ()?Это потому, что они кажутся мне лучше.

glTexCoord2f и glVertex2f - это устаревшие функции, которые были удалены в OpenGL 3 и доступны только в профиле совместимости.Вы не должны их использовать.


Эти строки находятся не в том месте:

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Они должны идти после того, как вы связали текстуру:

 glGenTextures(1, &texture);
 glBindTexture(GL_TEXTURE_2D, texture);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data);
 // sets the filtering for the bound texture:
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Поскольку вопрос помечен : вам не нужно задавать униформу в этом случае.Вы можете указать расположение и привязки непосредственно в шейдерах:

const char* vertextShader =
    "#version 450 core\n" STR(
    layout(location = 0) in vec4 position;
    layout(location = 1) in vec4 texcoordIn;
    layout(location = 0) out vec4 texcoordOut;
    void main(void)
    {
        gl_Position = position;
        texcoordOut = texcoordIn;
    }
);

const char* fragmentShader =
    "#version 450 core\n" STR(
    layout(location = 0) in vec4 texcoord;
    layout(binding = 0) uniform sampler2D TEX;
    layout(location = 0) out vec4 OUT;
    void main(void)
    {
        OUT = texture(TEX, texcoord);
    }   
);
1 голос
/ 16 апреля 2019

несколько правок

   const char* vertextShader = STR(
    attribute vec4 position;
    attribute vec4 vertexColorIn;
    varying vec4 vertexColorOut;
    out vec2 TexCoord;//--->add
    void main(void)
    {
        gl_Position = position;
        vertexColorOut = vertexColorIn;
        TexCoord = vec2(aPos.x/2.0+0.5, 0.5-aPos.y/2.0);//a hack,ideally you need to pass the UV coordinates for proper texture mapping.UVs need to be passed in as a uniform or an attribute depending on preference.
    }
);

const char* fragmentShader = STR(
    varying vec4 vertexColorOut;
    uniform sampler2D texture;
    in vec2 TexCoord; //---->add
    void main(void)
    {
        gl_FragColor  = texture2D(texture,TexCoord) //( no clue how to use it) -->here is the change
        //gl_FragColor = vertexColorOut;
    }   
);
...