Unified the OpenGL and OpenGL ES renderers and removed the fixed function pipeline.

Also made some other rendering optimizations and cleaned up some code.
This commit is contained in:
Leon Styhre 2022-03-13 23:52:32 +01:00
parent adb162e0d1
commit a7db474a64
19 changed files with 300 additions and 363 deletions

View file

@ -86,7 +86,6 @@ void MediaViewer::render(const glm::mat4& /*parentTrans*/)
if (mVideo && !mDisplayingImage) { if (mVideo && !mDisplayingImage) {
mVideo->render(trans); mVideo->render(trans);
#if defined(USE_OPENGL_21)
Renderer::postProcessingParams videoParameters; Renderer::postProcessingParams videoParameters;
unsigned int shaders {0}; unsigned int shaders {0};
if (Settings::getInstance()->getBool("MediaViewerVideoScanlines")) if (Settings::getInstance()->getBool("MediaViewerVideoScanlines"))
@ -111,20 +110,19 @@ void MediaViewer::render(const glm::mat4& /*parentTrans*/)
videoParameters.blurPasses = 2; // 1080 videoParameters.blurPasses = 2; // 1080
// clang-format on // clang-format on
} }
if (shaders != 0)
Renderer::shaderPostprocessing(shaders, videoParameters); Renderer::shaderPostprocessing(shaders, videoParameters);
#endif
} }
else if (mImage && mImage->hasImage() && mImage->getSize() != glm::vec2 {}) { else if (mImage && mImage->hasImage() && mImage->getSize() != glm::vec2 {}) {
mImage->render(trans); mImage->render(trans);
#if defined(USE_OPENGL_21)
if (mCurrentImageIndex == mScreenshotIndex && if (mCurrentImageIndex == mScreenshotIndex &&
Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Settings::getInstance()->getBool("MediaViewerScreenshotScanlines"))
Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES);
else if (mCurrentImageIndex == mTitleScreenIndex && else if (mCurrentImageIndex == mTitleScreenIndex &&
Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Settings::getInstance()->getBool("MediaViewerScreenshotScanlines"))
Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES);
#endif
// This is necessary so that the video loops if viewing an image when // This is necessary so that the video loops if viewing an image when
// the video ends. // the video ends.

View file

@ -267,10 +267,8 @@ void Screensaver::renderScreensaver()
if (isScreensaverActive()) { if (isScreensaverActive()) {
if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") { if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") {
if (mHasMediaFiles) { if (mHasMediaFiles) {
#if defined(USE_OPENGL_21)
if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines")) if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines"))
Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES);
#endif
if (Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo") && if (Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo") &&
mGameOverlay) { mGameOverlay) {
if (mGameOverlayRectangleCoords.size() == 4) { if (mGameOverlayRectangleCoords.size() == 4) {
@ -295,7 +293,6 @@ void Screensaver::renderScreensaver()
} }
else if (Settings::getInstance()->getString("ScreensaverType") == "video") { else if (Settings::getInstance()->getString("ScreensaverType") == "video") {
if (mHasMediaFiles) { if (mHasMediaFiles) {
#if defined(USE_OPENGL_21)
Renderer::postProcessingParams videoParameters; Renderer::postProcessingParams videoParameters;
unsigned int shaders {0}; unsigned int shaders {0};
if (Settings::getInstance()->getBool("ScreensaverVideoScanlines")) if (Settings::getInstance()->getBool("ScreensaverVideoScanlines"))
@ -320,8 +317,10 @@ void Screensaver::renderScreensaver()
videoParameters.blurPasses = 2; // 1080 videoParameters.blurPasses = 2; // 1080
// clang-format on // clang-format on
} }
if (shaders != 0)
Renderer::shaderPostprocessing(shaders, videoParameters); Renderer::shaderPostprocessing(shaders, videoParameters);
#endif
if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo") && mGameOverlay) { if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo") && mGameOverlay) {
if (mGameOverlayRectangleCoords.size() == 4) { if (mGameOverlayRectangleCoords.size() == 4) {
Renderer::drawRect( Renderer::drawRect(
@ -345,7 +344,6 @@ void Screensaver::renderScreensaver()
} }
if (mFallbackScreensaver || if (mFallbackScreensaver ||
Settings::getInstance()->getString("ScreensaverType") == "dim") { Settings::getInstance()->getString("ScreensaverType") == "dim") {
#if defined(USE_OPENGL_21)
Renderer::postProcessingParams dimParameters; Renderer::postProcessingParams dimParameters;
dimParameters.dimming = mDimValue; dimParameters.dimming = mDimValue;
dimParameters.saturation = mSaturationAmount; dimParameters.saturation = mSaturationAmount;
@ -354,22 +352,13 @@ void Screensaver::renderScreensaver()
mDimValue = glm::clamp(mDimValue - 0.015f, 0.68f, 1.0f); mDimValue = glm::clamp(mDimValue - 0.015f, 0.68f, 1.0f);
if (mSaturationAmount > 0.0) if (mSaturationAmount > 0.0)
mSaturationAmount = glm::clamp(mSaturationAmount - 0.035f, 0.0f, 1.0f); 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") { else if (Settings::getInstance()->getString("ScreensaverType") == "black") {
#if defined(USE_OPENGL_21)
Renderer::postProcessingParams blackParameters; Renderer::postProcessingParams blackParameters;
blackParameters.dimming = mDimValue; blackParameters.dimming = mDimValue;
Renderer::shaderPostprocessing(Renderer::SHADER_CORE, blackParameters); Renderer::shaderPostprocessing(Renderer::SHADER_CORE, blackParameters);
if (mDimValue > 0.0) if (mDimValue > 0.0)
mDimValue = glm::clamp(mDimValue - 0.045f, 0.0f, 1.0f); mDimValue = glm::clamp(mDimValue - 0.045f, 0.0f, 1.0f);
#else
Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(),
0x000000FF, 0x000000FF);
#endif
} }
} }
} }

View file

@ -41,7 +41,6 @@ GuiMediaViewerOptions::GuiMediaViewerOptions(const std::string& title)
} }
}); });
#if defined(USE_OPENGL_21)
// Render scanlines for videos using a shader. // Render scanlines for videos using a shader.
auto video_scanlines = std::make_shared<SwitchComponent>(); auto video_scanlines = std::make_shared<SwitchComponent>();
video_scanlines->setState(Settings::getInstance()->getBool("MediaViewerVideoScanlines")); video_scanlines->setState(Settings::getInstance()->getBool("MediaViewerVideoScanlines"));
@ -79,5 +78,4 @@ GuiMediaViewerOptions::GuiMediaViewerOptions(const std::string& title)
setNeedsSaving(); setNeedsSaving();
} }
}); });
#endif
} }

View file

