क्या सभी सक्रिय (glDrawBuffers() के अनुसार) एफबीओ रंग अनुलग्नकों के लिए एकल-आउटपुट टुकड़े शेडर के मूल्य को प्रसारित करने के लिए ओपनजीएल ईएस 3.0 प्राप्त करने का कोई तरीका है?

यदि संभव हो तो मैं अपने शेड्स को कमोबेश यथावत रखना चाहता हूं और कई layout'd आउटपुट के लिए आवश्यक री-राइट से बचना चाहता हूं:

layout( location = 0 ) out vec4 out_color0;
layout( location = 1 ) out vec4 out_color1;
layout( location = 2 ) out vec4 out_color2;
layout( location = 3 ) out vec4 out_color3;
void main()
{
    out_color0 = vec4( 1.0, 0.2, 0.0, 1.0 );
    out_color1 = vec4( 1.0, 0.2, 0.0, 1.0 );
    out_color2 = vec4( 1.0, 0.2, 0.0, 1.0 );
    out_color3 = vec4( 1.0, 0.2, 0.0, 1.0 );
}

या एक आउटपुट सरणी:

out vec4 out_color[4];
void main()
{
    out_color[0] = vec4( 1.0, 0.2, 0.0, 1.0 );
    out_color[1] = vec4( 1.0, 0.2, 0.0, 1.0 );
    out_color[2] = vec4( 1.0, 0.2, 0.0, 1.0 );
    out_color[3] = vec4( 1.0, 0.2, 0.0, 1.0 );
}

यहां वह प्रोग्राम है जिसका मैं परीक्षण के लिए उपयोग कर रहा हूं, यह (कोशिश करता है) सभी चार एफबीओ अनुलग्नकों के लिए एक लाल त्रिकोण खींचने के लिए और फिर डिफ़ॉल्ट फ्रेमबफर के लिए तीसरे अनुलग्नक को ब्लिट करता है:

#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#include <cstdlib>
#include <cstdarg>
#include <iostream>
#include <vector>

struct Program
{
    static GLuint Load( const char* shader, ... )
    {
        const GLuint prog = glCreateProgram();
        va_list args;
        va_start( args, shader );
        while( shader )
        {
            AttachShader( prog, va_arg( args, GLenum ), shader );
            shader = va_arg( args, const char* );
        }
        va_end( args );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    }

private:
    static void CheckStatus( GLuint obj )
    {
        GLint status = GL_FALSE;
        if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] = { 0 };
        if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
        if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
        std::cerr << log << std::endl;
        std::exit( EXIT_FAILURE );
    }

    static void AttachShader( GLuint program, GLenum type, const char* src )
    {
        const GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    }
};

const char* vert = 1 + R"GLSL(
#version 300 es
void main()
{
    const vec2 verts[3] = vec2[3]
    (
        vec2( -0.5, -0.5 ),
        vec2(  0.5, -0.5 ),
        vec2(  0.0,  0.5 )
    );
    gl_Position = vec4( verts[ gl_VertexID ], 0.0, 1.0 );
}
)GLSL";

const char* frag = 1 + R"GLSL(
#version 300 es
precision mediump float;
out vec4 out_color;
void main()
{
    out_color = vec4( 1.0, 0.2, 0.0, 1.0 );
}
)GLSL";

