当前位置: 首页 > 知识库问答 >
问题:

颜色作为片段着色器的采样器输入?

万俟英锐
2023-03-14

我需要一个着色程序,然后我需要一个着色程序。一旦我从我的着色器中获得COLOR_ATTACHMENT0COLOR_ATTACHMENT1后,是否可以将它们作为采样器发送到着色器中,以便在屏幕上渲染到四元体上?

我需要将颜色附件发送到第二个着色器的原因是,我正在不同的监视器上渲染COLOR\u ATTACHMENT0COLOR\u ATTACHMENT1COLOR_ATTACHMENT0将出现在一个屏幕上,而COLOR_ATTACHMENT1将出现在另一个屏幕上。。。

我正在做测试视力的心理实验。我的第一个着色器处理我的原始纹理集,但由于两个输出纹理所需的大部分处理是相同的,所以如果不需要,我基本上不想运行着色器两次。

我用的是GLFW,GLEW和GLM。因此,使用这些库的任何解决方案都是理想的

const GLchar* vertexSource =
    "#version 150 core\n"
    "in vec2 position;"
    "in vec2 texcoord;"
    "out vec2 Texcoord;"
    "void main() {"
    "   Texcoord = texcoord;"
    "   gl_Position = vec4(position, 0.0, 1.0);"
    "}";
const GLchar* fragmentSource =
    "#version 150 core\n"
    "in vec2 Texcoord;"
    "out vec4 outColor0;"
    "out vec4 outColor1;"
    "uniform sampler2D texLite;"
    "uniform sampler2D texDark;"
    "void main() {"
    "   outColor0 = texture(texLite, Texcoord);"
    "   outColor1 = texture(texDark, Texcoord);"
    "}";
const GLchar* vertexSourceDisp =
    "#version 150 core\n"
    "in vec2 position;"
    "in vec2 texcoord;"
    "out vec2 Texcoord;"
    "void main() {"
    "   Texcoord = texcoord;"
    "   gl_Position = vec4(position, 0.0, 1.0);"
    "}";
const GLchar* fragmentSourceDisp =
    "#version 150 core\n"
    "in vec2 Texcoord;"
    "out vec4 outColor;"
    "uniform sampler2D tex;"
    "void main() {"
    "   outColor = texture(tex, Texcoord);"
    "}";

当我运行glFrameBufferTexture 2D时,它会将纹理图像附加到帧缓冲区,因此当着色器运行时,我的着色器输出的vec4是否存储回纹理以及颜色附件中?

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <stdio.h>

// Simple through-put vertex shader
const GLchar* vertexSource =
    "#version 150 core\n"
    "in vec2 position;"
    "in vec2 texcoord;"
    "out vec2 Texcoord;"
    "void main() {"
    "   Texcoord = texcoord;"
    "   gl_Position = vec4(position, 0.0, 1.0);"
    "}";

// Basic fragment shader for the moment 
const GLchar* fragmentSource =
    "#version 150 core\n"
    "in vec2 Texcoord;"
    "out vec4 outColor0;"
    "out vec4 outColor1;"
    "uniform sampler2D texLite;"
    "uniform sampler2D texDark;"
    "void main() {"
    "   vec4 colLena = texture(texLite, Texcoord);"
    "   vec4 colTex7 = texture(texDark, Texcoord);"
    "   outColor0 = mix(colLena, colTex7, 0.0);"
    "   outColor1 = mix(colLena, colTex7, 1.0);"
    "}";

const GLchar* vertexSourceDisp =
    "#version 150 core\n"
    "in vec2 position;"
    "in vec2 texcoord;"
    "out vec2 Texcoord;"
    "void main() {"
    "   Texcoord = texcoord;"
    "   gl_Position = vec4(position, 0.0, 1.0);"
    "}";

const GLchar* fragmentSourceDisp =
    "#version 150 core\n"
    "in vec2 Texcoord;"
    "out vec4 outColor;"
    "uniform sampler2D tex;"
    "void main() {"
    "   outColor = texture(tex, Texcoord);"
    "}";

    void printShaderInfoLog(GLuint obj)
{
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;

    glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
        printf("%s\n",infoLog);
        free(infoLog);
    }
}

void printProgramInfoLog(GLuint obj)
{
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;

    glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
        printf("%s\n",infoLog);
        free(infoLog);
    }
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