@ -493,7 +493,6 @@ void GuiMenu::openUIOptions()
screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this)); screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this));
s->addRow(screensaver_row); s->addRow(screensaver_row);
#if defined(USE_OPENGL_21)
// Blur background when the menu is open. // Blur background when the menu is open.
auto menu_blur_background = std::make_shared<SwitchComponent>(); auto menu_blur_background = std::make_shared<SwitchComponent>();
menu_blur_background->setState(Settings::getInstance()->getBool("MenuBlurBackground")); menu_blur_background->setState(Settings::getInstance()->getBool("MenuBlurBackground"));
@ -507,7 +506,6 @@ void GuiMenu::openUIOptions()
s->setInvalidateCachedBackground(); s->setInvalidateCachedBackground();
} }
}); });
#endif
// Display pillarboxes (and letterboxes) for videos in the gamelists. // Display pillarboxes (and letterboxes) for videos in the gamelists.
auto gamelistVideoPillarbox = std::make_shared<SwitchComponent>(); auto gamelistVideoPillarbox = std::make_shared<SwitchComponent>();
@ -522,7 +520,6 @@ void GuiMenu::openUIOptions()
} }
}); });
#if defined(USE_OPENGL_21)
// Render scanlines for videos in the gamelists. // Render scanlines for videos in the gamelists.
auto gamelistVideoScanlines = std::make_shared<SwitchComponent>(); auto gamelistVideoScanlines = std::make_shared<SwitchComponent>();
gamelistVideoScanlines->setState(Settings::getInstance()->getBool("GamelistVideoScanlines")); gamelistVideoScanlines->setState(Settings::getInstance()->getBool("GamelistVideoScanlines"));
@ -535,7 +532,6 @@ void GuiMenu::openUIOptions()
s->setNeedsSaving(); s->setNeedsSaving();
} }
}); });
#endif
// Sort folders on top of the gamelists. // Sort folders on top of the gamelists.
auto folders_on_top = std::make_shared<SwitchComponent>(); auto folders_on_top = std::make_shared<SwitchComponent>();
@ -751,13 +747,11 @@ void GuiMenu::openUIOptions()
->setOpacity(DISABLED_OPACITY); ->setOpacity(DISABLED_OPACITY);
// Scanlines are theme-controlled for newer themes. // Scanlines are theme-controlled for newer themes.
#if defined(USE_OPENGL_21)
gamelistVideoScanlines->setEnabled(false); gamelistVideoScanlines->setEnabled(false);
gamelistVideoScanlines->setOpacity(DISABLED_OPACITY); gamelistVideoScanlines->setOpacity(DISABLED_OPACITY);
gamelistVideoScanlines->getParent() gamelistVideoScanlines->getParent()
->getChild(gamelistVideoScanlines->getChildIndex() - 1) ->getChild(gamelistVideoScanlines->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY); ->setOpacity(DISABLED_OPACITY);
#endif
} }
else { else {
gamelist_view_style->setEnabled(true); gamelist_view_style->setEnabled(true);
@ -778,13 +772,11 @@ void GuiMenu::openUIOptions()
->getChild(gamelistVideoPillarbox->getChildIndex() - 1) ->getChild(gamelistVideoPillarbox->getChildIndex() - 1)
->setOpacity(1.0f); ->setOpacity(1.0f);
#if defined(USE_OPENGL_21)
gamelistVideoScanlines->setEnabled(true); gamelistVideoScanlines->setEnabled(true);
gamelistVideoScanlines->setOpacity(1.0f); gamelistVideoScanlines->setOpacity(1.0f);
gamelistVideoScanlines->getParent() gamelistVideoScanlines->getParent()
->getChild(gamelistVideoScanlines->getChildIndex() - 1) ->getChild(gamelistVideoScanlines->getChildIndex() - 1)
->setOpacity(1.0f); ->setOpacity(1.0f);
#endif
} }
}; };

View file

@ -149,7 +149,6 @@ void GuiScreensaverOptions::openSlideshowScreensaverOptions()
} }
}); });
#if defined(USE_OPENGL_21)
// Render scanlines using a shader. // Render scanlines using a shader.
auto screensaver_slideshow_scanlines = std::make_shared<SwitchComponent>(); auto screensaver_slideshow_scanlines = std::make_shared<SwitchComponent>();
screensaver_slideshow_scanlines->setState( screensaver_slideshow_scanlines->setState(
@ -163,7 +162,6 @@ void GuiScreensaverOptions::openSlideshowScreensaverOptions()
s->setNeedsSaving(); s->setNeedsSaving();
} }
}); });
#endif
// Whether to use custom images. // Whether to use custom images.
auto screensaver_slideshow_custom_images = std::make_shared<SwitchComponent>(); auto screensaver_slideshow_custom_images = std::make_shared<SwitchComponent>();
@ -262,7 +260,6 @@ void GuiScreensaverOptions::openVideoScreensaverOptions()
} }
}); });
#if defined(USE_OPENGL_21)
// Render scanlines using a shader. // Render scanlines using a shader.
auto screensaver_video_scanlines = std::make_shared<SwitchComponent>(); auto screensaver_video_scanlines = std::make_shared<SwitchComponent>();
screensaver_video_scanlines->setState( screensaver_video_scanlines->setState(
@ -289,7 +286,6 @@ void GuiScreensaverOptions::openVideoScreensaverOptions()
s->setNeedsSaving(); s->setNeedsSaving();
} }
}); });
#endif
s->setSize(mSize); s->setSize(mSize);
mWindow->pushGui(s); mWindow->pushGui(s);

View file

