From 7eead50806f4782bb09efc4a9a063f04676e3a29 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 6 Dec 2011 22:31:55 -0200 Subject: [PATCH 01/10] use GLSL shaders --- TODO | 8 +- modules/addon_console/commands.lua | 5 + modules/addon_console/console.lua | 8 +- modules/addon_console/console.otmod | 4 +- modules/client/client.lua | 2 +- modules/client_entergame/entergame.lua | 4 +- modules/client_options/options.lua | 2 +- .../core_scripts/{constants.lua => const.lua} | 6 +- modules/core_scripts/core_scripts.otmod | 8 +- modules/core_scripts/dispatcher.lua | 46 ++- modules/core_scripts/{gfx.lua => effects.lua} | 6 +- modules/core_scripts/ext/string.lua | 6 +- modules/core_scripts/ext/table.lua | 2 +- modules/core_scripts/util.lua | 14 +- modules/core_scripts/{ext => util}/color.lua | 0 modules/core_scripts/{ext => util}/point.lua | 0 modules/core_scripts/{ext => util}/rect.lua | 0 modules/core_scripts/{ext => util}/size.lua | 0 modules/core_scripts/widget.lua | 2 +- .../core_widgets/messagebox/messagebox.lua | 4 +- modules/core_widgets/tooltip/tooltip.lua | 2 +- src/framework/CMakeLists.txt | 4 + src/framework/application.cpp | 5 +- src/framework/core/module.cpp | 10 +- src/framework/graphics/animatedtexture.cpp | 2 +- src/framework/graphics/borderimage.cpp | 23 +- src/framework/graphics/declarations.h | 7 + src/framework/graphics/font.cpp | 14 +- src/framework/graphics/framebuffer.cpp | 106 ++----- src/framework/graphics/framebuffer.h | 4 +- src/framework/graphics/graphics.cpp | 285 +----------------- src/framework/graphics/graphics.h | 45 +-- src/framework/graphics/image.cpp | 6 +- src/framework/graphics/painter.cpp | 228 ++++++++++++++ src/framework/graphics/painter.h | 64 ++++ .../graphics/paintershaderprogram.cpp | 99 ++++++ src/framework/graphics/paintershaderprogram.h | 57 ++++ src/framework/graphics/paintershadersources.h | 76 +++++ src/framework/graphics/shader.cpp | 75 +++++ src/framework/graphics/shader.h | 51 ++++ src/framework/graphics/shaderprogram.cpp | 144 +++++++++ src/framework/graphics/shaderprogram.h | 93 ++++++ src/framework/graphics/texture.cpp | 12 +- src/framework/graphics/texture.h | 14 +- src/framework/luafunctions.cpp | 152 +++++++--- src/framework/platform/x11window.cpp | 2 +- src/framework/ui/uibutton.cpp | 4 +- src/framework/ui/uicheckbox.cpp | 4 +- src/framework/ui/uilineedit.cpp | 6 +- src/framework/ui/uimanager.cpp | 18 +- src/framework/ui/uiprogressbar.cpp | 8 +- src/framework/ui/uiwidget.cpp | 12 +- src/framework/util/rect.h | 4 +- src/framework/util/size.h | 4 +- src/framework/util/tools.h | 12 + src/main.cpp | 8 +- src/otclient/core/creature.cpp | 28 +- src/otclient/core/map.cpp | 6 +- src/otclient/core/thing.cpp | 2 +- src/otclient/otclient.cpp | 1 - src/otclient/ui/uicreature.cpp | 2 +- src/otclient/ui/uiitem.cpp | 2 +- src/otclient/ui/uimap.cpp | 6 +- .../generate_lua_bindings.lua | 15 +- 64 files changed, 1219 insertions(+), 630 deletions(-) create mode 100644 modules/addon_console/commands.lua rename modules/core_scripts/{constants.lua => const.lua} (96%) rename modules/core_scripts/{gfx.lua => effects.lua} (85%) rename modules/core_scripts/{ext => util}/color.lua (100%) rename modules/core_scripts/{ext => util}/point.lua (100%) rename modules/core_scripts/{ext => util}/rect.lua (100%) rename modules/core_scripts/{ext => util}/size.lua (100%) create mode 100644 src/framework/graphics/painter.cpp create mode 100644 src/framework/graphics/painter.h create mode 100644 src/framework/graphics/paintershaderprogram.cpp create mode 100644 src/framework/graphics/paintershaderprogram.h create mode 100644 src/framework/graphics/paintershadersources.h create mode 100644 src/framework/graphics/shader.cpp create mode 100644 src/framework/graphics/shader.h create mode 100644 src/framework/graphics/shaderprogram.cpp create mode 100644 src/framework/graphics/shaderprogram.h diff --git a/TODO b/TODO index e78600a8..1f448fd0 100644 --- a/TODO +++ b/TODO @@ -14,11 +14,10 @@ fix moving windows and tooltips conflicts todo display otclient icon in window bar remake otui styles states system padding - +break UILabel lines rename Game to g_game, etc implement Console key binding -fatal error if sprite load fails impl vertical sync, clipboard crash handler modify COnnection::poll() @@ -29,4 +28,7 @@ bind every global lua function in a static class use metatable for Point,Rect,Color,Size lua classes lua binder generator restore win32 platform -set special types for g_configs like lists/point/size \ No newline at end of file +set special types for g_configs like lists/point/size +restore ctrl+g and keybindings +create a class for reading binary files +handle corrupt errors in dat/spr \ No newline at end of file diff --git a/modules/addon_console/commands.lua b/modules/addon_console/commands.lua new file mode 100644 index 00000000..03ddf63d --- /dev/null +++ b/modules/addon_console/commands.lua @@ -0,0 +1,5 @@ +function dumpWidgets() + for i=1,UI.root:getChildCount() do + print(UI.root:getChildByIndex(i):getId()) + end +end \ No newline at end of file diff --git a/modules/addon_console/console.lua b/modules/addon_console/console.lua index 57dd9802..41a8e222 100644 --- a/modules/addon_console/console.lua +++ b/modules/addon_console/console.lua @@ -34,7 +34,7 @@ local function completeCommand() local cursorPos = commandLineEdit:getCursorPos() if cursorPos == 0 then return end - local commandBegin = string.sub(commandLineEdit:getText(), 1, cursorPos) + local commandBegin = commandLineEdit:getText():sub(1, cursorPos) local possibleCommands = {} -- create a list containing all globals @@ -43,7 +43,7 @@ local function completeCommand() -- match commands for k,v in pairs(allVars) do - if string.sub(k, 1, cursorPos) == commandBegin then + if k:sub(1, cursorPos) == commandBegin then table.insert(possibleCommands, k) end end @@ -63,9 +63,9 @@ local function completeCommand() if #possibleCommands[1] < cursorPos then break end - expandedComplete = commandBegin .. string.sub(possibleCommands[1], cursorPos, cursorPos) + expandedComplete = commandBegin .. possibleCommands[1]:sub(cursorPos, cursorPos) for i,v in ipairs(possibleCommands) do - if string.sub(v, 1, #expandedComplete) ~= expandedComplete then + if v:sub(1, #expandedComplete) ~= expandedComplete then done = true end end diff --git a/modules/addon_console/console.otmod b/modules/addon_console/console.otmod index bc6972b1..2a1634be 100644 --- a/modules/addon_console/console.otmod +++ b/modules/addon_console/console.otmod @@ -8,11 +8,9 @@ Module autoLoad: true autoLoadPriority: 20 - dependencies: - - core - onLoad: | require 'console' + require 'commands' Console.init() return true diff --git a/modules/client/client.lua b/modules/client/client.lua index 99ae68a5..8d074c04 100644 --- a/modules/client/client.lua +++ b/modules/client/client.lua @@ -3,7 +3,7 @@ Client = { } -- TODO: load and save configurations function Client.init() g_window.move({ x=220, y=220 }) - g_window.resize({ width=800, height=600 }) + g_window.resize({ width=800, height=480 }) g_window.setTitle('OTClient') g_window.setIcon('clienticon.png') return true diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index 93caf339..ba38bb3c 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -23,8 +23,8 @@ local function onError(protocol, error) end local function onMotd(protocol, motd) - motdNumber = tonumber(string.sub(motd, 0, string.find(motd, "\n"))) - motdMessage = string.sub(motd, string.find(motd, "\n") + 1, string.len(motd)) + motdNumber = tonumber(motd:sub(0, motd:find("\n"))) + motdMessage = motd:sub(motd:find("\n") + 1, #motd) TopMenu.getButton('motdButton'):show() end diff --git a/modules/client_options/options.lua b/modules/client_options/options.lua index 30fa3b79..68f6060a 100644 --- a/modules/client_options/options.lua +++ b/modules/client_options/options.lua @@ -7,7 +7,7 @@ local vsyncEnabled = false function getConfig(name, default) if g_configs.exists(name) then - local val = string.trim(g_configs.get(name)) + local val = g_configs.get(name):trim() if val == 'true' or val == 'false' then return toboolean(val) else diff --git a/modules/core_scripts/constants.lua b/modules/core_scripts/const.lua similarity index 96% rename from modules/core_scripts/constants.lua rename to modules/core_scripts/const.lua index b40cbb10..2783a32d 100644 --- a/modules/core_scripts/constants.lua +++ b/modules/core_scripts/const.lua @@ -1,4 +1,3 @@ --- AnchorEdge AnchorNone = 0 AnchorTop = 1 AnchorBottom = 2 @@ -15,9 +14,6 @@ LogFatal = 4 ActiveFocusReason = 2 -EmptyFunction = function() end - --- KeyCodes KeyUnknown = 0 KeyEscape = 1 KeyTab = 2 @@ -57,7 +53,7 @@ KeyLeftParen = 40 -- ( KeyRightParen = 41 -- ) KeyAsterisk = 42 -- * KeyPlus = 43 -- + -KeyComma = 44 -- +KeyComma = 44 -- , KeyMinus = 45 -- - KeyPeriod = 46 -- . KeySlash = 47 -- / diff --git a/modules/core_scripts/core_scripts.otmod b/modules/core_scripts/core_scripts.otmod index 8c52ba30..a4478608 100644 --- a/modules/core_scripts/core_scripts.otmod +++ b/modules/core_scripts/core_scripts.otmod @@ -7,10 +7,14 @@ Module onLoad: | require 'ext/table' require 'ext/string' - require 'constants' + require 'util/point' + require 'util/size' + require 'util/color' + require 'util/rect' + require 'const' require 'util' require 'dispatcher' require 'widget' require 'ui' - require 'gfx' + require 'effects' return true diff --git a/modules/core_scripts/dispatcher.lua b/modules/core_scripts/dispatcher.lua index bea374b8..ee13f5a0 100644 --- a/modules/core_scripts/dispatcher.lua +++ b/modules/core_scripts/dispatcher.lua @@ -1,43 +1,33 @@ local eventId = 0 -local eventsTable = { } -local orig = { scheduleEvent = scheduleEvent, - addEvent = addEvent } +local eventList = {} --- fix original scheduleEvent function scheduleEvent(func, delay) eventId = eventId + 1 local id = eventId local function proxyFunc() - if eventsTable[id] then - func() - eventsTable[id] = nil + if eventList[id] then + if eventList[id].active then + func() + end + eventList[id] = nil end end - eventsTable[id] = proxyFunc - orig.scheduleEvent(proxyFunc, delay) + eventList[id] = { func = proxyFunc, active = true } + if delay and delay > 0 then + g_dispatcher.scheduleEvent(proxyFunc, delay) + else + g_dispatcher.addEvent(proxyFunc, false) + end return id end --- FIXME: the event function can be collected --- and the dispatcher would call an invalid function, generating an warning +function addEvent(func) + return scheduleEvent(func, 0) +end + function removeEvent(id) - if id and eventsTable[id] then - eventsTable[id] = nil + if id and eventList[id] then + eventList[id].active = false return true end end - --- fix original addEvent -function addEvent(func) - eventId = eventId + 1 - local id = eventId - local function proxyFunc() - if eventsTable[id] then - func() - eventsTable[id] = nil - end - end - eventsTable[id] = proxyFunc - orig.addEvent(proxyFunc) - return id -end \ No newline at end of file diff --git a/modules/core_scripts/gfx.lua b/modules/core_scripts/effects.lua similarity index 85% rename from modules/core_scripts/gfx.lua rename to modules/core_scripts/effects.lua index af0aa0db..b92307a8 100644 --- a/modules/core_scripts/gfx.lua +++ b/modules/core_scripts/effects.lua @@ -1,6 +1,6 @@ -GFX = { } +Effects = {} -function GFX.fadeIn(widget, time, elapsed) +function Effects.fadeIn(widget, time, elapsed) if not elapsed then elapsed = 0 end if not time then time = 250 end widget:setOpacity(math.min((255*elapsed)/time, 255)) @@ -11,7 +11,7 @@ function GFX.fadeIn(widget, time, elapsed) end end -function GFX.fadeOut(widget, time, elapsed) +function Effects.fadeOut(widget, time, elapsed) if not elapsed then elapsed = 0 end if not time then time = 250 end widget:setOpacity((255*(time - elapsed))/time) diff --git a/modules/core_scripts/ext/string.lua b/modules/core_scripts/ext/string.lua index a619a7a9..b3bb10b6 100644 --- a/modules/core_scripts/ext/string.lua +++ b/modules/core_scripts/ext/string.lua @@ -13,12 +13,12 @@ function string:starts(start) return self:sub(1, #start) == start end -function string.trim(str) - return str:match'^%s*(.*%S)' or '' +function string:trim() + return self:match('^%s*(.*%S)') or '' end function toboolean(str) - str = string.trim(str) + str = str:trim() if str == '1' or str == 'true' then return true end diff --git a/modules/core_scripts/ext/table.lua b/modules/core_scripts/ext/table.lua index 8627cc5f..5a8e8e68 100644 --- a/modules/core_scripts/ext/table.lua +++ b/modules/core_scripts/ext/table.lua @@ -1,7 +1,7 @@ function table.dump(t, depth) if not depth then depth = 0 end for k,v in pairs(t) do - str = string.rep(' ', depth * 2) .. k .. ': ' + str = (' '):rep(depth * 2) .. k .. ': ' if type(v) ~= "table" then print(str .. tostring(v)) else diff --git a/modules/core_scripts/util.lua b/modules/core_scripts/util.lua index 9bf33688..cd65806e 100644 --- a/modules/core_scripts/util.lua +++ b/modules/core_scripts/util.lua @@ -6,10 +6,8 @@ function print(...) Logger.log(LogInfo, msg) end -function createEnvironment() - local env = { } - setmetatable(env, { __index = _G} ) - return env +function fatal(msg) + Logger.log(LogFatal, msg) end function connect(object, signalsAndSlots, pushFront) @@ -28,10 +26,10 @@ function connect(object, signalsAndSlots, pushFront) end end -function dumpWidgets() - for i=1,UI.root:getChildCount() do - print(UI.root:getChildByIndex(i):getId()) - end +function createEnvironment() + local env = { } + setmetatable(env, { __index = _G} ) + return env end function getCallingScriptSourcePath(depth) diff --git a/modules/core_scripts/ext/color.lua b/modules/core_scripts/util/color.lua similarity index 100% rename from modules/core_scripts/ext/color.lua rename to modules/core_scripts/util/color.lua diff --git a/modules/core_scripts/ext/point.lua b/modules/core_scripts/util/point.lua similarity index 100% rename from modules/core_scripts/ext/point.lua rename to modules/core_scripts/util/point.lua diff --git a/modules/core_scripts/ext/rect.lua b/modules/core_scripts/util/rect.lua similarity index 100% rename from modules/core_scripts/ext/rect.lua rename to modules/core_scripts/util/rect.lua diff --git a/modules/core_scripts/ext/size.lua b/modules/core_scripts/util/size.lua similarity index 100% rename from modules/core_scripts/ext/size.lua rename to modules/core_scripts/util/size.lua diff --git a/modules/core_scripts/widget.lua b/modules/core_scripts/widget.lua index edcc0b09..88e82ca0 100644 --- a/modules/core_scripts/widget.lua +++ b/modules/core_scripts/widget.lua @@ -16,4 +16,4 @@ function UIWidget:setMargin(...) self:setMarginBottom(params[3]) self:setMarginLeft(params[4]) end -end \ No newline at end of file +end diff --git a/modules/core_widgets/messagebox/messagebox.lua b/modules/core_widgets/messagebox/messagebox.lua index 6486371a..cd4704ba 100644 --- a/modules/core_widgets/messagebox/messagebox.lua +++ b/modules/core_widgets/messagebox/messagebox.lua @@ -28,7 +28,7 @@ function MessageBox.create(title, text, flags) if flags == MessageBoxOk then buttonRight:setText("Ok") - box.onOk = EmptyFunction + box.onOk = function() end buttonRight.onClick = function() box.onOk() box:destroy() @@ -37,7 +37,7 @@ function MessageBox.create(title, text, flags) window.onEscape = buttonRight.onClick elseif flags == MessageBoxCancel then buttonRight:setText("Cancel") - box.onCancel = EmptyFunction + box.onCancel = function() end buttonRight.onClick = function() box.onCancel() box:destroy() diff --git a/modules/core_widgets/tooltip/tooltip.lua b/modules/core_widgets/tooltip/tooltip.lua index 0dcc88ba..20630da0 100644 --- a/modules/core_widgets/tooltip/tooltip.lua +++ b/modules/core_widgets/tooltip/tooltip.lua @@ -28,7 +28,7 @@ function ToolTip.display(text) local size = label:getSize() size.width = size.width + 4 size.height = size.height + 4 - currentToolTip:setSize(size) + currentToolTip:resize(size) moveToolTip(currentToolTip) end end diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 659fc10a..a2497ef8 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -135,6 +135,7 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/graphics/font.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp @@ -142,6 +143,9 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/borderimage.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/shader.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp # framework otml ${CMAKE_CURRENT_LIST_DIR}/otml/otmldocument.cpp diff --git a/src/framework/application.cpp b/src/framework/application.cpp index 25542cc3..5adeecb4 100644 --- a/src/framework/application.cpp +++ b/src/framework/application.cpp @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include <../../oglrenderer/graphics/painter.h> Application *g_app = nullptr; @@ -134,7 +136,6 @@ void Application::terminate() // terminate graphics if(m_appFlags & Fw::AppEnableGraphics) { g_ui.terminate(); - g_graphics.terminate(); g_window.terminate(); } @@ -217,8 +218,8 @@ void Application::render() void Application::resize(const Size& size) { - g_graphics.resize(size); g_ui.resize(size); + g_graphics.resize(size); } void Application::inputEvent(const InputEvent& event) diff --git a/src/framework/core/module.cpp b/src/framework/core/module.cpp index a6bb2377..ea2361ae 100644 --- a/src/framework/core/module.cpp +++ b/src/framework/core/module.cpp @@ -79,15 +79,13 @@ bool Module::load() } } - if(m_loadCallback) { - m_loaded = m_loadCallback(); - if(!m_loaded) { - logError("Unable to load module '", m_name, "' because its onLoad event returned false"); - return false; - } + if(m_loadCallback && !m_loadCallback()) { + logError("Unable to load module '", m_name, "' because its onLoad event returned false"); + return false; } logInfo("Loaded module '", m_name, "'"); + m_loaded = true; return true; } diff --git a/src/framework/graphics/animatedtexture.cpp b/src/framework/graphics/animatedtexture.cpp index d84077b6..7d200e51 100644 --- a/src/framework/graphics/animatedtexture.cpp +++ b/src/framework/graphics/animatedtexture.cpp @@ -29,7 +29,7 @@ AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFra Texture(), m_numFrames(numFrames) { - m_size.setSize(width, height); + m_size.resize(width, height); m_framesTextureId.resize(numFrames); m_framesDelay.resize(numFrames); diff --git a/src/framework/graphics/borderimage.cpp b/src/framework/graphics/borderimage.cpp index 2fa82dca..9e5dd228 100644 --- a/src/framework/graphics/borderimage.cpp +++ b/src/framework/graphics/borderimage.cpp @@ -137,68 +137,63 @@ void BorderImage::draw(const Rect& screenCoords) Rect rectCoords; Size centerSize = screenCoords.size() - m_bordersSize; - g_graphics.bindTexture(m_texture); - g_graphics.startDrawing(); - // first the center if(centerSize.area() > 0) { rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(), screenCoords.top() + m_topBorderTexCoords.height(), centerSize); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords); + g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords); } // top left corner rectCoords = Rect(screenCoords.topLeft(), m_topLeftCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_topLeftCornerTexCoords); + g_painter.drawTexturedRect(rectCoords, m_texture, m_topLeftCornerTexCoords); // top rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width(), screenCoords.topLeft().y, centerSize.width(), m_topBorderTexCoords.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_topBorderTexCoords); + g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_topBorderTexCoords); // top right corner rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width() + centerSize.width(), screenCoords.top(), m_topRightCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_topRightCornerTexCoords); + g_painter.drawTexturedRect(rectCoords, m_texture, m_topRightCornerTexCoords); // left rectCoords = Rect(screenCoords.left(), screenCoords.top() + m_topLeftCornerTexCoords.height(), m_leftBorderTexCoords.width(), centerSize.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_leftBorderTexCoords); + g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_leftBorderTexCoords); // right rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width() + centerSize.width(), screenCoords.top() + m_topRightCornerTexCoords.height(), m_rightBorderTexCoords.width(), centerSize.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_rightBorderTexCoords); + g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_rightBorderTexCoords); // bottom left corner rectCoords = Rect(screenCoords.left(), screenCoords.top() + m_topLeftCornerTexCoords.height() + centerSize.height(), m_bottomLeftCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_bottomLeftCornerTexCoords); + g_painter.drawTexturedRect(rectCoords, m_texture, m_bottomLeftCornerTexCoords); // bottom rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width(), screenCoords.top() + m_topBorderTexCoords.height() + centerSize.height(), centerSize.width(), m_bottomBorderTexCoords.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_bottomBorderTexCoords); + g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_bottomBorderTexCoords); // bottom right corner rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width() + centerSize.width(), screenCoords.top() + m_topRightCornerTexCoords.height() + centerSize.height(), m_bottomRightCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_bottomRightCornerTexCoords); - - g_graphics.stopDrawing(); + g_painter.drawTexturedRect(rectCoords, m_texture, m_bottomRightCornerTexCoords); } \ No newline at end of file diff --git a/src/framework/graphics/declarations.h b/src/framework/graphics/declarations.h index 54a14cac..132d6343 100644 --- a/src/framework/graphics/declarations.h +++ b/src/framework/graphics/declarations.h @@ -32,6 +32,9 @@ class Font; class Image; class BorderImage; class FrameBuffer; +class Shader; +class ShaderProgram; +class PainterShaderProgram; typedef std::weak_ptr TextureWeakPtr; @@ -41,5 +44,9 @@ typedef std::shared_ptr FontPtr; typedef std::shared_ptr ImagePtr; typedef std::shared_ptr BorderImagePtr; typedef std::shared_ptr FrameBufferPtr; +typedef std::shared_ptr ShaderPtr; +typedef std::shared_ptr ShaderProgramPtr; +typedef std::shared_ptr PainterShaderProgramPtr; +typedef std::vector ShaderList; #endif diff --git a/src/framework/graphics/font.cpp b/src/framework/graphics/font.cpp index 29a4246c..ac7c0cef 100644 --- a/src/framework/graphics/font.cpp +++ b/src/framework/graphics/font.cpp @@ -64,7 +64,7 @@ void Font::renderText(const std::string& text, const Point& startPos, const Color& color) { - Size boxSize = g_graphics.getScreenSize() - startPos.toSize(); + Size boxSize = g_graphics.getViewportSize() - startPos.toSize(); Rect screenCoords(startPos, boxSize); renderText(text, screenCoords, Fw::AlignTopLeft, color); } @@ -85,9 +85,7 @@ void Font::renderText(const std::string& text, Size textBoxSize; const std::vector& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize); - g_graphics.bindColor(color); - g_graphics.bindTexture(m_texture); - g_graphics.startDrawing(); + g_painter.setColor(color); for(int i = 0; i < textLenght; ++i) { int glyph = (uchar)text[i]; @@ -149,10 +147,8 @@ void Font::renderText(const std::string& text, } // render glyph - g_graphics.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords); + g_painter.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords); } - - g_graphics.stopDrawing(); } const std::vector& Font::calculateGlyphsPositions(const std::string& text, @@ -172,7 +168,7 @@ const std::vector& Font::calculateGlyphsPositions(const std::string& text // return if there is no text if(textLength == 0) { if(textBoxSize) - textBoxSize->setSize(0,m_glyphHeight); + textBoxSize->resize(0,m_glyphHeight); return glyphsPositions; } @@ -280,6 +276,6 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize) lastColumnFilledPixels = columnFilledPixels; } // store glyph size - m_glyphsSize[glyph].setSize(width, m_glyphHeight); + m_glyphsSize[glyph].resize(width, m_glyphHeight); } } diff --git a/src/framework/graphics/framebuffer.cpp b/src/framework/graphics/framebuffer.cpp index 3cd16bdb..8d7ba498 100644 --- a/src/framework/graphics/framebuffer.cpp +++ b/src/framework/graphics/framebuffer.cpp @@ -26,110 +26,52 @@ FrameBuffer::FrameBuffer(int width, int height) { - m_fbo = 0; - // create FBO texture m_texture = TexturePtr(new Texture(width, height, 4)); m_texture->enableBilinearFilter(); - // use FBO ext only if supported - if(g_graphics.isExtensionSupported("GL_ARB_framebuffer_object")) { - m_fallbackOldImp = false; + // generate FBO + glGenFramebuffers(1, &m_fbo); + if(!m_fbo) + logFatal("Unable to create framebuffer object"); - // generate FBO - glGenFramebuffers(1, &m_fbo); - glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); - // attach 2D texture to this FBO - glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->getId(), 0); + // attach 2D texture to this FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); - switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - //ok - break; - default: // fallback to old implementation - m_fallbackOldImp = true; - break; - } + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if(status != GL_FRAMEBUFFER_COMPLETE) + logFatal("Unable to create framebuffer object"); - // restore back buffer - glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - glDrawBuffer(GL_BACK); - glReadBuffer(GL_BACK); - } else { - // otherwise fallback to copy texture from screen implementation - m_fallbackOldImp = true; - } - - if(m_fallbackOldImp) - logInfo("Framebuffers not supported, falling back to old implementation."); + // restore back buffer + glBindFramebuffer(GL_FRAMEBUFFER, 0); } FrameBuffer::~FrameBuffer() { - if(m_fbo) - glDeleteFramebuffers(1, &m_fbo); + glDeleteFramebuffers(1, &m_fbo); } void FrameBuffer::bind() { - if(!m_fallbackOldImp) { - // bind framebuffer - glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); - } else { - int screenWidth = g_graphics.getScreenSize().width(); - int screenHeight = g_graphics.getScreenSize().height(); - - if(!m_screenBackup || m_screenBackup->getSize() != g_graphics.getScreenSize()) - m_screenBackup = TexturePtr(new Texture(screenWidth, screenHeight, 4)); - - // save screen state - glBindTexture(GL_TEXTURE_2D, m_screenBackup->getId()); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth, screenHeight); - } - - // setup framebuffer viewport - glViewport(0, 0, m_texture->getWidth(), m_texture->getHeight()); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0f, m_texture->getWidth(), m_texture->getHeight(), 0, -1, 1); - - // back to model view - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // clear framebuffer - glClearColor(0.0, 0.0, 0.0, 1.0); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, m_texture->getWidth(), m_texture->getHeight()); + g_painter.updateProjectionMatrix(m_texture->getSize(), true); } -void FrameBuffer::unbind() +void FrameBuffer::release() { - if(!m_fallbackOldImp) { - // bind back buffer again - glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - glDrawBuffer(GL_BACK); - glReadBuffer(GL_BACK); + // bind back buffer again + glBindFramebuffer(GL_FRAMEBUFFER, 0); - // restore graphics viewport - g_graphics.restoreViewport(); - } else { - // copy screen to texture - glBindTexture(GL_TEXTURE_2D, m_texture->getId()); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_texture->getWidth(), m_texture->getHeight()); - - // restore graphics viewport - g_graphics.restoreViewport(); - - // restore screen - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - g_graphics.drawTexturedRect(Rect(Point(0,0), g_graphics.getScreenSize()), m_screenBackup, Rect(), true); - } + // restore graphics viewport + glViewport(0, 0, g_graphics.getViewportSize().width(), g_graphics.getViewportSize().height()); + g_painter.updateProjectionMatrix(g_graphics.getViewportSize()); } -void FrameBuffer::draw(const Rect& screenCoords, const Rect& framebufferCoords) +void FrameBuffer::draw(const Rect& dest) { - g_graphics.drawTexturedRect(screenCoords, m_texture, framebufferCoords, true); + g_painter.drawTexturedRect(dest, m_texture); } diff --git a/src/framework/graphics/framebuffer.h b/src/framework/graphics/framebuffer.h index 182ef1a9..16ce6cdc 100644 --- a/src/framework/graphics/framebuffer.h +++ b/src/framework/graphics/framebuffer.h @@ -32,8 +32,8 @@ public: virtual ~FrameBuffer(); void bind(); - void unbind(); - void draw(const Rect& screenCoords, const Rect& framebufferCoords = Rect()); + void release(); + void draw(const Rect& dest); TexturePtr getTexture() { return m_texture; } diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index d768b568..b8ca60b3 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -30,307 +30,48 @@ Graphics g_graphics; void Graphics::init() { // setup opengl - glEnable(GL_ALPHA_TEST); // enable alpha by default - glAlphaFunc(GL_GREATER, 0.0f); // default alpha func - glDisable(GL_DEPTH_TEST); // we are rendering 2D only, we don't need depth buffer - glEnable(GL_TEXTURE_2D); // enable textures by default - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glShadeModel(GL_SMOOTH); glEnable(GL_BLEND); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); logInfo("GPU ", glGetString(GL_RENDERER)); logInfo("OpenGL ", glGetString(GL_VERSION)); - m_drawing = false; - m_opacity = 255; + //if(!isExtensionSupported("GL_ARB_framebuffer_object")) + // logFatal("Your graphics card is not supported."); + m_emptyTexture = TexturePtr(new Texture); - bindColor(Fw::white); - bindBlendFunc(Fw::BlendDefault); + g_painter.init(); } void Graphics::terminate() { g_fonts.releaseFonts(); + g_painter.terminate(); m_emptyTexture.reset(); } bool Graphics::isExtensionSupported(const char *extension) { - const GLubyte *extensions = NULL; - const GLubyte *start; - GLubyte *where, *terminator; - where = (GLubyte *)strchr(extension, ' '); - - if(where || *extension == '\0') - return 0; - - extensions = glGetString(GL_EXTENSIONS); - - start = extensions; - while(true) { - where = (GLubyte *) strstr((const char *)start, extension); - if(!where) - break; - - terminator = where + strlen(extension); - - if(where == start || *(where - 1) == ' ') - if(*terminator == ' ' || *terminator == '\0') - return 1; - - start = terminator; - } - return 0; + std::string extensionsString = (const char*)glGetString(GL_EXTENSIONS); + auto extensions = Fw::split(extensionsString); + return std::find(extensions.begin(), extensions.end(), extension) != extensions.end(); } void Graphics::resize(const Size& size) { - m_screenSize = size; - restoreViewport(); -} - -void Graphics::restoreViewport() -{ - const int& width = m_screenSize.width(); - const int& height = m_screenSize.height(); - - // resize gl viewport - glViewport(0, 0, width, height); - - /* - 0,0---------0,w - | | - | | - | | - h,0---------h,w - */ - // setup view region like above - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0f, width, height, 0.0f, -1, 1); - - // back to model view - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + glViewport(0, 0, size.width(), size.height()); + g_painter.updateProjectionMatrix(size); + m_viewportSize = size; } void Graphics::beginRender() { glClear(GL_COLOR_BUFFER_BIT); - glLoadIdentity(); } void Graphics::endRender() { - assert(!m_drawing); -} - -void Graphics::drawTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords, - bool upsideDown) -{ - if(screenCoords.isEmpty() || texture->getId() == 0) - return; - - // rect correction for opengl - int right = screenCoords.right() + 1; - int bottom = screenCoords.bottom() + 1; - int top = screenCoords.top(); - int left = screenCoords.left(); - - float textureRight; - float textureBottom; - float textureTop; - float textureLeft; - const Size& textureSize = texture->getGlSize(); - - if(textureCoords.isEmpty()) { - textureRight = texture->getWidth() / (float)textureSize.width(); - if(upsideDown) { - textureBottom = 0.0f; - textureTop = texture->getHeight() / (float)textureSize.height(); - } else { - textureBottom = texture->getHeight() / (float)textureSize.height(); - textureTop = 0.0f; - } - textureLeft = 0.0f; - } else { - textureRight = (textureCoords.right() + 1) / (float)textureSize.width(); - if(upsideDown) { - textureTop = (textureCoords.bottom() + 1) / (float)textureSize.height(); - textureBottom = textureCoords.top() / (float)textureSize.height(); - } else { - textureBottom = (textureCoords.bottom() + 1) / (float)textureSize.height(); - textureTop = textureCoords.top() / (float)textureSize.height(); - } - textureLeft = textureCoords.left() / (float)textureSize.width(); - } - - if(!m_drawing) { - bindTexture(texture); - glBegin(GL_QUADS); - } - - glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); - glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); - glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); - glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); - - if(!m_drawing) - glEnd(); -} - -void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords) -{ - if(screenCoords.isEmpty() || texture->getId() == 0 || textureCoords.isEmpty()) - return; - - bool mustStopDrawing = false; - if(!m_drawing) { - bindTexture(texture); - startDrawing(); - mustStopDrawing = true; - } - - // render many repeated texture rects - Rect virtualScreenCoords(0,0,screenCoords.size()); - for(int y = 0; y <= virtualScreenCoords.height(); y += textureCoords.height()) { - for(int x = 0; x <= virtualScreenCoords.width(); x += textureCoords.width()) { - Rect partialCoords(x, y, textureCoords.size()); - Rect partialTextureCoords = textureCoords; - - // partialCoords to screenCoords bottomRight - if(partialCoords.bottom() > virtualScreenCoords.bottom()) { - partialTextureCoords.setBottom(partialTextureCoords.bottom() + - (virtualScreenCoords.bottom() - partialCoords.bottom())); - partialCoords.setBottom(virtualScreenCoords.bottom()); - } - if(partialCoords.right() > virtualScreenCoords.right()) { - partialTextureCoords.setRight(partialTextureCoords.right() + - (virtualScreenCoords.right() - partialCoords.right())); - partialCoords.setRight(virtualScreenCoords.right()); - } - - partialCoords.translate(screenCoords.topLeft()); - drawTexturedRect(partialCoords, texture, partialTextureCoords); - } - } - - if(mustStopDrawing) - stopDrawing(); -} - -void Graphics::drawFilledRect(const Rect& screenCoords) -{ - assert(!m_drawing); - - if(screenCoords.isEmpty()) - return; - - // rect correction for opengl - int right = screenCoords.right() + 1; - int bottom = screenCoords.bottom() + 1; - int top = screenCoords.top(); - int left = screenCoords.left(); - - glDisable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - - glVertex2i(left, top); - glVertex2i(left, bottom); - glVertex2i(right, bottom); - glVertex2i(right, top); - - glEnd(); - glEnable(GL_TEXTURE_2D); -} - - -void Graphics::drawBoundingRect(const Rect& screenCoords, - int innerLineWidth) -{ - assert(!m_drawing); - - if(screenCoords.isEmpty() || 2 * innerLineWidth > screenCoords.height()) - return; - - // rect correction for opengl - int right = screenCoords.right()+1; - int bottom = screenCoords.bottom()+1; - int top = screenCoords.top(); - int left = screenCoords.left(); - - glDisable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - - // top line - glVertex2i(left, top); - glVertex2i(left, top + innerLineWidth); - glVertex2i(right, top + innerLineWidth); - glVertex2i(right, top); - - // left - glVertex2i(left, screenCoords.top() + innerLineWidth); - glVertex2i(left, bottom - innerLineWidth); - glVertex2i(left + innerLineWidth, bottom - innerLineWidth); - glVertex2i(left + innerLineWidth, screenCoords.top() + innerLineWidth); - - // bottom line - glVertex2i(left, bottom); - glVertex2i(left, bottom - innerLineWidth); - glVertex2i(right, bottom - innerLineWidth); - glVertex2i(right, bottom); - - // right line - glVertex2i(right , top + innerLineWidth); - glVertex2i(right , bottom - innerLineWidth); - glVertex2i(right - innerLineWidth, bottom - innerLineWidth); - glVertex2i(right - innerLineWidth, top + innerLineWidth); - - glEnd(); - glEnable(GL_TEXTURE_2D); -} - -void Graphics::bindColor(const Color& color) -{ - Color tmp = color; - tmp.setAlpha(std::min((uint8)m_opacity, color.a())); - glColor4ubv(tmp.rgbaPtr()); -} - -void Graphics::bindTexture(const TexturePtr& texture) -{ - glBindTexture(GL_TEXTURE_2D, texture->getId()); -} - -void Graphics::bindBlendFunc(Fw::BlendFunc blendType) -{ - switch(blendType) { - case Fw::BlendDefault: - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - case Fw::BlendColorzing: - glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); - break; - } -} - -void Graphics::startDrawing() -{ - assert(!m_drawing); - glBegin(GL_QUADS); - m_drawing = true; -} - -void Graphics::stopDrawing() -{ - assert(m_drawing); - glEnd(); - m_drawing = false; + glFlush(); } diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h index fcc26feb..4096666b 100644 --- a/src/framework/graphics/graphics.h +++ b/src/framework/graphics/graphics.h @@ -24,64 +24,25 @@ #define GRAPHICS_H #include "declarations.h" +#include "painter.h" class Graphics { public: - /// Initialize default OpenGL states void init(); - - /// Termiante graphics void terminate(); - /// Check if a GL extension is supported bool isExtensionSupported(const char *extension); - /// Resizes OpenGL viewport void resize(const Size& size); - - /// Restore original viewport - void restoreViewport(); - - /// Called before every render void beginRender(); - - /// Called after every render void endRender(); - void bindColor(const Color& color); - void bindTexture(const TexturePtr& texture); - void bindBlendFunc(Fw::BlendFunc blendType); - - // drawing API - void drawTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords = Rect(), - bool upsideDown = false); - - void drawRepeatedTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords); - - void drawFilledRect(const Rect& screenCoords); - - void drawBoundingRect(const Rect& screenCoords, - int innerLineWidth = 1); - - const Size& getScreenSize() const { return m_screenSize; } - - void startDrawing(); - void stopDrawing(); - bool isDrawing() const { return m_drawing; } - - int getOpacity() const { return m_opacity; } - void setOpacity(int opacity) { m_opacity = opacity; } + const Size& getViewportSize() const { return m_viewportSize; } TexturePtr getEmptyTexture() { return m_emptyTexture; } private: - bool m_drawing; - int m_opacity; - Size m_screenSize; + Size m_viewportSize; TexturePtr m_emptyTexture; }; diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp index 146f0016..e3e04fd0 100644 --- a/src/framework/graphics/image.cpp +++ b/src/framework/graphics/image.cpp @@ -63,12 +63,12 @@ void Image::draw(const Rect& screenCoords) else if(texSize.width() > texCoordsSize.width()) texCoordsOffset.x = (texSize.width() - texCoordsSize.width())/2; - g_graphics.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize)); + g_painter.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize)); } else { if(m_repeated) - g_graphics.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords); + g_painter.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords); else - g_graphics.drawTexturedRect(screenCoords, m_texture, m_textureCoords); + g_painter.drawTexturedRect(screenCoords, m_texture, m_textureCoords); } } } diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp new file mode 100644 index 00000000..3a439513 --- /dev/null +++ b/src/framework/graphics/painter.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "painter.h" +#include "texture.h" +#include "paintershadersources.h" +#include "paintershaderprogram.h" +#include "shaderprogram.h" +#include "graphics.h" + +Painter g_painter; + +void Painter::init() +{ + setColor(Fw::white); + setOpacity(255); + setCompositionMode(CompositionMode_SourceOver); + + PainterShaderProgramPtr program = PainterShaderProgramPtr(new PainterShaderProgram); + program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader); + program->addShaderFromSourceCode(Shader::Vertex, glslPositionOnlyVertexShader); + program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader); + program->addShaderFromSourceCode(Shader::Fragment, glslTextureSrcFragmentShader); + program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); + program->bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); + assert(program->link()); + program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); + program->bindUniformLocation(PainterShaderProgram::TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix"); + program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); + program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); + program->bindUniformLocation(PainterShaderProgram::TEXTURE_UNIFORM, "texture"); + m_drawTexturedProgram = program; + + program = PainterShaderProgramPtr(new PainterShaderProgram); + program->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader); + program->addShaderFromSourceCode(Shader::Vertex, glslPositionOnlyVertexShader); + program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader); + program->addShaderFromSourceCode(Shader::Fragment, glslSolidColorFragmentShader); + program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); + assert(program->link()); + program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); + program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); + program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); + m_drawSolidColorProgram = program; +} + +void Painter::terminate() +{ + m_drawTexturedProgram.reset(); + m_drawSolidColorProgram.reset(); +} + +void Painter::updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis) +{ + // The projection matrix converts from Painter's coordinate system to GL's coordinate system + // * GL's viewport is 2x2, Painter's is width x height + // * GL has +y -> -y going from bottom -> top, Painter is the other way round + // * GL has [0,0] in the center, Painter has it in the top-left + // + // This results in the Projection matrix below, which is multiplied by the painter's + // transformation matrix, as shown below: + // + // Projection Matrix Painter Coord GL Coord + // ------------------------------------------------ --------- --------- + // | 2.0 / width | 0.0 | -1.0 | | x | | y' | + // | 0.0 | -2.0 / height | 1.0 | * | y | = | x' | + // | 0.0 | 0.0 | 0.0 | | 1 | | 0 | + // ------------------------------------------------ --------- --------- + float w = viewportSize.width(); + float h = viewportSize.height(); + if(inverseYAxis) { + m_projectionMatrix[0][0] = 2.0f/w; m_projectionMatrix[0][1] = 0.0f; m_projectionMatrix[0][2] =-1.0f; + m_projectionMatrix[1][0] = 0.0f; m_projectionMatrix[1][1] = 2.0f/h; m_projectionMatrix[1][2] =-1.0f; + m_projectionMatrix[2][0] = 0.0f; m_projectionMatrix[2][1] = 0.0f; m_projectionMatrix[2][2] = 0.0f; + } else { + m_projectionMatrix[0][0] = 2.0f/w; m_projectionMatrix[0][1] = 0.0f; m_projectionMatrix[0][2] =-1.0f; + m_projectionMatrix[1][0] = 0.0f; m_projectionMatrix[1][1] =-2.0f/h; m_projectionMatrix[1][2] = 1.0f; + m_projectionMatrix[2][0] = 0.0f; m_projectionMatrix[2][1] = 0.0f; m_projectionMatrix[2][2] = 0.0f; + } +} + +void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture) +{ + drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); +} + +void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + GLfloat vertexCoords[] = { (float)dest.left(), (float)dest.top(), + (float)dest.right()+1, (float)dest.top(), + (float)dest.left(), (float)dest.bottom()+1, + (float)dest.right()+1, (float)dest.bottom()+1 }; + + GLfloat textureCoords[] = { (float)src.left(), (float)src.top(), + (float)src.right()+1, (float)src.top(), + (float)src.left(), (float)src.bottom()+1, + (float)src.right()+1, (float)src.bottom()+1 }; + + m_drawTexturedProgram->prepareForDraw(); + m_drawTexturedProgram->setProjectionMatrix(m_projectionMatrix); + m_drawTexturedProgram->setOpacity(m_currentOpacity); + m_drawTexturedProgram->setColor(m_currentColor); + m_drawTexturedProgram->setTexture(texture); + m_drawTexturedProgram->setVertexCoords(vertexCoords); + m_drawTexturedProgram->setTextureCoords(textureCoords); + m_drawTexturedProgram->drawTriangleStrip(4); + m_drawTexturedProgram->releaseFromDraw(); +} + +void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + //TODO: use vertex arrays.. + Rect virtualDest(0, 0, dest.size()); + for(int y = 0; y <= virtualDest.height(); y += src.height()) { + for(int x = 0; x <= virtualDest.width(); x += src.width()) { + Rect partialDest(x, y, src.size()); + Rect partialSrc = src; + + // partialCoords to screenCoords bottomRight + if(partialDest.bottom() > virtualDest.bottom()) { + partialSrc.setBottom(partialSrc.bottom() + (virtualDest.bottom() - partialDest.bottom())); + partialDest.setBottom(virtualDest.bottom()); + } + if(partialDest.right() > virtualDest.right()) { + partialSrc.setRight(partialSrc.right() + (virtualDest.right() - partialDest.right())); + partialDest.setRight(virtualDest.right()); + } + + partialDest.translate(dest.topLeft()); + drawTexturedRect(partialDest, texture, partialSrc); + } + } +} + +void Painter::drawFilledRect(const Rect& dest) +{ + if(dest.isEmpty()) + return; + + GLfloat right = dest.right()+1; + GLfloat bottom = dest.bottom()+1; + GLfloat top = dest.top(); + GLfloat left = dest.left(); + + GLfloat vertexCoords[] = { left, top, + right, top, + left, bottom, + right, bottom }; + + m_drawSolidColorProgram->prepareForDraw(); + m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix); + m_drawSolidColorProgram->setOpacity(m_currentOpacity); + m_drawSolidColorProgram->setColor(m_currentColor); + m_drawSolidColorProgram->setVertexCoords(vertexCoords); + m_drawSolidColorProgram->drawTriangleStrip(4); + m_drawSolidColorProgram->releaseFromDraw(); +} + +void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth) +{ + if(dest.isEmpty() || innerLineWidth == 0) + return; + + GLfloat right = dest.right()+1; + GLfloat bottom = dest.bottom()+1; + GLfloat top = dest.top(); + GLfloat left = dest.left(); + GLfloat w = innerLineWidth; + + GLfloat vertexCoords[] = { left, top, + right, top, + left, top+w, + right, top+w, + right-w, top+w, + right, bottom, + right-w, bottom, + right-w, bottom-w, + left, bottom, + left, bottom-w, + left+w, bottom-w, + left, top+w, + left+w, top+w }; + + m_drawSolidColorProgram->prepareForDraw(); + m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix); + m_drawSolidColorProgram->setOpacity(m_currentOpacity); + m_drawSolidColorProgram->setColor(m_currentColor); + m_drawSolidColorProgram->setVertexCoords(vertexCoords); + m_drawSolidColorProgram->drawTriangleStrip(13); + m_drawSolidColorProgram->releaseFromDraw(); +} + +void Painter::setCompositionMode(Painter::CompositionMode compositionMode) +{ + switch(compositionMode) { + case CompositionMode_SourceOver: + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + case CompositionMode_ColorizeDest: + glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); + break; + } +} diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h new file mode 100644 index 00000000..b336d90c --- /dev/null +++ b/src/framework/graphics/painter.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PAINTER_H +#define PAINTER_H + +#include "declarations.h" + +class Painter +{ +public: + enum CompositionMode { + CompositionMode_SourceOver, + CompositionMode_ColorizeDest + }; + + void init(); + void terminate(); + + void updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis = false); + void drawTexturedRect(const Rect& dest, const TexturePtr& texture); + void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawFilledRect(const Rect& dest); + void drawBoundingRect(const Rect& dest, int innerLineWidth = 1); + + void setColor(const Color& color) { m_currentColor = color; } + Color getColor() { return m_currentColor; } + + void setOpacity(int opacity) { m_currentOpacity = opacity / 255.0f; } + int getOpacity() { return m_currentOpacity * 255.0f; } + + void setCompositionMode(CompositionMode compositionMode); + +private: + PainterShaderProgramPtr m_drawTexturedProgram; + PainterShaderProgramPtr m_drawSolidColorProgram; + GLfloat m_projectionMatrix[3][3]; + Color m_currentColor; + GLfloat m_currentOpacity; +}; + +extern Painter g_painter; + +#endif diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp new file mode 100644 index 00000000..645078e2 --- /dev/null +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "paintershaderprogram.h" +#include "painter.h" +#include "texture.h" +#include "texturemanager.h" + +void PainterShaderProgram::setProjectionMatrix(float projectionMatrix[3][3]) +{ + setUniformValue(PROJECTION_MATRIX_UNIFORM, projectionMatrix, true); +} + +void PainterShaderProgram::setColor(const Color& color) +{ + setUniformValue(COLOR_UNIFORM, + color.r() / 255.0f, + color.g() / 255.0f, + color.b() / 255.0f, + color.a() / 255.0f); +} + +void PainterShaderProgram::setOpacity(GLfloat opacity) +{ + setUniformValue(OPACITY_UNIFORM, opacity); +} + +void PainterShaderProgram::setTexture(const TexturePtr& texture) +{ + float w = texture->getGlSize().width(); + float h = texture->getGlSize().height(); + + GLfloat textureTransformMatrix[2][2] = { + { 1.0f/w, 0.0f }, + { 0.0f, 1.0f/h } + }; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->getId()); + setUniformValue(TEXTURE_UNIFORM, 0); + setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix, true); +} + +void PainterShaderProgram::setVertexCoords(const GLfloat *vertices) +{ + enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); + setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, vertices, 2); +} + +void PainterShaderProgram::setTextureCoords(const GLfloat *textureCoords) +{ + enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); + setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, textureCoords, 2); + m_mustDisableTexCoordsArray = true; +} + +void PainterShaderProgram::prepareForDraw() +{ + assert(bind()); +} + +void PainterShaderProgram::drawTriangleStrip(int numVertices) +{ + glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices); +} + +void PainterShaderProgram::releaseFromDraw() +{ + if(m_mustDisableTexCoordsArray) { + disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); + m_mustDisableTexCoordsArray = false; + } + + if(m_mustDisableVertexArray) { + disableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); + m_mustDisableVertexArray = false; + } + + //release(); +} diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h new file mode 100644 index 00000000..74bb728e --- /dev/null +++ b/src/framework/graphics/paintershaderprogram.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PAINTERSHADER_H +#define PAINTERSHADER_H + +#include "shaderprogram.h" + +class PainterShaderProgram : public ShaderProgram +{ +public: + enum { + VERTEX_COORDS_ATTR = 0, + TEXTURE_COORDS_ATTR = 1, + PROJECTION_MATRIX_UNIFORM = 0, + TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1, + COLOR_UNIFORM = 2, + OPACITY_UNIFORM = 3, + TEXTURE_UNIFORM = 4 + }; + + void setProjectionMatrix(GLfloat projectionMatrix[3][3]); + void setColor(const Color& color); + void setOpacity(GLfloat opacity); + void setTexture(const TexturePtr& texture); + void setVertexCoords(const GLfloat *vertices); + void setTextureCoords(const GLfloat *textureCoords); + + void prepareForDraw(); + void drawTriangleStrip(int numVertices); + void releaseFromDraw(); + +private: + Boolean m_mustDisableVertexArray; + Boolean m_mustDisableTexCoordsArray; +}; + +#endif diff --git a/src/framework/graphics/paintershadersources.h b/src/framework/graphics/paintershadersources.h new file mode 100644 index 00000000..a020be4b --- /dev/null +++ b/src/framework/graphics/paintershadersources.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +static int VERTEX_COORDS_ATTR = 0; +static int TEXTURE_COORDS_ATTR = 1; + +static int PROJECTION_MATRIX_UNIFORM = 0; +static int TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1; +static int COLOR_UNIFORM = 2; +static int OPACITY_UNIFORM = 3; +static int TEXTURE_UNIFORM = 4; + +static const char *glslMainVertexShader = "\n\ + vec4 calculatePosition();\n\ + void main() {\n\ + gl_Position = calculatePosition();\n\ + }\n"; + +static const char *glslMainWithTexCoordsVertexShader = "\n\ + attribute vec2 textureCoord;\n\ + uniform mat2 textureTransformMatrix;\n\ + varying vec2 textureCoords;\n\ + vec4 calculatePosition();\n\ + void main()\n\ + {\n\ + gl_Position = calculatePosition();\n\ + textureCoords = textureTransformMatrix * textureCoord;\n\ + }\n"; + +static const char *glslPositionOnlyVertexShader = "\n\ + attribute vec2 vertexCoord;\n\ + uniform mat3 projectionMatrix;\n\ + vec4 calculatePosition() {\n\ + return vec4(projectionMatrix * vec3(vertexCoord.xy, 1), 1);\n\ + }\n"; + +static const char *glslMainFragmentShader = "\n\ + uniform float opacity;\n\ + vec4 calculatePixel();\n\ + void main()\n\ + {\n\ + gl_FragColor = calculatePixel() * opacity;\n\ + }\n"; + +static const char *glslTextureSrcFragmentShader = "\n\ + varying vec2 textureCoords;\n\ + uniform vec4 color;\n\ + uniform sampler2D texture;\n\ + vec4 calculatePixel() {\n\ + return texture2D(texture, textureCoords) * color;\n\ + }\n"; + +static const char *glslSolidColorFragmentShader = "\n\ + uniform vec4 color;\n\ + vec4 calculatePixel() {\n\ + return color;\n\ + }\n"; diff --git a/src/framework/graphics/shader.cpp b/src/framework/graphics/shader.cpp new file mode 100644 index 00000000..328ae81c --- /dev/null +++ b/src/framework/graphics/shader.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shader.h" + +Shader::Shader(Shader::ShaderType shaderType) +{ + m_shaderType = shaderType; + switch(shaderType) { + case Vertex: + m_shaderId = glCreateShader(GL_VERTEX_SHADER); + break; + case Fragment: + m_shaderId = glCreateShader(GL_FRAGMENT_SHADER); + break; + } + + if(!m_shaderId) + logFatal("Unable to create GL shader"); +} + +Shader::~Shader() +{ + glDeleteShader(m_shaderId); +} + +bool Shader::compileSourceCode(const std::string& sourceCode) +{ + const char *c_source = sourceCode.c_str(); + glShaderSource(m_shaderId, 1, &c_source, NULL); + glCompileShader(m_shaderId); + + int res; + glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &res); + return (res == GL_TRUE); +} + +bool Shader::compileSourceFile(const std::string& sourceFile) +{ + std::ifstream fin(sourceFile); + std::string sourceCode((std::istreambuf_iterator(fin)), std::istreambuf_iterator()); + return compileSourceCode(sourceCode); +} + +std::string Shader::log() +{ + std::string infoLog; + GLint infoLogLength; + glGetShaderiv(m_shaderId, GL_INFO_LOG_LENGTH, &infoLogLength); + if(infoLogLength > 1) { + std::vector buf(infoLogLength); + glGetShaderInfoLog(m_shaderId, infoLogLength-1, NULL, &buf[0]); + infoLog = &buf[0]; + } + return infoLog; +} diff --git a/src/framework/graphics/shader.h b/src/framework/graphics/shader.h new file mode 100644 index 00000000..226fe20e --- /dev/null +++ b/src/framework/graphics/shader.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHADER_H +#define SHADER_H + +#include "declarations.h" + +class Shader +{ +public: + enum ShaderType { + Vertex, + Fragment + }; + + Shader(ShaderType shaderType); + ~Shader(); + + bool compileSourceCode(const std::string& sourceCode); + bool compileSourceFile(const std::string& sourceFile); + std::string log(); + + GLuint getShaderId() { return m_shaderId; } + ShaderType getShaderType() { return m_shaderType; } + +private: + GLuint m_shaderId; + ShaderType m_shaderType; +}; + +#endif diff --git a/src/framework/graphics/shaderprogram.cpp b/src/framework/graphics/shaderprogram.cpp new file mode 100644 index 00000000..8899f07a --- /dev/null +++ b/src/framework/graphics/shaderprogram.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shaderprogram.h" + +GLuint ShaderProgram::m_currentProgram = 0; + +ShaderProgram::ShaderProgram() +{ + m_linked = false; + m_programId = glCreateProgram(); + m_uniformLocations.fill(-1); + if(!m_programId) + logFatal("Unable to create GL shader program"); +} + +ShaderProgram::~ShaderProgram() +{ + glDeleteProgram(m_programId); +} + +bool ShaderProgram::addShader(const ShaderPtr& shader) { + glAttachShader(m_programId, shader->getShaderId()); + m_linked = false; + m_shaders.push_back(shader); + return true; +} + +bool ShaderProgram::addShaderFromSourceCode(Shader::ShaderType shaderType, const std::string& sourceCode) { + ShaderPtr shader(new Shader(shaderType)); + if(!shader->compileSourceCode(sourceCode)) { + logError("failed to compile shader: ", shader->log()); + return false; + } + return addShader(shader); +} + +bool ShaderProgram::addShaderFromSourceFile(Shader::ShaderType shaderType, const std::string& sourceFile) { + ShaderPtr shader(new Shader(shaderType)); + if(!shader->compileSourceFile(sourceFile)) { + logError("failed to compile shader: ", shader->log()); + return false; + } + return addShader(shader); +} + +void ShaderProgram::removeShader(const ShaderPtr& shader) +{ + auto it = std::find(m_shaders.begin(), m_shaders.end(), shader); + if(it == m_shaders.end()) + return; + + glDetachShader(m_programId, shader->getShaderId()); + m_shaders.erase(it); + m_linked = false; +} + +void ShaderProgram::removeAllShaders() +{ + while(!m_shaders.empty()) + removeShader(m_shaders.front()); +} + +bool ShaderProgram::link() +{ + if(m_linked) + return true; + + glLinkProgram(m_programId); + + GLint value; + glGetProgramiv(m_programId, GL_LINK_STATUS, &value); + m_linked = (value != GL_FALSE); + + if(!m_linked) + logTraceWarning(log()); + return m_linked; +} + +bool ShaderProgram::bind() +{ + if(m_currentProgram != m_programId) { + if(!m_linked && !link()) + return false; + glUseProgram(m_programId); + m_currentProgram = m_programId; + } + return true; +} + +void ShaderProgram::release() +{ + m_currentProgram = 0; + glUseProgram(0); +} + +std::string ShaderProgram::log() +{ + std::string infoLog; + GLint infoLogLength; + glGetProgramiv(m_programId, GL_INFO_LOG_LENGTH, &infoLogLength); + if(infoLogLength > 1) { + std::vector buf(infoLogLength); + glGetShaderInfoLog(m_programId, infoLogLength-1, NULL, &buf[0]); + infoLog = &buf[0]; + } + return infoLog; +} + +int ShaderProgram::getAttributeLocation(const char* name) +{ + return glGetAttribLocation(m_programId, name); +} + +void ShaderProgram::bindAttributeLocation(int location, const char* name) +{ + return glBindAttribLocation(m_programId, location, name); +} + +void ShaderProgram::bindUniformLocation(int location, const char* name) +{ + assert(m_linked); + assert(location >= 0 && location < 10); + m_uniformLocations[location] = glGetUniformLocation(m_programId, name); +} diff --git a/src/framework/graphics/shaderprogram.h b/src/framework/graphics/shaderprogram.h new file mode 100644 index 00000000..b1096415 --- /dev/null +++ b/src/framework/graphics/shaderprogram.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHADERPROGRAM_H +#define SHADERPROGRAM_H + +#include "shader.h" + +class ShaderProgram +{ + enum { + MAX_UNIFORM_LOCATIONS = 10 + }; +public: + ShaderProgram(); + ~ShaderProgram(); + + bool addShader(const ShaderPtr& shader); + bool addShaderFromSourceCode(Shader::ShaderType shaderType, const std::string& sourceCode); + bool addShaderFromSourceFile(Shader::ShaderType shaderType, const std::string& sourceFile); + void removeShader(const ShaderPtr& shader); + void removeAllShaders(); + bool link(); + bool bind(); + void release(); + std::string log(); + + void disableAttributeArray(int location) { glDisableVertexAttribArray(location); } + void enableAttributeArray(int location) { glEnableVertexAttribArray(location); } + void disableAttributeArray(const char *name) { glDisableVertexAttribArray(getAttributeLocation(name)); } + void enableAttributeArray(const char *name) { glEnableVertexAttribArray(getAttributeLocation(name)); } + + int getAttributeLocation(const char *name); + void bindAttributeLocation(int location, const char *name); + void bindUniformLocation(int location, const char *name); + + void setAttributeArray(int location, const GLfloat *values, int size, int stride = 0) { glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE, stride, values); } + void setAttributeValue(int location, GLfloat value) { glVertexAttrib1f(location, value); } + void setAttributeValue(int location, GLfloat x, GLfloat y) { glVertexAttrib2f(location, x, y); } + void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z) { glVertexAttrib3f(location, x, y, z); } + void setAttributeArray(const char *name, const GLfloat *values, int size, int stride = 0) { glVertexAttribPointer(getAttributeLocation(name), size, GL_FLOAT, GL_FALSE, stride, values); } + void setAttributeValue(const char *name, GLfloat value) { glVertexAttrib1f(getAttributeLocation(name), value); } + void setAttributeValue(const char *name, GLfloat x, GLfloat y) { glVertexAttrib2f(getAttributeLocation(name), x, y); } + void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z) { glVertexAttrib3f(getAttributeLocation(name), x, y, z); } + + void setUniformValue(int location, GLint value) { glUniform1i(m_uniformLocations[location], value); } + void setUniformValue(int location, GLfloat value) { glUniform1f(m_uniformLocations[location], value); } + void setUniformValue(int location, GLfloat x, GLfloat y) { glUniform2f(m_uniformLocations[location], x, y); } + void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z) { glUniform3f(m_uniformLocations[location], x, y, z); } + void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glUniform4f(m_uniformLocations[location], x, y, z, w); } + void setUniformValue(int location, GLfloat mat2[2][2], bool transpose) { glUniformMatrix2fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat2); } + void setUniformValue(int location, GLfloat mat3[3][3], bool transpose) { glUniformMatrix3fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat3); } + void setUniformValue(const char *name, GLint value) { glUniform1i(glGetUniformLocation(m_programId, name), value); } + void setUniformValue(const char *name, GLfloat value) { glUniform1f(glGetUniformLocation(m_programId, name), value); } + void setUniformValue(const char *name, GLfloat x, GLfloat y) { glUniform2f(glGetUniformLocation(m_programId, name), x, y); } + void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z) { glUniform3f(glGetUniformLocation(m_programId, name), x, y, z); } + void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glUniform4f(glGetUniformLocation(m_programId, name), x, y, z, w); } + void setUniformValue(const char *name, GLfloat mat2[2][2], bool transpose = false) { glUniformMatrix2fv(glGetUniformLocation(m_programId, name), 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat2); } + void setUniformValue(const char *name, GLfloat mat3[3][3], bool transpose = false) { glUniformMatrix3fv(glGetUniformLocation(m_programId, name), 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat3); } + + // Point, PointF, Color, Size, SizeF, + bool isLinked() { return m_linked; } + GLuint getProgramId() { return m_programId; } + ShaderList getShaders() { return m_shaders; } + +private: + bool m_linked; + GLuint m_programId; + static GLuint m_currentProgram; + ShaderList m_shaders; + std::array m_uniformLocations; +}; + +#endif diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index ef3a8de2..2ce5dc7c 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -36,7 +36,6 @@ Texture::Texture(int width, int height, int channels, uchar *pixels) Texture::~Texture() { - assert(!g_graphics.isDrawing()); // free texture from gl memory if(m_textureId > 0) glDeleteTextures(1, &m_textureId); @@ -44,9 +43,7 @@ Texture::~Texture() uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height) { - assert(!g_graphics.isDrawing()); - - m_size.setSize(width, height); + m_size.resize(width, height); // gets max texture size supported by the driver static GLint maxTexSize = -1; @@ -70,7 +67,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int std::vector tmp; // old opengl drivers only accept power of two dimensions - //if(!g_graphics.isExtensionSupported("GL_ARB_texture_non_power_of_two")) { + //if(!g_painter.isExtensionSupported("GL_ARB_texture_non_power_of_two")) { int glWidth = 1; while(glWidth < width) glWidth = glWidth << 1; @@ -88,7 +85,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int pixels = &tmp[0]; } - m_glSize.setSize(glWidth, glHeight); + m_glSize.resize(glWidth, glHeight); //} else // m_glSize = m_size; @@ -110,7 +107,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int } // load pixels into gl memory - glTexImage2D(GL_TEXTURE_2D, 0, channels, m_glSize.width(), m_glSize.height(), 0, format, GL_UNSIGNED_BYTE, pixels); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_glSize.width(), m_glSize.height(), 0, format, GL_UNSIGNED_BYTE, pixels); // disable texture border glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -119,7 +116,6 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int // nearest filtering (non smooth) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - return id; } diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index e0e88795..0fe4cd73 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -37,22 +37,22 @@ public: virtual void enableBilinearFilter(); /// Get OpenGL texture id - uint getId() const { return m_textureId; } + GLuint getId() { return m_textureId; } /// Copy pixels from OpenGL texture std::vector getPixels(); - int getWidth() const { return m_size.width(); } - int getHeight() const { return m_size.height(); } - const Size& getSize() const { return m_size; } - const Size& getGlSize() const { return m_glSize; } + int getWidth() { return m_size.width(); } + int getHeight() { return m_size.height(); } + const Size& getSize() { return m_size; } + const Size& getGlSize() { return m_glSize; } bool isEmpty() const { return m_textureId == 0; } protected: - uint internalLoadGLTexture(uchar* pixels, int channels, int w, int h); + GLuint internalLoadGLTexture(uchar* pixels, int channels, int w, int h); - uint m_textureId; + GLuint m_textureId; Size m_size; Size m_glSize; }; diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 8c57cf3b..c9aad99b 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -36,73 +36,110 @@ void Application::registerLuaFunctions() // UIWidget g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIWidget::create); - g_lua.bindClassMemberFunction("getId", &UIWidget::getId); - g_lua.bindClassMemberFunction("setId", &UIWidget::setId); - g_lua.bindClassMemberFunction("isEnabled", &UIWidget::isEnabled); - g_lua.bindClassMemberFunction("setEnabled", &UIWidget::setEnabled); - g_lua.bindClassMemberFunction("isExplicitlyVisible", &UIWidget::isExplicitlyVisible); + g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy); g_lua.bindClassMemberFunction("setVisible", &UIWidget::setVisible); - g_lua.bindClassMemberFunction("getWidth", &UIWidget::getWidth); - g_lua.bindClassMemberFunction("setWidth", &UIWidget::setWidth); - g_lua.bindClassMemberFunction("getHeight", &UIWidget::getHeight); - g_lua.bindClassMemberFunction("setHeight", &UIWidget::setHeight); - g_lua.bindClassMemberFunction("getSize", &UIWidget::getSize); - g_lua.bindClassMemberFunction("setSize", &UIWidget::resize); - g_lua.bindClassMemberFunction("getPosition", &UIWidget::getPosition); - g_lua.bindClassMemberFunction("getX", &UIWidget::getX); - g_lua.bindClassMemberFunction("getY", &UIWidget::getY); - g_lua.bindClassMemberFunction("moveTo", &UIWidget::moveTo); - g_lua.bindClassMemberFunction("moveChildToIndex", &UIWidget::moveChildToIndex); - g_lua.bindClassMemberFunction("getParent", &UIWidget::getParent); - g_lua.bindClassMemberFunction("setParent", &UIWidget::setParent); - g_lua.bindClassMemberFunction("getBackgroundColor", &UIWidget::getBackgroundColor); - g_lua.bindClassMemberFunction("setBackgroundColor", &UIWidget::setBackgroundColor); - g_lua.bindClassMemberFunction("getForegroundColor", &UIWidget::getForegroundColor); - g_lua.bindClassMemberFunction("setForegroundColor", &UIWidget::setForegroundColor); - g_lua.bindClassMemberFunction("getOpacity", &UIWidget::getOpacity); - g_lua.bindClassMemberFunction("setOpacity", &UIWidget::setOpacity); + g_lua.bindClassMemberFunction("setEnabled", &UIWidget::setEnabled); + g_lua.bindClassMemberFunction("setPressed", &UIWidget::setPressed); + g_lua.bindClassMemberFunction("setId", &UIWidget::setId); + g_lua.bindClassMemberFunction("setFocusable", &UIWidget::setFocusable); + g_lua.bindClassMemberFunction("setPhantom", &UIWidget::setPhantom); g_lua.bindClassMemberFunction("setStyle", &UIWidget::setStyle); - g_lua.bindClassMemberFunction("applyStyle", &UIWidget::applyStyle); - g_lua.bindClassMemberFunction("getStyle", &UIWidget::getStyle); - g_lua.bindClassMemberFunction("getMarginTop", &UIWidget::getMarginTop); + g_lua.bindClassMemberFunction("setStyleFromNode", &UIWidget::setStyleFromNode); + //g_lua.bindClassMemberFunction("setLayout", &UIWidget::setLayout); + g_lua.bindClassMemberFunction("setParent", &UIWidget::setParent); + g_lua.bindClassMemberFunction("setRect", &UIWidget::setRect); + g_lua.bindClassMemberFunction("setX", &UIWidget::setX); + g_lua.bindClassMemberFunction("setY", &UIWidget::setY); + g_lua.bindClassMemberFunction("setWidth", &UIWidget::setWidth); + g_lua.bindClassMemberFunction("setHeight", &UIWidget::setHeight); + //g_lua.bindClassMemberFunction("setImage", &UIWidget::setImage); + //g_lua.bindClassMemberFunction("setFont", &UIWidget::setFont); + g_lua.bindClassMemberFunction("setOpacity", &UIWidget::setOpacity); + g_lua.bindClassMemberFunction("setBackgroundColor", &UIWidget::setBackgroundColor); + g_lua.bindClassMemberFunction("setForegroundColor", &UIWidget::setForegroundColor); g_lua.bindClassMemberFunction("setMarginTop", &UIWidget::setMarginTop); - g_lua.bindClassMemberFunction("getMarginBottom", &UIWidget::getMarginBottom); - g_lua.bindClassMemberFunction("setMarginBottom", &UIWidget::setMarginBottom); - g_lua.bindClassMemberFunction("getMarginLeft", &UIWidget::getMarginLeft); - g_lua.bindClassMemberFunction("setMarginLeft", &UIWidget::setMarginLeft); - g_lua.bindClassMemberFunction("getMarginRight", &UIWidget::getMarginRight); g_lua.bindClassMemberFunction("setMarginRight", &UIWidget::setMarginRight); - g_lua.bindClassMemberFunction("isVisible", &UIWidget::isVisible); - g_lua.bindClassMemberFunction("isHidden", &UIWidget::isHidden); - g_lua.bindClassMemberFunction("isHovered", &UIWidget::isHovered); - g_lua.bindClassMemberFunction("isFocused", &UIWidget::isFocused); - g_lua.bindClassMemberFunction("isPressed", &UIWidget::isPressed); - g_lua.bindClassMemberFunction("isEnabled", &UIWidget::isEnabled); - g_lua.bindClassMemberFunction("isDisabled", &UIWidget::isDisabled); - g_lua.bindClassMemberFunction("isActive", &UIWidget::isActive); + g_lua.bindClassMemberFunction("setMarginBottom", &UIWidget::setMarginBottom); + g_lua.bindClassMemberFunction("setMarginLeft", &UIWidget::setMarginLeft); + g_lua.bindClassMemberFunction("setSizeFixed", &UIWidget::setSizeFixed); + g_lua.bindClassMemberFunction("setLastFocusReason", &UIWidget::setLastFocusReason); + g_lua.bindClassMemberFunction("resize", &UIWidget::resize); + g_lua.bindClassMemberFunction("moveTo", &UIWidget::moveTo); g_lua.bindClassMemberFunction("hide", &UIWidget::hide); g_lua.bindClassMemberFunction("show", &UIWidget::show); + g_lua.bindClassMemberFunction("disable", &UIWidget::disable); + g_lua.bindClassMemberFunction("enable", &UIWidget::enable); g_lua.bindClassMemberFunction("lock", &UIWidget::lock); g_lua.bindClassMemberFunction("unlock", &UIWidget::unlock); g_lua.bindClassMemberFunction("focus", &UIWidget::focus); - g_lua.bindClassMemberFunction("getChildren", &UIWidget::getChildren); - g_lua.bindClassMemberFunction("recursiveGetChildById", &UIWidget::recursiveGetChildById); - g_lua.bindClassMemberFunction("getChildById", &UIWidget::getChildById); - g_lua.bindClassMemberFunction("getChildByIndex", &UIWidget::getChildByIndex); + g_lua.bindClassMemberFunction("isActive", &UIWidget::isActive); + g_lua.bindClassMemberFunction("isEnabled", &UIWidget::isEnabled); + g_lua.bindClassMemberFunction("isDisabled", &UIWidget::isDisabled); + g_lua.bindClassMemberFunction("isFocused", &UIWidget::isFocused); + g_lua.bindClassMemberFunction("isHovered", &UIWidget::isHovered); + g_lua.bindClassMemberFunction("isPressed", &UIWidget::isPressed); + g_lua.bindClassMemberFunction("isVisible", &UIWidget::isVisible); + g_lua.bindClassMemberFunction("isHidden", &UIWidget::isHidden); + g_lua.bindClassMemberFunction("isExplicitlyEnabled", &UIWidget::isExplicitlyEnabled); + g_lua.bindClassMemberFunction("isExplicitlyVisible", &UIWidget::isExplicitlyVisible); + g_lua.bindClassMemberFunction("isFocusable", &UIWidget::isFocusable); + g_lua.bindClassMemberFunction("isPhantom", &UIWidget::isPhantom); + g_lua.bindClassMemberFunction("isSizeFixed", &UIWidget::isSizeFixed); + g_lua.bindClassMemberFunction("hasChildren", &UIWidget::hasChildren); + g_lua.bindClassMemberFunction("hasChild", &UIWidget::hasChild); + g_lua.bindClassMemberFunction("getId", &UIWidget::getId); g_lua.bindClassMemberFunction("getChildCount", &UIWidget::getChildCount); + //g_lua.bindClassMemberFunction("getLayout", &UIWidget::getLayout); + g_lua.bindClassMemberFunction("getParent", &UIWidget::getParent); + g_lua.bindClassMemberFunction("getRootParent", &UIWidget::getRootParent); + g_lua.bindClassMemberFunction("getPosition", &UIWidget::getPosition); + g_lua.bindClassMemberFunction("getSize", &UIWidget::getSize); + g_lua.bindClassMemberFunction("getRect", &UIWidget::getRect); + g_lua.bindClassMemberFunction("getX", &UIWidget::getX); + g_lua.bindClassMemberFunction("getY", &UIWidget::getY); + g_lua.bindClassMemberFunction("getWidth", &UIWidget::getWidth); + g_lua.bindClassMemberFunction("getHeight", &UIWidget::getHeight); + //g_lua.bindClassMemberFunction("getImage", &UIWidget::getImage); + //g_lua.bindClassMemberFunction("getFont", &UIWidget::getFont); + g_lua.bindClassMemberFunction("getForegroundColor", &UIWidget::getForegroundColor); + g_lua.bindClassMemberFunction("getBackgroundColor", &UIWidget::getBackgroundColor); + g_lua.bindClassMemberFunction("getOpacity", &UIWidget::getOpacity); + g_lua.bindClassMemberFunction("getMarginTop", &UIWidget::getMarginTop); + g_lua.bindClassMemberFunction("getMarginRight", &UIWidget::getMarginRight); + g_lua.bindClassMemberFunction("getMarginBottom", &UIWidget::getMarginBottom); + g_lua.bindClassMemberFunction("getMarginLeft", &UIWidget::getMarginLeft); + g_lua.bindClassMemberFunction("getLastFocusReason", &UIWidget::getLastFocusReason); + g_lua.bindClassMemberFunction("getStyle", &UIWidget::getStyle); + g_lua.bindClassMemberFunction("getChildren", &UIWidget::getChildren); g_lua.bindClassMemberFunction("getFocusedChild", &UIWidget::getFocusedChild); + g_lua.bindClassMemberFunction("getChildAfter", &UIWidget::getChildAfter); + g_lua.bindClassMemberFunction("getChildBefore", &UIWidget::getChildBefore); + g_lua.bindClassMemberFunction("getChildById", &UIWidget::getChildById); + g_lua.bindClassMemberFunction("getChildByPos", &UIWidget::getChildByPos); + g_lua.bindClassMemberFunction("getChildByIndex", &UIWidget::getChildByIndex); + g_lua.bindClassMemberFunction("recursiveGetChildById", &UIWidget::recursiveGetChildById); + g_lua.bindClassMemberFunction("recursiveGetChildByPos", &UIWidget::recursiveGetChildByPos); + g_lua.bindClassMemberFunction("backwardsGetWidgetById", &UIWidget::backwardsGetWidgetById); + g_lua.bindClassMemberFunction("addChild", &UIWidget::addChild); g_lua.bindClassMemberFunction("insertChild", &UIWidget::insertChild); g_lua.bindClassMemberFunction("removeChild", &UIWidget::removeChild); - g_lua.bindClassMemberFunction("hasChild", &UIWidget::hasChild); - g_lua.bindClassMemberFunction("addChild", &UIWidget::addChild); g_lua.bindClassMemberFunction("focusChild", &UIWidget::focusChild); g_lua.bindClassMemberFunction("focusNextChild", &UIWidget::focusNextChild); g_lua.bindClassMemberFunction("focusPreviousChild", &UIWidget::focusPreviousChild); + g_lua.bindClassMemberFunction("moveChildToTop", &UIWidget::moveChildToTop); + g_lua.bindClassMemberFunction("moveChildToIndex", &UIWidget::moveChildToIndex); g_lua.bindClassMemberFunction("lockChild", &UIWidget::lockChild); g_lua.bindClassMemberFunction("unlockChild", &UIWidget::unlockChild); - g_lua.bindClassMemberFunction("updateLayout", &UIWidget::updateLayout); + g_lua.bindClassMemberFunction("isChildLocked", &UIWidget::isChildLocked); + g_lua.bindClassMemberFunction("getChildIndex", &UIWidget::getChildIndex); g_lua.bindClassMemberFunction("updateParentLayout", &UIWidget::updateParentLayout); - g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy); + g_lua.bindClassMemberFunction("updateLayout", &UIWidget::updateLayout); + g_lua.bindClassMemberFunction("updateStates", &UIWidget::updateStates); + g_lua.bindClassMemberFunction("updateState", &UIWidget::updateState); + g_lua.bindClassMemberFunction("setState", &UIWidget::setState); + g_lua.bindClassMemberFunction("hasState", &UIWidget::hasState); + g_lua.bindClassMemberFunction("updateStyle", &UIWidget::updateStyle); + g_lua.bindClassMemberFunction("applyStyle", &UIWidget::applyStyle); // UILabel g_lua.registerClass(); @@ -175,12 +212,27 @@ void Application::registerLuaFunctions() g_lua.bindClassStaticFunction("fireOldMessages", std::bind(&Logger::fireOldMessages, &g_logger)); g_lua.bindClassStaticFunction("setOnLog", std::bind(&Logger::setOnLog, &g_logger, _1)); + // Font + + /* + // FontManager + g_lua.registerStaticClass("g_fonts"); + g_lua.bindClassStaticFunction("g_fonts", "releaseFonts", std::bind(&FontManager::releaseFonts, &g_fonts)); + g_lua.bindClassStaticFunction("g_fonts", "importFont", std::bind(&FontManager::importFont, &g_fonts, _1)); + g_lua.bindClassStaticFunction("g_fonts", "fontExists", std::bind(&FontManager::fontExists, &g_fonts, _1)); + g_lua.bindClassStaticFunction("g_fonts", "getFont", std::bind(&FontManager::getFont, &g_fonts, _1)); + g_lua.bindClassStaticFunction("g_fonts", "getDefaultFont", std::bind(&FontManager::getDefaultFont, &g_fonts)); + g_lua.bindClassStaticFunction("g_fonts", "setDefaultFont", std::bind(&FontManager::setDefaultFont, &g_fonts, _1)); + */ + + g_lua.registerStaticClass("g_dispatcher"); + g_lua.bindClassStaticFunction("g_dispatcher", "addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, _2)); + g_lua.bindClassStaticFunction("g_dispatcher", "scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2)); + // global functions g_lua.bindGlobalFunction("importFont", std::bind(&FontManager::importFont, &g_fonts, _1)); g_lua.bindGlobalFunction("importStyles", std::bind(&UIManager::importStyles, &g_ui, _1)); g_lua.bindGlobalFunction("setDefaultFont", std::bind(&FontManager::setDefaultFont, &g_fonts, _1)); g_lua.bindGlobalFunction("loadUI", std::bind(&UIManager::loadUI, &g_ui, _1, _2)); g_lua.bindGlobalFunction("getRootWidget", std::bind(&UIManager::getRootWidget, &g_ui)); - g_lua.bindGlobalFunction("addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, false)); - g_lua.bindGlobalFunction("scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2)); } diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index eeab1bf4..09f6ed12 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -340,7 +340,7 @@ void X11Window::internalChooseGLVisual() m_rootWindow = RootWindow(m_display, m_visual->screen); #else static int attrList[] = { - EGL_BUFFER_SIZE, 16, + EGL_BUFFER_SIZE, 24, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; diff --git a/src/framework/ui/uibutton.cpp b/src/framework/ui/uibutton.cpp index a8650f8b..da42d0cb 100644 --- a/src/framework/ui/uibutton.cpp +++ b/src/framework/ui/uibutton.cpp @@ -40,9 +40,9 @@ void UIButton::render() if(m_icon) { Rect iconRect; - iconRect.setSize(m_icon->getSize()); + iconRect.resize(m_icon->getSize()); iconRect.moveCenter(m_rect.center()); - g_graphics.drawTexturedRect(iconRect, m_icon); + g_painter.drawTexturedRect(iconRect, m_icon); } Rect textRect = m_rect; diff --git a/src/framework/ui/uicheckbox.cpp b/src/framework/ui/uicheckbox.cpp index 5dc7962c..444414c2 100644 --- a/src/framework/ui/uicheckbox.cpp +++ b/src/framework/ui/uicheckbox.cpp @@ -38,10 +38,10 @@ void UICheckBox::render() { if(m_image) { Rect boxRect; - boxRect.setSize(m_boxSize); + boxRect.resize(m_boxSize); boxRect.moveLeft(m_rect.left()); boxRect.moveVerticalCenter(m_rect.verticalCenter()); - g_graphics.bindColor(m_backgroundColor); + g_painter.setColor(m_backgroundColor); m_image->draw(boxRect); } diff --git a/src/framework/ui/uilineedit.cpp b/src/framework/ui/uilineedit.cpp index 91df18e9..31ea118d 100644 --- a/src/framework/ui/uilineedit.cpp +++ b/src/framework/ui/uilineedit.cpp @@ -47,9 +47,9 @@ void UILineEdit::render() int textLength = m_text.length(); const TexturePtr& texture = m_font->getTexture(); - g_graphics.bindColor(m_foregroundColor); + g_painter.setColor(m_foregroundColor); for(int i=0;i= 0) { @@ -63,7 +63,7 @@ void UILineEdit::render() cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight()); else cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight()); - g_graphics.drawFilledRect(cursorRect); + g_painter.drawFilledRect(cursorRect); } else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) { m_cursorTicks = g_clock.ticks(); } diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index 6a8b3ada..344302c8 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -25,6 +25,7 @@ #include #include +#include UIManager g_ui; @@ -33,7 +34,7 @@ void UIManager::init() // creates root widget m_rootWidget = UIWidget::create(); m_rootWidget->setId("root"); - m_rootWidget->resize(g_graphics.getScreenSize()); + m_rootWidget->resize(g_window.getSize()); } void UIManager::terminate() @@ -50,7 +51,7 @@ void UIManager::render() void UIManager::resize(const Size& size) { - m_rootWidget->resize(g_graphics.getScreenSize()); + m_rootWidget->resize(g_window.getSize()); } void UIManager::inputEvent(const InputEvent& event) @@ -174,12 +175,15 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const U if(parent) parent->addChild(widget); - widget->setStyleFromNode(styleNode); + if(widget) { + widget->setStyleFromNode(styleNode); - for(const OTMLNodePtr& childNode : widgetNode->children()) { - if(!childNode->isUnique()) - loadWidgetFromOTML(childNode, widget); - } + for(const OTMLNodePtr& childNode : widgetNode->children()) { + if(!childNode->isUnique()) + loadWidgetFromOTML(childNode, widget); + } + } else + logError("Unable to create widget of type '", widgetType, "'"); return widget; } diff --git a/src/framework/ui/uiprogressbar.cpp b/src/framework/ui/uiprogressbar.cpp index 12013a1c..27ba173a 100644 --- a/src/framework/ui/uiprogressbar.cpp +++ b/src/framework/ui/uiprogressbar.cpp @@ -35,14 +35,14 @@ void UIProgressBar::render() { UIWidget::render(); - g_graphics.bindColor(m_foregroundColor); - g_graphics.drawBoundingRect(m_rect, 1); + g_painter.setColor(m_foregroundColor); + g_painter.drawBoundingRect(m_rect, 1); Rect fillRect = m_rect.expanded(-1); fillRect.setWidth(fillRect.width() * m_percent / 100.0); - g_graphics.bindColor(m_backgroundColor); - g_graphics.drawFilledRect(fillRect); + g_painter.setColor(m_backgroundColor); + g_painter.drawFilledRect(fillRect); } void UIProgressBar::setPercent(double percent) diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 53dfe14d..96d13480 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -69,7 +69,7 @@ void UIWidget::renderSelf() { // draw background if(m_image) { - g_graphics.bindColor(m_backgroundColor); + g_painter.setColor(m_backgroundColor); m_image->draw(m_rect); } } @@ -81,20 +81,20 @@ void UIWidget::renderChildren() // render only visible children with a valid rect inside our rect if(child->isExplicitlyVisible() && child->getRect().isValid() && child->getRect().intersects(m_rect)) { // store current graphics opacity - int oldOpacity = g_graphics.getOpacity(); + int oldOpacity = g_painter.getOpacity(); // decrease to self opacity if(child->getOpacity() < oldOpacity) - g_graphics.setOpacity(child->getOpacity()); + g_painter.setOpacity(child->getOpacity()); child->render(); // debug draw box - //g_graphics.bindColor(Fw::green); - //g_graphics.drawBoundingRect(child->getRect()); + //g_painter.setColor(Fw::green); + //g_painter.drawBoundingRect(child->getRect()); //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Fw::red); - g_graphics.setOpacity(oldOpacity); + g_painter.setOpacity(oldOpacity); } } } diff --git a/src/framework/util/rect.h b/src/framework/util/rect.h index f5e699b8..68d68387 100644 --- a/src/framework/util/rect.h +++ b/src/framework/util/rect.h @@ -78,8 +78,8 @@ public: void setBottomLeft(const TPoint &p) { x1 = p.x; y2 = p.y; } void setWidth(T width) { x2 = x1 + width - 1; } void setHeight(T height) { y2 = y1 + height- 1; } - void setSize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; } - void setSize(const TSize& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } + void resize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; } + void resize(const TSize& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } void setRect(T x, T y, T width, T height) { x1 = x; y1 = y; x2 = (x + width - 1); y2 = (y + height - 1); } void setCoords(int left, int top, int right, int bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; } diff --git a/src/framework/util/size.h b/src/framework/util/size.h index f76204f5..9b373eee 100644 --- a/src/framework/util/size.h +++ b/src/framework/util/size.h @@ -43,7 +43,7 @@ public: int width() const { return wd; } int height() const { return ht; } - void setSize(T w, T h) { wd = w; ht = h; } + void resize(T w, T h) { wd = w; ht = h; } void setWidth(T w) { wd = w; } void setHeight(T h) { ht = h; } @@ -115,7 +115,7 @@ std::istream& operator>>(std::istream& in, TSize& size) { T w, h; in >> w >> h; - size.setSize(w, h); + size.resize(w, h); return in; } diff --git a/src/framework/util/tools.h b/src/framework/util/tools.h index 03ff0ed4..73dd18a7 100644 --- a/src/framework/util/tools.h +++ b/src/framework/util/tools.h @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "types.h" #include "exception.h" @@ -258,6 +260,16 @@ inline std::string ip2str(uint32 ip) { return std::string(host); } +template +std::vector split(const std::string& str, const std::string& separators = " ") { + std::vector splitted; + boost::split(splitted, str, boost::is_any_of(std::string(separators))); + std::vector results(splitted.size()); + for(uint i=0;i(splitted[i]); + return results; +} + template void throwException(const T&... args) { throw Exception(Fw::mkstr(args...)); diff --git a/src/main.cpp b/src/main.cpp index 982cf3a2..53a1a48c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,9 +25,9 @@ int main(int argc, const char* argv[]) { std::vector args(argv, argv + argc); - OTClient otclient; - otclient.init(args); - otclient.run(); - otclient.terminate(); + OTClient app; + app.init(args); + app.run(); + app.terminate(); return 0; } diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 35f11bd2..b8ece933 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -47,8 +47,8 @@ void Creature::draw(const Point& p) { // TODO: activate on attack, follow, discover how 'attacked' works if(m_showSquareColor) { - g_graphics.bindColor(Outfit::getColor(m_squareColor)); - g_graphics.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2); + g_painter.setColor(Outfit::getColor(m_squareColor)); + g_painter.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2); } // Render creature @@ -59,33 +59,33 @@ void Creature::draw(const Point& p) continue; // draw white item - g_graphics.bindColor(Fw::white); + g_painter.setColor(Fw::white); internalDraw(p + m_walkOffset, 0); // draw mask if exists if(m_type->dimensions[ThingType::Layers] > 1) { // switch to blend color mode - g_graphics.bindBlendFunc(Fw::BlendColorzing); + g_painter.setCompositionMode(Painter::CompositionMode_ColorizeDest); // head - g_graphics.bindColor(m_outfit.getHeadColor()); + g_painter.setColor(m_outfit.getHeadColor()); internalDraw(p + m_walkOffset, 1, Otc::SpriteYellowMask); // body - g_graphics.bindColor(m_outfit.getBodyColor()); + g_painter.setColor(m_outfit.getBodyColor()); internalDraw(p + m_walkOffset, 1, Otc::SpriteRedMask); // legs - g_graphics.bindColor(m_outfit.getLegsColor()); + g_painter.setColor(m_outfit.getLegsColor()); internalDraw(p + m_walkOffset, 1, Otc::SpriteGreenMask); // feet - g_graphics.bindColor(m_outfit.getFeetColor()); + g_painter.setColor(m_outfit.getFeetColor()); internalDraw(p + m_walkOffset, 1, Otc::SpriteBlueMask); // restore default blend func - g_graphics.bindBlendFunc(Fw::BlendDefault); - g_graphics.bindColor(Fw::white); + g_painter.setCompositionMode(Painter::CompositionMode_SourceOver); + g_painter.setColor(Fw::white); } } } @@ -115,11 +115,11 @@ void Creature::drawInformation(int x, int y, bool useGray, const Rect& rect) healthRect.setWidth((m_healthPercent / 100.0) * 25); // draw - g_graphics.bindColor(Fw::black); - g_graphics.drawFilledRect(backgroundRect); + g_painter.setColor(Fw::black); + g_painter.drawFilledRect(backgroundRect); - g_graphics.bindColor(fillColor); - g_graphics.drawFilledRect(healthRect); + g_painter.setColor(fillColor); + g_painter.drawFilledRect(healthRect); m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor); } diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 54a7e8e1..72173ef3 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -41,7 +41,7 @@ void Map::draw(const Rect& rect) if(!m_framebuffer) m_framebuffer = FrameBufferPtr(new FrameBuffer(m_visibleSize.width() * NUM_TILE_PIXELS, m_visibleSize.height() * NUM_TILE_PIXELS)); - g_graphics.bindColor(Fw::white); + g_painter.setColor(Fw::white); m_framebuffer->bind(); // draw offsets @@ -80,9 +80,9 @@ void Map::draw(const Rect& rect) } } - m_framebuffer->unbind(); + m_framebuffer->release(); - g_graphics.bindColor(Fw::white); + g_painter.setColor(Fw::white); m_framebuffer->draw(rect); // calculate stretch factor diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index 6066047a..972d4ee1 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -55,7 +55,7 @@ void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask) Rect drawRect((p.x - xi*32) - m_type->parameters[ThingType::DisplacementX], (p.y - yi*32) - m_type->parameters[ThingType::DisplacementY], 32, 32); - g_graphics.drawTexturedRect(drawRect, spriteTex); + g_painter.drawTexturedRect(drawRect, spriteTex); } } } diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp index ef2c282a..6d5e4f47 100644 --- a/src/otclient/otclient.cpp +++ b/src/otclient/otclient.cpp @@ -36,6 +36,5 @@ void OTClient::init(const std::vector& args) g_modules.discoverModules(); g_modules.autoLoadModules(100); g_modules.ensureModuleLoaded("client"); - g_modules.ensureModuleLoaded("game"); g_modules.autoLoadModules(1000); } diff --git a/src/otclient/ui/uicreature.cpp b/src/otclient/ui/uicreature.cpp index f78751e2..76973b84 100644 --- a/src/otclient/ui/uicreature.cpp +++ b/src/otclient/ui/uicreature.cpp @@ -34,7 +34,7 @@ void UICreature::render() renderSelf(); if(m_creature) { - g_graphics.bindColor(Fw::white); + g_painter.setColor(Fw::white); m_creature->draw(m_rect.bottomRight() - Point(32, 32) + m_creatureMargin); } diff --git a/src/otclient/ui/uiitem.cpp b/src/otclient/ui/uiitem.cpp index da19fb0c..7a98c979 100644 --- a/src/otclient/ui/uiitem.cpp +++ b/src/otclient/ui/uiitem.cpp @@ -34,7 +34,7 @@ void UIItem::render() renderSelf(); if(m_item) { - g_graphics.bindColor(Fw::white); + g_painter.setColor(Fw::white); m_item->draw(m_rect.bottomRight() - Point(32, 32) + m_itemMargin); } diff --git a/src/otclient/ui/uimap.cpp b/src/otclient/ui/uimap.cpp index 3523562a..2359b539 100644 --- a/src/otclient/ui/uimap.cpp +++ b/src/otclient/ui/uimap.cpp @@ -35,8 +35,8 @@ void UIMap::render() { renderSelf(); - g_graphics.bindColor(Fw::black); - g_graphics.drawBoundingRect(m_mapRect.expanded(1)); + g_painter.setColor(Fw::black); + g_painter.drawBoundingRect(m_mapRect.expanded(1)); g_map.draw(m_mapRect); renderChildren(); @@ -78,6 +78,6 @@ void UIMap::onGeometryUpdate(const Rect& oldRect, const Rect& newRect) Size mapSize(g_map.getVibibleSize().width() * Map::NUM_TILE_PIXELS, g_map.getVibibleSize().height() * Map::NUM_TILE_PIXELS); mapSize.scale(mapRect.size(), Fw::KeepAspectRatio); - m_mapRect.setSize(mapSize); + m_mapRect.resize(mapSize); m_mapRect.moveCenter(newRect.center()); } diff --git a/tools/lua-binding-generator/generate_lua_bindings.lua b/tools/lua-binding-generator/generate_lua_bindings.lua index b77022d2..a887bd2f 100755 --- a/tools/lua-binding-generator/generate_lua_bindings.lua +++ b/tools/lua-binding-generator/generate_lua_bindings.lua @@ -15,16 +15,16 @@ if not io.open(cppclassheader, 'r') then return false end -function string.matchcount(str, pattern) +function string:matchcount(pattern) local count = 0 - for w in str:gmatch(pattern) do count = count + 1 end + for w in self:gmatch(pattern) do count = count + 1 end return count end -function string.splitlines(str) +function string:splitlines() local t = {} local function helper(line) table.insert(t, line) return "" end - helper((str:gsub("(.-)\r?\n", helper))) + helper((self:gsub("(.-)\r?\n", helper))) return t end @@ -34,7 +34,7 @@ for line in io.lines(cppclassheader) do foundclassname = line:match('^class ([%w_]+)') if foundclassname then if not cppclassname then - guessedclassname = cppclassheader:match('([%w_]+).h'):lower() + guessedclassname = cppclassheader:match('([%w_]+)\.h$'):lower() if foundclassname:lower() == guessedclassname then cppclassname = foundclassname end @@ -69,8 +69,9 @@ for line in io.lines(cppclassheader) do elseif line:match('private:') or line:match('protected:') then publicmethods = false elseif publicmethods then - for funcname,args in line:gmatch(' *[%w :_]* ([%w_]+)%(([^%(]*%)) *[;{].*$') do - if funcname ~= cppclassname then + funcname, args = line:match('^ *[%w <>&\*:_]* ([%w_]+)%(([^%)]*%))[%w ]*[;{].*$') + if funcname then + if funcname ~= cppclassname and funcname ~= 'create' then numargs = args:matchcount('[^,)]+[,)]') if cppclassinstance then From 203d5768cb7155d4c54ed9a8cc514e61da06d708 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 6 Dec 2011 22:45:38 -0200 Subject: [PATCH 02/10] fix compile issues on n900 --- src/framework/application.cpp | 1 - src/framework/graphics/texture.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/framework/application.cpp b/src/framework/application.cpp index 5adeecb4..9dfdd62b 100644 --- a/src/framework/application.cpp +++ b/src/framework/application.cpp @@ -33,7 +33,6 @@ #include #include #include -#include <../../oglrenderer/graphics/painter.h> Application *g_app = nullptr; diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index 2ce5dc7c..acb1034e 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -132,7 +132,7 @@ std::vector Texture::getPixels() // copy pixels from opengl memory std::vector pixels(m_glSize.area()*4, 0); glBindTexture(GL_TEXTURE_2D, m_textureId); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); + //glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); // convert pixels to the real texture size if(m_size != m_glSize) From a6b66e3f7e462e84f9f5daa9d4192c0ed85ed472 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 6 Dec 2011 22:49:34 -0200 Subject: [PATCH 03/10] fix warning --- src/otclient/net/protocolgameparse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index f98f321c..b7caa765 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -717,7 +717,7 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg) std::string name = msg.getString(); // name int level = msg.getU16(); // level int type = msg.getU8(); - int channelId; + int channelId = 0; Position creaturePos; switch(type) { From f89bc352d5dd97b329d9a4c1cc129d1588b6a726 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 6 Dec 2011 23:48:39 -0200 Subject: [PATCH 04/10] fix shaders for OpenGL ES --- src/framework/CMakeLists.txt | 2 +- src/framework/graphics/painter.cpp | 12 ++++-------- src/framework/graphics/paintershadersources.h | 15 +++++++++------ src/framework/platform/x11window.cpp | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index a2497ef8..ae51645f 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -79,7 +79,7 @@ IF(WIN32) ENDIF(NO_CONSOLE) ELSE(WIN32) SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -rdynamic") - SET(ADDITIONAL_LIBRARIES pthread) + SET(ADDITIONAL_LIBRARIES pthread X11) SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/platform/x11window.cpp) ENDIF(WIN32) diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index 3a439513..207f2da4 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -36,10 +36,8 @@ void Painter::init() setCompositionMode(CompositionMode_SourceOver); PainterShaderProgramPtr program = PainterShaderProgramPtr(new PainterShaderProgram); - program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader); - program->addShaderFromSourceCode(Shader::Vertex, glslPositionOnlyVertexShader); - program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader); - program->addShaderFromSourceCode(Shader::Fragment, glslTextureSrcFragmentShader); + program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader); program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); program->bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); assert(program->link()); @@ -51,10 +49,8 @@ void Painter::init() m_drawTexturedProgram = program; program = PainterShaderProgramPtr(new PainterShaderProgram); - program->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader); - program->addShaderFromSourceCode(Shader::Vertex, glslPositionOnlyVertexShader); - program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader); - program->addShaderFromSourceCode(Shader::Fragment, glslSolidColorFragmentShader); + program->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader); + program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader); program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); assert(program->link()); program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); diff --git a/src/framework/graphics/paintershadersources.h b/src/framework/graphics/paintershadersources.h index a020be4b..667d35ca 100644 --- a/src/framework/graphics/paintershadersources.h +++ b/src/framework/graphics/paintershadersources.h @@ -29,13 +29,13 @@ static int COLOR_UNIFORM = 2; static int OPACITY_UNIFORM = 3; static int TEXTURE_UNIFORM = 4; -static const char *glslMainVertexShader = "\n\ +static const std::string glslMainVertexShader = "\n\ vec4 calculatePosition();\n\ void main() {\n\ gl_Position = calculatePosition();\n\ }\n"; -static const char *glslMainWithTexCoordsVertexShader = "\n\ +static const std::string glslMainWithTexCoordsVertexShader = "\n\ attribute vec2 textureCoord;\n\ uniform mat2 textureTransformMatrix;\n\ varying vec2 textureCoords;\n\ @@ -46,14 +46,16 @@ static const char *glslMainWithTexCoordsVertexShader = "\n\ textureCoords = textureTransformMatrix * textureCoord;\n\ }\n"; -static const char *glslPositionOnlyVertexShader = "\n\ +static std::string glslPositionOnlyVertexShader = "\n\ attribute vec2 vertexCoord;\n\ uniform mat3 projectionMatrix;\n\ vec4 calculatePosition() {\n\ return vec4(projectionMatrix * vec3(vertexCoord.xy, 1), 1);\n\ }\n"; -static const char *glslMainFragmentShader = "\n\ +static const std::string glslMainFragmentShader = "\n\ + precision lowp vec4;\n\ + precision lowp float;\n\ uniform float opacity;\n\ vec4 calculatePixel();\n\ void main()\n\ @@ -61,7 +63,8 @@ static const char *glslMainFragmentShader = "\n\ gl_FragColor = calculatePixel() * opacity;\n\ }\n"; -static const char *glslTextureSrcFragmentShader = "\n\ +static const std::string glslTextureSrcFragmentShader = "\n\ + precision mediump vec2;\n\ varying vec2 textureCoords;\n\ uniform vec4 color;\n\ uniform sampler2D texture;\n\ @@ -69,7 +72,7 @@ static const char *glslTextureSrcFragmentShader = "\n\ return texture2D(texture, textureCoords) * color;\n\ }\n"; -static const char *glslSolidColorFragmentShader = "\n\ +static const std::string glslSolidColorFragmentShader = "\n\ uniform vec4 color;\n\ vec4 calculatePixel() {\n\ return color;\n\ diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index 09f6ed12..5e36c4a0 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -340,7 +340,7 @@ void X11Window::internalChooseGLVisual() m_rootWindow = RootWindow(m_display, m_visual->screen); #else static int attrList[] = { - EGL_BUFFER_SIZE, 24, + //EGL_BUFFER_SIZE, 24, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; From b37a34219d0d5bd02fa11b7d046616e83c500e49 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 7 Dec 2011 00:09:44 -0200 Subject: [PATCH 05/10] fix shaders for OpenGL ES --- src/framework/graphics/paintershadersources.h | 15 ++++++--------- src/framework/graphics/shader.cpp | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/framework/graphics/paintershadersources.h b/src/framework/graphics/paintershadersources.h index 667d35ca..1e5d06a7 100644 --- a/src/framework/graphics/paintershadersources.h +++ b/src/framework/graphics/paintershadersources.h @@ -30,7 +30,7 @@ static int OPACITY_UNIFORM = 3; static int TEXTURE_UNIFORM = 4; static const std::string glslMainVertexShader = "\n\ - vec4 calculatePosition();\n\ + highp vec4 calculatePosition();\n\ void main() {\n\ gl_Position = calculatePosition();\n\ }\n"; @@ -54,26 +54,23 @@ static std::string glslPositionOnlyVertexShader = "\n\ }\n"; static const std::string glslMainFragmentShader = "\n\ - precision lowp vec4;\n\ - precision lowp float;\n\ - uniform float opacity;\n\ - vec4 calculatePixel();\n\ + uniform lowp float opacity;\n\ + lowp vec4 calculatePixel();\n\ void main()\n\ {\n\ gl_FragColor = calculatePixel() * opacity;\n\ }\n"; static const std::string glslTextureSrcFragmentShader = "\n\ - precision mediump vec2;\n\ - varying vec2 textureCoords;\n\ - uniform vec4 color;\n\ + varying mediump vec2 textureCoords;\n\ + uniform lowp vec4 color;\n\ uniform sampler2D texture;\n\ vec4 calculatePixel() {\n\ return texture2D(texture, textureCoords) * color;\n\ }\n"; static const std::string glslSolidColorFragmentShader = "\n\ - uniform vec4 color;\n\ + uniform lowp vec4 color;\n\ vec4 calculatePixel() {\n\ return color;\n\ }\n"; diff --git a/src/framework/graphics/shader.cpp b/src/framework/graphics/shader.cpp index 328ae81c..34503202 100644 --- a/src/framework/graphics/shader.cpp +++ b/src/framework/graphics/shader.cpp @@ -45,7 +45,21 @@ Shader::~Shader() bool Shader::compileSourceCode(const std::string& sourceCode) { - const char *c_source = sourceCode.c_str(); +#ifndef OPENGL_ES2 + static const char *qualifierDefines = + "#define lowp\n" + "#define mediump\n" + "#define highp\n"; +#else + static const char *qualifierDefines = + "#ifndef GL_FRAGMENT_PRECISION_HIGH\n" + "#define highp mediump\n" + "#endif\n"; +#endif + + std::string code = qualifierDefines; + code.append(sourceCode); + const char *c_source = code.c_str(); glShaderSource(m_shaderId, 1, &c_source, NULL); glCompileShader(m_shaderId); From cc7c334d734b6d605d1bf6b2acad521e86ba9bab Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 7 Dec 2011 00:13:24 -0200 Subject: [PATCH 06/10] ... --- src/framework/graphics/paintershadersources.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/framework/graphics/paintershadersources.h b/src/framework/graphics/paintershadersources.h index 1e5d06a7..1e7db419 100644 --- a/src/framework/graphics/paintershadersources.h +++ b/src/framework/graphics/paintershadersources.h @@ -36,10 +36,10 @@ static const std::string glslMainVertexShader = "\n\ }\n"; static const std::string glslMainWithTexCoordsVertexShader = "\n\ - attribute vec2 textureCoord;\n\ - uniform mat2 textureTransformMatrix;\n\ - varying vec2 textureCoords;\n\ - vec4 calculatePosition();\n\ + attribute highp vec2 textureCoord;\n\ + uniform highp mat2 textureTransformMatrix;\n\ + varying highp vec2 textureCoords;\n\ + highp vec4 calculatePosition();\n\ void main()\n\ {\n\ gl_Position = calculatePosition();\n\ @@ -47,9 +47,9 @@ static const std::string glslMainWithTexCoordsVertexShader = "\n\ }\n"; static std::string glslPositionOnlyVertexShader = "\n\ - attribute vec2 vertexCoord;\n\ - uniform mat3 projectionMatrix;\n\ - vec4 calculatePosition() {\n\ + attribute highp vec2 vertexCoord;\n\ + uniform highp mat3 projectionMatrix;\n\ + highp vec4 calculatePosition() {\n\ return vec4(projectionMatrix * vec3(vertexCoord.xy, 1), 1);\n\ }\n"; @@ -65,12 +65,12 @@ static const std::string glslTextureSrcFragmentShader = "\n\ varying mediump vec2 textureCoords;\n\ uniform lowp vec4 color;\n\ uniform sampler2D texture;\n\ - vec4 calculatePixel() {\n\ + lowp vec4 calculatePixel() {\n\ return texture2D(texture, textureCoords) * color;\n\ }\n"; static const std::string glslSolidColorFragmentShader = "\n\ uniform lowp vec4 color;\n\ - vec4 calculatePixel() {\n\ + lowp vec4 calculatePixel() {\n\ return color;\n\ }\n"; From 1a3dcb215ec70175509b71f1684900d7936da65f Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 7 Dec 2011 16:49:20 -0200 Subject: [PATCH 07/10] use vertex buffers --- TODO | 7 +- src/framework/CMakeLists.txt | 1 + src/framework/graphics/borderimage.cpp | 125 +++++++++-------- src/framework/graphics/coordsbuffer.cpp | 110 +++++++++++++++ src/framework/graphics/coordsbuffer.h | 55 ++++++++ src/framework/graphics/glbuffer.cpp | 24 ++++ src/framework/graphics/glbuffer.h | 30 ++++ src/framework/graphics/image.cpp | 16 ++- src/framework/graphics/image.h | 4 + src/framework/graphics/painter.cpp | 131 +++++++----------- src/framework/graphics/painter.h | 7 + .../graphics/paintershaderprogram.cpp | 5 + src/framework/graphics/paintershaderprogram.h | 1 + src/framework/graphics/texture.cpp | 2 +- src/framework/graphics/textureglyphcache.cpp | 24 ++++ src/framework/graphics/textureglyphcache.h | 30 ++++ src/framework/graphics/vertexarray.h | 67 +++++++++ src/framework/util/databuffer.h | 69 +++++++++ 18 files changed, 558 insertions(+), 150 deletions(-) create mode 100644 src/framework/graphics/coordsbuffer.cpp create mode 100644 src/framework/graphics/coordsbuffer.h create mode 100644 src/framework/graphics/glbuffer.cpp create mode 100644 src/framework/graphics/glbuffer.h create mode 100644 src/framework/graphics/textureglyphcache.cpp create mode 100644 src/framework/graphics/textureglyphcache.h create mode 100644 src/framework/graphics/vertexarray.h create mode 100644 src/framework/util/databuffer.h diff --git a/TODO b/TODO index 1f448fd0..3e235b7e 100644 --- a/TODO +++ b/TODO @@ -31,4 +31,9 @@ restore win32 platform set special types for g_configs like lists/point/size restore ctrl+g and keybindings create a class for reading binary files -handle corrupt errors in dat/spr \ No newline at end of file +handle corrupt errors in dat/spr + +use CoordsBuffer in font +cache into framebuffers +implement glbuffer for CoordsBuffer +use indices in CoordsBuffer \ No newline at end of file diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index ae51645f..4f55c7c0 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -146,6 +146,7 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/graphics/shader.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/coordsbuffer.cpp # framework otml ${CMAKE_CURRENT_LIST_DIR}/otml/otmldocument.cpp diff --git a/src/framework/graphics/borderimage.cpp b/src/framework/graphics/borderimage.cpp index 9e5dd228..1f547c2b 100644 --- a/src/framework/graphics/borderimage.cpp +++ b/src/framework/graphics/borderimage.cpp @@ -133,67 +133,72 @@ BorderImagePtr BorderImage::loadFromOTML(const OTMLNodePtr& borderImageNode) void BorderImage::draw(const Rect& screenCoords) { //TODO: borderimage drawing could be optimized by caching the render into a texture + if(screenCoords != m_cachedScreenCoords) { + m_cachedScreenCoords = screenCoords; + m_coordsBuffer.clear(); - Rect rectCoords; - Size centerSize = screenCoords.size() - m_bordersSize; + Rect rectCoords; + Size centerSize = screenCoords.size() - m_bordersSize; - // first the center - if(centerSize.area() > 0) { - rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(), - screenCoords.top() + m_topBorderTexCoords.height(), - centerSize); - g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords); + // first the center + if(centerSize.area() > 0) { + rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(), + screenCoords.top() + m_topBorderTexCoords.height(), + centerSize); + m_coordsBuffer.addRepeatedRects(rectCoords, m_centerTexCoords); + } + + // top left corner + rectCoords = Rect(screenCoords.topLeft(), + m_topLeftCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_topLeftCornerTexCoords); + + // top + rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width(), + screenCoords.topLeft().y, + centerSize.width(), + m_topBorderTexCoords.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_topBorderTexCoords); + + + // top right corner + rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width() + centerSize.width(), + screenCoords.top(), + m_topRightCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_topRightCornerTexCoords); + + // left + rectCoords = Rect(screenCoords.left(), + screenCoords.top() + m_topLeftCornerTexCoords.height(), + m_leftBorderTexCoords.width(), + centerSize.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_leftBorderTexCoords); + + // right + rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width() + centerSize.width(), + screenCoords.top() + m_topRightCornerTexCoords.height(), + m_rightBorderTexCoords.width(), + centerSize.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_rightBorderTexCoords); + + // bottom left corner + rectCoords = Rect(screenCoords.left(), + screenCoords.top() + m_topLeftCornerTexCoords.height() + centerSize.height(), + m_bottomLeftCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_bottomLeftCornerTexCoords); + + // bottom + rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width(), + screenCoords.top() + m_topBorderTexCoords.height() + centerSize.height(), + centerSize.width(), + m_bottomBorderTexCoords.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_bottomBorderTexCoords); + + // bottom right corner + rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width() + centerSize.width(), + screenCoords.top() + m_topRightCornerTexCoords.height() + centerSize.height(), + m_bottomRightCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_bottomRightCornerTexCoords); } - - // top left corner - rectCoords = Rect(screenCoords.topLeft(), - m_topLeftCornerTexCoords.size()); - g_painter.drawTexturedRect(rectCoords, m_texture, m_topLeftCornerTexCoords); - - // top - rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width(), - screenCoords.topLeft().y, - centerSize.width(), - m_topBorderTexCoords.height()); - g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_topBorderTexCoords); - - - // top right corner - rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width() + centerSize.width(), - screenCoords.top(), - m_topRightCornerTexCoords.size()); - g_painter.drawTexturedRect(rectCoords, m_texture, m_topRightCornerTexCoords); - - // left - rectCoords = Rect(screenCoords.left(), - screenCoords.top() + m_topLeftCornerTexCoords.height(), - m_leftBorderTexCoords.width(), - centerSize.height()); - g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_leftBorderTexCoords); - - // right - rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width() + centerSize.width(), - screenCoords.top() + m_topRightCornerTexCoords.height(), - m_rightBorderTexCoords.width(), - centerSize.height()); - g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_rightBorderTexCoords); - - // bottom left corner - rectCoords = Rect(screenCoords.left(), - screenCoords.top() + m_topLeftCornerTexCoords.height() + centerSize.height(), - m_bottomLeftCornerTexCoords.size()); - g_painter.drawTexturedRect(rectCoords, m_texture, m_bottomLeftCornerTexCoords); - - // bottom - rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width(), - screenCoords.top() + m_topBorderTexCoords.height() + centerSize.height(), - centerSize.width(), - m_bottomBorderTexCoords.height()); - g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_bottomBorderTexCoords); - - // bottom right corner - rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width() + centerSize.width(), - screenCoords.top() + m_topRightCornerTexCoords.height() + centerSize.height(), - m_bottomRightCornerTexCoords.size()); - g_painter.drawTexturedRect(rectCoords, m_texture, m_bottomRightCornerTexCoords); + g_painter.drawTextureCoords(m_coordsBuffer, m_texture); } \ No newline at end of file diff --git a/src/framework/graphics/coordsbuffer.cpp b/src/framework/graphics/coordsbuffer.cpp new file mode 100644 index 00000000..a3068aa9 --- /dev/null +++ b/src/framework/graphics/coordsbuffer.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "coordsbuffer.h" + +void CoordsBuffer::clear() +{ + m_destRects.reset(); + m_srcRects.reset(); + m_textureCoords.clear(); + m_vertexCoords.clear(); + m_updateCache = true; +} + +void CoordsBuffer::addRect(const Rect& dest) +{ + m_destRects << dest; + m_updateCache = true; +} + +void CoordsBuffer::addRect(const Rect& dest, const Rect& src) +{ + m_destRects << dest; + m_srcRects << src; + m_updateCache = true; +} + +void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth) +{ + int left = dest.left(); + int right = dest.right(); + int top = dest.top(); + int bottom = dest.bottom(); + int width = dest.width(); + int height = dest.height(); + int w = innerLineWidth; + + addRect(Rect(left, top, width - w, w)); // top + addRect(Rect(right - w + 1, top, w, height - w)); // right + addRect(Rect(left + w, bottom - w + 1, width - w, w)); // bottom + addRect(Rect(left, top + w, w, height - w)); // left + m_updateCache = true; +} + +void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty()) + return; + + Rect virtualDest(0, 0, dest.size()); + for(int y = 0; y <= virtualDest.height(); y += src.height()) { + for(int x = 0; x <= virtualDest.width(); x += src.width()) { + Rect partialDest(x, y, src.size()); + Rect partialSrc(src); + + // partialCoords to screenCoords bottomRight + if(partialDest.bottom() > virtualDest.bottom()) { + partialSrc.setBottom(partialSrc.bottom() + (virtualDest.bottom() - partialDest.bottom())); + partialDest.setBottom(virtualDest.bottom()); + } + if(partialDest.right() > virtualDest.right()) { + partialSrc.setRight(partialSrc.right() + (virtualDest.right() - partialDest.right())); + partialDest.setRight(virtualDest.right()); + } + + partialDest.translate(dest.topLeft()); + m_destRects << partialDest; + m_srcRects << partialSrc; + } + } + m_updateCache = true; +} + +void CoordsBuffer::cacheVertexArrays() +{ + if(!m_updateCache) + return; + + int numDestRects = m_destRects.size(); + int numSrcRects = m_srcRects.size(); + m_vertexCoords.clear(); + m_textureCoords.clear(); + + for(int i=0;i + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef COORDSBUFFER_H +#define COORDSBUFFER_H + +#include "vertexarray.h" + +class CoordsBuffer +{ +public: + void clear(); + + // no texture + void addRect(const Rect& dest); + void addBoudingRect(const Rect& dest, int innerLineWidth); + + // textured + void addRect(const Rect& dest, const Rect& src); + void addRepeatedRects(const Rect& dest, const Rect& src); + + void cacheVertexArrays(); + + GLfloat *getVertexCoords() const { return m_vertexCoords.vertexArray(); } + GLfloat *getTextureCoords() const { return m_textureCoords.vertexArray(); } + int getVertexCount() const { return m_vertexCoords.vertexCount(); } + +private: + DataBuffer m_destRects; + DataBuffer m_srcRects; + VertexArray m_vertexCoords; + VertexArray m_textureCoords; + Boolean m_updateCache; +}; + +#endif diff --git a/src/framework/graphics/glbuffer.cpp b/src/framework/graphics/glbuffer.cpp new file mode 100644 index 00000000..7d6ddcc4 --- /dev/null +++ b/src/framework/graphics/glbuffer.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "glbuffer.h" + diff --git a/src/framework/graphics/glbuffer.h b/src/framework/graphics/glbuffer.h new file mode 100644 index 00000000..ba31f943 --- /dev/null +++ b/src/framework/graphics/glbuffer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GLBUFFER_H +#define GLBUFFER_H + +class GLBuffer +{ +}; + +#endif diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp index e3e04fd0..fce2d55b 100644 --- a/src/framework/graphics/image.cpp +++ b/src/framework/graphics/image.cpp @@ -52,7 +52,13 @@ void Image::loadFromOTML(const OTMLNodePtr& imageNode) void Image::draw(const Rect& screenCoords) { - if(m_texture) { + if(!m_texture) + return; + + if(m_cachedScreenCoords != screenCoords) { + m_cachedScreenCoords = screenCoords; + m_coordsBuffer.clear(); + if(m_fixedRatio) { const Size& texSize = m_texture->getSize(); Size texCoordsSize = screenCoords.size(); @@ -63,12 +69,14 @@ void Image::draw(const Rect& screenCoords) else if(texSize.width() > texCoordsSize.width()) texCoordsOffset.x = (texSize.width() - texCoordsSize.width())/2; - g_painter.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize)); + m_coordsBuffer.addRect(screenCoords, Rect(texCoordsOffset, texCoordsSize)); } else { if(m_repeated) - g_painter.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords); + m_coordsBuffer.addRepeatedRects(screenCoords, m_textureCoords); else - g_painter.drawTexturedRect(screenCoords, m_texture, m_textureCoords); + m_coordsBuffer.addRect(screenCoords, m_textureCoords); } } + + g_painter.drawTextureCoords(m_coordsBuffer, m_texture); } diff --git a/src/framework/graphics/image.h b/src/framework/graphics/image.h index 61b884d4..ee09cf3e 100644 --- a/src/framework/graphics/image.h +++ b/src/framework/graphics/image.h @@ -24,6 +24,7 @@ #define IMAGE_H #include "declarations.h" +#include "coordsbuffer.h" #include @@ -41,6 +42,9 @@ protected: Rect m_textureCoords; bool m_fixedRatio; bool m_repeated; + + Rect m_cachedScreenCoords; + CoordsBuffer m_coordsBuffer; }; #endif diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index 207f2da4..f156bcd7 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -26,6 +26,7 @@ #include "paintershaderprogram.h" #include "shaderprogram.h" #include "graphics.h" +#include "vertexarray.h" Painter g_painter; @@ -94,6 +95,40 @@ void Painter::updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis } } +void Painter::drawCoords(CoordsBuffer& coordsBuffer) +{ + coordsBuffer.cacheVertexArrays(); + + if(coordsBuffer.getVertexCount() < 3) + return; + + m_drawSolidColorProgram->prepareForDraw(); + m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix); + m_drawSolidColorProgram->setOpacity(m_currentOpacity); + m_drawSolidColorProgram->setColor(m_currentColor); + m_drawSolidColorProgram->setVertexCoords(coordsBuffer.getVertexCoords()); + m_drawSolidColorProgram->drawTriangles(coordsBuffer.getVertexCount()); + m_drawSolidColorProgram->releaseFromDraw(); +} + +void Painter::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) +{ + coordsBuffer.cacheVertexArrays(); + + if(coordsBuffer.getVertexCount() < 3) + return; + + m_drawTexturedProgram->prepareForDraw(); + m_drawTexturedProgram->setProjectionMatrix(m_projectionMatrix); + m_drawTexturedProgram->setOpacity(m_currentOpacity); + m_drawTexturedProgram->setColor(m_currentColor); + m_drawTexturedProgram->setTexture(texture); + m_drawTexturedProgram->setVertexCoords(coordsBuffer.getVertexCoords()); + m_drawTexturedProgram->setTextureCoords(coordsBuffer.getTextureCoords()); + m_drawTexturedProgram->drawTriangles(coordsBuffer.getVertexCount()); + m_drawTexturedProgram->releaseFromDraw(); +} + void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); @@ -104,25 +139,9 @@ void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture, cons if(dest.isEmpty() || src.isEmpty() || !texture->getId()) return; - GLfloat vertexCoords[] = { (float)dest.left(), (float)dest.top(), - (float)dest.right()+1, (float)dest.top(), - (float)dest.left(), (float)dest.bottom()+1, - (float)dest.right()+1, (float)dest.bottom()+1 }; - - GLfloat textureCoords[] = { (float)src.left(), (float)src.top(), - (float)src.right()+1, (float)src.top(), - (float)src.left(), (float)src.bottom()+1, - (float)src.right()+1, (float)src.bottom()+1 }; - - m_drawTexturedProgram->prepareForDraw(); - m_drawTexturedProgram->setProjectionMatrix(m_projectionMatrix); - m_drawTexturedProgram->setOpacity(m_currentOpacity); - m_drawTexturedProgram->setColor(m_currentColor); - m_drawTexturedProgram->setTexture(texture); - m_drawTexturedProgram->setVertexCoords(vertexCoords); - m_drawTexturedProgram->setTextureCoords(textureCoords); - m_drawTexturedProgram->drawTriangleStrip(4); - m_drawTexturedProgram->releaseFromDraw(); + m_coordsBuffer.clear(); + m_coordsBuffer.addRect(dest, src); + drawTextureCoords(m_coordsBuffer, texture); } void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) @@ -130,27 +149,9 @@ void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& textu if(dest.isEmpty() || src.isEmpty() || !texture->getId()) return; - //TODO: use vertex arrays.. - Rect virtualDest(0, 0, dest.size()); - for(int y = 0; y <= virtualDest.height(); y += src.height()) { - for(int x = 0; x <= virtualDest.width(); x += src.width()) { - Rect partialDest(x, y, src.size()); - Rect partialSrc = src; - - // partialCoords to screenCoords bottomRight - if(partialDest.bottom() > virtualDest.bottom()) { - partialSrc.setBottom(partialSrc.bottom() + (virtualDest.bottom() - partialDest.bottom())); - partialDest.setBottom(virtualDest.bottom()); - } - if(partialDest.right() > virtualDest.right()) { - partialSrc.setRight(partialSrc.right() + (virtualDest.right() - partialDest.right())); - partialDest.setRight(virtualDest.right()); - } - - partialDest.translate(dest.topLeft()); - drawTexturedRect(partialDest, texture, partialSrc); - } - } + m_coordsBuffer.clear(); + m_coordsBuffer.addRepeatedRects(dest, src); + drawTextureCoords(m_coordsBuffer, texture); } void Painter::drawFilledRect(const Rect& dest) @@ -158,23 +159,9 @@ void Painter::drawFilledRect(const Rect& dest) if(dest.isEmpty()) return; - GLfloat right = dest.right()+1; - GLfloat bottom = dest.bottom()+1; - GLfloat top = dest.top(); - GLfloat left = dest.left(); - - GLfloat vertexCoords[] = { left, top, - right, top, - left, bottom, - right, bottom }; - - m_drawSolidColorProgram->prepareForDraw(); - m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix); - m_drawSolidColorProgram->setOpacity(m_currentOpacity); - m_drawSolidColorProgram->setColor(m_currentColor); - m_drawSolidColorProgram->setVertexCoords(vertexCoords); - m_drawSolidColorProgram->drawTriangleStrip(4); - m_drawSolidColorProgram->releaseFromDraw(); + m_coordsBuffer.clear(); + m_coordsBuffer.addRect(dest); + drawCoords(m_coordsBuffer); } void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth) @@ -182,33 +169,9 @@ void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth) if(dest.isEmpty() || innerLineWidth == 0) return; - GLfloat right = dest.right()+1; - GLfloat bottom = dest.bottom()+1; - GLfloat top = dest.top(); - GLfloat left = dest.left(); - GLfloat w = innerLineWidth; - - GLfloat vertexCoords[] = { left, top, - right, top, - left, top+w, - right, top+w, - right-w, top+w, - right, bottom, - right-w, bottom, - right-w, bottom-w, - left, bottom, - left, bottom-w, - left+w, bottom-w, - left, top+w, - left+w, top+w }; - - m_drawSolidColorProgram->prepareForDraw(); - m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix); - m_drawSolidColorProgram->setOpacity(m_currentOpacity); - m_drawSolidColorProgram->setColor(m_currentColor); - m_drawSolidColorProgram->setVertexCoords(vertexCoords); - m_drawSolidColorProgram->drawTriangleStrip(13); - m_drawSolidColorProgram->releaseFromDraw(); + m_coordsBuffer.clear(); + m_coordsBuffer.addBoudingRect(dest, innerLineWidth); + drawCoords(m_coordsBuffer); } void Painter::setCompositionMode(Painter::CompositionMode compositionMode) diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index b336d90c..10652974 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -24,6 +24,8 @@ #define PAINTER_H #include "declarations.h" +#include +#include "coordsbuffer.h" class Painter { @@ -37,6 +39,10 @@ public: void terminate(); void updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis = false); + + void drawCoords(CoordsBuffer& coordsBuffer); + void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); + void drawTexturedRect(const Rect& dest, const TexturePtr& texture); void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); @@ -57,6 +63,7 @@ private: GLfloat m_projectionMatrix[3][3]; Color m_currentColor; GLfloat m_currentOpacity; + CoordsBuffer m_coordsBuffer; }; extern Painter g_painter; diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp index 645078e2..2fd9fa6f 100644 --- a/src/framework/graphics/paintershaderprogram.cpp +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -83,6 +83,11 @@ void PainterShaderProgram::drawTriangleStrip(int numVertices) glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices); } +void PainterShaderProgram::drawTriangles(int numVertices) +{ + glDrawArrays(GL_TRIANGLES, 0, numVertices); +} + void PainterShaderProgram::releaseFromDraw() { if(m_mustDisableTexCoordsArray) { diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index 74bb728e..f7d9d409 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -47,6 +47,7 @@ public: void prepareForDraw(); void drawTriangleStrip(int numVertices); + void drawTriangles(int numVertices); void releaseFromDraw(); private: diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index acb1034e..2ce5dc7c 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -132,7 +132,7 @@ std::vector Texture::getPixels() // copy pixels from opengl memory std::vector pixels(m_glSize.area()*4, 0); glBindTexture(GL_TEXTURE_2D, m_textureId); - //glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); // convert pixels to the real texture size if(m_size != m_glSize) diff --git a/src/framework/graphics/textureglyphcache.cpp b/src/framework/graphics/textureglyphcache.cpp new file mode 100644 index 00000000..6a5c7d47 --- /dev/null +++ b/src/framework/graphics/textureglyphcache.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "textureglyphcache.h" + diff --git a/src/framework/graphics/textureglyphcache.h b/src/framework/graphics/textureglyphcache.h new file mode 100644 index 00000000..15833249 --- /dev/null +++ b/src/framework/graphics/textureglyphcache.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TEXTUREGLYPHCACHE_H +#define TEXTUREGLYPHCACHE_H + +class TextureGlyphCache +{ +}; + +#endif diff --git a/src/framework/graphics/vertexarray.h b/src/framework/graphics/vertexarray.h new file mode 100644 index 00000000..ce31ff34 --- /dev/null +++ b/src/framework/graphics/vertexarray.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef VERTEXARRAY_H +#define VERTEXARRAY_H + +#include "declarations.h" +#include + +class VertexArray +{ +public: + inline void addVertex(GLfloat x, GLfloat y) { m_buffer << x << y; } + inline void addRect(const Rect& rect) { + GLfloat top = rect.top(); + GLfloat right = rect.right()+1; + GLfloat bottom = rect.bottom()+1; + GLfloat left = rect.left(); + + addVertex(left, top); + addVertex(right, top); + addVertex(left, bottom); + addVertex(left, bottom); + addVertex(right, top); + addVertex(right, bottom); + } + + inline void addQuad(const Rect& rect) { + GLfloat top = rect.top(); + GLfloat right = rect.right()+1; + GLfloat bottom = rect.bottom()+1; + GLfloat left = rect.left(); + + addVertex(left, top); + addVertex(right, top); + addVertex(left, bottom); + addVertex(right, bottom); + } + + void clear() { m_buffer.reset(); } + GLfloat *vertexArray() const { return m_buffer.data(); } + int vertexCount() const { return m_buffer.size() / 2; } + +private: + DataBuffer m_buffer; +}; + +#endif diff --git a/src/framework/util/databuffer.h b/src/framework/util/databuffer.h new file mode 100644 index 00000000..56b88a44 --- /dev/null +++ b/src/framework/util/databuffer.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DATABUFFER_H +#define DATABUFFER_H + +template +class DataBuffer +{ +public: + DataBuffer(int res = 64) { + m_capacity = res; + m_buffer = new T[m_capacity]; + m_size = 0; + } + ~DataBuffer() { delete[] m_buffer; } + + inline void reset() { m_size = 0; } + inline bool isEmpty() const { return m_size == 0; } + + inline int size() const { return m_size; } + inline T *data() const { return m_buffer; } + + inline const T& at(int i) const { return m_buffer[i]; } + inline const T& last() const { return m_buffer[m_size-1]; } + inline const T& first() const { return m_buffer[0]; } + inline const T& operator[](int i) const { return m_buffer[i]; } + inline T& operator[](int i) { return m_buffer[i]; } + + inline void add(const T &t) { + if(m_size >= m_capacity) { + m_capacity *= 2; + T *buffer = new T[m_capacity]; + for(int i=0;i Date: Wed, 7 Dec 2011 17:54:28 -0200 Subject: [PATCH 08/10] test shader effect --- TODO | 1 + modules/shadertest.frag | 53 +++++++++++++++++++ src/framework/graphics/glbuffer.cpp | 17 ++++++ src/framework/graphics/glbuffer.h | 14 +++++ src/framework/graphics/painter.cpp | 2 + src/framework/graphics/painter.h | 2 + .../graphics/paintershaderprogram.cpp | 2 + src/framework/graphics/paintershaderprogram.h | 3 +- src/framework/graphics/shader.cpp | 4 +- src/otclient/core/map.cpp | 40 ++++++++++++-- 10 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 modules/shadertest.frag diff --git a/TODO b/TODO index 3e235b7e..e4b9fe8f 100644 --- a/TODO +++ b/TODO @@ -33,6 +33,7 @@ restore ctrl+g and keybindings create a class for reading binary files handle corrupt errors in dat/spr +create image class use CoordsBuffer in font cache into framebuffers implement glbuffer for CoordsBuffer diff --git a/modules/shadertest.frag b/modules/shadertest.frag new file mode 100644 index 00000000..1a4f6e3e --- /dev/null +++ b/modules/shadertest.frag @@ -0,0 +1,53 @@ +uniform sampler2D texture; +varying vec2 textureCoords; +uniform vec4 color; +uniform float opacity; + +uniform float ticks; +uniform float rt_w = 18*32; +uniform float rt_h = 14*32; + +uniform float radius = 300.0; +uniform float angle = 0.2; +uniform vec2 center = vec2(8*32, 5*32); + +vec4 PostFX(sampler2D tex, vec2 uv, float time) +{ + vec2 texSize = vec2(rt_w, rt_h); + vec2 tc = uv * texSize; + tc -= center; + float dist = length(tc); + if (dist < radius) + { + float percent = (radius - dist) / radius; + float theta = percent * percent * ((int)ticks % 1000)/1000.0 * 8.0; + float s = sin(theta); + float c = cos(theta); + tc = vec2(dot(tc, vec2(c, -s)), dot(tc, vec2(s, c))); + } + tc += center; + vec3 color = texture2D(texture, tc / texSize).rgb; + return vec4(color, 1.0); +} + +void main (void) +{ + vec2 uv = textureCoords.st; + gl_FragColor = PostFX(texture, uv, ticks) * opacity; +} + +/* +uniform float opacity; +vec4 calculatePixel(); +void main() +{ + gl_FragColor = calculatePixel() * opacity; +} + +varying vec2 textureCoords; +uniform vec4 color; +uniform sampler2D texture; +vec4 calculatePixel() { + return texture2D(texture, textureCoords) * color; +} +*/ \ No newline at end of file diff --git a/src/framework/graphics/glbuffer.cpp b/src/framework/graphics/glbuffer.cpp index 7d6ddcc4..fd2e1cad 100644 --- a/src/framework/graphics/glbuffer.cpp +++ b/src/framework/graphics/glbuffer.cpp @@ -22,3 +22,20 @@ #include "glbuffer.h" +GLBuffer::GLBuffer() +{ + glGenBuffers(1, &m_id); + if(!m_id) + logFatal("Unable to create a simple GL buffer"); +} + +void GLBuffer::bind() +{ + gl +} + +void GLBuffer::release() +{ + +} + diff --git a/src/framework/graphics/glbuffer.h b/src/framework/graphics/glbuffer.h index ba31f943..6977363b 100644 --- a/src/framework/graphics/glbuffer.h +++ b/src/framework/graphics/glbuffer.h @@ -23,8 +23,22 @@ #ifndef GLBUFFER_H #define GLBUFFER_H +#include "declarations.h" + class GLBuffer { +public: + GLBuffer(); + ~GLBuffer(); + + void write(const + void bind(); + void release(); + + GLuint bufferId(); + +private: + GLuint m_id; }; #endif diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index f156bcd7..313c58c9 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -47,6 +47,7 @@ void Painter::init() program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); program->bindUniformLocation(PainterShaderProgram::TEXTURE_UNIFORM, "texture"); + program->bindUniformLocation(PainterShaderProgram::TICKS_UNIFORM, "ticks"); m_drawTexturedProgram = program; program = PainterShaderProgramPtr(new PainterShaderProgram); @@ -57,6 +58,7 @@ void Painter::init() program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); + program->bindUniformLocation(PainterShaderProgram::TICKS_UNIFORM, "ticks"); m_drawSolidColorProgram = program; } diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index 10652974..73f75a67 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -57,6 +57,8 @@ public: void setCompositionMode(CompositionMode compositionMode); + GLfloat *getProjectionMatrix() { return (GLfloat*)m_projectionMatrix; } + private: PainterShaderProgramPtr m_drawTexturedProgram; PainterShaderProgramPtr m_drawSolidColorProgram; diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp index 2fd9fa6f..99f50c1c 100644 --- a/src/framework/graphics/paintershaderprogram.cpp +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -24,6 +24,7 @@ #include "painter.h" #include "texture.h" #include "texturemanager.h" +#include void PainterShaderProgram::setProjectionMatrix(float projectionMatrix[3][3]) { @@ -76,6 +77,7 @@ void PainterShaderProgram::setTextureCoords(const GLfloat *textureCoords) void PainterShaderProgram::prepareForDraw() { assert(bind()); + setUniformValue(TICKS_UNIFORM, (GLfloat)g_clock.ticks()); } void PainterShaderProgram::drawTriangleStrip(int numVertices) diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index f7d9d409..89393961 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -35,7 +35,8 @@ public: TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1, COLOR_UNIFORM = 2, OPACITY_UNIFORM = 3, - TEXTURE_UNIFORM = 4 + TEXTURE_UNIFORM = 4, + TICKS_UNIFORM = 5 }; void setProjectionMatrix(GLfloat projectionMatrix[3][3]); diff --git a/src/framework/graphics/shader.cpp b/src/framework/graphics/shader.cpp index 34503202..ca24c03d 100644 --- a/src/framework/graphics/shader.cpp +++ b/src/framework/graphics/shader.cpp @@ -21,6 +21,7 @@ */ #include "shader.h" +#include Shader::Shader(Shader::ShaderType shaderType) { @@ -70,8 +71,7 @@ bool Shader::compileSourceCode(const std::string& sourceCode) bool Shader::compileSourceFile(const std::string& sourceFile) { - std::ifstream fin(sourceFile); - std::string sourceCode((std::istreambuf_iterator(fin)), std::istreambuf_iterator()); + std::string sourceCode = g_resources.loadFile(sourceFile); return compileSourceCode(sourceCode); } diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 72173ef3..7ea70ccb 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -28,7 +28,9 @@ #include "missile.h" #include #include - +#include +#include +#include Map g_map; Map::Map() @@ -36,11 +38,27 @@ Map::Map() setVisibleSize(Size(MAP_VISIBLE_WIDTH, MAP_VISIBLE_HEIGHT)); } +PainterShaderProgramPtr program; void Map::draw(const Rect& rect) { - if(!m_framebuffer) + if(!m_framebuffer) { m_framebuffer = FrameBufferPtr(new FrameBuffer(m_visibleSize.width() * NUM_TILE_PIXELS, m_visibleSize.height() * NUM_TILE_PIXELS)); + + program = PainterShaderProgramPtr(new PainterShaderProgram); + program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + program->addShaderFromSourceFile(Shader::Fragment, "/shadertest.frag"); + program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); + program->bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); + assert(program->link()); + program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); + program->bindUniformLocation(PainterShaderProgram::TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix"); + program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); + program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); + program->bindUniformLocation(PainterShaderProgram::TEXTURE_UNIFORM, "texture"); + program->bindUniformLocation(PainterShaderProgram::TICKS_UNIFORM, "ticks"); + } + g_painter.setColor(Fw::white); m_framebuffer->bind(); @@ -82,8 +100,22 @@ void Map::draw(const Rect& rect) m_framebuffer->release(); - g_painter.setColor(Fw::white); - m_framebuffer->draw(rect); + //g_painter.setColor(Fw::white); + //m_framebuffer->draw(rect); + + + CoordsBuffer coordsBuffer; + coordsBuffer.addRect(rect, Rect(0,0,m_framebuffer->getTexture()->getSize())); + coordsBuffer.cacheVertexArrays(); + program->prepareForDraw(); + program->setProjectionMatrix((GLfloat (*)[3])g_painter.getProjectionMatrix()); + program->setOpacity(1.0f); + program->setColor(Fw::white); + program->setTexture(m_framebuffer->getTexture()); + program->setVertexCoords(coordsBuffer.getVertexCoords()); + program->setTextureCoords(coordsBuffer.getTextureCoords()); + program->drawTriangles(coordsBuffer.getVertexCount()); + program->releaseFromDraw(); // calculate stretch factor float horizontalStretchFactor = rect.width() / (float)(m_visibleSize.width() * NUM_TILE_PIXELS); From 5ec386b35f5a561ab388b40abe2aa920ec1a8611 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Wed, 7 Dec 2011 21:43:12 -0200 Subject: [PATCH 09/10] bloom shader --- modules/shadertest.frag | 37 ++++++++- src/framework/graphics/coordsbuffer.cpp | 6 +- src/framework/graphics/coordsbuffer.h | 9 ++- src/framework/graphics/painter.cpp | 73 ++++++----------- src/framework/graphics/painter.h | 7 +- .../graphics/paintershaderprogram.cpp | 79 +++++++++++-------- src/framework/graphics/paintershaderprogram.h | 20 ++--- src/framework/graphics/shaderprogram.h | 2 +- src/framework/graphics/vertexarray.h | 2 +- src/otclient/core/map.cpp | 27 +------ 10 files changed, 136 insertions(+), 126 deletions(-) diff --git a/modules/shadertest.frag b/modules/shadertest.frag index 1a4f6e3e..fe3e74c6 100644 --- a/modules/shadertest.frag +++ b/modules/shadertest.frag @@ -1,5 +1,40 @@ uniform sampler2D texture; varying vec2 textureCoords; + +void main() +{ + vec4 sum = vec4(0); + vec2 texcoord = textureCoords; + int j; + int i; + + for( i= -4 ;i < 4; i++) + { + for (j = -3; j < 3; j++) + { + sum += texture2D(texture, texcoord + vec2(j, i)*0.004) * 0.25; + } + } + if (texture2D(texture, texcoord).r < 0.3) + { + gl_FragColor = sum*sum*0.012 + texture2D(texture, texcoord); + } + else + { + if (texture2D(texture, texcoord).r < 0.5) + { + gl_FragColor = sum*sum*0.009 + texture2D(texture, texcoord); + } + else + { + gl_FragColor = sum*sum*0.0075 + texture2D(texture, texcoord); + } + } +} + +/* +uniform sampler2D texture; +varying vec2 textureCoords; uniform vec4 color; uniform float opacity; @@ -35,7 +70,7 @@ void main (void) vec2 uv = textureCoords.st; gl_FragColor = PostFX(texture, uv, ticks) * opacity; } - +*/ /* uniform float opacity; vec4 calculatePixel(); diff --git a/src/framework/graphics/coordsbuffer.cpp b/src/framework/graphics/coordsbuffer.cpp index a3068aa9..1f59c682 100644 --- a/src/framework/graphics/coordsbuffer.cpp +++ b/src/framework/graphics/coordsbuffer.cpp @@ -27,7 +27,7 @@ void CoordsBuffer::clear() m_destRects.reset(); m_srcRects.reset(); m_textureCoords.clear(); - m_vertexCoords.clear(); + m_vertices.clear(); m_updateCache = true; } @@ -97,11 +97,11 @@ void CoordsBuffer::cacheVertexArrays() int numDestRects = m_destRects.size(); int numSrcRects = m_srcRects.size(); - m_vertexCoords.clear(); + m_vertices.clear(); m_textureCoords.clear(); for(int i=0;i m_destRects; DataBuffer m_srcRects; - VertexArray m_vertexCoords; + VertexArray m_vertices; VertexArray m_textureCoords; Boolean m_updateCache; }; diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp index 313c58c9..c08eebb4 100644 --- a/src/framework/graphics/painter.cpp +++ b/src/framework/graphics/painter.cpp @@ -36,30 +36,15 @@ void Painter::init() setOpacity(255); setCompositionMode(CompositionMode_SourceOver); - PainterShaderProgramPtr program = PainterShaderProgramPtr(new PainterShaderProgram); - program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); - program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader); - program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); - program->bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); - assert(program->link()); - program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); - program->bindUniformLocation(PainterShaderProgram::TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix"); - program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); - program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); - program->bindUniformLocation(PainterShaderProgram::TEXTURE_UNIFORM, "texture"); - program->bindUniformLocation(PainterShaderProgram::TICKS_UNIFORM, "ticks"); - m_drawTexturedProgram = program; + m_drawTexturedProgram = PainterShaderProgramPtr(new PainterShaderProgram); + m_drawTexturedProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + m_drawTexturedProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader); + assert(m_drawTexturedProgram->link()); - program = PainterShaderProgramPtr(new PainterShaderProgram); - program->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader); - program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader); - program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); - assert(program->link()); - program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); - program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); - program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); - program->bindUniformLocation(PainterShaderProgram::TICKS_UNIFORM, "ticks"); - m_drawSolidColorProgram = program; + m_drawSolidColorProgram = PainterShaderProgramPtr(new PainterShaderProgram); + m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader); + m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader); + assert(m_drawSolidColorProgram->link()); } void Painter::terminate() @@ -97,38 +82,23 @@ void Painter::updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis } } -void Painter::drawCoords(CoordsBuffer& coordsBuffer) +void Painter::drawProgram(const PainterShaderProgramPtr& program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode) { coordsBuffer.cacheVertexArrays(); - - if(coordsBuffer.getVertexCount() < 3) + if(coordsBuffer.getVertexCount() == 0) return; - m_drawSolidColorProgram->prepareForDraw(); - m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix); - m_drawSolidColorProgram->setOpacity(m_currentOpacity); - m_drawSolidColorProgram->setColor(m_currentColor); - m_drawSolidColorProgram->setVertexCoords(coordsBuffer.getVertexCoords()); - m_drawSolidColorProgram->drawTriangles(coordsBuffer.getVertexCount()); - m_drawSolidColorProgram->releaseFromDraw(); + program->setProjectionMatrix(m_projectionMatrix); + program->setOpacity(m_currentOpacity); + program->setColor(m_currentColor); + program->draw(coordsBuffer, drawMode); } void Painter::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) { - coordsBuffer.cacheVertexArrays(); - - if(coordsBuffer.getVertexCount() < 3) - return; - - m_drawTexturedProgram->prepareForDraw(); - m_drawTexturedProgram->setProjectionMatrix(m_projectionMatrix); - m_drawTexturedProgram->setOpacity(m_currentOpacity); - m_drawTexturedProgram->setColor(m_currentColor); - m_drawTexturedProgram->setTexture(texture); - m_drawTexturedProgram->setVertexCoords(coordsBuffer.getVertexCoords()); - m_drawTexturedProgram->setTextureCoords(coordsBuffer.getTextureCoords()); - m_drawTexturedProgram->drawTriangles(coordsBuffer.getVertexCount()); - m_drawTexturedProgram->releaseFromDraw(); + PainterShaderProgramPtr program = m_customProgram ? m_customProgram : m_drawTexturedProgram; + program->setTexture(texture); + drawProgram(program, coordsBuffer); } void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture) @@ -163,7 +133,7 @@ void Painter::drawFilledRect(const Rect& dest) m_coordsBuffer.clear(); m_coordsBuffer.addRect(dest); - drawCoords(m_coordsBuffer); + drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram, m_coordsBuffer); } void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth) @@ -173,7 +143,12 @@ void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth) m_coordsBuffer.clear(); m_coordsBuffer.addBoudingRect(dest, innerLineWidth); - drawCoords(m_coordsBuffer); + drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram, m_coordsBuffer); +} + +void Painter::setCustomProgram(PainterShaderProgramPtr program) +{ + m_customProgram = program; } void Painter::setCompositionMode(Painter::CompositionMode compositionMode) diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h index 73f75a67..87b570b4 100644 --- a/src/framework/graphics/painter.h +++ b/src/framework/graphics/painter.h @@ -26,6 +26,7 @@ #include "declarations.h" #include #include "coordsbuffer.h" +#include "paintershaderprogram.h" class Painter { @@ -40,9 +41,8 @@ public: void updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis = false); - void drawCoords(CoordsBuffer& coordsBuffer); + void drawProgram(const PainterShaderProgramPtr& program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode = PainterShaderProgram::Triangles); void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); - void drawTexturedRect(const Rect& dest, const TexturePtr& texture); void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); @@ -55,6 +55,8 @@ public: void setOpacity(int opacity) { m_currentOpacity = opacity / 255.0f; } int getOpacity() { return m_currentOpacity * 255.0f; } + void setCustomProgram(PainterShaderProgramPtr program); + void releaseCustomProgram() { m_customProgram = nullptr; } void setCompositionMode(CompositionMode compositionMode); GLfloat *getProjectionMatrix() { return (GLfloat*)m_projectionMatrix; } @@ -62,6 +64,7 @@ public: private: PainterShaderProgramPtr m_drawTexturedProgram; PainterShaderProgramPtr m_drawSolidColorProgram; + PainterShaderProgramPtr m_customProgram; GLfloat m_projectionMatrix[3][3]; Color m_currentColor; GLfloat m_currentOpacity; diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp index 99f50c1c..0d10f47e 100644 --- a/src/framework/graphics/paintershaderprogram.cpp +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -26,13 +26,31 @@ #include "texturemanager.h" #include +bool PainterShaderProgram::link() +{ + bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); + bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); + if(ShaderProgram::link()) { + bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); + bindUniformLocation(TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix"); + bindUniformLocation(COLOR_UNIFORM, "color"); + bindUniformLocation(OPACITY_UNIFORM, "opacity"); + bindUniformLocation(TEXTURE_UNIFORM, "texture"); + bindUniformLocation(TICKS_UNIFORM, "ticks"); + return true; + } + return false; +} + void PainterShaderProgram::setProjectionMatrix(float projectionMatrix[3][3]) { + bind(); setUniformValue(PROJECTION_MATRIX_UNIFORM, projectionMatrix, true); } void PainterShaderProgram::setColor(const Color& color) { + bind(); setUniformValue(COLOR_UNIFORM, color.r() / 255.0f, color.g() / 255.0f, @@ -42,11 +60,15 @@ void PainterShaderProgram::setColor(const Color& color) void PainterShaderProgram::setOpacity(GLfloat opacity) { + bind(); setUniformValue(OPACITY_UNIFORM, opacity); } void PainterShaderProgram::setTexture(const TexturePtr& texture) { + if(!texture) + return; + float w = texture->getGlSize().width(); float h = texture->getGlSize().height(); @@ -55,52 +77,45 @@ void PainterShaderProgram::setTexture(const TexturePtr& texture) { 0.0f, 1.0f/h } }; + bind(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture->getId()); setUniformValue(TEXTURE_UNIFORM, 0); setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix, true); } -void PainterShaderProgram::setVertexCoords(const GLfloat *vertices) -{ - enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); - setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, vertices, 2); -} - -void PainterShaderProgram::setTextureCoords(const GLfloat *textureCoords) -{ - enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); - setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, textureCoords, 2); - m_mustDisableTexCoordsArray = true; -} - -void PainterShaderProgram::prepareForDraw() +void PainterShaderProgram::draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode) { assert(bind()); + setUniformValue(TICKS_UNIFORM, (GLfloat)g_clock.ticks()); -} -void PainterShaderProgram::drawTriangleStrip(int numVertices) -{ - glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices); -} + int numVertices = coordsBuffer.getVertexCount(); + if(numVertices == 0) + return; -void PainterShaderProgram::drawTriangles(int numVertices) -{ - glDrawArrays(GL_TRIANGLES, 0, numVertices); -} - -void PainterShaderProgram::releaseFromDraw() -{ - if(m_mustDisableTexCoordsArray) { - disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); - m_mustDisableTexCoordsArray = false; + bool mustDisableVertexArray = false; + if(coordsBuffer.getVertexCount() > 0) { + enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); + setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, coordsBuffer.getVertices(), 2); + mustDisableVertexArray = true; } - if(m_mustDisableVertexArray) { + bool mustDisableTexCoordsArray = false; + if(coordsBuffer.getTextureCoords() > 0) { + enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); + setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, coordsBuffer.getTextureCoords(), 2); + mustDisableTexCoordsArray = true; + } + + glDrawArrays(drawMode, 0, numVertices); + + if(mustDisableVertexArray) disableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); - m_mustDisableVertexArray = false; - } + + if(mustDisableTexCoordsArray) + disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); //release(); } + diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index 89393961..9abdeb4d 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -24,10 +24,10 @@ #define PAINTERSHADER_H #include "shaderprogram.h" +#include "coordsbuffer.h" class PainterShaderProgram : public ShaderProgram { -public: enum { VERTEX_COORDS_ATTR = 0, TEXTURE_COORDS_ATTR = 1, @@ -38,22 +38,22 @@ public: TEXTURE_UNIFORM = 4, TICKS_UNIFORM = 5 }; +public: + enum DrawMode { + Triangles = GL_TRIANGLES, + TriangleStrip = GL_TRIANGLE_STRIP + }; + + bool link(); void setProjectionMatrix(GLfloat projectionMatrix[3][3]); void setColor(const Color& color); void setOpacity(GLfloat opacity); void setTexture(const TexturePtr& texture); - void setVertexCoords(const GLfloat *vertices); - void setTextureCoords(const GLfloat *textureCoords); - - void prepareForDraw(); - void drawTriangleStrip(int numVertices); - void drawTriangles(int numVertices); - void releaseFromDraw(); + void draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); private: - Boolean m_mustDisableVertexArray; - Boolean m_mustDisableTexCoordsArray; + DrawMode m_drawMode; }; #endif diff --git a/src/framework/graphics/shaderprogram.h b/src/framework/graphics/shaderprogram.h index b1096415..c09c0894 100644 --- a/src/framework/graphics/shaderprogram.h +++ b/src/framework/graphics/shaderprogram.h @@ -39,7 +39,7 @@ public: bool addShaderFromSourceFile(Shader::ShaderType shaderType, const std::string& sourceFile); void removeShader(const ShaderPtr& shader); void removeAllShaders(); - bool link(); + virtual bool link(); bool bind(); void release(); std::string log(); diff --git a/src/framework/graphics/vertexarray.h b/src/framework/graphics/vertexarray.h index ce31ff34..b21cdf82 100644 --- a/src/framework/graphics/vertexarray.h +++ b/src/framework/graphics/vertexarray.h @@ -57,7 +57,7 @@ public: } void clear() { m_buffer.reset(); } - GLfloat *vertexArray() const { return m_buffer.data(); } + GLfloat *vertices() const { return m_buffer.data(); } int vertexCount() const { return m_buffer.size() / 2; } private: diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 7ea70ccb..ea63e35e 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -48,15 +48,7 @@ void Map::draw(const Rect& rect) program = PainterShaderProgramPtr(new PainterShaderProgram); program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); program->addShaderFromSourceFile(Shader::Fragment, "/shadertest.frag"); - program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); - program->bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); assert(program->link()); - program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); - program->bindUniformLocation(PainterShaderProgram::TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix"); - program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color"); - program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity"); - program->bindUniformLocation(PainterShaderProgram::TEXTURE_UNIFORM, "texture"); - program->bindUniformLocation(PainterShaderProgram::TICKS_UNIFORM, "ticks"); } g_painter.setColor(Fw::white); @@ -100,22 +92,11 @@ void Map::draw(const Rect& rect) m_framebuffer->release(); - //g_painter.setColor(Fw::white); - //m_framebuffer->draw(rect); - - CoordsBuffer coordsBuffer; - coordsBuffer.addRect(rect, Rect(0,0,m_framebuffer->getTexture()->getSize())); - coordsBuffer.cacheVertexArrays(); - program->prepareForDraw(); - program->setProjectionMatrix((GLfloat (*)[3])g_painter.getProjectionMatrix()); - program->setOpacity(1.0f); - program->setColor(Fw::white); - program->setTexture(m_framebuffer->getTexture()); - program->setVertexCoords(coordsBuffer.getVertexCoords()); - program->setTextureCoords(coordsBuffer.getTextureCoords()); - program->drawTriangles(coordsBuffer.getVertexCount()); - program->releaseFromDraw(); + g_painter.setCustomProgram(program); + g_painter.setColor(Fw::white); + m_framebuffer->draw(rect); + g_painter.releaseCustomProgram(); // calculate stretch factor float horizontalStretchFactor = rect.width() / (float)(m_visibleSize.width() * NUM_TILE_PIXELS); From 04ee85dc927aeccd07e04db7c3315897dd8a8242 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Thu, 8 Dec 2011 15:28:29 -0200 Subject: [PATCH 10/10] experiment shaders in outfit --- modules/outfit.frag | 49 +++++++++++ modules/shadertest.frag | 37 +++++++- .../graphics/paintershaderprogram.cpp | 19 ++-- src/framework/graphics/paintershaderprogram.h | 1 + src/framework/graphics/shaderprogram.cpp | 2 +- src/framework/graphics/shaderprogram.h | 4 +- src/otclient/const.h | 8 -- src/otclient/core/creature.cpp | 86 ++++++++++++++----- src/otclient/core/spritemanager.cpp | 39 ++------- src/otclient/core/spritemanager.h | 10 +-- src/otclient/core/thing.cpp | 4 +- src/otclient/core/thing.h | 2 +- 12 files changed, 174 insertions(+), 87 deletions(-) create mode 100644 modules/outfit.frag diff --git a/modules/outfit.frag b/modules/outfit.frag new file mode 100644 index 00000000..e1df99fa --- /dev/null +++ b/modules/outfit.frag @@ -0,0 +1,49 @@ +uniform float opacity; +uniform vec4 color; +uniform float ticks; + +uniform sampler2D texture; // outfit texture +varying vec2 textureCoords; // outfit texture coords +uniform sampler2D maskTexture; // outfit color mask + +uniform vec4 headColor; +uniform vec4 bodyColor; +uniform vec4 legsColor; +uniform vec4 feetColor; + +vec4 calcPixel(vec2 texCoord) +{ + vec4 pixel = texture2D(texture, texCoord); + vec4 maskColor = texture2D(maskTexture, texCoord); + + vec4 outColor = vec4(0); + if(maskColor.r == 1.0 && maskColor.g == 1.0) { + outColor = headColor; + } else if(maskColor.r == 1.0) { + outColor = bodyColor; + } else if(maskColor.g == 1.0) { + outColor = legsColor; + } else if(maskColor.b == 1.0) { + outColor = feetColor; + } + + if(outColor.a != 0.0) + pixel = pixel * outColor; + return pixel; +} +void main() +{ + vec4 pixel = calcPixel(textureCoords); + int num = 16; + + vec4 sum = vec4(0); + int i, j; + for(i=-num/2;igetId()); + setUniformValue(location, index); +} + void PainterShaderProgram::setTexture(const TexturePtr& texture) { if(!texture) @@ -78,9 +83,7 @@ void PainterShaderProgram::setTexture(const TexturePtr& texture) }; bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->getId()); - setUniformValue(TEXTURE_UNIFORM, 0); + setUniformTexture(TEXTURE_UNIFORM, texture, 0); setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix, true); } diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h index 9abdeb4d..80f1e19f 100644 --- a/src/framework/graphics/paintershaderprogram.h +++ b/src/framework/graphics/paintershaderprogram.h @@ -50,6 +50,7 @@ public: void setColor(const Color& color); void setOpacity(GLfloat opacity); void setTexture(const TexturePtr& texture); + void setUniformTexture(int location, const TexturePtr& texture, int index); void draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); private: diff --git a/src/framework/graphics/shaderprogram.cpp b/src/framework/graphics/shaderprogram.cpp index 8899f07a..ace96f81 100644 --- a/src/framework/graphics/shaderprogram.cpp +++ b/src/framework/graphics/shaderprogram.cpp @@ -139,6 +139,6 @@ void ShaderProgram::bindAttributeLocation(int location, const char* name) void ShaderProgram::bindUniformLocation(int location, const char* name) { assert(m_linked); - assert(location >= 0 && location < 10); + assert(location >= 0 && location < MAX_UNIFORM_LOCATIONS); m_uniformLocations[location] = glGetUniformLocation(m_programId, name); } diff --git a/src/framework/graphics/shaderprogram.h b/src/framework/graphics/shaderprogram.h index c09c0894..f05cd226 100644 --- a/src/framework/graphics/shaderprogram.h +++ b/src/framework/graphics/shaderprogram.h @@ -28,7 +28,7 @@ class ShaderProgram { enum { - MAX_UNIFORM_LOCATIONS = 10 + MAX_UNIFORM_LOCATIONS = 30 }; public: ShaderProgram(); @@ -62,6 +62,7 @@ public: void setAttributeValue(const char *name, GLfloat x, GLfloat y) { glVertexAttrib2f(getAttributeLocation(name), x, y); } void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z) { glVertexAttrib3f(getAttributeLocation(name), x, y, z); } + void setUniformValue(int location, const Color& color) { glUniform4f(m_uniformLocations[location], color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f); } void setUniformValue(int location, GLint value) { glUniform1i(m_uniformLocations[location], value); } void setUniformValue(int location, GLfloat value) { glUniform1f(m_uniformLocations[location], value); } void setUniformValue(int location, GLfloat x, GLfloat y) { glUniform2f(m_uniformLocations[location], x, y); } @@ -69,6 +70,7 @@ public: void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glUniform4f(m_uniformLocations[location], x, y, z, w); } void setUniformValue(int location, GLfloat mat2[2][2], bool transpose) { glUniformMatrix2fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat2); } void setUniformValue(int location, GLfloat mat3[3][3], bool transpose) { glUniformMatrix3fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat3); } + void setUniformValue(const char *name, const Color& color) { glUniform4f(glGetUniformLocation(m_programId, name), color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f); } void setUniformValue(const char *name, GLint value) { glUniform1i(glGetUniformLocation(m_programId, name), value); } void setUniformValue(const char *name, GLfloat value) { glUniform1f(glGetUniformLocation(m_programId, name), value); } void setUniformValue(const char *name, GLfloat x, GLfloat y) { glUniform2f(glGetUniformLocation(m_programId, name), x, y); } diff --git a/src/otclient/const.h b/src/otclient/const.h index 554f65a2..150d209e 100644 --- a/src/otclient/const.h +++ b/src/otclient/const.h @@ -250,14 +250,6 @@ namespace Otc ClientGetObjectInfo = 243 }; - enum SpriteMask { - SpriteRedMask = 0, - SpriteGreenMask, - SpriteBlueMask, - SpriteYellowMask, - SpriteNoMask = 255 - }; - enum InventorySlots { InventorySlotHead = 1, InventorySlotNecklace, diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index b8ece933..08bf079e 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -31,6 +31,10 @@ #include #include +#include +#include +#include "spritemanager.h" + Creature::Creature() : Thing() { m_healthPercent = 0; @@ -43,6 +47,13 @@ Creature::Creature() : Thing() m_informationFont = g_fonts.getFont("verdana-11px-rounded"); } +PainterShaderProgramPtr outfitProgram; +int HEAD_COLOR_UNIFORM = 10; +int BODY_COLOR_UNIFORM = 11; +int LEGS_COLOR_UNIFORM = 12; +int FEET_COLOR_UNIFORM = 13; +int MASK_TEXTURE_UNIFORM = 14; + void Creature::draw(const Point& p) { // TODO: activate on attack, follow, discover how 'attacked' works @@ -51,6 +62,18 @@ void Creature::draw(const Point& p) g_painter.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2); } + if(!outfitProgram) { + outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); + outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + outfitProgram->addShaderFromSourceFile(Shader::Fragment, "/outfit.frag"); + assert(outfitProgram->link()); + outfitProgram->bindUniformLocation(HEAD_COLOR_UNIFORM, "headColor"); + outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor"); + outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); + outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); + outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture"); + } + // Render creature for(m_yPattern = 0; m_yPattern < m_type->dimensions[ThingType::PatternY]; m_yPattern++) { @@ -58,35 +81,52 @@ void Creature::draw(const Point& p) if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1)))) continue; - // draw white item - g_painter.setColor(Fw::white); - internalDraw(p + m_walkOffset, 0); + g_painter.setCustomProgram(outfitProgram); - // draw mask if exists - if(m_type->dimensions[ThingType::Layers] > 1) { - // switch to blend color mode - g_painter.setCompositionMode(Painter::CompositionMode_ColorizeDest); + outfitProgram->bind(); + outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); + outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); + outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); + outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); - // head - g_painter.setColor(m_outfit.getHeadColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteYellowMask); + for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) { + for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) { + int sprIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases]) + * m_type->dimensions[ThingType::PatternZ] + m_zPattern) + * m_type->dimensions[ThingType::PatternY] + m_yPattern) + * m_type->dimensions[ThingType::PatternX] + m_xPattern) + * m_type->dimensions[ThingType::Layers] + 0) + * m_type->dimensions[ThingType::Height] + yi) + * m_type->dimensions[ThingType::Width] + xi; + if(m_type->dimensions[ThingType::Layers] > 1) { + int maskIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases]) + * m_type->dimensions[ThingType::PatternZ] + m_zPattern) + * m_type->dimensions[ThingType::PatternY] + m_yPattern) + * m_type->dimensions[ThingType::PatternX] + m_xPattern) + * m_type->dimensions[ThingType::Layers] + 1) + * m_type->dimensions[ThingType::Height] + yi) + * m_type->dimensions[ThingType::Width] + xi; + int spriteId = m_type->sprites[maskIndex]; + if(!spriteId) + continue; + TexturePtr maskTex = g_sprites.getSpriteTexture(spriteId); + outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); + } - // body - g_painter.setColor(m_outfit.getBodyColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteRedMask); + int spriteId = m_type->sprites[sprIndex]; + if(!spriteId) + continue; - // legs - g_painter.setColor(m_outfit.getLegsColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteGreenMask); + TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); - // feet - g_painter.setColor(m_outfit.getFeetColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteBlueMask); - - // restore default blend func - g_painter.setCompositionMode(Painter::CompositionMode_SourceOver); - g_painter.setColor(Fw::white); + Rect drawRect(((p + m_walkOffset).x - xi*32) - m_type->parameters[ThingType::DisplacementX], + ((p + m_walkOffset).y - yi*32) - m_type->parameters[ThingType::DisplacementY], + 32, 32); + g_painter.drawTexturedRect(drawRect, spriteTex); + } } + + g_painter.releaseCustomProgram(); } } diff --git a/src/otclient/core/spritemanager.cpp b/src/otclient/core/spritemanager.cpp index f1d5d0c5..731e66c1 100644 --- a/src/otclient/core/spritemanager.cpp +++ b/src/otclient/core/spritemanager.cpp @@ -118,30 +118,7 @@ TexturePtr SpriteManager::loadSpriteTexture(int id) return TexturePtr(new Texture(32, 32, 4, pixels)); } -TexturePtr SpriteManager::loadSpriteMask(TexturePtr spriteTex, Otc::SpriteMask mask) -{ - auto pixels = spriteTex->getPixels(); - - static uint32 maskColors[4] = { Fw::red, Fw::green, Fw::blue, Fw::yellow }; - uint32 maskColor = maskColors[mask]; - uint32 whiteColor = Fw::white; - uint32 alphaColor = Fw::alpha; - - // convert pixels - // masked color -> white color - // any other color -> alpha color - for(int i=0;i<4096;i+=4) { - uint32& currentColor = *(uint32*)&pixels[i]; - if(currentColor == maskColor) - currentColor = whiteColor; - else - currentColor = alphaColor; - } - - return TexturePtr(new Texture(32, 32, 4, &pixels[0])); -} - -TexturePtr SpriteManager::getSpriteTexture(int id, Otc::SpriteMask mask) +TexturePtr SpriteManager::getSpriteTexture(int id) { if(id == 0) return g_graphics.getEmptyTexture(); @@ -149,17 +126,11 @@ TexturePtr SpriteManager::getSpriteTexture(int id, Otc::SpriteMask mask) assert(id > 0 && id <= m_spritesCount); // load sprites on demand - Sprite& sprite = m_sprites[id-1]; - if(!sprite.texture) - sprite.texture = loadSpriteTexture(id); + TexturePtr& sprite = m_sprites[id-1]; + if(!sprite) + sprite = loadSpriteTexture(id); //TODO: release unused sprites textures after X seconds // to avoid massive texture allocations - - if(mask != Otc::SpriteNoMask) { - if(!sprite.masks[mask]) - sprite.masks[mask] = loadSpriteMask(sprite.texture, mask); - return sprite.masks[mask]; - } else - return sprite.texture; + return sprite; } diff --git a/src/otclient/core/spritemanager.h b/src/otclient/core/spritemanager.h index 0c97f8a2..7b1dfb2c 100644 --- a/src/otclient/core/spritemanager.h +++ b/src/otclient/core/spritemanager.h @@ -26,11 +26,6 @@ #include "declarations.h" #include -struct Sprite { - TexturePtr texture; - TexturePtr masks[4]; -}; - class SpriteManager { public: @@ -42,16 +37,15 @@ public: uint32 getSignature() { return m_signature; } int getSpritesCount() { return m_spritesCount; } - TexturePtr getSpriteTexture(int id, Otc::SpriteMask mask = Otc::SpriteNoMask); + TexturePtr getSpriteTexture(int id); private: TexturePtr loadSpriteTexture(int id); - TexturePtr loadSpriteMask(TexturePtr spriteTex, Otc::SpriteMask mask); uint32 m_signature; uint16 m_spritesCount; std::stringstream m_fin; - std::vector m_sprites; + std::vector m_sprites; TexturePtr m_transparentSprite; }; diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index 972d4ee1..109a0d0a 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -34,7 +34,7 @@ Thing::Thing() : m_id(0) m_type = g_thingsType.getEmptyThingType(); } -void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask) +void Thing::internalDraw(const Point& p, int layers) { for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) { for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) { @@ -50,7 +50,7 @@ void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask) if(!spriteId) continue; - TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId, mask); + TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); Rect drawRect((p.x - xi*32) - m_type->parameters[ThingType::DisplacementX], (p.y - yi*32) - m_type->parameters[ThingType::DisplacementY], diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 3614d512..29328d47 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -63,7 +63,7 @@ public: virtual LocalPlayerPtr asLocalPlayer() { return nullptr; } protected: - void internalDraw(const Point& p, int layers, Otc::SpriteMask mask = Otc::SpriteNoMask); + void internalDraw(const Point& p, int layers); uint32 m_id; Position m_position;