int main()
{
    if (glfwInit() != GL_TRUE)
    {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return -1;
    }

    int count;
    GLFWmonitor** monitors = glfwGetMonitors(&count);

    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* window0;
    GLFWwindow* window1;

    window0 = glfwCreateWindow(1680, 1050, "OpenGL", monitors[2], window1); // Front Screen
    window1 = glfwCreateWindow(1280, 800, "OpenGL", monitors[1], window0); // Back Screen

    glfwMakeContextCurrent(window0);
    glfwSetKeyCallback(window0, key_callback);

    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK)
    {
        fprintf(stderr, "Failed to initialize GLEW\n");
        return -1;
    }

     // Vertex array object - Contains all vertex information
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // Vertex buffer object
    GLuint vbo;
    glGenBuffers(1, &vbo);

    // Vertices to use inside my shader
    GLfloat vertices[] = {
        -1.0f,  1.0f, 0.0f, 0.0f,
         1.0f,  1.0f, 1.0f, 0.0f,
         1.0f, -1.0f, 1.0f, 1.0f,
        -1.0f, -1.0f, 0.0f, 1.0f
    };

    // Attached vertices to my GPU
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Element buffer object - allows me to reuse vertices
    GLuint ebo;
    glGenBuffers(1, &ebo);

    // Index into the rows of vertices to use different vertices more than once
    GLuint elements[] = {
        0, 1, 2,
        2, 3, 0
    };

    // Attach element array to use on GPU
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

    // Set up shader
    // Vertex Shader
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexSource, NULL);
    glCompileShader(vertexShader);
    printShaderInfoLog(vertexShader);

    // Fragment shader
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
    glCompileShader(fragmentShader);
    printShaderInfoLog(fragmentShader);

    // Shader program
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glBindFragDataLocation(shaderProgram, 0, "outColor0");
    glBindFragDataLocation(shaderProgram, 1, "outColor1");
    printProgramInfoLog(shaderProgram);
    glLinkProgram(shaderProgram);

    GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(posAttrib);
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0);

    GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
    glEnableVertexAttribArray(texAttrib);
    glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE,
                            4*sizeof(float), (void*)(2*sizeof(float)));

    cv::VideoCapture cap("movie.mov");
    cv::Mat image0;
    cv::Mat image1;
    int width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
    int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    // float ratio = width/(float)height;

    //Set up samplers
    GLuint ldrTextures[2];
    glGenTextures(2, ldrTextures);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, ldrTextures[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
                    GL_BGR, GL_UNSIGNED_BYTE, NULL);

    glUniform1i(glGetUniformLocation(shaderProgram, "texLite"), 0);

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

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, ldrTextures[1]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
                    GL_BGR, GL_UNSIGNED_BYTE, NULL);

    glUniform1i(glGetUniformLocation(shaderProgram, "texDark"), 1);

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

    //Set up framebuffer
    GLuint frameBuffer;
    glGenFramebuffers(1, &frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);

    //Set up target textures
    GLuint dispTextures[2];
    glGenTextures(2, dispTextures);

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, dispTextures[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
                    GL_BGR, GL_UNSIGNED_BYTE, NULL);

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

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dispTextures[0], 0);  

    glActiveTexture(GL_TEXTURE3);
    glBindTexture(GL_TEXTURE_2D, dispTextures[1]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
                    GL_BGR, GL_UNSIGNED_BYTE, NULL);

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

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, dispTextures[1], 0);

    GLenum bufs[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
    glDrawBuffers(2, bufs);

    bool success;

    //Render loop
    while(!glfwWindowShouldClose(window0) && !glfwWindowShouldClose(window1))
    {
        std::cout << "Loop" << std::endl;

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        // glClear(GL_COLOR_BUFFER_BIT);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //Grab two frames from video
        success = cap.read(image0);

        if(!success)
        {
            std::cout << "Could not grab a frame" << std::endl;
            exit(0);
        }

        success = cap.read(image1);

        if(!success)
        {
            std::cout << "Could not grab a frame" << std::endl;
            exit(0);
        }

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, ldrTextures[0]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
                    GL_BGR, GL_UNSIGNED_BYTE, image0.data);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, ldrTextures[1]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
                    GL_BGR, GL_UNSIGNED_BYTE, image1.data);

        glfwMakeContextCurrent(window0);
        glfwSetKeyCallback(window0, key_callback);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(shaderProgram);

        // glViewport(0,0,width,height);

        // glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glActiveTexture(GL_TEXTURE2);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
        glActiveTexture(GL_TEXTURE3);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

        glfwMakeContextCurrent(window0);
        glfwSetKeyCallback(window0, key_callback);

        glViewport(0,0,width,height);

        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D, dispTextures[0]);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window0);
        glfwPollEvents();

        glfwMakeContextCurrent(window1);
        glfwSetKeyCallback(window1, key_callback);

        glViewport(0,0,width,height);

        glActiveTexture(GL_TEXTURE3);
        glBindTexture(GL_TEXTURE_2D, dispTextures[1]);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glfwSwapBuffers(window1);
        glfwPollEvents();
    }

    //Clean up memory, remember good coding practices
    glDeleteTextures(1, ldrTextures);
    glDeleteTextures(1, dispTextures);

    glDeleteFramebuffers(1, &frameBuffer);

    glDeleteProgram(shaderProgram);
    glDeleteShader(fragmentShader);
    glDeleteShader(vertexShader);

    glDeleteBuffers(1, &ebo);
    glDeleteBuffers(1, &vbo);

    glDeleteVertexArrays(1, &vao);

    glfwTerminate();

}