@ -150,8 +150,6 @@ set(CORE_SOURCES
# Renderer # Renderer
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Renderer_GL21.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 ${CMAKE_CURRENT_SOURCE_DIR}/src/renderers/Shader_GL21.cpp
# Resources # Resources

View file

@ -20,9 +20,7 @@
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
#if defined(USE_OPENGL_21)
#define CLOCK_BACKGROUND_CREATION false #define CLOCK_BACKGROUND_CREATION false
#endif
Window::Window() noexcept Window::Window() noexcept
: mScreensaver {nullptr} : mScreensaver {nullptr}
@ -124,12 +122,10 @@ bool Window::init()
mDefaultFonts.push_back(Font::get(FONT_SIZE_LARGE)); 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()); mBackgroundOverlay->setResize(Renderer::getScreenWidth(), Renderer::getScreenHeight());
#if defined(USE_OPENGL_21)
mPostprocessedBackground = TextureResource::get(""); mPostprocessedBackground = TextureResource::get("");
#endif
mListScrollFont = Font::get(FONT_SIZE_LARGE); mListScrollFont = Font::get(FONT_SIZE_LARGE);
@ -146,9 +142,7 @@ void Window::deinit()
for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); ++it) for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); ++it)
(*it)->onHide(); (*it)->onHide();
#if defined(USE_OPENGL_21)
mPostprocessedBackground.reset(); mPostprocessedBackground.reset();
#endif
InputManager::getInstance().deinit(); InputManager::getInstance().deinit();
ResourceManager::getInstance().unloadAll(); ResourceManager::getInstance().unloadAll();
@ -445,7 +439,6 @@ void Window::render()
bottom->render(trans); bottom->render(trans);
if (bottom != top || mRenderLaunchScreen) { if (bottom != top || mRenderLaunchScreen) {
#if defined(USE_OPENGL_21)
if (!mCachedBackground && mInvalidateCacheTimer == 0) { if (!mCachedBackground && mInvalidateCacheTimer == 0) {
// Generate a cache texture of the shaded background when opening the menu, which // 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 // 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. // Also dim the background slightly.
backgroundParameters.dimming = 0.60f; backgroundParameters.dimming = 0.60f;
Renderer::shaderPostprocessing(Renderer::SHADER_BLUR_HORIZONTAL | Renderer::shaderPostprocessing(Renderer::SHADER_CORE |
Renderer::SHADER_BLUR_HORIZONTAL |
Renderer::SHADER_BLUR_VERTICAL, Renderer::SHADER_BLUR_VERTICAL,
backgroundParameters, &processedTexture[0]); backgroundParameters, &processedTexture[0]);
} }
@ -527,7 +521,6 @@ void Window::render()
mBackgroundOverlayOpacity = mBackgroundOverlayOpacity =
glm::clamp(mBackgroundOverlayOpacity + 0.118f, 0.0f, 1.0f); glm::clamp(mBackgroundOverlayOpacity + 0.118f, 0.0f, 1.0f);
} }
#endif // USE_OPENGL_21
mBackgroundOverlay->render(trans); mBackgroundOverlay->render(trans);

View file

@ -172,10 +172,7 @@ private:
GuiInfoPopup* mInfoPopup; GuiInfoPopup* mInfoPopup;
std::queue<std::pair<std::string, int>> mInfoPopupQueue; std::queue<std::pair<std::string, int>> mInfoPopupQueue;
#if defined(USE_OPENGL_21)
std::shared_ptr<TextureResource> mPostprocessedBackground; std::shared_ptr<TextureResource> mPostprocessedBackground;
#endif
std::string mListScrollText; std::string mListScrollText;
std::shared_ptr<Font> mListScrollFont; std::shared_ptr<Font> mListScrollFont;

View file

