Win32 现代 OpenGL 着色器根本无法渲染任何东西 [关闭]

问题描述 投票:0回答:0

我正在使用 win32 编写一个基本的 opengl 抽象库,并且我一直坚持获取 2d 纹理以渲染为两个三角形四边形。我得到的不是渲染四边形,而是一个空白的黑屏。用其他着色器绘图效果很好,但这个不行。

我认为这一定与纹理有关,但即使尝试使用测试着色器渲染原始几何体,它也不会渲染纹理映射到的两个三角形。尝试使用 glIsShader() 验证着色器返回 GL_FALSE,但我没有从日志中收到任何信息。所以我不知道着色器的问题是什么,或者我做错了什么。 我所有的 gl 函数都是手动加载的,所以 _g 在那里,因为我不能重用它们的名称,因为我使用的是 glext.h。我知道这对我的函数没有任何影响,因为它们都加载了一个有效的函数地址。

这是我的 github 页面: https://github.com/HyperBitGore/g_engine_2d

这是我的着色器编译器 编辑:更改着色器代码

GLuint EngineNewGL::compileShader(const char* vertex_file, const char* fragment_file) {
    // Create the shaders
    GLuint VertexShaderID = glCreateShader_g(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader_g(GL_FRAGMENT_SHADER);

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    std::cout << "Compiling vertex shader" << std::endl;
    char const* VertexSourcePointer = vertex_file;
    glShaderSource_g(VertexShaderID, 1, &VertexSourcePointer, NULL);
    glCompileShader_g(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv_g(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv_g(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
        glGetShaderInfoLog_g(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        printf("%s\n", &VertexShaderErrorMessage[0]);
    }


    // Compile Fragment Shader
    std::cout << "Compiling fragment shader" << std::endl;;
    char const* FragmentSourcePointer = fragment_file;
    glShaderSource_g(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
    glCompileShader_g(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv_g(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv_g(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
        glGetShaderInfoLog_g(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        printf("%s\n", &FragmentShaderErrorMessage[0]);
    }

    // Link the program
    std::cout << "Linking program" << std::endl;
    GLuint ProgramID = glCreateProgram_g();
    glAttachShader_g(ProgramID, VertexShaderID);
    glAttachShader_g(ProgramID, FragmentShaderID);
    glLinkProgram_g(ProgramID);

    // Check the program
    glGetProgramiv_g(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv_g(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
        glGetProgramInfoLog_g(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
        printf("%s\n", &ProgramErrorMessage[0]);
    }

    glDetachShader_g(ProgramID, VertexShaderID);
    glDetachShader_g(ProgramID, FragmentShaderID);

    glDeleteShader_g(VertexShaderID);
    glDeleteShader_g(FragmentShaderID);
    return ProgramID;
}

这就是我初始化 OpenGL 的方式

EngineNewGL::EngineNewGL(LPCWSTR window_name, int width, int height) {
    PIXELFORMATDESCRIPTOR windowPixelFormatDesc = { 0 };
    windowPixelFormatDesc.nSize = sizeof(windowPixelFormatDesc);
    windowPixelFormatDesc.nVersion = 1;
    windowPixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
    windowPixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    windowPixelFormatDesc.cColorBits = 32;
    windowPixelFormatDesc.cAlphaBits = 8;
    windowPixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
    windowPixelFormatDesc.cDepthBits = 24;
    windowPixelFormatDesc.cStencilBits = 8;

    //function pointers
    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
    PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;

    //create window
    wind = new Window(window_name, L"ENG1", width, height, 300, 300);
    in = new Input();
    //getting device context
    dc_w = GetDC(wind->getHwnd());
    {
        // to get WGL functions we need valid GL context, so create dummy window for dummy GL contetx
        HWND dummy = CreateWindowExW(
            0, L"STATIC", L"DummyWindow", WS_OVERLAPPED,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, NULL, NULL);
        Assert(dummy && "Failed to create dummy window");

        HDC dc = GetDC(dummy);
        Assert(dc && "Failed to get device context for dummy window");

        PIXELFORMATDESCRIPTOR desc =
        {
            desc.nSize = sizeof(desc),
            desc.nVersion = 1,
            desc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
            desc.iPixelType = PFD_TYPE_RGBA,
            desc.cColorBits = 32,
        };

        int format = ChoosePixelFormat(dc, &desc);
        if (!format)
        {
            FatalError("Cannot choose OpenGL pixel format for dummy window!");
        }

        int ok = DescribePixelFormat(dc, format, sizeof(desc), &desc);
        Assert(ok && "Failed to describe OpenGL pixel format");

        // reason to create dummy window is that SetPixelFormat can be called only once for the window
        if (!SetPixelFormat(dc, format, &desc))
        {
            FatalError("Cannot set OpenGL pixel format for dummy window!");
        }

        HGLRC rc = wglCreateContext(dc);
        Assert(rc && "Failed to create OpenGL context for dummy window");

        ok = wglMakeCurrent(dc, rc);
        Assert(ok && "Failed to make current OpenGL context for dummy window");
        //now get wgl functions using the dummy context


        PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
            (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
        const char* ext = wglGetExtensionsStringARB(dc);
        wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
        wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");

        wglMakeCurrent(NULL, NULL);
        wglDeleteContext(rc);
        ReleaseDC(dummy, dc);
        DestroyWindow(dummy);
    }
    dc_w = GetDC(wind->getHwnd());

    // set pixel format for OpenGL context
    {
        int attrib[] =
        {
            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
            WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
            WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
            //WGL_TEXTURE_2D_ARB,       GL_TRUE,
            WGL_ACCELERATION_ARB,   WGL_FULL_ACCELERATION_ARB,
            //WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB,
            WGL_PIXEL_TYPE_ARB,     WGL_TYPE_RGBA_ARB,
            WGL_COLOR_BITS_ARB,     32,
            WGL_DEPTH_BITS_ARB,     24,
            WGL_STENCIL_BITS_ARB,   8,

            // uncomment for sRGB framebuffer, from WGL_ARB_framebuffer_sRGB extension
            // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_framebuffer_sRGB.txt
            //WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE,

            // uncomment for multisampeld framebuffer, from WGL_ARB_multisample extension
            // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_multisample.txt
            //WGL_SAMPLE_BUFFERS_ARB, 1,
            //WGL_SAMPLES_ARB,        4, // 4x MSAA

            0,
        };

        int format;
        UINT formats;
        if (!wglChoosePixelFormatARB(dc_w, attrib, NULL, 1, &format, &formats) || formats == 0)
        {
            FatalError("OpenGL does not support required pixel format!");
        }

        PIXELFORMATDESCRIPTOR desc;
        desc.nSize = sizeof(desc);
        int ok = DescribePixelFormat(dc_w, format, sizeof(desc), &desc);
        Assert(ok && "Failed to describe OpenGL pixel format");

        if (!SetPixelFormat(dc_w, format, &desc))
        {
            FatalError("Cannot set OpenGL selected pixel format!");
        }
    }
    //now create opengl context
    int attrib[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
        WGL_CONTEXT_MINOR_VERSION_ARB, 3,
        WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
    #ifndef NDEBUG
        // ask for debug context for non "Release" builds
        // this is so we can enable debug callback
        WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
    #endif
        0,
    };
    context = wglCreateContextAttribsARB(dc_w, NULL, attrib);
    //context = wglCreateContext(dc);
    if (!wglMakeCurrent(dc_w, context)) {
        std::cerr << "Failed to make context current\n";
    }
    glEnable(GL_TEXTURE_2D);
    //glEnable(GL_BLEND);
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

    loadFunctions();


    //start modern opengl needed stuff like shaders and vertex buffers
    glGenVertexArrays_g(1, &VAO_Triangle);
    //glBindVertexArray_g(VAO_Triangle);

    glGenVertexArrays_g(1, &VAO_Points);
    //glBindVertexArray_g(VAO_Points);

    glGenVertexArrays_g(1, &VAO_Line);
    //glBindVertexArray_g(VAO_Line);

    glGenVertexArrays_g(1, &VAO_Img);
    //glBindVertexArray_g(VAO_Img);

    glGenBuffers_g(1, &uv_buffer);
    glBindBuffer_g(GL_ARRAY_BUFFER, uv_buffer);
    glGenBuffers_g(1, &vertex_buffer);
    glBindBuffer_g(GL_ARRAY_BUFFER, vertex_buffer);
    //shader compiles

    const char* vertex_shader_img = "#version 330 core\nlayout(location = 0) in vec2 pos;\nlayout(location = 1) in vec2 uv;\nout vec2 tex_coords;\nvoid main(){\n"
        "gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);\n"
        "tex_coords = vec2(uv.x, uv.y);\n"
        "}\0";
    const char* fragment_shader_img = "#version 330 core\nin vec2 tex_coords;\nout vec4 color;\nuniform sampler2D image_tex;\nvoid main(){\n"
        "color = texture(image_tex, tex_coords);\n}\0";
        //"color = vec3(1.0f, 0.2f, 0.2f);\n}\0";
    
    const char* test_shader = "#version 330 core\nlayout(location = 0) in vec2 pos;\nvoid main(){\ngl_Position = vec4(pos.x, pos.y, 0.0, 1.0);\n}\0";
    const char* test_frag = "#version 330 core\nout vec4 color;\nvoid main(){\ncolor = vec4(1.0, 0.2, 0.2, 1.0);\n}\0";

    shader_img = compileShader(vertex_shader_img, fragment_shader_img);
    glValidateProgram_g(shader_img);
    int  success;
    char infoLog[512];
    glGetProgramInfoLog_g(shader_img, 512, &success, infoLog);
    std::cout << infoLog << "\n";
    std::cout << shader_img << "\n";
    if (glIsShader_g(shader_img) == GL_TRUE) {
        std::cout << "is shader\n";
    }
    std::cout << std::to_string(glIsShader_g(shader_img)) << "\n";
    glUseProgram_g(shader_img);
    glBindVertexArray_g(VAO_Img);

    GLuint position = glGetAttribLocation_g(shader_img, "pos");
    glEnableVertexAttribArray_g(position);
    glVertexAttribPointer_g(position, 2, GL_FLOAT, GL_FALSE, sizeof(vec2), (void*)0);
    glBindBuffer_g(GL_ARRAY_BUFFER, vertex_buffer);

    position = glGetAttribLocation_g(shader_img, "uv");
    glEnableVertexAttribArray_g(position);
    glVertexAttribPointer_g(position, 2, GL_FLOAT, GL_FALSE, sizeof(vec2), (void*)0);
    glBindBuffer_g(GL_ARRAY_BUFFER, uv_buffer);


    glBindBuffer_g(GL_ARRAY_BUFFER, 0);
    //speed up push_backs
    buffer_2d.reserve(1000);
    buffer_3d.reserve(1000);
    buffer_uv.reserve(1000);

    ShowWindow(wind->getHwnd(), SW_SHOW);
}

实际绘图功能

void EngineNewGL::renderImg(IMG img, float x, float y, int w, int h) {
    //glEnable(GL_BLEND);
    //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);



    //triangle 1
    buffer_2d.push_back({ x, y });
    buffer_2d.push_back({ x + w, y });
    buffer_2d.push_back({ x, y + h });
    //triangle 2
    buffer_2d.push_back({ x + w, y });
    buffer_2d.push_back({ x + w, y + h });
    buffer_2d.push_back({ x, y + h });
    
    //uv triangle 1
    buffer_uv.push_back({ 0, 0 });
    buffer_uv.push_back({ 1, 0 });
    buffer_uv.push_back({ 0, 1 });
    //uv triangle 2
    buffer_uv.push_back({ 1, 0 });
    buffer_uv.push_back({ 1, 1 });
    buffer_uv.push_back({ 0, 1 });

    float verts[] = { x, y, x + w, y, x, y + h, x + w, y, x + w, y + h,x, y + h };
    float uvs[] = { 0,0,1,0,0,1,1,0,1,1,0,1 };


    
    


    glUseProgram_g(shader_img);
    if (glGetError() == GL_INVALID_VALUE) {
        //std::cout << "invalid value\n";
        std::cout << glGetError() << "\n";
    }

    glActiveTexture_g(GL_TEXTURE0);
    GLuint texUniformLocation = glGetUniformLocation_g(shader_img, "image_tex");
    glUniform1i_g(texUniformLocation, 0);
    glBindTexture(GL_TEXTURE_2D, img->tex);

    glBindVertexArray_g(VAO_Img);
    
    glBindBuffer_g(GL_ARRAY_BUFFER, vertex_buffer);
    glBufferData_g(GL_ARRAY_BUFFER, buffer_2d.size() * sizeof(vec2), &buffer_2d[0], GL_STATIC_DRAW);
    
    glBindBuffer_g(GL_ARRAY_BUFFER, uv_buffer);
    glBufferData_g(GL_ARRAY_BUFFER, buffer_uv.size() * sizeof(vec2), &buffer_uv[0], GL_STATIC_DRAW);
    
    glDrawArrays(GL_TRIANGLES, 0, buffer_2d.size());
    buffer_2d.clear();
    buffer_uv.clear();
    glBindVertexArray_g(0);
    glBindBuffer_g(GL_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    //glDisable(GL_BLEND);
}

这是我加载函数的方式

//to load new gl functions
void* GetGLFuncAddress(const char* name) {
    void* p = (void*)wglGetProcAddress(name);
    if (p == 0x0 || p == (void*)0x01 || p == (void*)0x02 || p == (void*)0x03 || p == (void*)-0x1) {
        HMODULE module = LoadLibraryA("opengl32.dll");
        p = (void*)GetProcAddress(module, name);
    }
    std::cout << p << "\n";
    return p;
}





PFNGLBINDBUFFERPROC glBindBuffer_g;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_g;
PFNGLGENBUFFERSPROC glGenBuffers_g;
PFNGLBUFFERDATAPROC glBufferData_g;
PFNGLATTACHSHADERPROC glAttachShader_g;
PFNGLCOMPILESHADERPROC glCompileShader_g;
PFNGLCREATEPROGRAMPROC glCreateProgram_g;
PFNGLCREATESHADERPROC glCreateShader_g;
PFNGLDELETESHADERPROC glDeleteShader_g;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray_g;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray_g;
PFNGLGETPROGRAMIVPROC glGetProgramiv_g;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog_g;
PFNGLLINKPROGRAMPROC glLinkProgram_g;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog_g;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray_g;
PFNGLSHADERSOURCEPROC glShaderSource_g;
PFNGLGETSHADERIVPROC glGetShaderiv_g;
PFNGLUSEPROGRAMPROC glUseProgram_g;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer_g;
PFNGLUNIFORM1IPROC glUniform1i_g;
PFNGLACTIVETEXTUREPROC glActiveTexture_g;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_g;
PFNGLISSHADERPROC glIsShader_g;
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation_g;
PFNGLVALIDATEPROGRAMPROC glValidateProgram_g;

void EngineNewGL::loadFunctions() {
    glBindBuffer_g = (PFNGLBINDBUFFERPROC)GetGLFuncAddress("glBindBuffer");
    glGenVertexArrays_g = (PFNGLGENVERTEXARRAYSPROC)GetGLFuncAddress("glGenVertexArrays");
    glGenBuffers_g = (PFNGLGENBUFFERSPROC)GetGLFuncAddress("glGenBuffers");
    glBufferData_g = (PFNGLBUFFERDATAPROC)GetGLFuncAddress("glBufferData");
    glAttachShader_g = (PFNGLATTACHSHADERPROC)GetGLFuncAddress("glAttachShader");
    glCompileShader_g = (PFNGLCOMPILESHADERPROC)GetGLFuncAddress("glCompileShader");
    glCreateProgram_g = (PFNGLCREATEPROGRAMPROC)GetGLFuncAddress("glCreateProgram");
    glCreateShader_g = (PFNGLCREATESHADERPROC)GetGLFuncAddress("glCreateShader");
    glDeleteShader_g = (PFNGLDELETESHADERPROC)GetGLFuncAddress("glDeleteShader");
    glDisableVertexAttribArray_g = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)GetGLFuncAddress("glDisableVertexAttribArray");
    glEnableVertexAttribArray_g = (PFNGLENABLEVERTEXATTRIBARRAYPROC)GetGLFuncAddress("glEnableVertexAttribArray");
    glGetProgramiv_g = (PFNGLGETPROGRAMIVPROC)GetGLFuncAddress("glGetProgramiv");
    glGetProgramInfoLog_g = (PFNGLGETPROGRAMINFOLOGPROC)GetGLFuncAddress("glGetProgramInfoLog");
    glLinkProgram_g = (PFNGLLINKPROGRAMPROC)GetGLFuncAddress("glLinkProgram");
    glGetShaderInfoLog_g = (PFNGLGETSHADERINFOLOGPROC)GetGLFuncAddress("glGetShaderInfoLog");
    glBindVertexArray_g = (PFNGLBINDVERTEXARRAYPROC)GetGLFuncAddress("glBindVertexArray");
    glShaderSource_g = (PFNGLSHADERSOURCEPROC)GetGLFuncAddress("glShaderSource");
    glGetShaderiv_g = (PFNGLGETSHADERIVPROC)GetGLFuncAddress("glGetShaderiv");
    glUseProgram_g = (PFNGLUSEPROGRAMPROC)GetGLFuncAddress("glUseProgram");
    glVertexAttribPointer_g = (PFNGLVERTEXATTRIBPOINTERPROC)GetGLFuncAddress("glVertexAttribPointer");
    glUniform1i_g = (PFNGLUNIFORM1IPROC)GetGLFuncAddress("glUniform1i");
    glActiveTexture_g = (PFNGLACTIVETEXTUREPROC)GetGLFuncAddress("glActiveTexture");
    glGetUniformLocation_g = (PFNGLGETUNIFORMLOCATIONPROC)GetGLFuncAddress("glGetUniformLocation");
    glIsShader_g = (PFNGLISSHADERPROC)GetGLFuncAddress("glIsShader");
    glGetAttribLocation_g = (PFNGLGETATTRIBLOCATIONPROC)GetGLFuncAddress("glGetAttribLocation");
    glValidateProgram_g = (PFNGLVALIDATEPROGRAMPROC)GetGLFuncAddress("glValidateProgram");
}

以及我如何初始化窗口

       Window::Window(LPCWSTR title, LPCWSTR CLASS_NAME, int h, int w, int x, int y)
        : m_hinstance(GetModuleHandle(nullptr))
    {
        class_name = CLASS_NAME;
        WNDCLASS wnd = {};
        wnd.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        wnd.lpszClassName = CLASS_NAME;
        wnd.hInstance = m_hinstance;
        wnd.hIcon = LoadIcon(NULL, IDI_WINLOGO);
        wnd.hCursor = LoadIcon(NULL, IDC_ARROW);
        wnd.hbrBackground = 0;
        wnd.lpfnWndProc = WindowProc;
    
        RegisterClass(&wnd);
    
        DWORD windStyle = WS_OVERLAPPEDWINDOW | WS_MINIMIZEBOX | WS_SYSMENU;
        height = h;
        width = w;
    
        RECT rect;
        rect.left = x;
        rect.top = y;
        rect.right = rect.left + width;
        rect.bottom = rect.top + height;
    
        AdjustWindowRect(&rect, windStyle, false);
    
        m_hwnd = CreateWindowEx(0, CLASS_NAME,
            title,
            windStyle,
            rect.left,
            rect.top,
            rect.right - rect.left,
            rect.bottom - rect.top,
            NULL,
            NULL,
            m_hinstance,
            NULL
        );

}
c++ winapi opengl glsl opengl-3
© www.soinside.com 2019 - 2024. All rights reserved.