片段着色器:texture2D() 和 texelFetch()

fragment shader: texture2D() and texelFetch()

我的程序显示一张用 openCV 从带有 openGL 的网络摄像头加载的图像。

下面的程序可以正常工作,但我在代码后面列出了一些问题。

主要内容:

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW\glfw3.h>
#include <iostream>
#include <fstream> //std::ifstream
#include <algorithm> //std::max()
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>

cv::VideoCapture capture0;
cv::VideoCapture capture1;

void captureFromWebcam(cv::Mat &frame, cv::VideoCapture &capture)
{
    capture.read(frame);
}

bool initializeCapturing()
{
    capture0.open(0);
    capture1.open(1);

    if(!capture0.isOpened() | !capture1.isOpened())
    {
        std::cout << "Ein oder mehrere VideoCaptures konnten nicht geöffnet werden" << std::endl;

        if(!capture0.isOpened())
            capture0.release(); 
        if(!capture1.isOpened())
            capture1.release();
        return false;
    }

    return true;
}

void releaseCapturing()
{
    capture0.release();
    capture1.release();
}

GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){

    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
    if(VertexShaderStream.is_open())
    {
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    }

    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if(FragmentShaderStream.is_open()){
        std::string Line = "";
        while(std::getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
    }

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);

    // Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);

    // Link the program
    fprintf(stdout, "Linking program\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    return ProgramID;
}


int main ()
{
    int w = 640,h=480;

    glfwInit();

    //configure glfw 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);


    GLFWwindow* window = glfwCreateWindow(w, h, "OpenGL", NULL, nullptr); // windowed
    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    glewInit();

    initializeCapturing();

    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // An array of 3 vectors which represents 3 vertices (singular: vertex -> ein Punkt im dreidimensionalen raum)
    static const GLfloat g_vertex_buffer_data[] = {
        //x,y,z
       -1.0f, -1.0f, 0.0f, //unten links
       1.0f, 1.0f, 0.0f, //oben rechts
       -1.0f,  1.0f, 0.0f, //oben links
       -1.0f, -1.0f, 0.0f, //unten links
       1.0f, 1.0f, 0.0f, //oben rechts
       1.0f,-1.0f,0.0f //unten rechts

    };
    static const GLfloat vertex_buffer_coordinates[] ={
    0.0f,0.0f,
    1.0f,1.0f,
    0.0f,1.0f,
    0.0f,0.0f,
    1.0f,1.0f,
    1.0f,0.0f,
    };
    GLuint coordinateBuffer;
    glGenBuffers(1,&coordinateBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, coordinateBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_coordinates), vertex_buffer_coordinates, GL_STATIC_DRAW);


    // This will identify our vertex buffer
    GLuint vertexbuffer;

    // Generate 1 buffer, put the resulting identifier in vertexbuffer
    glGenBuffers(1, &vertexbuffer);

    // The following commands will talk about our 'vertexbuffer' buffer
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

    // Give our vertices to OpenGL.
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);


    GLuint shader_programm = LoadShaders("vertex.shader","fragment.shader");

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    //was passiert wenn die texture koordinaten außerhalb des bereichs sind?
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    //was passiert wenn die textur gestreckt/gestaucht wird?
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    cv::Mat frame;
    captureFromWebcam(frame,capture0);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,frame.size().width,frame.size().height,0,GL_RGB,GL_UNSIGNED_BYTE,frame.data);
    glUniform1i(glGetUniformLocation(shader_programm, "myTextureSampler"), 0);


    while(!glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, GL_TRUE);

        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
           0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
           3,                  // size
           GL_FLOAT,           // type
           GL_FALSE,           // normalized?
           0,                  // stride
           (void*)0            // array buffer offset
        );

        // 2nd attribute buffer : colors
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, coordinateBuffer);
        glVertexAttribPointer(
            1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
            3,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            0,                                // stride
            (void*)0                          // array buffer offset
        );
        const GLfloat color[] = {0.0f,0.2f,0.0f,1.0f};
        glClearBufferfv(GL_COLOR,0,color);
        glUseProgram(shader_programm);
        // Draw the triangle !
        glDrawArrays(GL_TRIANGLES, 0, 2*3); // Starting from vertex 0; 3 vertices total -> 1 triangle
        //glDrawArrays(GL_POINTS,0,1);
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);


        glfwSwapBuffers(window);
    }
    glDeleteVertexArrays(1,&VertexArrayID);
    glDeleteProgram(shader_programm);
    glDeleteVertexArrays(1,&VertexArrayID);

    releaseCapturing();
    glfwTerminate();

    return 1;
}

顶点着色器:

#version 330 core

layout (location = 0) in vec3 vertexPosition_modelspace; //input vom vertexbuffer
layout (location = 1) in vec2 UVcoord;

out vec2 UV;

void main(void)
{
    gl_Position.xyz = vertexPosition_modelspace;
    gl_Position.w = 1.0; //Zoomfaktor

    UV = UVcoord;
}

片段着色器:

#version 330 core

in vec2 UV;
out vec4 color;

// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;

void main(void)
{
    //color = texture2D(myTextureSampler,UV);
    color = texelFetch(myTextureSampler,ivec2(gl_FragCoord.xy),0);
}

GLSL texture 使用归一化坐标寻址,即 [0, 1] 范围内的值并执行过滤。 texelFetch 从特定的 mipmap 级别按绝对像素索引寻址并且 过滤。

根据您的屏幕截图判断,您传递给 texture 的纹理坐标是错误的,或者处理错误; texelFetch 代码不使用明确指定的纹理坐标,而是使用视口像素坐标。

查看纹理坐标调用的 glVertexAttribPointer,您告诉 OpenGL 每个纹理坐标有 3 个元素,而数组只有 2 个。所以这可能是您的问题。