@ -44,11 +44,6 @@ GIFAnimComponent::GIFAnimComponent()
{ {
// Get an empty texture for rendering the animation. // Get an empty texture for rendering the animation.
mTexture = TextureResource::get(""); 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.read_proc = readProc;
mAnimIO.write_proc = writeProc; mAnimIO.write_proc = writeProc;

View file

@ -39,11 +39,6 @@ LottieAnimComponent::LottieAnimComponent()
{ {
// Get an empty texture for rendering the animation. // Get an empty texture for rendering the animation.
mTexture = TextureResource::get(""); 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. // Keep per-file cache size within 0 to 1024 MiB.
mMaxCacheSize = static_cast<size_t>( mMaxCacheSize = static_cast<size_t>(

View file

@ -47,11 +47,15 @@ namespace Renderer
}; };
static std::vector<Shader*> sShaderProgramVector; static std::vector<Shader*> sShaderProgramVector;
static GLuint shaderFBO1; static GLuint shaderFBO1 {0};
static GLuint shaderFBO2; static GLuint shaderFBO2 {0};
// This is simply to get rid of a GCC false positive -Wunused-variable compiler warning. 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 shaderFBODummy1 {shaderFBO1};
static GLuint shaderFBODummy2 {shaderFBO2}; static GLuint shaderFBODummy2 {shaderFBO2};
static GLuint vertexBufferDummy1 {vertexBuffer1};
static GLuint vertexBufferDummy2 {vertexBuffer2};
static constexpr glm::mat4 getIdentity() { return glm::mat4 {1.0f}; } static constexpr glm::mat4 getIdentity() { return glm::mat4 {1.0f}; }
static inline glm::mat4 mTrans {getIdentity()}; static inline glm::mat4 mTrans {getIdentity()};
@ -64,11 +68,11 @@ namespace Renderer
const GLenum errorCode = glGetError(); const GLenum errorCode = glGetError();
if (errorCode != GL_NO_ERROR) { if (errorCode != GL_NO_ERROR) {
#if defined(USE_OPENGL_21) #if defined(USE_OPENGLES)
LOG(LogError) << "OpenGL error: " << _funcName << " failed with error code: 0x" LOG(LogError) << "OpenGL ES error: " << _funcName << " failed with error code: 0x"
<< std::hex << errorCode; << std::hex << errorCode;
#else #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; << std::hex << errorCode;
#endif #endif
} }
@ -98,7 +102,7 @@ namespace Renderer
enum Type { enum Type {
RGBA, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0). RGBA, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0).
BGRA, BGRA,
ALPHA RED
}; };
} }
@ -124,6 +128,7 @@ namespace Renderer
float saturation; float saturation;
float dimming; float dimming;
bool convertBGRAToRGBA; bool convertBGRAToRGBA;
bool font;
bool postProcessing; bool postProcessing;
unsigned int shaders; unsigned int shaders;
@ -132,6 +137,7 @@ namespace Renderer
, saturation {1.0f} , saturation {1.0f}
, dimming {1.0f} , dimming {1.0f}
, convertBGRAToRGBA {false} , convertBGRAToRGBA {false}
, font {false}
, postProcessing {false} , postProcessing {false}
, shaders {0} , shaders {0}
{ {
@ -144,6 +150,7 @@ namespace Renderer
, saturation {1.0f} , saturation {1.0f}
, dimming {1.0f} , dimming {1.0f}
, convertBGRAToRGBA {false} , convertBGRAToRGBA {false}
, font {false}
, postProcessing {false} , postProcessing {false}
, shaders {0} , shaders {0}
{ {

View file

@ -3,11 +3,9 @@
// EmulationStation Desktop Edition // EmulationStation Desktop Edition
// Renderer_GL21.cpp // Renderer_GL21.cpp
// //
// OpenGL 2.1 rendering functions. // OpenGL / OpenGL ES renderer.
// //
#if defined(USE_OPENGL_21)
#include "Settings.h" #include "Settings.h"
#include "Shader_GL21.h" #include "Shader_GL21.h"
#include "renderers/Renderer.h" #include "renderers/Renderer.h"
@ -47,8 +45,12 @@ namespace Renderer
// clang-format off // clang-format off
switch (type) { switch (type) {
case Texture::RGBA: { return GL_RGBA; } break; 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::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; } default: { return GL_ZERO; }
} }
// clang-format on // clang-format on
@ -56,15 +58,16 @@ namespace Renderer
void setupWindow() void setupWindow()
{ {
#if defined(__APPLE__)
// This is required on macOS, as the operating system will otherwise insist on using #if defined(USE_OPENGLES)
// a newer OpenGL version which completely breaks the application. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#else #else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 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 #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_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
@ -75,7 +78,6 @@ namespace Renderer
bool createContext() bool createContext()
{ {
bool missingExtension = false;
sdlContext = SDL_GL_CreateContext(getSDLWindow()); sdlContext = SDL_GL_CreateContext(getSDLWindow());
if (!sdlContext) { if (!sdlContext) {
@ -103,46 +105,37 @@ namespace Renderer
LOG(LogInfo) << "GL renderer: " << renderer; LOG(LogInfo) << "GL renderer: " << renderer;
LOG(LogInfo) << "GL version: " << version; LOG(LogInfo) << "GL version: " << version;
#if defined(_WIN64) #if defined(_WIN64)
LOG(LogInfo) << "EmulationStation renderer: OpenGL 2.1 with GLEW"; LOG(LogInfo) << "EmulationStation renderer: OpenGL 3.3 with GLEW";
#else #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 #endif
LOG(LogInfo) << "Checking available OpenGL extensions..."; #endif
std::string glExts = glGetString(GL_EXTENSIONS) ?
reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)) : #if !defined(USE_OPENGLES)
""; // TODO: Fix the issue that causes the first glClearColor function call to fail.
if (extensions.find("GL_ARB_texture_non_power_of_two") == std::string::npos) { GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
LOG(LogError) << "GL_ARB_texture_non_power_of_two: MISSING"; #endif
missingExtension = true;
} GL_CHECK_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
else { GL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
LOG(LogInfo) << "GL_ARB_texture_non_power_of_two: OK"; GL_CHECK_ERROR(glEnable(GL_BLEND));
} GL_CHECK_ERROR(glPixelStorei(GL_PACK_ALIGNMENT, 1));
if (extensions.find("GL_ARB_vertex_shader") == std::string::npos) { GL_CHECK_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
LOG(LogError) << "GL_ARB_vertex_shader: MISSING";
missingExtension = true; // These are used for the shader post processing.
} GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO1));
else { GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO2));
LOG(LogInfo) << "GL_ARB_vertex_shader: OK";
} GL_CHECK_ERROR(glGenBuffers(1, &vertexBuffer1));
if (extensions.find("GL_ARB_fragment_shader") == std::string::npos) { GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer1));
LOG(LogError) << "GL_ARB_fragment_shader: MISSING"; GL_CHECK_ERROR(glGenVertexArrays(1, &vertexBuffer2));
missingExtension = true; GL_CHECK_ERROR(glBindVertexArray(vertexBuffer2));
}
else { uint8_t data[4] = {255, 255, 255, 255};
LOG(LogInfo) << "GL_ARB_fragment_shader: OK"; whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data);
}
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;
}
postProcTexture1 = createTexture(Texture::RGBA, false, false, false, postProcTexture1 = createTexture(Texture::RGBA, false, false, false,
static_cast<unsigned int>(getScreenWidth()), static_cast<unsigned int>(getScreenWidth()),
@ -152,21 +145,16 @@ namespace Renderer
static_cast<unsigned int>(getScreenWidth()), static_cast<unsigned int>(getScreenWidth()),
static_cast<unsigned int>(getScreenHeight()), nullptr); static_cast<unsigned int>(getScreenHeight()), nullptr);
uint8_t data[4] = {255, 255, 255, 255}; // Attach textures to the shader framebuffers.
whiteTexture = createTexture(Texture::RGBA, false, false, true, 1, 1, data); 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(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shaderFBO2));
GL_CHECK_ERROR(glEnable(GL_TEXTURE_2D)); GL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
GL_CHECK_ERROR(glEnable(GL_BLEND)); postProcTexture2, 0));
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));
// These framebuffers are used for the shader post processing. GL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO1));
GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO2));
return true; return true;
} }
@ -209,24 +197,8 @@ namespace Renderer
linearMagnify ? static_cast<GLfloat>(GL_LINEAR) : linearMagnify ? static_cast<GLfloat>(GL_LINEAR) :
static_cast<GLfloat>(GL_NEAREST))); static_cast<GLfloat>(GL_NEAREST)));
if (textureType == GL_LUMINANCE_ALPHA) { GL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, textureType, width, height, 0, textureType,
uint8_t* a_data {reinterpret_cast<uint8_t*>(data)}; GL_UNSIGNED_BYTE, 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));
}
return texture; return texture;
} }
@ -246,26 +218,8 @@ namespace Renderer
const GLenum textureType = convertTextureType(type); const GLenum textureType = convertTextureType(type);
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, texture)); 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<uint8_t*>(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_CHECK_ERROR(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, textureType,
GL_UNSIGNED_BYTE, data)); GL_UNSIGNED_BYTE, data));
}
GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture)); GL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, whiteTexture));
} }
@ -286,51 +240,57 @@ namespace Renderer
const float width {vertices[3].position[0]}; const float width {vertices[3].position[0]};
const float height {vertices[3].position[1]}; 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( GL_CHECK_ERROR(
glBlendFunc(convertBlendFactor(srcBlendFactor), convertBlendFactor(dstBlendFactor))); glBlendFunc(convertBlendFactor(srcBlendFactor), convertBlendFactor(dstBlendFactor)));
if (vertices->shaders == 0 || vertices->shaders & SHADER_CORE) { if (vertices->shaders == 0 || vertices->shaders & SHADER_CORE) {
Shader* runShader = getShaderProgram(SHADER_CORE); Shader* shader {getShaderProgram(SHADER_CORE)};
if (runShader) { if (shader) {
runShader->activateShaders(); shader->activateShaders();
runShader->setModelViewProjectionMatrix(mTrans); shader->setModelViewProjectionMatrix(mTrans);
runShader->setOpacity(vertices->opacity); shader->setAttribPointers();
runShader->setSaturation(vertices->saturation); GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices,
runShader->setDimming(vertices->dimming); GL_DYNAMIC_DRAW));
runShader->setBGRAToRGBA(vertices->convertBGRAToRGBA); shader->setOpacity(vertices->opacity);
runShader->setPostProcessing(vertices->postProcessing); 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)); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
runShader->deactivateShaders(); shader->deactivateShaders();
} }
} }
else if (vertices->shaders & SHADER_BLUR_HORIZONTAL) { else if (vertices->shaders & SHADER_BLUR_HORIZONTAL) {
Shader* runShader = getShaderProgram(SHADER_BLUR_HORIZONTAL); Shader* shader {getShaderProgram(SHADER_BLUR_HORIZONTAL)};
if (runShader) { if (shader) {
runShader->activateShaders(); shader->activateShaders();
runShader->setModelViewProjectionMatrix(mTrans); shader->setModelViewProjectionMatrix(mTrans);
runShader->setTextureSize({width, height}); 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)); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
runShader->deactivateShaders(); shader->deactivateShaders();
} }
return; return;
} }
else if (vertices->shaders & SHADER_BLUR_VERTICAL) { else if (vertices->shaders & SHADER_BLUR_VERTICAL) {
Shader* runShader = getShaderProgram(SHADER_BLUR_VERTICAL); Shader* shader {getShaderProgram(SHADER_BLUR_VERTICAL)};
if (runShader) { if (shader) {
runShader->activateShaders(); shader->activateShaders();
runShader->setModelViewProjectionMatrix(mTrans); shader->setModelViewProjectionMatrix(mTrans);
runShader->setTextureSize({width, height}); 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)); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
runShader->deactivateShaders(); shader->deactivateShaders();
} }
return; return;
} }
else if (vertices->shaders & SHADER_SCANLINES) { else if (vertices->shaders & SHADER_SCANLINES) {
Shader* runShader {getShaderProgram(SHADER_SCANLINES)}; Shader* shader {getShaderProgram(SHADER_SCANLINES)};
float shaderWidth {width * 1.2f}; float shaderWidth {width * 1.2f};
// Scale the scanlines relative to screen resolution. // Scale the scanlines relative to screen resolution.
float screenHeightModifier {getScreenHeightModifier()}; float screenHeightModifier {getScreenHeightModifier()};
@ -350,13 +310,16 @@ namespace Renderer
float modifier {1.41f + relativeAdjustment / 7.0f - (0.14f * screenHeightModifier)}; float modifier {1.41f + relativeAdjustment / 7.0f - (0.14f * screenHeightModifier)};
shaderHeight = height * modifier; shaderHeight = height * modifier;
} }
if (runShader) { if (shader) {
runShader->activateShaders(); shader->activateShaders();
runShader->setModelViewProjectionMatrix(mTrans); shader->setModelViewProjectionMatrix(mTrans);
runShader->setOpacity(vertices->opacity); shader->setAttribPointers();
runShader->setTextureSize({shaderWidth, shaderHeight}); 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)); GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices));
runShader->deactivateShaders(); shader->deactivateShaders();
} }
} }
} }
@ -446,8 +409,8 @@ namespace Renderer
vertices->dimming = parameters.dimming; vertices->dimming = parameters.dimming;
vertices->postProcessing = true; 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) if (shaders & Renderer::SHADER_BLUR_HORIZONTAL)
shaderList.push_back(Renderer::SHADER_BLUR_HORIZONTAL); shaderList.push_back(Renderer::SHADER_BLUR_HORIZONTAL);
if (shaders & Renderer::SHADER_BLUR_VERTICAL) if (shaders & Renderer::SHADER_BLUR_VERTICAL)
@ -458,16 +421,8 @@ namespace Renderer
setMatrix(getIdentity()); setMatrix(getIdentity());
bindTexture(postProcTexture1); 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)); 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. // Blit the screen contents to postProcTexture.
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
GL_COLOR_BUFFER_BIT, GL_NEAREST)); GL_COLOR_BUFFER_BIT, GL_NEAREST));
@ -545,5 +500,3 @@ namespace Renderer
} }
} // namespace Renderer } // namespace Renderer
#endif // USE_OPENGL_21