共有1个答案

公冶谦
2023-03-14

示例代码仅显示正在编译和链接的单个GLSL着色器程序。这里应该有两个不同的程序,一个用于第一遍,另一个用于第二遍(缺少)。

一旦你解决了这个问题,你就需要相应地设置采样器。根据你第一个窗口的代码(window0)判断,它将使用采样器tex=2。第二个窗口(window1)将使用tex=3。现在,如果您了解OpenGL中的每个渲染上下文都有自己的状态机,这实际上是完全没有必要的(换句话说,纹理绑定状态不会在您的两个窗口之间共享)。您可以在两个渲染上下文中将每个窗口使用的纹理绑定到2,然后不必将tex采样器统一的值设置为2以外的任何值。

这里需要做的,也是真正困扰我的是,您试图使用一个渲染上下文的输出作为另一个渲染上下文的输入,而不进行同步。OpenGL中的渲染上下文是不同步的,不能保证在window0执行的第一步命令在window1尝试读取其输出图像时完成。最简单的解决方法是在从window0切换到window1之前添加对glFinish()的调用,这将导致OpenGL阻塞,直到所有这些命令完成。这不是最有效的解决方案(Geofence同步会更好),但它是最简单的。

 类似资料:
  • 我希望在2D OpenGL应用程序上实现着色器。我的计划是将场景渲染到帧缓冲区对象,然后使用着色器将该帧缓冲区对象渲染到屏幕。 这是我绘制到帧缓冲区对象的场景,然后从那里绘制到屏幕。使用箭头键可以让月亮四处移动(我很自豪!) 但是,当我尝试使用着色器程序将帧缓冲区对象渲染到屏幕上时,我得到以下结果: 这是非常可悲的。这个片段着色器是我从一个教程中得到的,我相信问题一定是统一变量。 以下是片段着色器

  • 在一个简单的hello world OpenGL程序中,它只是在窗口上绘制一个静态三角形,当我将三角形的3个顶点设置为红色、绿色和蓝色时,三角形将填充渐变。 但是当我使用这样的着色器时: 顶点着色器: 其中属性和来自顶点缓冲区,通过的调用传递。 片段着色器: 三角形仍然充满了梯度,问题来了: 如果顶点着色器是按顶点计算的,则应为的每个实例指定顶点的颜色。顶点颜色应为红色、绿色或蓝色,如顶点缓冲区中

  • 我创建了一个FBO,并有一个纹理绑定作为其颜色附件,我有多个着色器程序,对纹理做一些后处理,一切都很好,但它对我来说没有意义,纹理可以用作输入(sampler2D)以及同时着色器的输出。 以下是我采取的步骤: 创建一个FBO。 创建一个纹理,并将其绑定为的颜色附件。 调用将绑定到帧缓冲区目标。 调用使用着色器程序。 调用来绘制一些东西(最终在上绘制,因为当前绑定)。 调用使用shader程序,它在

  • 假设我遇到这样的问题:现在我有一个帧缓冲区,一个纹理只包含一个颜色组件(例如,GL_RED)已经绑定到它。碎片着色器会是什么样子?我想答案是: ...浮出ex_color; 颜色=。。。; 我的问题来了:着色器会自动检测帧缓冲区的格式并向其写入值吗?如果片段着色器输出浮点值但帧缓冲区格式GL_RGBA怎么办? 顺便问一下,创建只有一个组件的纹理的正确方法是什么?我阅读了g-truc的示例,其示例如

  • WebGL的着色器代码分为顶点着色器代码和片元着色器代码两部分,顶点着色器代码会在GPU的顶点着色器单元执行,片元着色器代码会在GPU的片元着色器单元执行,在WebGL渲染管线流程中,或者说GPU的渲染流程中,顶点着色器代码先执行处理顶点,得到一系列片元,然后再执行片元着色器代码处理片元。 main()函数 顶点着色器和片元着色器代码都有一个唯一的主函数main(),attribute、varyi

  • 片段着色器调用每个需要渲染的像素。我们将开发一个红色透镜,它将会增加图片的红色通道的值。 配置场景(Setting up the scene) 首先我们配置我们的场景,在区域中央使用一个网格显示我们的源图片(source image)。 import QtQuick 2.0 Rectangle { width: 480; height: 240 color: '#1e1e1e'