int main( int argc, char** argv )
{
    glfwSetErrorCallback( []( int err, const char* desc )
    {
        std::cerr << "GLFW error: " << desc << std::endl;
    } );

    if( !glfwInit() )
        return EXIT_FAILURE;

    glfwWindowHint( GLFW_CLIENT_API, GLFW_OPENGL_ES_API );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 0 );
    glfwWindowHint( GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API );
    GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
    if( nullptr == window )
        return EXIT_FAILURE;

    glfwMakeContextCurrent( window );
    glfwSwapInterval( 1 );
    gladLoadGLES2Loader( (GLADloadproc)glfwGetProcAddress );

    const GLuint prog = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
    glUseProgram( prog );

    // init framebuffer attachments
    std::vector< GLuint > textures( 4, 0 );
    glGenTextures( 4, textures.data() );
    for( size_t i = 0; i < textures.size(); ++ i )
    {
        glBindTexture( GL_TEXTURE_2D, textures[i] );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
    }
    GLuint rbDepth = 0;
    glGenRenderbuffers(1, &rbDepth );
    glBindRenderbuffer( GL_RENDERBUFFER, rbDepth );
    glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32 );

    // init FBO
    GLuint fbo = 0;
    glGenFramebuffers( 1, &fbo );
    glBindFramebuffer( GL_FRAMEBUFFER, fbo );
    for( size_t i = 0; i < textures.size(); ++ i )
    {
        glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0 );
    }
    glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbDepth );
    if( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus( GL_FRAMEBUFFER ) )
    {
        std::cerr << "Incomplete framebuffer" << std::endl;
        std::exit( EXIT_FAILURE );
    }

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

        // render to FBO
        glBindFramebuffer( GL_FRAMEBUFFER, fbo );
        GLenum bufs[] =
        {
            GL_COLOR_ATTACHMENT0 + 0,
            GL_COLOR_ATTACHMENT0 + 1,
            GL_COLOR_ATTACHMENT0 + 2,
            GL_COLOR_ATTACHMENT0 + 3,
        };
        glDrawBuffers( 4, bufs );
        glViewport( 0, 0, 32, 32 );
        glClearColor( 0.0f, 0.6f, 1.0f, 1.f );
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glDrawArrays( GL_TRIANGLES, 0, 3 );

        // switch back to default framebuffer & clear it with non-black color
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
        GLenum defaultBuf = GL_BACK;
        glDrawBuffers( 1, &defaultBuf );
        glClearColor( 1.0f, 0.0f, 1.0f, 1.f );
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        // blit a color attachment to the default framebuffer
        glBindFramebuffer( GL_READ_FRAMEBUFFER, fbo );
        glReadBuffer( GL_COLOR_ATTACHMENT0 + 2 );
        glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
        glBlitFramebuffer( 0, 0, 32, 32, 0, 0, 640, 480, GL_COLOR_BUFFER_BIT, GL_LINEAR );

        glfwSwapBuffers( window );
    }

    glfwMakeContextCurrent( NULL );
    glfwDestroyWindow( window );

    glfwTerminate();
    return EXIT_SUCCESS;
}

इस Windows 10 मशीन पर हाल ही के-ish ANGLE बिल्ड का उपयोग करके मुझे नीला स्पष्ट रंग मिलता है लेकिन कोई त्रिकोण नहीं ( "अपरिभाषित") तीसरे अनुलग्नक के लिए:

bad output

पहला लगाव ठीक है:

good output

1
genpfault 8 पद 2018, 01:21

1 उत्तर

सबसे बढ़िया उत्तर

एपीआई में ऐसी कोई कार्यक्षमता मौजूद नहीं है:

3) क्या हमें gl_FragColor से सभी gl_FragData[x] पर प्रसारण का समर्थन करना चाहिए या इसे gl_FragData[0] का पर्याय होना चाहिए?

चर्चा: NV_draw_buffers के साथ, gl_FragColor को लिखना सभी सक्षम ड्रा बफ़र्स (यानी प्रसारण) को लिखता है। ओपनजीएल ईएस 3.0 में ईएसएसएल 1.0 का उपयोग करते समय, gl_FragColor एक आउटपुट को gl_FragData [0] पर लिखने के बराबर है और कई आउटपुट संभव नहीं हैं। ईएसएसएल 3.0 का उपयोग करते समय, केवल उपयोगकर्ता-परिभाषित आउट वेरिएबल्स का उपयोग किया जा सकता है।

यदि प्रसारण समर्थित है, तो कुछ कार्यान्वयनों को लेखन को gl_FragColor में बदलना पड़ सकता है, जब यह एक्सटेंशन सक्षम होता है, तो सभी संभावित gl_FragData स्थानों पर दोहराए गए लेखन के साथ।

हल किया गया: लिखने के लिए gl_FragColor को सभी सक्षम रंगों में प्रसारित किया जाता है बफ़र्स ईएसएसएल 1.0 का उपयोग कर ईएस 3.0 प्रसारण का समर्थन नहीं करता है क्योंकि ईएसएसएल 1.0 को कई रंग आउटपुट के लिए विस्तारित नहीं किया गया था (लेकिन वह है यह एक्सटेंशन क्या जोड़ता है)। ईएसएसएल 3.0 प्रसारण का समर्थन नहीं करता क्योंकि इसमें gl_FragColor वैरिएबल बिल्कुल नहीं है, और केवल उपयोगकर्ता है- परिभाषित आउट वेरिएबल्स। यह एक्सटेंशन ईएसएसएल 1.0 को कई तक बढ़ाता है रंग आउटपुट। Gl_FragColor से सभी सक्षम रंगों में प्रसारण बफ़र्स मौजूदा ड्रॉ बफ़र एक्सटेंशन के साथ सबसे संगत है दिनांक (NV_draw_buffers और डेस्कटॉप GL दोनों)।

2
genpfault 10 पद 2018, 15:32