切换多个着色器程序(在OpenGL-ES 2.0中)

时间:2016-11-24 04:45:24

标签: c++ shader opengl-es-2.0

我真的有噩梦来实现我在OpenGles 2.0中所需要的 在发布代码参考之前,让我告诉我需要什么。

我有2D纹理片段着色器。在纹理的顶部,我想绘制红色线。我可以绘制线但是着色为红色不起作用。

着色器声明:

static const char s_v_shader[] =
    "attribute vec4 vPosition; \n"
    "attribute vec2 my_Texcoor;     \n"
    "uniform   mat4 u_TransMatrix;   \n"
    "varying vec2 vTexcoor;         \n"
    "void main() \n"
    "{ \n"
    "  vTexcoor = my_Texcoor;       \n"
    " gl_Position = u_TransMatrix*vPosition; \n"
    "} \n";

    static const char s_f_shader[] =
    "precision mediump float;\n"
    "uniform sampler2D my_Sampler;                    \n"
    "varying vec2 vTexcoor;                           \n"
    "void main() \n"
    "{ \n"
    " vec4 tex = texture2D(my_Sampler, vTexcoor);    \n"
    "  gl_FragColor = tex;                            \n"
    "} \n";

在纹理之上,我在无限循环中渲染来自相机的视频帧。 在渲染视频之前,我正在使用下面的代码设置2D纹理的坐标。

现在我将从main函数

解释我的代码
main()

    {
    const GLfloat vertices[][2] = {
        { -1.0f, -1.0f},
        {  1.0f, -1.0f},
        { -1.0f, 1.0f},
        {  1.0f,  1.0f}
    };

    const GLfloat texcoords[][2] = {
        { 0.0f, 1.0f},
        { 1.0f, 1.0f},
        { 0.0f, 0.0f},
        { 1.0f, 0.0f}
    };
    GLfloat transformMatrix[16] =
    {
        1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f
    };

        // setup OpenGl environment......
        Setup_coordinates()

    }

    Setup_coordinates()
    {
        LoadShaders(s_v_shader, s_f_shader);

 -- Complete function defined below 
        // By now I should be using  shader program.

        // Grab location of shader attributes.


    GLint locVertices = glGetAttribLocation(programHandle, "vPosition");
                GLint locTexcoord = glGetAttribLocation(programHandle, "my_Texcoor");

            // Transform Matrix is uniform for all vertices here.
                GLint locTransformMat = glGetUniformLocation(programHandle, "u_TransMatrix");
                GLint locSampler = glGetUniformLocation(programHandle, "my_Sampler");     

            /* Create the texture. */
                glGenTextures(1, &gTexObj);
                glBindTexture(GL_TEXTURE_2D, gTexObj);
                if (gTexObj == 0)
                {
                    printf("Could not load the texture \n");
                    return -1;
                }

                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_EDGE);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    

                glUniformMatrix4fv(locTransformMat, 1, GL_FALSE, transformMatrix);

                glUniform1i(locSampler, 0);

                glClearColor(0.0f, 0.5f, 0.0f, 0.0f);
                glClear(GL_COLOR_BUFFER_BIT);


            while(1) -- Infinite loop to render video frames on 2D texture and draw red color line.
            {
              // enable vertex arrays to push the data.


    glEnableVertexAttribArray(locVertices);
                glEnableVertexAttribArray(locTexcoord);

                 // set data in the arrays.
                glVertexAttribPointer(locVertices, 2, GL_FLOAT, GL_FALSE, 0, &vertices[0][0]);
                glVertexAttribPointer(locTexcoord, 2, GL_FLOAT, GL_FALSE, 0, &texcoords[0][0]);

            Render video frames logic goes here...................................
            Each frame of video is abosultely rendering fine.

            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        Now comes the tricky part to draw the line and color it with red.



float red_left_1[] =
    {
        -0.85f, -0.9f, -0.6f, -0.5f,
    };
        glVertexAttribPointer ( 1, 2, GL_FLOAT, GL_FALSE, 0, red_left_1 );
        glEnableVertexAttribArray (1 );

        glDrawArrays ( GL_LINES , 0, 2 );
        glLineWidth( width_test );

        }

        }



void LoadShaders(const char * vShader, const char * pShader)
    {
        vertShaderNum = glCreateShader(GL_VERTEX_SHADER);
        pixelShaderNum = glCreateShader(GL_FRAGMENT_SHADER);

        if (CompileShader(vShader, vertShaderNum) == 0)
        {
            printf("%d: PS compile failed.\n", __LINE__);
            return;
        }

        if (CompileShader(pShader, pixelShaderNum) == 0)
        {
            printf("%d: VS compile failed.\n", __LINE__);
            return;
        }

        programHandle = glCreateProgram();

        glAttachShader(programHandle, vertShaderNum);
        glAttachShader(programHandle, pixelShaderNum);

        // Bind vPosition to attribute 0
        glBindAttribLocation ( programHandle, 0, "vPosition" );

        glLinkProgram(programHandle);
        // Check if linking succeeded.
        GLint linked = 0;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linked);
        if (!linked)
        {
            printf("%d: Link failed.\n", __LINE__);
            // Retrieve error buffer size.
            GLint errorBufSize, errorLength;
            glGetShaderiv(programHandle, GL_INFO_LOG_LENGTH, &errorBufSize);

            char * infoLog = (char*)malloc(errorBufSize * sizeof (char) + 1);
            if (infoLog)
            {
                // Retrieve error.
                glGetProgramInfoLog(programHandle, errorBufSize, &errorLength, infoLog);
                infoLog[errorBufSize + 1] = '\0';
                fprintf(stderr, "%s", infoLog);

                free(infoLog);
            }

            return;
        }
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glUseProgram(programHandle);
    }

大多数天才人士建议如上所述再声明一个着色器,但用统一的vec4颜色替换统一的sampler2D my_Sampler。

void main()
    {
    gl_FragColor = color
    }

然后在使用glUseProgram显示纹理和绘制颜色线的同时在这些着色器程序之间切换。

我试过并且绝对放弃了,因为切换到着色器程序的绘图线不起作用。

1 个答案:

答案 0 :(得分:0)

以下是用于生成可用于线条的彩色1x1纹理的代码(位于mainSetup_coordinates)。使用此解决方案,您将不需要另一个着色器。

GLuint lineTexture;
glGenTextures(1, &lineTexture);
unsigned char red[4] = { 255, 0, 0, 255};
glBindTexture(GL_TEXTURE_2D, lineTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, red);
glBindTexture(GL_TEXTURE_2D, 0);

在致电glDrawArrays之前,请使用此选项切换到正确的纹理。

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <lineTexture or gTexObj>);
glUniform1i(locSampler, 0);

一个更通用的解决方案(我个人在我的OpenGL项目中实现)是创建一个白色纹理,为着色器添加一个颜色均匀,并将该系列与texture2D返回值相乘。使用此方法,您可以使用相同的白色纹理创建不同的彩色线条和图形,仅更改颜色均匀。对于视频帧,您将发送白色并且像素将保持不变。这将只需要很少的代码更改,我相信如果你认为它听起来更好,你可以弄明白。 :)