View file

@ -6,8 +6,6 @@
// OpenGL 2.1 GLSL shader functions. // OpenGL 2.1 GLSL shader functions.
// //
#if defined(USE_OPENGL_21)
#include "Shader_GL21.h" #include "Shader_GL21.h"
#include "Log.h" #include "Log.h"
@ -19,11 +17,16 @@ namespace Renderer
Renderer::Shader::Shader() Renderer::Shader::Shader()
: mProgramID {0} : mProgramID {0}
, shaderMVPMatrix {0} , shaderMVPMatrix {0}
, shaderTextureSize {0} , shaderPosition {0}
, shaderTextureCoord {0} , shaderTextureCoord {0}
, shaderColor {0}
, shaderTextureSize {0}
, shaderOpacity {0} , shaderOpacity {0}
, shaderSaturation {0} , shaderSaturation {0}
, shaderDimming {0} , shaderDimming {0}
, shaderBGRAToRGBA {0}
, shaderFont {0}
, shaderPostProcessing {0}
{ {
} }
@ -42,9 +45,12 @@ namespace Renderer
const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)}; const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)};
shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length); shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length);
// Define the GLSL version (version 120 = OpenGL 2.1). // Define the GLSL version.
preprocessorDefines = "#version 120\n"; #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 // Define the preprocessor constants that will let the shader compiler know whether
// the VERTEX or FRAGMENT portion of the code should be used. // the VERTEX or FRAGMENT portion of the code should be used.
if (shaderType == GL_VERTEX_SHADER) if (shaderType == GL_VERTEX_SHADER)
@ -76,9 +82,12 @@ namespace Renderer
if (shaderCompiled != GL_TRUE) { if (shaderCompiled != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " (" LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " ("
<< std::get<0>(*it) << ")."; << std::get<0>(*it) << ").";
printShaderInfoLog(currentShader, std::get<2>(*it)); printShaderInfoLog(currentShader, std::get<2>(*it), true);
return false; return false;
} }
else {
printShaderInfoLog(currentShader, std::get<2>(*it), false);
}
GL_CHECK_ERROR(glAttachShader(mProgramID, currentShader)); GL_CHECK_ERROR(glAttachShader(mProgramID, currentShader));
} }
@ -93,6 +102,16 @@ namespace Renderer
} }
getVariableLocations(mProgramID); 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; return true;
} }
@ -105,12 +124,15 @@ namespace Renderer
{ {
// Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders. // Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders.
shaderMVPMatrix = glGetUniformLocation(mProgramID, "MVPMatrix"); shaderMVPMatrix = glGetUniformLocation(mProgramID, "MVPMatrix");
shaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize"); shaderPosition = glGetAttribLocation(mProgramID, "positionAttrib");
shaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord"); shaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord");
shaderColor = glGetAttribLocation(mProgramID, "colorAttrib");
shaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize");
shaderOpacity = glGetUniformLocation(mProgramID, "opacity"); shaderOpacity = glGetUniformLocation(mProgramID, "opacity");
shaderSaturation = glGetUniformLocation(mProgramID, "saturation"); shaderSaturation = glGetUniformLocation(mProgramID, "saturation");
shaderDimming = glGetUniformLocation(mProgramID, "dimming"); shaderDimming = glGetUniformLocation(mProgramID, "dimming");
shaderBGRAToRGBA = glGetUniformLocation(mProgramID, "BGRAToRGBA"); shaderBGRAToRGBA = glGetUniformLocation(mProgramID, "BGRAToRGBA");
shaderFont = glGetUniformLocation(mProgramID, "font");
shaderPostProcessing = glGetUniformLocation(mProgramID, "postProcessing"); shaderPostProcessing = glGetUniformLocation(mProgramID, "postProcessing");
} }
@ -121,48 +143,62 @@ namespace Renderer
reinterpret_cast<GLfloat*>(&mvpMatrix))); reinterpret_cast<GLfloat*>(&mvpMatrix)));
} }
void Renderer::Shader::setTextureSize(std::array<GLfloat, 2> shaderVec2) void Renderer::Shader::setAttribPointers()
{ {
if (shaderTextureSize != GL_INVALID_VALUE && shaderTextureSize != GL_INVALID_OPERATION) if (shaderPosition != -1)
GL_CHECK_ERROR(glUniform2f(shaderTextureSize, shaderVec2[0], shaderVec2[1])); GL_CHECK_ERROR(
glVertexAttribPointer(shaderPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const void*>(offsetof(Vertex, position))));
if (shaderTextureCoord != -1)
GL_CHECK_ERROR(
glVertexAttribPointer(shaderTextureCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const void*>(offsetof(Vertex, texture))));
if (shaderColor != -1)
GL_CHECK_ERROR(
glVertexAttribPointer(shaderColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex),
reinterpret_cast<const void*>(offsetof(Vertex, color))));
} }
void Renderer::Shader::setTextureCoordinates(std::array<GLfloat, 4> shaderVec4) void Renderer::Shader::setTextureSize(std::array<GLfloat, 2> shaderVec2)
{ {
if (shaderTextureCoord != GL_INVALID_OPERATION) { if (shaderTextureSize != -1)
glVertexAttrib4f(shaderTextureCoord, shaderVec4[0], shaderVec4[1], shaderVec4[2], GL_CHECK_ERROR(glUniform2f(shaderTextureSize, shaderVec2[0], shaderVec2[1]));
shaderVec4[3]);
}
} }
void Renderer::Shader::setOpacity(GLfloat opacity) void Renderer::Shader::setOpacity(GLfloat opacity)
{ {
if (shaderOpacity != GL_INVALID_VALUE && shaderOpacity != GL_INVALID_OPERATION) if (shaderOpacity != -1)
GL_CHECK_ERROR(glUniform1f(shaderOpacity, opacity)); GL_CHECK_ERROR(glUniform1f(shaderOpacity, opacity));
} }
void Renderer::Shader::setSaturation(GLfloat saturation) void Renderer::Shader::setSaturation(GLfloat saturation)
{ {
if (shaderSaturation != GL_INVALID_VALUE && shaderSaturation != GL_INVALID_OPERATION) if (shaderSaturation != -1)
GL_CHECK_ERROR(glUniform1f(shaderSaturation, saturation)); GL_CHECK_ERROR(glUniform1f(shaderSaturation, saturation));
} }
void Renderer::Shader::setDimming(GLfloat dimming) void Renderer::Shader::setDimming(GLfloat dimming)
{ {
if (shaderDimming != GL_INVALID_VALUE && shaderDimming != GL_INVALID_OPERATION) if (shaderDimming != -1)
GL_CHECK_ERROR(glUniform1f(shaderDimming, dimming)); GL_CHECK_ERROR(glUniform1f(shaderDimming, dimming));
} }
void Renderer::Shader::setBGRAToRGBA(GLboolean BGRAToRGBA) 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)); 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) void Renderer::Shader::setPostProcessing(GLboolean postProcessing)
{ {
if (shaderPostProcessing != GL_INVALID_VALUE && if (shaderPostProcessing != -1)
shaderPostProcessing != GL_INVALID_OPERATION)
GL_CHECK_ERROR(glUniform1i(shaderPostProcessing, postProcessing ? 1 : 0)); 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)) { if (glIsShader(shaderID)) {
int logLength; int logLength;
@ -208,10 +244,14 @@ namespace Renderer
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength); glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<char> infoLog(maxLength); std::vector<char> infoLog(maxLength);
if (infoLog.size() == 0)
return;
glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front()); glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front());
if (logLength > 0) { 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" : << (shaderType == GL_VERTEX_SHADER ? "VERTEX section:\n" :
"FRAGMENT section:\n") "FRAGMENT section:\n")
<< std::string(infoLog.begin(), infoLog.end()); << std::string(infoLog.begin(), infoLog.end());
@ -223,5 +263,3 @@ namespace Renderer
} }
} // namespace Renderer } // namespace Renderer
#endif // USE_OPENGL_21

