From a7db474a645542cc5f3da3e2625fa4e45b45dcda Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Sun, 13 Mar 2022 23:52:32 +0100 Subject: [PATCH] Unified the OpenGL and OpenGL ES renderers and removed the fixed function pipeline. Also made some other rendering optimizations and cleaned up some code. --- es-app/src/MediaViewer.cpp | 8 +- es-app/src/Screensaver.cpp | 19 +- es-app/src/guis/GuiMediaViewerOptions.cpp | 2 - es-app/src/guis/GuiMenu.cpp | 8 - es-app/src/guis/GuiScreensaverOptions.cpp | 4 - es-core/CMakeLists.txt | 2 - es-core/src/Window.cpp | 13 +- es-core/src/Window.h | 3 - es-core/src/components/GIFAnimComponent.cpp | 5 - .../src/components/LottieAnimComponent.cpp | 5 - es-core/src/renderers/Renderer.h | 21 +- es-core/src/renderers/Renderer_GL21.cpp | 243 +++++++----------- es-core/src/renderers/Shader_GL21.cpp | 90 +++++-- es-core/src/renderers/Shader_GL21.h | 18 +- es-core/src/resources/Font.cpp | 13 +- resources/shaders/glsl/blur_horizontal.glsl | 49 ++-- resources/shaders/glsl/blur_vertical.glsl | 49 ++-- resources/shaders/glsl/core.glsl | 69 +++-- resources/shaders/glsl/scanlines.glsl | 42 +-- 19 files changed, 300 insertions(+), 363 deletions(-) diff --git a/es-app/src/MediaViewer.cpp b/es-app/src/MediaViewer.cpp index f04fc7284..5cbf9ff05 100644 --- a/es-app/src/MediaViewer.cpp +++ b/es-app/src/MediaViewer.cpp @@ -86,7 +86,6 @@ void MediaViewer::render(const glm::mat4& /*parentTrans*/) if (mVideo && !mDisplayingImage) { mVideo->render(trans); -#if defined(USE_OPENGL_21) Renderer::postProcessingParams videoParameters; unsigned int shaders {0}; if (Settings::getInstance()->getBool("MediaViewerVideoScanlines")) @@ -111,20 +110,19 @@ void MediaViewer::render(const glm::mat4& /*parentTrans*/) videoParameters.blurPasses = 2; // 1080 // clang-format on } - Renderer::shaderPostprocessing(shaders, videoParameters); -#endif + + if (shaders != 0) + Renderer::shaderPostprocessing(shaders, videoParameters); } else if (mImage && mImage->hasImage() && mImage->getSize() != glm::vec2 {}) { mImage->render(trans); -#if defined(USE_OPENGL_21) if (mCurrentImageIndex == mScreenshotIndex && Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); else if (mCurrentImageIndex == mTitleScreenIndex && Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); -#endif // This is necessary so that the video loops if viewing an image when // the video ends. diff --git a/es-app/src/Screensaver.cpp b/es-app/src/Screensaver.cpp index d11155fda..65798d87c 100644 --- a/es-app/src/Screensaver.cpp +++ b/es-app/src/Screensaver.cpp @@ -267,10 +267,8 @@ void Screensaver::renderScreensaver() if (isScreensaverActive()) { if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") { if (mHasMediaFiles) { -#if defined(USE_OPENGL_21) if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines")) Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); -#endif if (Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo") && mGameOverlay) { if (mGameOverlayRectangleCoords.size() == 4) { @@ -295,7 +293,6 @@ void Screensaver::renderScreensaver() } else if (Settings::getInstance()->getString("ScreensaverType") == "video") { if (mHasMediaFiles) { -#if defined(USE_OPENGL_21) Renderer::postProcessingParams videoParameters; unsigned int shaders {0}; if (Settings::getInstance()->getBool("ScreensaverVideoScanlines")) @@ -320,8 +317,10 @@ void Screensaver::renderScreensaver() videoParameters.blurPasses = 2; // 1080 // clang-format on } - Renderer::shaderPostprocessing(shaders, videoParameters); -#endif + + if (shaders != 0) + Renderer::shaderPostprocessing(shaders, videoParameters); + if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo") && mGameOverlay) { if (mGameOverlayRectangleCoords.size() == 4) { Renderer::drawRect( @@ -345,7 +344,6 @@ void Screensaver::renderScreensaver() } if (mFallbackScreensaver || Settings::getInstance()->getString("ScreensaverType") == "dim") { -#if defined(USE_OPENGL_21) Renderer::postProcessingParams dimParameters; dimParameters.dimming = mDimValue; dimParameters.saturation = mSaturationAmount; @@ -354,22 +352,13 @@ void Screensaver::renderScreensaver() mDimValue = glm::clamp(mDimValue - 0.015f, 0.68f, 1.0f); if (mSaturationAmount > 0.0) mSaturationAmount = glm::clamp(mSaturationAmount - 0.035f, 0.0f, 1.0f); -#else - Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), - 0x000000A0, 0x000000A0); -#endif } else if (Settings::getInstance()->getString("ScreensaverType") == "black") { -#if defined(USE_OPENGL_21) Renderer::postProcessingParams blackParameters; blackParameters.dimming = mDimValue; Renderer::shaderPostprocessing(Renderer::SHADER_CORE, blackParameters); if (mDimValue > 0.0) mDimValue = glm::clamp(mDimValue - 0.045f, 0.0f, 1.0f); -#else - Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), - 0x000000FF, 0x000000FF); -#endif } } } diff --git a/es-app/src/guis/GuiMediaViewerOptions.cpp b/es-app/src/guis/GuiMediaViewerOptions.cpp index 0c0b9878f..0d8f06a6e 100644 --- a/es-app/src/guis/GuiMediaViewerOptions.cpp +++ b/es-app/src/guis/GuiMediaViewerOptions.cpp @@ -41,7 +41,6 @@ GuiMediaViewerOptions::GuiMediaViewerOptions(const std::string& title) } }); -#if defined(USE_OPENGL_21) // Render scanlines for videos using a shader. auto video_scanlines = std::make_shared(); video_scanlines->setState(Settings::getInstance()->getBool("MediaViewerVideoScanlines")); @@ -79,5 +78,4 @@ GuiMediaViewerOptions::GuiMediaViewerOptions(const std::string& title) setNeedsSaving(); } }); -#endif } diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 905282472..1e964403e 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -493,7 +493,6 @@ void GuiMenu::openUIOptions() screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); s->addRow(screensaver_row); -#if defined(USE_OPENGL_21) // Blur background when the menu is open. auto menu_blur_background = std::make_shared(); menu_blur_background->setState(Settings::getInstance()->getBool("MenuBlurBackground")); @@ -507,7 +506,6 @@ void GuiMenu::openUIOptions() s->setInvalidateCachedBackground(); } }); -#endif // Display pillarboxes (and letterboxes) for videos in the gamelists. auto gamelistVideoPillarbox = std::make_shared(); @@ -522,7 +520,6 @@ void GuiMenu::openUIOptions() } }); -#if defined(USE_OPENGL_21) // Render scanlines for videos in the gamelists. auto gamelistVideoScanlines = std::make_shared(); gamelistVideoScanlines->setState(Settings::getInstance()->getBool("GamelistVideoScanlines")); @@ -535,7 +532,6 @@ void GuiMenu::openUIOptions() s->setNeedsSaving(); } }); -#endif // Sort folders on top of the gamelists. auto folders_on_top = std::make_shared(); @@ -751,13 +747,11 @@ void GuiMenu::openUIOptions() ->setOpacity(DISABLED_OPACITY); // Scanlines are theme-controlled for newer themes. -#if defined(USE_OPENGL_21) gamelistVideoScanlines->setEnabled(false); gamelistVideoScanlines->setOpacity(DISABLED_OPACITY); gamelistVideoScanlines->getParent() ->getChild(gamelistVideoScanlines->getChildIndex() - 1) ->setOpacity(DISABLED_OPACITY); -#endif } else { gamelist_view_style->setEnabled(true); @@ -778,13 +772,11 @@ void GuiMenu::openUIOptions() ->getChild(gamelistVideoPillarbox->getChildIndex() - 1) ->setOpacity(1.0f); -#if defined(USE_OPENGL_21) gamelistVideoScanlines->setEnabled(true); gamelistVideoScanlines->setOpacity(1.0f); gamelistVideoScanlines->getParent() ->getChild(gamelistVideoScanlines->getChildIndex() - 1) ->setOpacity(1.0f); -#endif } }; diff --git a/es-app/src/guis/GuiScreensaverOptions.cpp b/es-app/src/guis/GuiScreensaverOptions.cpp index 9ec6cf0e1..905d86c14 100644 --- a/es-app/src/guis/GuiScreensaverOptions.cpp +++ b/es-app/src/guis/GuiScreensaverOptions.cpp @@ -149,7 +149,6 @@ void GuiScreensaverOptions::openSlideshowScreensaverOptions() } }); -#if defined(USE_OPENGL_21) // Render scanlines using a shader. auto screensaver_slideshow_scanlines = std::make_shared(); screensaver_slideshow_scanlines->setState( @@ -163,7 +162,6 @@ void GuiScreensaverOptions::openSlideshowScreensaverOptions() s->setNeedsSaving(); } }); -#endif // Whether to use custom images. auto screensaver_slideshow_custom_images = std::make_shared(); @@ -262,7 +260,6 @@ void GuiScreensaverOptions::openVideoScreensaverOptions() } }); -#if defined(USE_OPENGL_21) // Render scanlines using a shader. auto screensaver_video_scanlines = std::make_shared(); screensaver_video_scanlines->setState( @@ -289,7 +286,6 @@ void GuiScreensaverOptions::openVideoScreensaverOptions() s->setNeedsSaving(); } }); -#endif s->setSize(mSize); mWindow->pushGui(s); diff --git a/es-core/CMakeLists.txt b/es-core/CMakeLists.txt index bf480e77d..b79d626c6 100644 --- a/es-core/CMakeLists.txt +++ b/es-core/CMakeLists.txt @@ -150,8 +150,6 @@ set(CORE_SOURCES # Renderer ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GL21.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GLES10.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GLES20.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Shader_GL21.cpp # Resources diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 2d90a2402..faf5482da 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -20,9 +20,7 @@ #include #include -#if defined(USE_OPENGL_21) #define CLOCK_BACKGROUND_CREATION false -#endif Window::Window() noexcept : mScreensaver {nullptr} @@ -124,12 +122,10 @@ bool Window::init() mDefaultFonts.push_back(Font::get(FONT_SIZE_LARGE)); } - mBackgroundOverlay->setImage(":/graphics/screen_gradient.png"); + mBackgroundOverlay->setImage(":/graphics/frame.png"); mBackgroundOverlay->setResize(Renderer::getScreenWidth(), Renderer::getScreenHeight()); -#if defined(USE_OPENGL_21) mPostprocessedBackground = TextureResource::get(""); -#endif mListScrollFont = Font::get(FONT_SIZE_LARGE); @@ -146,9 +142,7 @@ void Window::deinit() for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); ++it) (*it)->onHide(); -#if defined(USE_OPENGL_21) mPostprocessedBackground.reset(); -#endif InputManager::getInstance().deinit(); ResourceManager::getInstance().unloadAll(); @@ -445,7 +439,6 @@ void Window::render() bottom->render(trans); if (bottom != top || mRenderLaunchScreen) { -#if defined(USE_OPENGL_21) if (!mCachedBackground && mInvalidateCacheTimer == 0) { // Generate a cache texture of the shaded background when opening the menu, which // will remain valid until the menu is closed. This is way faster than having to @@ -483,7 +476,8 @@ void Window::render() // Also dim the background slightly. backgroundParameters.dimming = 0.60f; - Renderer::shaderPostprocessing(Renderer::SHADER_BLUR_HORIZONTAL | + Renderer::shaderPostprocessing(Renderer::SHADER_CORE | + Renderer::SHADER_BLUR_HORIZONTAL | Renderer::SHADER_BLUR_VERTICAL, backgroundParameters, &processedTexture[0]); } @@ -527,7 +521,6 @@ void Window::render() mBackgroundOverlayOpacity = glm::clamp(mBackgroundOverlayOpacity + 0.118f, 0.0f, 1.0f); } -#endif // USE_OPENGL_21 mBackgroundOverlay->render(trans); diff --git a/es-core/src/Window.h b/es-core/src/Window.h index 82ec2263c..beacd950f 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -172,10 +172,7 @@ private: GuiInfoPopup* mInfoPopup; std::queue> mInfoPopupQueue; - -#if defined(USE_OPENGL_21) std::shared_ptr mPostprocessedBackground; -#endif std::string mListScrollText; std::shared_ptr mListScrollFont; diff --git a/es-core/src/components/GIFAnimComponent.cpp b/es-core/src/components/GIFAnimComponent.cpp index 540fc9412..42fcfa85d 100644 --- a/es-core/src/components/GIFAnimComponent.cpp +++ b/es-core/src/components/GIFAnimComponent.cpp @@ -44,11 +44,6 @@ GIFAnimComponent::GIFAnimComponent() { // Get an empty texture for rendering the animation. mTexture = TextureResource::get(""); -#if defined(USE_OPENGLES_10) || defined(USE_OPENGLES_20) - // This is not really supported by the OpenGL ES standard so hopefully it works - // with all drivers and on all operating systems. - mTexture->setFormat(Renderer::Texture::BGRA); -#endif mAnimIO.read_proc = readProc; mAnimIO.write_proc = writeProc; diff --git a/es-core/src/components/LottieAnimComponent.cpp b/es-core/src/components/LottieAnimComponent.cpp index 630367aab..506d7639f 100644 --- a/es-core/src/components/LottieAnimComponent.cpp +++ b/es-core/src/components/LottieAnimComponent.cpp @@ -39,11 +39,6 @@ LottieAnimComponent::LottieAnimComponent() { // Get an empty texture for rendering the animation. mTexture = TextureResource::get(""); -#if defined(USE_OPENGLES_10) || defined(USE_OPENGLES_20) - // This is not really supported by the OpenGL ES standard so hopefully it works - // with all drivers and on all operating systems. - mTexture->setFormat(Renderer::Texture::BGRA); -#endif // Keep per-file cache size within 0 to 1024 MiB. mMaxCacheSize = static_cast( diff --git a/es-core/src/renderers/Renderer.h b/es-core/src/renderers/Renderer.h index a08e216f9..2a72184d5 100644 --- a/es-core/src/renderers/Renderer.h +++ b/es-core/src/renderers/Renderer.h @@ -47,11 +47,15 @@ namespace Renderer }; static std::vector sShaderProgramVector; - static GLuint shaderFBO1; - static GLuint shaderFBO2; - // This is simply to get rid of a GCC false positive -Wunused-variable compiler warning. + static GLuint shaderFBO1 {0}; + static GLuint shaderFBO2 {0}; + static GLuint vertexBuffer1 {0}; + static GLuint vertexBuffer2 {0}; + // This is simply to get rid of some GCC false positive -Wunused-variable compiler warnings. static GLuint shaderFBODummy1 {shaderFBO1}; static GLuint shaderFBODummy2 {shaderFBO2}; + static GLuint vertexBufferDummy1 {vertexBuffer1}; + static GLuint vertexBufferDummy2 {vertexBuffer2}; static constexpr glm::mat4 getIdentity() { return glm::mat4 {1.0f}; } static inline glm::mat4 mTrans {getIdentity()}; @@ -64,11 +68,11 @@ namespace Renderer const GLenum errorCode = glGetError(); if (errorCode != GL_NO_ERROR) { -#if defined(USE_OPENGL_21) - LOG(LogError) << "OpenGL error: " << _funcName << " failed with error code: 0x" +#if defined(USE_OPENGLES) + LOG(LogError) << "OpenGL ES error: " << _funcName << " failed with error code: 0x" << std::hex << errorCode; #else - LOG(LogError) << "OpenGL ES error: " << _funcName << " failed with error code: 0x" + LOG(LogError) << "OpenGL error: " << _funcName << " failed with error code: 0x" << std::hex << errorCode; #endif } @@ -98,7 +102,7 @@ namespace Renderer enum Type { RGBA, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0). BGRA, - ALPHA + RED }; } @@ -124,6 +128,7 @@ namespace Renderer float saturation; float dimming; bool convertBGRAToRGBA; + bool font; bool postProcessing; unsigned int shaders; @@ -132,6 +137,7 @@ namespace Renderer , saturation {1.0f} , dimming {1.0f} , convertBGRAToRGBA {false} + , font {false} , postProcessing {false} , shaders {0} { @@ -144,6 +150,7 @@ namespace Renderer , saturation {1.0f} , dimming {1.0f} , convertBGRAToRGBA {false} + , font {false} , postProcessing {false} , shaders {0} { diff --git a/es-core/src/renderers/Renderer_GL21.cpp b/es-core/src/renderers/Renderer_GL21.cpp index 5900f263c..edeb845d4 100644 --- a/es-core/src/renderers/Renderer_GL21.cpp +++ b/es-core/src/renderers/Renderer_GL21.cpp @@ -3,11 +3,9 @@ // EmulationStation Desktop Edition // Renderer_GL21.cpp // -// OpenGL 2.1 rendering functions. +// OpenGL / OpenGL ES renderer. // -#if defined(USE_OPENGL_21) - #include "Settings.h" #include "Shader_GL21.h" #include "renderers/Renderer.h" @@ -47,8 +45,12 @@ namespace Renderer // clang-format off switch (type) { case Texture::RGBA: { return GL_RGBA; } break; +#if defined(USE_OPENGLES) + case Texture::BGRA: { return GL_BGRA_EXT; } break; +#else case Texture::BGRA: { return GL_BGRA; } break; - case Texture::ALPHA: { return GL_LUMINANCE_ALPHA; } break; +#endif + case Texture::RED: { return GL_RED; } break; default: { return GL_ZERO; } } // clang-format on @@ -56,15 +58,16 @@ namespace Renderer void setupWindow() { -#if defined(__APPLE__) - // This is required on macOS, as the operating system will otherwise insist on using - // a newer OpenGL version which completely breaks the application. - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); + +#if defined(USE_OPENGLES) + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #else SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); #endif - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); @@ -75,7 +78,6 @@ namespace Renderer bool createContext() { - bool missingExtension = false; sdlContext = SDL_GL_CreateContext(getSDLWindow()); if (!sdlContext) { @@ -103,46 +105,37 @@ namespace Renderer LOG(LogInfo) << "GL renderer: " << renderer; LOG(LogInfo) << "GL version: " << version; #if defined(_WIN64) - LOG(LogInfo) << "EmulationStation renderer: OpenGL 2.1 with GLEW"; + LOG(LogInfo) << "EmulationStation renderer: OpenGL 3.3 with GLEW"; #else - LOG(LogInfo) << "EmulationStation renderer: OpenGL 2.1"; +#if defined(USE_OPENGLES) + LOG(LogInfo) << "EmulationStation renderer: OpenGL ES 3.0"; +#else + LOG(LogInfo) << "EmulationStation renderer: OpenGL 3.3"; #endif - LOG(LogInfo) << "Checking available OpenGL extensions..."; - std::string glExts = glGetString(GL_EXTENSIONS) ? - reinterpret_cast(glGetString(GL_EXTENSIONS)) : - ""; - if (extensions.find("GL_ARB_texture_non_power_of_two") == std::string::npos) { - LOG(LogError) << "GL_ARB_texture_non_power_of_two: MISSING"; - missingExtension = true; - } - else { - LOG(LogInfo) << "GL_ARB_texture_non_power_of_two: OK"; - } - if (extensions.find("GL_ARB_vertex_shader") == std::string::npos) { - LOG(LogError) << "GL_ARB_vertex_shader: MISSING"; - missingExtension = true; - } - else { - LOG(LogInfo) << "GL_ARB_vertex_shader: OK"; - } - if (extensions.find("GL_ARB_fragment_shader") == std::string::npos) { - LOG(LogError) << "GL_ARB_fragment_shader: MISSING"; - missingExtension = true; - } - else { - LOG(LogInfo) << "GL_ARB_fragment_shader: OK"; - } - if (extensions.find("GL_EXT_framebuffer_blit") == std::string::npos) { - LOG(LogError) << "GL_EXT_framebuffer_blit: MISSING"; - missingExtension = true; - } - else { - LOG(LogInfo) << "GL_EXT_framebuffer_blit: OK"; - } - if (missingExtension) { - LOG(LogError) << "Required OpenGL extensions missing."; - return false; - } +#endif + +#if !defined(USE_OPENGLES) + // TODO: Fix the issue that causes the first glClearColor function call to fail. + GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); +#endif + + GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); + GL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0)); + GL_CHECK_ERROR(glEnable(GL_BLEND)); + GL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, 1)); + GL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); + + // These are used for the shader post processing. + GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO1)); + GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO2)); + + GL_CHECK_ERROR(glGenBuffers(1, &vertexBuffer1)); + GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer1)); + GL_CHECK_ERROR(glGenVertexArrays(1, &vertexBuffer2)); + GL_CHECK_ERROR(glBindVertexArray(vertexBuffer2)); + + uint8_t data[4] = {255, 255, 255, 255}; + whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data); postProcTexture1 = createTexture(Texture::RGBA, false, false, false, static_cast(getScreenWidth()), @@ -152,21 +145,16 @@ namespace Renderer static_cast(getScreenWidth()), static_cast(getScreenHeight()), nullptr); - uint8_t data[4] = {255, 255, 255, 255}; - whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data); + // Attach textures to the shader framebuffers. + GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shaderFBO1)); + GL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + postProcTexture1, 0)); - GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); - GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D)); - GL_CHECK_ERROR(glEnable(GL_BLEND)); - GL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, 1)); - GL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); - GL_CHECK_ERROR(glEnableClientState(GL_VERTEX_ARRAY)); - GL_CHECK_ERROR(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - GL_CHECK_ERROR(glEnableClientState(GL_COLOR_ARRAY)); + GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shaderFBO2)); + GL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + postProcTexture2, 0)); - // These framebuffers are used for the shader post processing. - GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO1)); - GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO2)); + GL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0)); return true; } @@ -209,24 +197,8 @@ namespace Renderer linearMagnify ? static_cast(GL_LINEAR) : static_cast(GL_NEAREST))); - if (textureType == GL_LUMINANCE_ALPHA) { - uint8_t* a_data {reinterpret_cast(data)}; - uint8_t* la_data {new uint8_t[width * height * 2]}; - for (uint32_t i = 0; i < (width * height); ++i) { - la_data[(i * 2) + 0] = 255; - la_data[(i * 2) + 1] = a_data ? a_data[i] : 255; - } - - GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, - textureType, GL_UNSIGNED_BYTE, la_data)); - - delete[] la_data; - } - else { - GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, - textureType, GL_UNSIGNED_BYTE, data)); - } - + GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType, + GL_UNSIGNED_BYTE, data)); return texture; } @@ -246,26 +218,8 @@ namespace Renderer const GLenum textureType = convertTextureType(type); GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); - - // Regular GL_ALPHA textures are black + alpha when used in shaders, so create a - // GL_LUMINANCE_ALPHA texture instead so it's white + alpha. - if (textureType == GL_LUMINANCE_ALPHA) { - uint8_t* a_data {reinterpret_cast(data)}; - uint8_t* la_data {new uint8_t[width * height * 2]}; - for (uint32_t i = 0; i < (width * height); ++i) { - la_data[(i * 2) + 0] = 255; - la_data[(i * 2) + 1] = a_data ? a_data[i] : 255; - } - - GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, textureType, - GL_UNSIGNED_BYTE, la_data)); - - delete[] la_data; - } - else { - GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, textureType, - GL_UNSIGNED_BYTE, data)); - } + GL_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, textureType, + GL_UNSIGNED_BYTE, data)); GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); } @@ -286,51 +240,57 @@ namespace Renderer const float width {vertices[3].position[0]}; const float height {vertices[3].position[1]}; - GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].position)); - GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].texture)); - GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].color)); - GL_CHECK_ERROR( glBlendFunc(convertBlendFactor(srcBlendFactor), convertBlendFactor(dstBlendFactor))); if (vertices->shaders == 0 || vertices->shaders & SHADER_CORE) { - Shader* runShader = getShaderProgram(SHADER_CORE); - if (runShader) { - runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(mTrans); - runShader->setOpacity(vertices->opacity); - runShader->setSaturation(vertices->saturation); - runShader->setDimming(vertices->dimming); - runShader->setBGRAToRGBA(vertices->convertBGRAToRGBA); - runShader->setPostProcessing(vertices->postProcessing); + Shader* shader {getShaderProgram(SHADER_CORE)}; + if (shader) { + shader->activateShaders(); + shader->setModelViewProjectionMatrix(mTrans); + shader->setAttribPointers(); + GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, + GL_DYNAMIC_DRAW)); + shader->setOpacity(vertices->opacity); + shader->setSaturation(vertices->saturation); + shader->setDimming(vertices->dimming); + shader->setBGRAToRGBA(vertices->convertBGRAToRGBA); + shader->setFont(vertices->font); + shader->setPostProcessing(vertices->postProcessing); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); - runShader->deactivateShaders(); + shader->deactivateShaders(); } } else if (vertices->shaders & SHADER_BLUR_HORIZONTAL) { - Shader* runShader = getShaderProgram(SHADER_BLUR_HORIZONTAL); - if (runShader) { - runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(mTrans); - runShader->setTextureSize({width, height}); + Shader* shader {getShaderProgram(SHADER_BLUR_HORIZONTAL)}; + if (shader) { + shader->activateShaders(); + shader->setModelViewProjectionMatrix(mTrans); + shader->setAttribPointers(); + GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, + GL_DYNAMIC_DRAW)); + shader->setTextureSize({width, height}); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); - runShader->deactivateShaders(); + shader->deactivateShaders(); } return; } else if (vertices->shaders & SHADER_BLUR_VERTICAL) { - Shader* runShader = getShaderProgram(SHADER_BLUR_VERTICAL); - if (runShader) { - runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(mTrans); - runShader->setTextureSize({width, height}); + Shader* shader {getShaderProgram(SHADER_BLUR_VERTICAL)}; + if (shader) { + shader->activateShaders(); + shader->setModelViewProjectionMatrix(mTrans); + shader->setAttribPointers(); + GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, + GL_DYNAMIC_DRAW)); + shader->setTextureSize({width, height}); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); - runShader->deactivateShaders(); + shader->deactivateShaders(); } return; } else if (vertices->shaders & SHADER_SCANLINES) { - Shader* runShader {getShaderProgram(SHADER_SCANLINES)}; + Shader* shader {getShaderProgram(SHADER_SCANLINES)}; float shaderWidth {width * 1.2f}; // Scale the scanlines relative to screen resolution. float screenHeightModifier {getScreenHeightModifier()}; @@ -350,13 +310,16 @@ namespace Renderer float modifier {1.41f + relativeAdjustment / 7.0f - (0.14f * screenHeightModifier)}; shaderHeight = height * modifier; } - if (runShader) { - runShader->activateShaders(); - runShader->setModelViewProjectionMatrix(mTrans); - runShader->setOpacity(vertices->opacity); - runShader->setTextureSize({shaderWidth, shaderHeight}); + if (shader) { + shader->activateShaders(); + shader->setModelViewProjectionMatrix(mTrans); + shader->setAttribPointers(); + GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, + GL_DYNAMIC_DRAW)); + shader->setOpacity(vertices->opacity); + shader->setTextureSize({shaderWidth, shaderHeight}); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices)); - runShader->deactivateShaders(); + shader->deactivateShaders(); } } } @@ -446,8 +409,8 @@ namespace Renderer vertices->dimming = parameters.dimming; vertices->postProcessing = true; - shaderList.emplace_back(Renderer::SHADER_CORE); - + if (shaders & Renderer::SHADER_CORE) + shaderList.push_back(Renderer::SHADER_CORE); if (shaders & Renderer::SHADER_BLUR_HORIZONTAL) shaderList.push_back(Renderer::SHADER_BLUR_HORIZONTAL); if (shaders & Renderer::SHADER_BLUR_VERTICAL) @@ -458,16 +421,8 @@ namespace Renderer setMatrix(getIdentity()); bindTexture(postProcTexture1); - GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shaderFBO2)); - GL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - postProcTexture2, 0)); - GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shaderFBO1)); - // Attach texture to the shader framebuffer. - GL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - postProcTexture1, 0)); - // Blit the screen contents to postProcTexture. GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST)); @@ -545,5 +500,3 @@ namespace Renderer } } // namespace Renderer - -#endif // USE_OPENGL_21 diff --git a/es-core/src/renderers/Shader_GL21.cpp b/es-core/src/renderers/Shader_GL21.cpp index e3b8d1517..9701e08c0 100644 --- a/es-core/src/renderers/Shader_GL21.cpp +++ b/es-core/src/renderers/Shader_GL21.cpp @@ -6,8 +6,6 @@ // OpenGL 2.1 GLSL shader functions. // -#if defined(USE_OPENGL_21) - #include "Shader_GL21.h" #include "Log.h" @@ -19,11 +17,16 @@ namespace Renderer Renderer::Shader::Shader() : mProgramID {0} , shaderMVPMatrix {0} - , shaderTextureSize {0} + , shaderPosition {0} , shaderTextureCoord {0} + , shaderColor {0} + , shaderTextureSize {0} , shaderOpacity {0} , shaderSaturation {0} , shaderDimming {0} + , shaderBGRAToRGBA {0} + , shaderFont {0} + , shaderPostProcessing {0} { } @@ -42,9 +45,12 @@ namespace Renderer const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)}; shaderCode.assign(reinterpret_cast(shaderData.ptr.get()), shaderData.length); - // Define the GLSL version (version 120 = OpenGL 2.1). - preprocessorDefines = "#version 120\n"; - + // Define the GLSL version. +#if defined(USE_OPENGLES) + preprocessorDefines = "#version 300 es\n"; +#else + preprocessorDefines = "#version 330\n"; +#endif // Define the preprocessor constants that will let the shader compiler know whether // the VERTEX or FRAGMENT portion of the code should be used. if (shaderType == GL_VERTEX_SHADER) @@ -76,9 +82,12 @@ namespace Renderer if (shaderCompiled != GL_TRUE) { LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " (" << std::get<0>(*it) << ")."; - printShaderInfoLog(currentShader, std::get<2>(*it)); + printShaderInfoLog(currentShader, std::get<2>(*it), true); return false; } + else { + printShaderInfoLog(currentShader, std::get<2>(*it), false); + } GL_CHECK_ERROR(glAttachShader(mProgramID, currentShader)); } @@ -93,6 +102,16 @@ namespace Renderer } getVariableLocations(mProgramID); + + if (shaderPosition != -1) + GL_CHECK_ERROR(glEnableVertexAttribArray(shaderPosition)); + + if (shaderTextureCoord != -1) + GL_CHECK_ERROR(glEnableVertexAttribArray(shaderTextureCoord)); + + if (shaderColor != -1) + GL_CHECK_ERROR(glEnableVertexAttribArray(shaderColor)); + return true; } @@ -105,12 +124,15 @@ namespace Renderer { // Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders. shaderMVPMatrix = glGetUniformLocation(mProgramID, "MVPMatrix"); - shaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize"); + shaderPosition = glGetAttribLocation(mProgramID, "positionAttrib"); shaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord"); + shaderColor = glGetAttribLocation(mProgramID, "colorAttrib"); + shaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize"); shaderOpacity = glGetUniformLocation(mProgramID, "opacity"); shaderSaturation = glGetUniformLocation(mProgramID, "saturation"); shaderDimming = glGetUniformLocation(mProgramID, "dimming"); shaderBGRAToRGBA = glGetUniformLocation(mProgramID, "BGRAToRGBA"); + shaderFont = glGetUniformLocation(mProgramID, "font"); shaderPostProcessing = glGetUniformLocation(mProgramID, "postProcessing"); } @@ -121,48 +143,62 @@ namespace Renderer reinterpret_cast(&mvpMatrix))); } - void Renderer::Shader::setTextureSize(std::array shaderVec2) + void Renderer::Shader::setAttribPointers() { - if (shaderTextureSize != GL_INVALID_VALUE && shaderTextureSize != GL_INVALID_OPERATION) - GL_CHECK_ERROR(glUniform2f(shaderTextureSize, shaderVec2[0], shaderVec2[1])); + if (shaderPosition != -1) + GL_CHECK_ERROR( + glVertexAttribPointer(shaderPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offsetof(Vertex, position)))); + if (shaderTextureCoord != -1) + GL_CHECK_ERROR( + glVertexAttribPointer(shaderTextureCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), + reinterpret_cast(offsetof(Vertex, texture)))); + + if (shaderColor != -1) + GL_CHECK_ERROR( + glVertexAttribPointer(shaderColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), + reinterpret_cast(offsetof(Vertex, color)))); } - void Renderer::Shader::setTextureCoordinates(std::array shaderVec4) + void Renderer::Shader::setTextureSize(std::array shaderVec2) { - if (shaderTextureCoord != GL_INVALID_OPERATION) { - glVertexAttrib4f(shaderTextureCoord, shaderVec4[0], shaderVec4[1], shaderVec4[2], - shaderVec4[3]); - } + if (shaderTextureSize != -1) + GL_CHECK_ERROR(glUniform2f(shaderTextureSize, shaderVec2[0], shaderVec2[1])); } void Renderer::Shader::setOpacity(GLfloat opacity) { - if (shaderOpacity != GL_INVALID_VALUE && shaderOpacity != GL_INVALID_OPERATION) + if (shaderOpacity != -1) GL_CHECK_ERROR(glUniform1f(shaderOpacity, opacity)); } void Renderer::Shader::setSaturation(GLfloat saturation) { - if (shaderSaturation != GL_INVALID_VALUE && shaderSaturation != GL_INVALID_OPERATION) + if (shaderSaturation != -1) GL_CHECK_ERROR(glUniform1f(shaderSaturation, saturation)); } void Renderer::Shader::setDimming(GLfloat dimming) { - if (shaderDimming != GL_INVALID_VALUE && shaderDimming != GL_INVALID_OPERATION) + if (shaderDimming != -1) GL_CHECK_ERROR(glUniform1f(shaderDimming, dimming)); } void Renderer::Shader::setBGRAToRGBA(GLboolean BGRAToRGBA) { - if (shaderBGRAToRGBA != GL_INVALID_VALUE && shaderBGRAToRGBA != GL_INVALID_OPERATION) + if (shaderBGRAToRGBA != -1) GL_CHECK_ERROR(glUniform1i(shaderBGRAToRGBA, BGRAToRGBA ? 1 : 0)); } + void Renderer::Shader::setFont(GLboolean font) + { + if (shaderFont != -1) + GL_CHECK_ERROR(glUniform1i(shaderFont, font ? 1 : 0)); + } + void Renderer::Shader::setPostProcessing(GLboolean postProcessing) { - if (shaderPostProcessing != GL_INVALID_VALUE && - shaderPostProcessing != GL_INVALID_OPERATION) + if (shaderPostProcessing != -1) GL_CHECK_ERROR(glUniform1i(shaderPostProcessing, postProcessing ? 1 : 0)); } @@ -199,7 +235,7 @@ namespace Renderer } } - void Renderer::Shader::printShaderInfoLog(GLuint shaderID, GLenum shaderType) + void Renderer::Shader::printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error) { if (glIsShader(shaderID)) { int logLength; @@ -208,10 +244,14 @@ namespace Renderer glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength); std::vector infoLog(maxLength); + if (infoLog.size() == 0) + return; + glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front()); if (logLength > 0) { - LOG(LogDebug) << "Shader_GL21::printShaderInfoLog(): Error in " + LOG(LogDebug) << "Shader_GL21::printShaderInfoLog(): " + << (error ? "Error" : "Warning") << " in " << (shaderType == GL_VERTEX_SHADER ? "VERTEX section:\n" : "FRAGMENT section:\n") << std::string(infoLog.begin(), infoLog.end()); @@ -223,5 +263,3 @@ namespace Renderer } } // namespace Renderer - -#endif // USE_OPENGL_21 diff --git a/es-core/src/renderers/Shader_GL21.h b/es-core/src/renderers/Shader_GL21.h index 8131715bf..df26db76e 100644 --- a/es-core/src/renderers/Shader_GL21.h +++ b/es-core/src/renderers/Shader_GL21.h @@ -18,11 +18,11 @@ #endif #include -// Hack until shader support has been added for OpenGL ES. -#if defined(USE_OPENGL_21) -#include -#else +#if defined(USE_OPENGLES) +#include #include +#else +#include #endif #include #include @@ -47,12 +47,13 @@ namespace Renderer // One-way communication with the compiled shaders. void setModelViewProjectionMatrix(glm::mat4 mvpMatrix); + void setAttribPointers(); void setTextureSize(std::array shaderVec2); - void setTextureCoordinates(std::array shaderVec4); void setOpacity(GLfloat opacity); void setSaturation(GLfloat saturation); void setDimming(GLfloat dimming); void setBGRAToRGBA(GLboolean BGRAToRGBA); + void setFont(GLboolean font); void setPostProcessing(GLboolean postProcessing); // Sets the shader program to use the loaded shaders. void activateShaders(); @@ -62,7 +63,7 @@ namespace Renderer GLuint getProgramID() { return mProgramID; } // Only used for error logging if the shaders fail to compile or link. void printProgramInfoLog(GLuint programID); - void printShaderInfoLog(GLuint shaderID, GLenum shaderType); + void printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error); private: GLuint mProgramID; @@ -70,12 +71,15 @@ namespace Renderer // Variables used for communication with the compiled shaders. GLint shaderMVPMatrix; - GLint shaderTextureSize; + GLint shaderPosition; GLint shaderTextureCoord; + GLint shaderColor; + GLint shaderTextureSize; GLint shaderOpacity; GLint shaderSaturation; GLint shaderDimming; GLint shaderBGRAToRGBA; + GLint shaderFont; GLint shaderPostProcessing; }; diff --git a/es-core/src/resources/Font.cpp b/es-core/src/resources/Font.cpp index afdec8366..47ef377ec 100644 --- a/es-core/src/resources/Font.cpp +++ b/es-core/src/resources/Font.cpp @@ -199,8 +199,8 @@ bool Font::FontTexture::findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out void Font::FontTexture::initTexture() { assert(textureId == 0); - textureId = Renderer::createTexture(Renderer::Texture::ALPHA, false, false, false, - textureSize.x, textureSize.y, nullptr); + textureId = Renderer::createTexture(Renderer::Texture::RED, false, false, false, textureSize.x, + textureSize.y, nullptr); } void Font::FontTexture::deinitTexture() @@ -346,8 +346,8 @@ Font::Glyph* Font::getGlyph(unsigned int id) static_cast(g->metrics.horiBearingY) / 64.0f}; // Upload glyph bitmap to texture. - Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x, cursor.y, - glyphSize.x, glyphSize.y, g->bitmap.buffer); + Renderer::updateTexture(tex->textureId, Renderer::Texture::RED, cursor.x, cursor.y, glyphSize.x, + glyphSize.y, g->bitmap.buffer); // Update max glyph height. if (glyphSize.y > mMaxGlyphHeight) @@ -380,7 +380,7 @@ void Font::rebuildTextures() static_cast(it->second.texSize.y * tex->textureSize.y)}; // Upload to texture. - Renderer::updateTexture(tex->textureId, Renderer::Texture::ALPHA, cursor.x, cursor.y, + Renderer::updateTexture(tex->textureId, Renderer::Texture::RED, cursor.x, cursor.y, glyphSize.x, glyphSize.y, glyphSlot->bitmap.buffer); } } @@ -392,10 +392,11 @@ void Font::renderTextCache(TextCache* cache) return; } - for (auto it = cache->vertexLists.cbegin(); it != cache->vertexLists.cend(); ++it) { + for (auto it = cache->vertexLists.begin(); it != cache->vertexLists.end(); ++it) { assert(*it->textureIdPtr != 0); auto vertexList = *it; + it->verts[0].font = true; Renderer::bindTexture(*it->textureIdPtr); Renderer::drawTriangleStrips(&it->verts[0], diff --git a/resources/shaders/glsl/blur_horizontal.glsl b/resources/shaders/glsl/blur_horizontal.glsl index 87e8e835c..4a0b39d27 100644 --- a/resources/shaders/glsl/blur_horizontal.glsl +++ b/resources/shaders/glsl/blur_horizontal.glsl @@ -18,7 +18,6 @@ #else #define COMPAT_VARYING varying #define COMPAT_ATTRIBUTE attribute -#define COMPAT_TEXTURE texture2D #endif #ifdef GL_ES @@ -27,39 +26,19 @@ #define COMPAT_PRECISION #endif -COMPAT_ATTRIBUTE vec4 VertexCoord; -COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec2 positionAttrib; COMPAT_ATTRIBUTE vec4 TexCoord; -COMPAT_VARYING vec4 COL0; COMPAT_VARYING vec4 TEX0; - -vec4 _oPosition1; uniform mat4 MVPMatrix; -uniform COMPAT_PRECISION int FrameDirection; -uniform COMPAT_PRECISION int FrameCount; -uniform COMPAT_PRECISION vec2 OutputSize; -uniform COMPAT_PRECISION vec2 TextureSize; -uniform COMPAT_PRECISION vec2 InputSize; void main() { - gl_Position = MVPMatrix * gl_Vertex; - COL0 = COLOR; - TEX0.xy = gl_MultiTexCoord0.xy; + gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0); + TEX0.xy = TexCoord.xy; } #elif defined(FRAGMENT) -#if __VERSION__ >= 130 -#define COMPAT_VARYING in -#define COMPAT_TEXTURE texture -out vec4 FragColor; -#else -#define COMPAT_VARYING varying -#define FragColor gl_FragColor -#define COMPAT_TEXTURE texture2D -#endif - #ifdef GL_ES #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; @@ -71,20 +50,25 @@ precision mediump float; #define COMPAT_PRECISION #endif -uniform COMPAT_PRECISION int FrameDirection; -uniform COMPAT_PRECISION int FrameCount; -uniform COMPAT_PRECISION vec2 OutputSize; +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out COMPAT_PRECISION vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + uniform COMPAT_PRECISION vec2 TextureSize; -uniform COMPAT_PRECISION vec2 InputSize; uniform sampler2D Texture; -COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING COMPAT_PRECISION vec4 TEX0; // Compatibility #defines #define Source Texture #define vTexCoord TEX0.xy #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. -#define outsize vec4(OutputSize, 1.0 / OutputSize) void main() { @@ -129,8 +113,9 @@ void main() sampleWeights5; #else - float sampleOffsets[5] = {0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130}; - float sampleWeights[5] = {0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196}; + float sampleOffsets[5] = float[5](0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130); + float sampleWeights[5] = + float[5](0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196); vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0]; for (int i = 1; i < 5; i++) { diff --git a/resources/shaders/glsl/blur_vertical.glsl b/resources/shaders/glsl/blur_vertical.glsl index 4040a6c4c..e0ea30004 100644 --- a/resources/shaders/glsl/blur_vertical.glsl +++ b/resources/shaders/glsl/blur_vertical.glsl @@ -18,7 +18,6 @@ #else #define COMPAT_VARYING varying #define COMPAT_ATTRIBUTE attribute -#define COMPAT_TEXTURE texture2D #endif #ifdef GL_ES @@ -27,39 +26,19 @@ #define COMPAT_PRECISION #endif -COMPAT_ATTRIBUTE vec4 VertexCoord; -COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec2 positionAttrib; COMPAT_ATTRIBUTE vec4 TexCoord; -COMPAT_VARYING vec4 COL0; COMPAT_VARYING vec4 TEX0; - -vec4 _oPosition1; uniform mat4 MVPMatrix; -uniform COMPAT_PRECISION int FrameDirection; -uniform COMPAT_PRECISION int FrameCount; -uniform COMPAT_PRECISION vec2 OutputSize; -uniform COMPAT_PRECISION vec2 TextureSize; -uniform COMPAT_PRECISION vec2 InputSize; void main() { - gl_Position = MVPMatrix * gl_Vertex; - COL0 = COLOR; - TEX0.xy = gl_MultiTexCoord0.xy; + gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0); + TEX0.xy = TexCoord.xy; } #elif defined(FRAGMENT) -#if __VERSION__ >= 130 -#define COMPAT_VARYING in -#define COMPAT_TEXTURE texture -out vec4 FragColor; -#else -#define COMPAT_VARYING varying -#define FragColor gl_FragColor -#define COMPAT_TEXTURE texture2D -#endif - #ifdef GL_ES #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; @@ -71,20 +50,25 @@ precision mediump float; #define COMPAT_PRECISION #endif -uniform COMPAT_PRECISION int FrameDirection; -uniform COMPAT_PRECISION int FrameCount; -uniform COMPAT_PRECISION vec2 OutputSize; +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out COMPAT_PRECISION vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + uniform COMPAT_PRECISION vec2 TextureSize; -uniform COMPAT_PRECISION vec2 InputSize; uniform sampler2D Texture; -COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING COMPAT_PRECISION vec4 TEX0; // compatibility #defines #define Source Texture #define vTexCoord TEX0.xy #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. -#define outsize vec4(OutputSize, 1.0 / OutputSize) void main() { @@ -129,8 +113,9 @@ void main() sampleWeights5; #else - float sampleOffsets[5] = {0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130}; - float sampleWeights[5] = {0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196}; + float sampleOffsets[5] = float[5](0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130); + float sampleWeights[5] = + float[5](0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196); vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0]; for (int i = 1; i < 5; i++) { diff --git a/resources/shaders/glsl/core.glsl b/resources/shaders/glsl/core.glsl index e8377bbcf..6ed85d929 100644 --- a/resources/shaders/glsl/core.glsl +++ b/resources/shaders/glsl/core.glsl @@ -12,71 +12,98 @@ #if __VERSION__ >= 130 #define COMPAT_VARYING out +#define COMPAT_ATTRIBUTE in #else #define COMPAT_VARYING varying +#define COMPAT_ATTRIBUTE attribute +#endif + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION #endif uniform mat4 MVPMatrix; +COMPAT_ATTRIBUTE vec2 positionAttrib; +COMPAT_ATTRIBUTE vec2 TexCoord; +COMPAT_ATTRIBUTE vec4 colorAttrib; COMPAT_VARYING vec4 color; COMPAT_VARYING vec2 texCoord; void main(void) { - texCoord = gl_MultiTexCoord0.xy; - color.rgba = gl_Color.abgr; - gl_Position = MVPMatrix * gl_Vertex; + color.rgba = colorAttrib.abgr; + texCoord = TexCoord; + gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0); } #elif defined(FRAGMENT) // Fragment section of code: +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + #if __VERSION__ >= 130 -#define COMPAT_VARYING out +#define COMPAT_VARYING in #define COMPAT_TEXTURE texture +out COMPAT_PRECISION vec4 FragColor; #else #define COMPAT_VARYING varying #define COMPAT_TEXTURE texture2D +#define FragColor gl_FragColor #endif -COMPAT_VARYING vec4 color; -COMPAT_VARYING vec2 texCoord; -uniform float opacity = 1.0f; -uniform float saturation = 1.0f; -uniform float dimming = 1.0f; -uniform int BGRAToRGBA = 0; -uniform int postProcessing = 0; +COMPAT_VARYING COMPAT_PRECISION vec4 color; +COMPAT_VARYING COMPAT_PRECISION vec4 color2; +COMPAT_VARYING COMPAT_PRECISION vec2 texCoord; +uniform COMPAT_PRECISION float opacity; +uniform COMPAT_PRECISION float saturation; +uniform COMPAT_PRECISION float dimming; +uniform int BGRAToRGBA; +uniform int font; +uniform int postProcessing; uniform sampler2D myTexture; void main() { - vec4 color = COMPAT_TEXTURE(myTexture, texCoord) * color; + COMPAT_PRECISION vec4 sampledColor = COMPAT_TEXTURE(myTexture, texCoord); + + // For fonts the alpha information is stored in the red channel. + if (font == 1) + sampledColor = vec4(1.0f, 1.0f, 1.0f, sampledColor.r); + + sampledColor *= color; // When post-processing we drop the alpha channel to avoid strange issues // with some graphics drivers. if (postProcessing == 1) - color.a = 1.0f; + sampledColor.a = 1.0f; // Opacity. if (opacity != 1.0f) - color.a = color.a * opacity; + sampledColor.a = sampledColor.a * opacity; // Saturation. if (saturation != 1.0f) { - vec3 grayscale = vec3(dot(color.rgb, vec3(0.34f, 0.55f, 0.11f))); - vec3 blendedColor = mix(grayscale, color.rgb, saturation); - color = vec4(blendedColor, color.a); + COMPAT_PRECISION vec3 grayscale = vec3(dot(sampledColor.rgb, vec3(0.34f, 0.55f, 0.11f))); + COMPAT_PRECISION vec3 blendedColor = mix(grayscale, sampledColor.rgb, saturation); + sampledColor = vec4(blendedColor, sampledColor.a); } // Dimming if (dimming != 1.0f) { - vec4 dimColor = vec4(dimming, dimming, dimming, 1.0f); - color *= dimColor; + COMPAT_PRECISION vec4 dimColor = vec4(dimming, dimming, dimming, 1.0f); + sampledColor *= dimColor; } // BGRA to RGBA conversion. if (BGRAToRGBA == 1) - color = vec4(color.bgr, color.a); + sampledColor = vec4(sampledColor.bgr, sampledColor.a); - gl_FragColor = color; + FragColor = sampledColor; } #endif diff --git a/resources/shaders/glsl/scanlines.glsl b/resources/shaders/glsl/scanlines.glsl index 91d56ea0f..371e0a6f0 100644 --- a/resources/shaders/glsl/scanlines.glsl +++ b/resources/shaders/glsl/scanlines.glsl @@ -29,7 +29,6 @@ #else #define COMPAT_VARYING varying #define COMPAT_ATTRIBUTE attribute -#define COMPAT_TEXTURE texture2D #endif #ifdef GL_ES @@ -38,45 +37,27 @@ #define COMPAT_PRECISION #endif -COMPAT_ATTRIBUTE vec4 VertexCoord; -COMPAT_ATTRIBUTE vec4 COLOR; COMPAT_ATTRIBUTE vec4 TexCoord; -COMPAT_VARYING vec4 COL0; COMPAT_VARYING vec4 TEX0; COMPAT_VARYING vec2 onex; COMPAT_VARYING vec2 oney; -vec4 _oPosition1; uniform mat4 MVPMatrix; -uniform COMPAT_PRECISION int FrameDirection; -uniform COMPAT_PRECISION int FrameCount; -uniform COMPAT_PRECISION vec2 OutputSize; +COMPAT_ATTRIBUTE vec2 positionAttrib; uniform COMPAT_PRECISION vec2 TextureSize; -uniform COMPAT_PRECISION vec2 InputSize; #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. void main() { - gl_Position = MVPMatrix * gl_Vertex; - COL0 = COLOR; - TEX0.xy = gl_MultiTexCoord0.xy; + gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0); + TEX0.xy = TexCoord.xy; onex = vec2(SourceSize.z, 0.0); oney = vec2(0.0, SourceSize.w); } #elif defined(FRAGMENT) -#if __VERSION__ >= 130 -#define COMPAT_VARYING in -#define COMPAT_TEXTURE texture -out vec4 FragColor; -#else -#define COMPAT_VARYING varying -#define FragColor gl_FragColor -#define COMPAT_TEXTURE texture2D -#endif - #ifdef GL_ES #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; @@ -88,12 +69,18 @@ precision mediump float; #define COMPAT_PRECISION #endif -uniform COMPAT_PRECISION int FrameDirection; -uniform COMPAT_PRECISION int FrameCount; -uniform COMPAT_PRECISION vec2 OutputSize; +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out COMPAT_PRECISION vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + uniform COMPAT_PRECISION vec2 TextureSize; -uniform COMPAT_PRECISION vec2 InputSize; -uniform COMPAT_PRECISION float opacity = 1.0; +uniform COMPAT_PRECISION float opacity; uniform sampler2D Texture; COMPAT_VARYING vec4 TEX0; COMPAT_VARYING vec2 onex; @@ -104,7 +91,6 @@ COMPAT_VARYING vec2 oney; #define vTexCoord TEX0.xy #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. -#define OutputSize vec4(OutputSize, 1.0 / OutputSize) #ifdef PARAMETER_UNIFORM // All parameter floats need to have COMPAT_PRECISION in front of them.