View file

@ -18,11 +18,11 @@
#endif #endif
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
// Hack until shader support has been added for OpenGL ES. #if defined(USE_OPENGLES)
#if defined(USE_OPENGL_21) #include <GLES3/gl3.h>
#include <SDL2/SDL_opengl.h>
#else
#include <SDL2/SDL_opengles.h> #include <SDL2/SDL_opengles.h>
#else
#include <SDL2/SDL_opengl.h>
#endif #endif
#include <array> #include <array>
#include <string> #include <string>
@ -47,12 +47,13 @@ namespace Renderer
// One-way communication with the compiled shaders. // One-way communication with the compiled shaders.
void setModelViewProjectionMatrix(glm::mat4 mvpMatrix); void setModelViewProjectionMatrix(glm::mat4 mvpMatrix);
void setAttribPointers();
void setTextureSize(std::array<GLfloat, 2> shaderVec2); void setTextureSize(std::array<GLfloat, 2> shaderVec2);
void setTextureCoordinates(std::array<GLfloat, 4> shaderVec4);
void setOpacity(GLfloat opacity); void setOpacity(GLfloat opacity);
void setSaturation(GLfloat saturation); void setSaturation(GLfloat saturation);
void setDimming(GLfloat dimming); void setDimming(GLfloat dimming);
void setBGRAToRGBA(GLboolean BGRAToRGBA); void setBGRAToRGBA(GLboolean BGRAToRGBA);
void setFont(GLboolean font);
void setPostProcessing(GLboolean postProcessing); void setPostProcessing(GLboolean postProcessing);
// Sets the shader program to use the loaded shaders. // Sets the shader program to use the loaded shaders.
void activateShaders(); void activateShaders();
@ -62,7 +63,7 @@ namespace Renderer
GLuint getProgramID() { return mProgramID; } GLuint getProgramID() { return mProgramID; }
// Only used for error logging if the shaders fail to compile or link. // Only used for error logging if the shaders fail to compile or link.
void printProgramInfoLog(GLuint programID); void printProgramInfoLog(GLuint programID);
void printShaderInfoLog(GLuint shaderID, GLenum shaderType); void printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error);
private: private:
GLuint mProgramID; GLuint mProgramID;
@ -70,12 +71,15 @@ namespace Renderer
// Variables used for communication with the compiled shaders. // Variables used for communication with the compiled shaders.
GLint shaderMVPMatrix; GLint shaderMVPMatrix;
GLint shaderTextureSize; GLint shaderPosition;
GLint shaderTextureCoord; GLint shaderTextureCoord;
GLint shaderColor;
GLint shaderTextureSize;
GLint shaderOpacity; GLint shaderOpacity;
GLint shaderSaturation; GLint shaderSaturation;
GLint shaderDimming; GLint shaderDimming;
GLint shaderBGRAToRGBA; GLint shaderBGRAToRGBA;
GLint shaderFont;
GLint shaderPostProcessing; GLint shaderPostProcessing;
}; };

View file

@ -199,8 +199,8 @@ bool Font::FontTexture::findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out
void Font::FontTexture::initTexture() void Font::FontTexture::initTexture()
{ {
assert(textureId == 0); assert(textureId == 0);
textureId = Renderer::createTexture(Renderer::Texture::ALPHA, false, false, false, textureId = Renderer::createTexture(Renderer::Texture::RED, false, false, false, textureSize.x,
textureSize.x, textureSize.y, nullptr); textureSize.y, nullptr);
} }
void Font::FontTexture::deinitTexture() void Font::FontTexture::deinitTexture()
@ -346,8 +346,8 @@ Font::Glyph* Font::getGlyph(unsigned int id)
static_cast<float>(g->metrics.horiBearingY) / 64.0f}; static_cast<float>(g->metrics.horiBearingY) / 64.0f};
// Upload glyph bitmap to texture. // Upload glyph bitmap 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.x, glyphSize.y, g->bitmap.buffer); glyphSize.y, g->bitmap.buffer);
// Update max glyph height. // Update max glyph height.
if (glyphSize.y > mMaxGlyphHeight) if (glyphSize.y > mMaxGlyphHeight)
@ -380,7 +380,7 @@ void Font::rebuildTextures()
static_cast<int>(it->second.texSize.y * tex->textureSize.y)}; static_cast<int>(it->second.texSize.y * tex->textureSize.y)};
// Upload to texture. // 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); glyphSize.x, glyphSize.y, glyphSlot->bitmap.buffer);
} }
} }
@ -392,10 +392,11 @@ void Font::renderTextCache(TextCache* cache)
return; 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); assert(*it->textureIdPtr != 0);
auto vertexList = *it; auto vertexList = *it;
it->verts[0].font = true;
Renderer::bindTexture(*it->textureIdPtr); Renderer::bindTexture(*it->textureIdPtr);
Renderer::drawTriangleStrips(&it->verts[0], Renderer::drawTriangleStrips(&it->verts[0],

View file

@ -18,7 +18,6 @@
#else #else
#define COMPAT_VARYING varying #define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute #define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif #endif
#ifdef GL_ES #ifdef GL_ES
@ -27,39 +26,19 @@
#define COMPAT_PRECISION #define COMPAT_PRECISION
#endif #endif
COMPAT_ATTRIBUTE vec4 VertexCoord; COMPAT_ATTRIBUTE vec2 positionAttrib;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord; COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0; COMPAT_VARYING vec4 TEX0;
vec4 _oPosition1;
uniform mat4 MVPMatrix; 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() void main()
{ {
gl_Position = MVPMatrix * gl_Vertex; gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0);
COL0 = COLOR; TEX0.xy = TexCoord.xy;
TEX0.xy = gl_MultiTexCoord0.xy;
} }
#elif defined(FRAGMENT) #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_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH #ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float; precision highp float;
@ -71,20 +50,25 @@ precision mediump float;
#define COMPAT_PRECISION #define COMPAT_PRECISION
#endif #endif
uniform COMPAT_PRECISION int FrameDirection; #if __VERSION__ >= 130
uniform COMPAT_PRECISION int FrameCount; #define COMPAT_VARYING in
uniform COMPAT_PRECISION vec2 OutputSize; #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 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture; uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0; COMPAT_VARYING COMPAT_PRECISION vec4 TEX0;
// Compatibility #defines // Compatibility #defines
#define Source Texture #define Source Texture
#define vTexCoord TEX0.xy #define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize.
#define outsize vec4(OutputSize, 1.0 / OutputSize)
void main() void main()
{ {
@ -129,8 +113,9 @@ void main()
sampleWeights5; sampleWeights5;
#else #else
float sampleOffsets[5] = {0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130}; float sampleOffsets[5] = float[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 sampleWeights[5] =
float[5](0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196);
vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0]; vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0];
for (int i = 1; i < 5; i++) { for (int i = 1; i < 5; i++) {

View file

@ -18,7 +18,6 @@
#else #else
#define COMPAT_VARYING varying #define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute #define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif #endif
#ifdef GL_ES #ifdef GL_ES
@ -27,39 +26,19 @@
#define COMPAT_PRECISION #define COMPAT_PRECISION
#endif #endif
COMPAT_ATTRIBUTE vec4 VertexCoord; COMPAT_ATTRIBUTE vec2 positionAttrib;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord; COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0; COMPAT_VARYING vec4 TEX0;
vec4 _oPosition1;
uniform mat4 MVPMatrix; 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() void main()
{ {
gl_Position = MVPMatrix * gl_Vertex; gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0);
COL0 = COLOR; TEX0.xy = TexCoord.xy;
TEX0.xy = gl_MultiTexCoord0.xy;
} }
#elif defined(FRAGMENT) #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_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH #ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float; precision highp float;
@ -71,20 +50,25 @@ precision mediump float;
#define COMPAT_PRECISION #define COMPAT_PRECISION
#endif #endif
uniform COMPAT_PRECISION int FrameDirection; #if __VERSION__ >= 130
uniform COMPAT_PRECISION int FrameCount; #define COMPAT_VARYING in
uniform COMPAT_PRECISION vec2 OutputSize; #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 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture; uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0; COMPAT_VARYING COMPAT_PRECISION vec4 TEX0;
// compatibility #defines // compatibility #defines
#define Source Texture #define Source Texture
#define vTexCoord TEX0.xy #define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize.
#define outsize vec4(OutputSize, 1.0 / OutputSize)
void main() void main()
{ {
@ -129,8 +113,9 @@ void main()
sampleWeights5; sampleWeights5;
#else #else
float sampleOffsets[5] = {0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130}; float sampleOffsets[5] = float[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 sampleWeights[5] =
float[5](0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196);
vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0]; vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0];
for (int i = 1; i < 5; i++) { for (int i = 1; i < 5; i++) {

View file

@ -12,71 +12,98 @@
#if __VERSION__ >= 130 #if __VERSION__ >= 130
#define COMPAT_VARYING out #define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#else #else
#define COMPAT_VARYING varying #define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#endif
#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif #endif
uniform mat4 MVPMatrix; uniform mat4 MVPMatrix;
COMPAT_ATTRIBUTE vec2 positionAttrib;
COMPAT_ATTRIBUTE vec2 TexCoord;
COMPAT_ATTRIBUTE vec4 colorAttrib;
COMPAT_VARYING vec4 color; COMPAT_VARYING vec4 color;
COMPAT_VARYING vec2 texCoord; COMPAT_VARYING vec2 texCoord;
void main(void) void main(void)
{ {
texCoord = gl_MultiTexCoord0.xy; color.rgba = colorAttrib.abgr;
color.rgba = gl_Color.abgr; texCoord = TexCoord;
gl_Position = MVPMatrix * gl_Vertex; gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0);
} }
#elif defined(FRAGMENT) #elif defined(FRAGMENT)
// Fragment section of code: // Fragment section of code:
#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
#if __VERSION__ >= 130 #if __VERSION__ >= 130
#define COMPAT_VARYING out #define COMPAT_VARYING in
#define COMPAT_TEXTURE texture #define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else #else
#define COMPAT_VARYING varying #define COMPAT_VARYING varying
#define COMPAT_TEXTURE texture2D #define COMPAT_TEXTURE texture2D
#define FragColor gl_FragColor
#endif #endif
COMPAT_VARYING vec4 color; COMPAT_VARYING COMPAT_PRECISION vec4 color;
COMPAT_VARYING vec2 texCoord; COMPAT_VARYING COMPAT_PRECISION vec4 color2;
uniform float opacity = 1.0f; COMPAT_VARYING COMPAT_PRECISION vec2 texCoord;
uniform float saturation = 1.0f; uniform COMPAT_PRECISION float opacity;
uniform float dimming = 1.0f; uniform COMPAT_PRECISION float saturation;
uniform int BGRAToRGBA = 0; uniform COMPAT_PRECISION float dimming;
uniform int postProcessing = 0; uniform int BGRAToRGBA;
uniform int font;
uniform int postProcessing;
uniform sampler2D myTexture; uniform sampler2D myTexture;
void main() 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 // When post-processing we drop the alpha channel to avoid strange issues
// with some graphics drivers. // with some graphics drivers.
if (postProcessing == 1) if (postProcessing == 1)
color.a = 1.0f; sampledColor.a = 1.0f;
// Opacity. // Opacity.
if (opacity != 1.0f) if (opacity != 1.0f)
color.a = color.a * opacity; sampledColor.a = sampledColor.a * opacity;
// Saturation. // Saturation.
if (saturation != 1.0f) { if (saturation != 1.0f) {
vec3 grayscale = vec3(dot(color.rgb, vec3(0.34f, 0.55f, 0.11f))); COMPAT_PRECISION vec3 grayscale = vec3(dot(sampledColor.rgb, vec3(0.34f, 0.55f, 0.11f)));
vec3 blendedColor = mix(grayscale, color.rgb, saturation); COMPAT_PRECISION vec3 blendedColor = mix(grayscale, sampledColor.rgb, saturation);
color = vec4(blendedColor, color.a); sampledColor = vec4(blendedColor, sampledColor.a);
} }
// Dimming // Dimming
if (dimming != 1.0f) { if (dimming != 1.0f) {
vec4 dimColor = vec4(dimming, dimming, dimming, 1.0f); COMPAT_PRECISION vec4 dimColor = vec4(dimming, dimming, dimming, 1.0f);
color *= dimColor; sampledColor *= dimColor;
} }
// BGRA to RGBA conversion. // BGRA to RGBA conversion.
if (BGRAToRGBA == 1) if (BGRAToRGBA == 1)
color = vec4(color.bgr, color.a); sampledColor = vec4(sampledColor.bgr, sampledColor.a);
gl_FragColor = color; FragColor = sampledColor;
} }
#endif #endif

View file

@ -29,7 +29,6 @@
#else #else
#define COMPAT_VARYING varying #define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute #define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif #endif
#ifdef GL_ES #ifdef GL_ES
@ -38,45 +37,27 @@
#define COMPAT_PRECISION #define COMPAT_PRECISION
#endif #endif
COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord; COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0; COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec2 onex; COMPAT_VARYING vec2 onex;
COMPAT_VARYING vec2 oney; COMPAT_VARYING vec2 oney;
vec4 _oPosition1;
uniform mat4 MVPMatrix; uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection; COMPAT_ATTRIBUTE vec2 positionAttrib;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize; uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize.
void main() void main()
{ {
gl_Position = MVPMatrix * gl_Vertex; gl_Position = MVPMatrix * vec4(positionAttrib.xy, 0.0, 1.0);
COL0 = COLOR; TEX0.xy = TexCoord.xy;
TEX0.xy = gl_MultiTexCoord0.xy;
onex = vec2(SourceSize.z, 0.0); onex = vec2(SourceSize.z, 0.0);
oney = vec2(0.0, SourceSize.w); oney = vec2(0.0, SourceSize.w);
} }
#elif defined(FRAGMENT) #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_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH #ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float; precision highp float;
@ -88,12 +69,18 @@ precision mediump float;
#define COMPAT_PRECISION #define COMPAT_PRECISION
#endif #endif
uniform COMPAT_PRECISION int FrameDirection; #if __VERSION__ >= 130
uniform COMPAT_PRECISION int FrameCount; #define COMPAT_VARYING in
uniform COMPAT_PRECISION vec2 OutputSize; #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 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize; uniform COMPAT_PRECISION float opacity;
uniform COMPAT_PRECISION float opacity = 1.0;
uniform sampler2D Texture; uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0; COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec2 onex; COMPAT_VARYING vec2 onex;
@ -104,7 +91,6 @@ COMPAT_VARYING vec2 oney;
#define vTexCoord TEX0.xy #define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize. #define SourceSize vec4(TextureSize, 1.0 / TextureSize) // Either TextureSize or InputSize.
#define OutputSize vec4(OutputSize, 1.0 / OutputSize)
#ifdef PARAMETER_UNIFORM #ifdef PARAMETER_UNIFORM
// All parameter floats need to have COMPAT_PRECISION in front of them. // All parameter floats need to have COMPAT_PRECISION in front of them.