begin implementing OpenGL 1.0 engine

* option to pass -opengl1 or -opengl2 as argument
* note that with this commit there are a lot of graphics regressions and the master will remaing unstable for a while
* shaders disabled for a while
This commit is contained in:
Eduardo Bart 2012-04-18 20:03:43 -03:00
parent a4a00a49fe
commit 58d76e255d
46 changed files with 1303 additions and 510 deletions

View File

@ -5,6 +5,7 @@ uniform sampler2D tex0; // map texture
varying vec2 texCoord; // map texture coords varying vec2 texCoord; // map texture coords
//uniform vec4 awareArea; //uniform vec4 awareArea;
void main() void main()
{ {
gl_FragColor = texture2D(tex0, texCoord); gl_FragColor = texture2D(tex0, texCoord);
@ -84,3 +85,21 @@ void main()
gl_FragColor = color; gl_FragColor = color;
} }
*/ */
/*
void main()
{
vec4 sum = vec4(0);
vec2 texcoord = texCoord;
int j;
int i;
for( i= -4 ;i < 4; i++)
{
for (j = -4; j < 4; j++)
{
sum += texture2D(tex0, texcoord + vec2(j, i)*0.0025) * 0.0125;
}
}
gl_FragColor = texture2D(tex0, texCoord) + sum;
}
*/

View File

@ -189,6 +189,8 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl1.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl2.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp
@ -201,6 +203,7 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/shader.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/shader.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/paintershadermanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/coordsbuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/coordsbuffer.cpp
# framework sound # framework sound

View File

@ -45,7 +45,6 @@ ticks_t Clock::asyncTicks()
return std::chrono::duration_cast<std::chrono::milliseconds>(timeNow - m_startupTime).count(); return std::chrono::duration_cast<std::chrono::milliseconds>(timeNow - m_startupTime).count();
} }
void Clock::sleep(int ms) void Clock::sleep(int ms)
{ {
usleep(ms * 1000); usleep(ms * 1000);

View File

@ -23,13 +23,7 @@
#ifndef FRAMEWORK_GLOBAL_H #ifndef FRAMEWORK_GLOBAL_H
#define FRAMEWORK_GLOBAL_H #define FRAMEWORK_GLOBAL_H
#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) #include "util/compiler.h"
#error "sorry, you need gcc 4.6 or greater to compile"
#endif
#if !defined(__GXX_EXPERIMENTAL_CXX0X__)
#error "sorry, you must enable C++0x to compile"
#endif
// common C/C++ headers // common C/C++ headers
#include "pch.h" #include "pch.h"
@ -38,7 +32,6 @@
#include "const.h" #include "const.h"
// additional utilities // additional utilities
#include "util/compiler.h"
#include "util/types.h" #include "util/types.h"
#include "util/tools.h" #include "util/tools.h"
#include "math/point.h" #include "math/point.h"

View File

@ -26,18 +26,18 @@
CoordsBuffer::CoordsBuffer() CoordsBuffer::CoordsBuffer()
{ {
m_hardwareCacheMode = HardwareBuffer::DynamicDraw; m_hardwareCacheMode = HardwareBuffer::DynamicDraw;
m_hardwareVertexBuffer = nullptr; m_hardwareVertexArray = nullptr;
m_hardwareTextureVertexBuffer = nullptr; m_hardwareTextureCoordArray = nullptr;
m_hardwareCached = false; m_hardwareCached = false;
m_hardwareCaching = false; m_hardwareCaching = false;
} }
CoordsBuffer::~CoordsBuffer() CoordsBuffer::~CoordsBuffer()
{ {
if(m_hardwareVertexBuffer) if(m_hardwareVertexArray)
delete m_hardwareVertexBuffer; delete m_hardwareVertexArray;
if(m_hardwareTextureVertexBuffer) if(m_hardwareTextureCoordArray)
delete m_hardwareTextureVertexBuffer; delete m_hardwareTextureCoordArray;
} }
void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth) void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth)
@ -78,8 +78,8 @@ void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src)
} }
partialDest.translate(dest.topLeft()); partialDest.translate(dest.topLeft());
m_vertexBuffer.addRect(partialDest); m_vertexArray.addRect(partialDest);
m_textureVertexBuffer.addRect(partialSrc); m_textureCoordArray.addRect(partialSrc);
} }
} }
m_hardwareCached = false; m_hardwareCached = false;
@ -90,10 +90,6 @@ void CoordsBuffer::enableHardwareCaching(HardwareBuffer::UsagePattern usagePatte
if(!g_graphics.canUseHardwareBuffers()) if(!g_graphics.canUseHardwareBuffers())
return; return;
#ifndef OPENGL_ES2
if(!GL_ARB_vertex_buffer_object)
return;
#endif
m_hardwareCacheMode = usagePattern; m_hardwareCacheMode = usagePattern;
m_hardwareCaching = true; m_hardwareCaching = true;
m_hardwareCached = false; m_hardwareCached = false;
@ -104,18 +100,18 @@ void CoordsBuffer::updateCaches()
if(!m_hardwareCaching || m_hardwareCached) if(!m_hardwareCaching || m_hardwareCached)
return; return;
if(m_vertexBuffer.vertexCount() > 0) { if(m_vertexArray.vertexCount() > 0) {
if(!m_hardwareVertexBuffer && m_vertexBuffer.vertexCount() > 0) if(!m_hardwareVertexArray && m_vertexArray.vertexCount() > 0)
m_hardwareVertexBuffer = new HardwareBuffer(HardwareBuffer::VertexBuffer); m_hardwareVertexArray = new HardwareBuffer(HardwareBuffer::VertexBuffer);
m_hardwareVertexBuffer->bind(); m_hardwareVertexArray->bind();
m_hardwareVertexBuffer->write((void*)m_vertexBuffer.vertices(), m_vertexBuffer.size() * sizeof(float), m_hardwareCacheMode); m_hardwareVertexArray->write((void*)m_vertexArray.vertices(), m_vertexArray.size() * sizeof(float), m_hardwareCacheMode);
} }
if(m_textureVertexBuffer.vertexCount() > 0) { if(m_textureCoordArray.vertexCount() > 0) {
if(!m_hardwareTextureVertexBuffer && m_textureVertexBuffer.vertexCount() > 0) if(!m_hardwareTextureCoordArray && m_textureCoordArray.vertexCount() > 0)
m_hardwareTextureVertexBuffer = new HardwareBuffer(HardwareBuffer::VertexBuffer); m_hardwareTextureCoordArray = new HardwareBuffer(HardwareBuffer::VertexBuffer);
m_hardwareTextureVertexBuffer->bind(); m_hardwareTextureCoordArray->bind();
m_hardwareTextureVertexBuffer->write((void*)m_textureVertexBuffer.vertices(), m_textureVertexBuffer.size() * sizeof(float), m_hardwareCacheMode); m_hardwareTextureCoordArray->write((void*)m_textureCoordArray.vertices(), m_textureCoordArray.size() * sizeof(float), m_hardwareCacheMode);
} }
m_hardwareCached = true; m_hardwareCached = true;

View File

@ -33,23 +33,23 @@ public:
~CoordsBuffer(); ~CoordsBuffer();
void clear() { void clear() {
m_textureVertexBuffer.clear(); m_textureCoordArray.clear();
m_vertexBuffer.clear(); m_vertexArray.clear();
m_hardwareCached = false; m_hardwareCached = false;
} }
void addRect(const Rect& dest) { void addRect(const Rect& dest) {
m_vertexBuffer.addRect(dest); m_vertexArray.addRect(dest);
m_hardwareCached = false; m_hardwareCached = false;
} }
void addRect(const Rect& dest, const Rect& src) { void addRect(const Rect& dest, const Rect& src) {
m_vertexBuffer.addRect(dest); m_vertexArray.addRect(dest);
m_textureVertexBuffer.addRect(src); m_textureCoordArray.addRect(src);
m_hardwareCached = false; m_hardwareCached = false;
} }
void addQuad(const Rect& dest, const Rect& src) { void addQuad(const Rect& dest, const Rect& src) {
m_vertexBuffer.addQuad(dest); m_vertexArray.addQuad(dest);
m_textureVertexBuffer.addQuad(src); m_textureCoordArray.addQuad(src);
m_hardwareCached = false; m_hardwareCached = false;
} }
@ -60,20 +60,20 @@ public:
void updateCaches(); void updateCaches();
bool isHardwareCached() { return m_hardwareCached; } bool isHardwareCached() { return m_hardwareCached; }
float *getVertexBuffer() const { return m_vertexBuffer.vertices(); } float *getVertexArray() const { return m_vertexArray.vertices(); }
float *getTextureVertexBuffer() const { return m_textureVertexBuffer.vertices(); } float *getTextureCoordArray() const { return m_textureCoordArray.vertices(); }
int getVertexCount() const { return m_vertexBuffer.vertexCount(); } int getVertexCount() const { return m_vertexArray.vertexCount(); }
int getTextureVertexCount() const { return m_textureVertexBuffer.vertexCount(); } int getTextureCoordCount() const { return m_textureCoordArray.vertexCount(); }
HardwareBuffer *getHardwareVertexBuffer() { return m_hardwareVertexBuffer; } HardwareBuffer *getHardwareVertexArray() { return m_hardwareVertexArray; }
HardwareBuffer *getHardwareTextureVertexBuffer() { return m_hardwareTextureVertexBuffer; } HardwareBuffer *getHardwareTextureCoordArray() { return m_hardwareTextureCoordArray; }
private: private:
HardwareBuffer *m_hardwareVertexBuffer; HardwareBuffer *m_hardwareVertexArray;
HardwareBuffer *m_hardwareTextureVertexBuffer; HardwareBuffer *m_hardwareTextureCoordArray;
HardwareBuffer::UsagePattern m_hardwareCacheMode; HardwareBuffer::UsagePattern m_hardwareCacheMode;
VertexArray m_vertexBuffer; VertexArray m_vertexArray;
VertexArray m_textureVertexBuffer; VertexArray m_textureCoordArray;
bool m_hardwareCached; bool m_hardwareCached;
bool m_hardwareCaching; bool m_hardwareCaching;
}; };

View File

@ -77,7 +77,7 @@ void Font::drawText(const std::string& text, const Rect& screenCoords, Fw::Align
coordsBuffer.clear(); coordsBuffer.clear();
calculateDrawTextCoords(coordsBuffer, text, screenCoords, align); calculateDrawTextCoords(coordsBuffer, text, screenCoords, align);
g_painter.drawTextureCoords(coordsBuffer, m_texture); g_painter->drawTextureCoords(coordsBuffer, m_texture);
} }
void Font::calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align) void Font::calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align)

View File

@ -105,43 +105,44 @@ void FrameBuffer::clear(const Color& color, const Rect& rect)
{ {
bool clip = rect.isValid(); bool clip = rect.isValid();
if(clip) if(clip)
g_painter.setClipRect(Rect(0, 0, m_texture->getSize())); g_painter->setClipRect(Rect(0, 0, m_texture->getSize()));
glClearColor(color.rF(), color.gF(), color.bF(), color.aF()); glClearColor(color.rF(), color.gF(), color.bF(), color.aF());
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
if(clip) if(clip)
g_painter.resetClipRect(); g_painter->resetClipRect();
} }
void FrameBuffer::bind() void FrameBuffer::bind()
{ {
internalBind(); internalBind();
Matrix3 projectionMatrix = { 2.0f/m_texture->getWidth(), 0.0f, 0.0f, Matrix3 projectionMatrix = { 2.0f/m_texture->getWidth(), 0.0f, 0.0f,
0.0f, 2.0f/m_texture->getHeight(), 0.0f, 0.0f, 2.0f/m_texture->getHeight(), 0.0f,
-1.0f, -1.0f, 0.0f }; -1.0f, -1.0f, 1.0f };
g_painter->saveAndResetState();
g_painter->setProjectionMatrix(projectionMatrix);
m_oldProjectionMatrix = g_painter.getProjectionMatrix();
m_oldViewportSize = g_graphics.getViewportSize(); m_oldViewportSize = g_graphics.getViewportSize();
g_painter.setProjectionMatrix(projectionMatrix);
g_graphics.setViewportSize(m_texture->getSize()); g_graphics.setViewportSize(m_texture->getSize());
} }
void FrameBuffer::release() void FrameBuffer::release()
{ {
internalRelease(); internalRelease();
g_painter.setProjectionMatrix(m_oldProjectionMatrix); g_painter->restoreSavedState();
g_graphics.setViewportSize(m_oldViewportSize); g_graphics.setViewportSize(m_oldViewportSize);
} }
void FrameBuffer::draw(const Rect& dest, const Rect& src) void FrameBuffer::draw(const Rect& dest, const Rect& src)
{ {
g_painter.drawTexturedRect(dest, m_texture, src); g_painter->drawTexturedRect(dest, m_texture, src);
} }
void FrameBuffer::draw(const Rect& dest) void FrameBuffer::draw(const Rect& dest)
{ {
g_painter.drawTexturedRect(dest, m_texture, Rect(0,0, getSize())); g_painter->drawTexturedRect(dest, m_texture, Rect(0,0, getSize()));
} }
void FrameBuffer::internalBind() void FrameBuffer::internalBind()

View File

@ -50,7 +50,6 @@ private:
TexturePtr m_texture; TexturePtr m_texture;
TexturePtr m_screenBackup; TexturePtr m_screenBackup;
Matrix3 m_oldProjectionMatrix;
Size m_oldViewportSize; Size m_oldViewportSize;
uint m_fbo; uint m_fbo;
uint m_prevBoundFbo; uint m_prevBoundFbo;

View File

@ -27,12 +27,9 @@
#ifndef OPENGL_ES2 #ifndef OPENGL_ES2
#define GLEW_STATIC #define GLEW_STATIC
#include <GL/glew.h> #include <GL/glew.h>
//#include <GL/gl.h>
//#include <GL/glext.h>
#else #else
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <GLES2/gl2ext.h> //#include <GLES2/gl2ext.h>
#endif #endif
#endif #endif

View File

@ -21,6 +21,8 @@
*/ */
#include "fontmanager.h" #include "fontmanager.h"
#include "painterogl1.h"
#include "painterogl2.h"
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/texture.h> #include <framework/graphics/texture.h>
@ -33,6 +35,11 @@ void oglDebugCallback(unsigned int source, unsigned int type, unsigned int id, u
logWarning("OGL: ", message); logWarning("OGL: ", message);
} }
Graphics::Graphics()
{
m_maxTextureSize = -1;
}
void Graphics::init() void Graphics::init()
{ {
logInfo("GPU ", glGetString(GL_RENDERER)); logInfo("GPU ", glGetString(GL_RENDERER));
@ -50,29 +57,7 @@ void Graphics::init()
glDebugMessageCallbackARB(oglDebugCallback, NULL); glDebugMessageCallbackARB(oglDebugCallback, NULL);
#endif #endif
const char *requiredExtensions[] = { // overwrite framebuffer API if needed
"GL_ARB_vertex_program",
"GL_ARB_vertex_shader",
"GL_ARB_fragment_shader",
"GL_ARB_texture_non_power_of_two",
"GL_ARB_multitexture"
};
std::stringstream ss;
bool unsupported = false;
for(auto ext : requiredExtensions) {
if(!glewIsSupported(ext)) {
ss << ext << std::endl;
unsupported = true;
}
}
if(unsupported)
logFatal("The following OpenGL 2.0 extensions are not supported by your system graphics, please try updating your video drivers or buy a new hardware:\n",
ss.str(),
"Graphics card: ", glGetString(GL_RENDERER),
"\nOpenGL driver: ", glGetString(GL_VERSION));
if(GLEW_EXT_framebuffer_object && !GLEW_ARB_framebuffer_object) { if(GLEW_EXT_framebuffer_object && !GLEW_ARB_framebuffer_object) {
glGenFramebuffers = glGenFramebuffersEXT; glGenFramebuffers = glGenFramebuffersEXT;
glDeleteFramebuffers = glDeleteFramebuffersEXT; glDeleteFramebuffers = glDeleteFramebuffersEXT;
@ -82,41 +67,105 @@ void Graphics::init()
glGenerateMipmap = glGenerateMipmapEXT; glGenerateMipmap = glGenerateMipmapEXT;
} }
m_useFBO = m_useFBO && (GLEW_ARB_framebuffer_object || GLEW_EXT_framebuffer_object); // opengl 1 is always supported
m_generateHardwareMipmaps = m_generateHardwareMipmaps; // glGenerateMipmap is supported when framebuffers are g_painterOGL1 = new PainterOGL1;
// opengl 2 is only supported in newer hardware
if(GLEW_VERSION_2_0)
g_painterOGL2 = new PainterOGL2;
#else
g_painterOGL2 = new PainterOGL2;
#endif #endif
glEnable(GL_BLEND); // determine max texture size
glClear(GL_COLOR_BUFFER_BIT); static GLint maxTextureSize = -1;
if(maxTextureSize == -1)
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
if(m_maxTextureSize == -1 || m_maxTextureSize > maxTextureSize)
m_maxTextureSize = maxTextureSize;
//glClear(GL_COLOR_BUFFER_BIT);
//m_prefferedPainterEngine = Painter_OpenGL1;
selectPainterEngine(m_prefferedPainterEngine);
m_emptyTexture = TexturePtr(new Texture); m_emptyTexture = TexturePtr(new Texture);
g_painter.init();
} }
void Graphics::terminate() void Graphics::terminate()
{ {
g_fonts.releaseFonts(); g_fonts.releaseFonts();
g_painter.terminate();
if(g_painterOGL1) {
delete g_painterOGL1;
g_painterOGL1 = nullptr;
}
if(g_painterOGL2) {
delete g_painterOGL2;
g_painterOGL2 = nullptr;
}
g_painter = nullptr;
m_emptyTexture.reset(); m_emptyTexture.reset();
} }
bool Graphics::parseOption(const std::string& option) bool Graphics::parseOption(const std::string& option)
{ {
if(option == "-no-fbos") if(option == "-no-draw-arrays")
m_useDrawArrays = false;
else if(option == "-no-fbos")
m_useFBO = false; m_useFBO = false;
else if(option == "-no-mipmapping") else if(option == "-no-mipmaps")
m_generateMipmaps = false; m_useMipmaps = false;
else if(option == "-no-smoothing") else if(option == "-no-hardware-mipmaps")
m_useHardwareMipmaps = false;
else if(option == "-no-smooth")
m_useBilinearFiltering = false; m_useBilinearFiltering = false;
else if(option == "-no-hardware-buffering") else if(option == "-no-hardware-buffers")
m_useHardwareBuffers = false; m_useHardwareBuffers = false;
else if(option == "-no-non-power-of-two-textures")
m_useNonPowerOfTwoTextures = false;
else if(option == "-opengl1")
m_prefferedPainterEngine = Painter_OpenGL1;
else if(option == "-opengl2")
m_prefferedPainterEngine = Painter_OpenGL2;
else else
return false; return false;
return true; return true;
} }
bool Graphics::selectPainterEngine(PainterEngine painterEngine)
{
// always prefer OpenGL 2 over OpenGL 1
if(g_painterOGL2 && (painterEngine == Painter_OpenGL2 || painterEngine == Painter_Any))
g_painter = g_painterOGL2;
// fallback to OpenGL 1 in older hardwares
else if(g_painterOGL1 && (painterEngine == Painter_OpenGL1 || painterEngine == Painter_Any))
g_painter = g_painterOGL1;
else
logFatal("Neither OpenGL 1.0 nor OpenGL 2.0 painter engine is supported by your platform, "
"try updating your graphics drivers or your hardware and then run again.");
// switch painters GL state
if(g_painter)
g_painter->unbind();
g_painter->bind();
if(painterEngine == Painter_Any)
return true;
return getPainterEngine() == painterEngine;
}
Graphics::PainterEngine Graphics::getPainterEngine()
{
if(g_painter == g_painterOGL2)
return Painter_OpenGL2;
else
return Painter_OpenGL1;
}
void Graphics::resize(const Size& size) void Graphics::resize(const Size& size)
{ {
setViewportSize(size); setViewportSize(size);
@ -128,17 +177,21 @@ void Graphics::resize(const Size& size)
// //
// This results in the Projection matrix below. // This results in the Projection matrix below.
// //
// Projection Matrix Painter Coord GL Coord // Projection Matrix
// ------------------------------------------------ --------- --------- // Painter Coord ------------------------------------------------ GL Coord
// | 2.0 / width | 0.0 | -1.0 | | x | | x' | // ------------- | 2.0 / width | 0.0 | 0.0 | ---------------
// | 0.0 | -2.0 / height | 1.0 | * | y | = | y' | // | x y 1 | * | 0.0 | -2.0 / height | 0.0 | = | x' y' 1 |
// | 0.0 | 0.0 | 0.0 | | 1 | | 0 | // ------------- | -1.0 | 1.0 | 1.0 | ---------------
// ------------------------------------------------ --------- --------- // ------------------------------------------------
Matrix3 projectionMatrix = { 2.0f/size.width(), 0.0f, -1.0f, Matrix3 projectionMatrix = { 2.0f/size.width(), 0.0f, 0.0f,
0.0f, -2.0f/size.height(), 1.0f, 0.0f, -2.0f/size.height(), 0.0f,
0.0f, 0.0f, 0.0f }; -1.0f, 1.0f, 1.0f };
projectionMatrix.transpose();
g_painter.setProjectionMatrix(projectionMatrix); if(g_painterOGL1)
g_painterOGL1->setProjectionMatrix(projectionMatrix);
if(g_painterOGL2)
g_painterOGL2->setProjectionMatrix(projectionMatrix);
} }
void Graphics::beginRender() void Graphics::beginRender()
@ -149,16 +202,6 @@ void Graphics::beginRender()
void Graphics::endRender() void Graphics::endRender()
{ {
// this is a simple blur effect
/*
static Timer timer;
if(timer.ticksElapsed() >= 10) {
glAccum(GL_MULT, 0.9);
glAccum(GL_ACCUM, 0.1);
timer.restart();
}
glAccum(GL_RETURN, 1);
*/
} }
void Graphics::setViewportSize(const Size& size) void Graphics::setViewportSize(const Size& size)
@ -167,10 +210,71 @@ void Graphics::setViewportSize(const Size& size)
m_viewportSize = size; m_viewportSize = size;
} }
int Graphics::getMaxTextureSize() bool Graphics::canUseDrawArrays()
{ {
static GLint maxTexSize = -1; #ifndef OPENGL_ES2
if(maxTexSize == -1) if(!GLEW_VERSION_1_1)
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); return false;
return maxTexSize; #else
return false;
#endif
return m_useDrawArrays;
}
bool Graphics::canUseShaders()
{
#ifndef OPENGL_ES2
if(GLEW_ARB_vertex_program && GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
return true;
#else
return true;
#endif
return false;
}
bool Graphics::canUseFBO()
{
#ifndef OPENGL_ES2
if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object)
return false;
#endif
return m_useFBO;
}
bool Graphics::canUseBilinearFiltering()
{
return m_useBilinearFiltering;
}
bool Graphics::canUseHardwareBuffers()
{
#ifndef OPENGL_ES2
if(!GLEW_ARB_vertex_buffer_object)
return false;
#endif
return m_useHardwareBuffers;
}
bool Graphics::canUseNonPowerOfTwoTextures()
{
#ifndef OPENGL_ES2
if(!GLEW_ARB_texture_non_power_of_two)
return false;
#endif
return m_useNonPowerOfTwoTextures;
}
bool Graphics::canUseMipmaps()
{
return m_useMipmaps;
}
bool Graphics::canUseHardwareMipmaps()
{
#ifndef OPENGL_ES2
// glGenerateMipmap is supported when framebuffers are too
if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object)
return false;
#endif
return m_useHardwareMipmaps;
} }

View File

@ -29,15 +29,20 @@
class Graphics class Graphics
{ {
public: public:
Graphics();
enum PainterEngine {
Painter_Any,
Painter_OpenGL1,
Painter_OpenGL2
};
void init(); void init();
void terminate(); void terminate();
bool parseOption(const std::string& option); bool parseOption(const std::string& option);
bool canUseFBO() { return m_useFBO; } bool selectPainterEngine(PainterEngine painterEngine);
bool canUseBilinearFiltering() { return m_useBilinearFiltering; } PainterEngine getPainterEngine();
bool canUseHardwareBuffers() { return m_useHardwareBuffers; }
bool canGenerateMipmaps() { return m_generateMipmaps; }
bool canGenerateHardwareMipmaps() { return m_generateHardwareMipmaps; }
void resize(const Size& size); void resize(const Size& size);
void beginRender(); void beginRender();
@ -45,19 +50,32 @@ public:
void setViewportSize(const Size& size); void setViewportSize(const Size& size);
int getMaxTextureSize(); int getMaxTextureSize() { return m_maxTextureSize; }
const Size& getViewportSize() { return m_viewportSize; } const Size& getViewportSize() { return m_viewportSize; }
TexturePtr& getEmptyTexture() { return m_emptyTexture; } TexturePtr& getEmptyTexture() { return m_emptyTexture; }
bool canUseDrawArrays();
bool canUseShaders();
bool canUseFBO();
bool canUseBilinearFiltering();
bool canUseHardwareBuffers();
bool canUseNonPowerOfTwoTextures();
bool canUseMipmaps();
bool canUseHardwareMipmaps();
private: private:
Size m_viewportSize; Size m_viewportSize;
TexturePtr m_emptyTexture; TexturePtr m_emptyTexture;
int m_maxTextureSize;
Boolean<true> m_useDrawArrays;
Boolean<true> m_useFBO; Boolean<true> m_useFBO;
Boolean<true> m_useHardwareBuffers; Boolean<true> m_useHardwareBuffers;
Boolean<true> m_useBilinearFiltering; Boolean<true> m_useBilinearFiltering;
Boolean<true> m_generateMipmaps; Boolean<true> m_useNonPowerOfTwoTextures;
Boolean<true> m_generateHardwareMipmaps; Boolean<true> m_useMipmaps;
Boolean<true> m_useHardwareMipmaps;
PainterEngine m_prefferedPainterEngine;
}; };
extern Graphics g_graphics; extern Graphics g_graphics;

View File

@ -53,7 +53,6 @@ public:
void bind() { glBindBuffer(m_type, m_id); } void bind() { glBindBuffer(m_type, m_id); }
static void unbind(Type type) { glBindBuffer(type, 0); } static void unbind(Type type) { glBindBuffer(type, 0); }
void write(void *data, int count, UsagePattern usage) { glBufferData(m_type, count, data, usage); } void write(void *data, int count, UsagePattern usage) { glBufferData(m_type, count, data, usage); }
//void read(void *data, int count);
private: private:
Type m_type; Type m_type;

View File

@ -21,102 +21,108 @@
*/ */
#include "painter.h" #include "painter.h"
#include "texture.h"
#include "paintershadersources.h"
#include "paintershaderprogram.h"
#include "shaderprogram.h"
#include "graphics.h" #include "graphics.h"
#include "vertexarray.h"
Painter g_painter; Painter *g_painter = nullptr;
void Painter::init() Painter::Painter()
{ {
setColor(Color::white); m_glTextureId = 0;
setOpacity(1.0f); m_oldStateIndex = 0;
setCompositionMode(CompositionMode_Normal); m_color = Color::white;
releaseCustomProgram(); m_opacity = 1.0f;
m_compositionMode = CompositionMode_Normal;
m_drawTexturedProgram = PainterShaderProgramPtr(new PainterShaderProgram); m_shaderProgram = nullptr;
m_drawTexturedProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); m_texture = nullptr;
m_drawTexturedProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader);
m_drawTexturedProgram->link();
m_drawSolidColorProgram = PainterShaderProgramPtr(new PainterShaderProgram);
m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader);
m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader);
m_drawSolidColorProgram->link();
} }
void Painter::terminate() void Painter::resetState()
{ {
m_drawTexturedProgram.reset(); resetColor();
m_drawSolidColorProgram.reset(); resetOpacity();
resetCompositionMode();
resetClipRect();
resetShaderProgram();
resetTexture();
} }
void Painter::drawProgram(PainterShaderProgram *program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode) void Painter::refreshState()
{ {
if(coordsBuffer.getVertexCount() == 0) updateGlCompositionMode();
return; updateGlClipRect();
updateGlTexture();
program->setProjectionMatrix(m_projectionMatrix);
program->setOpacity(m_opacity);
program->setColor(m_color);
program->draw(coordsBuffer, drawMode);
} }
void Painter::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) void Painter::saveAndResetState()
{ {
PainterShaderProgram *program = m_customProgram ? m_customProgram : m_drawTexturedProgram.get(); assert(m_oldStateIndex<10);
program->setTexture(texture); m_olderStates[m_oldStateIndex].projectionMatrix = m_projectionMatrix;
drawProgram(program, coordsBuffer); m_olderStates[m_oldStateIndex].textureMatrix = m_textureMatrix;
m_olderStates[m_oldStateIndex].color = m_color;
m_olderStates[m_oldStateIndex].opacity = m_opacity;
m_olderStates[m_oldStateIndex].compositionMode = m_compositionMode;
m_olderStates[m_oldStateIndex].clipRect = m_clipRect;
m_olderStates[m_oldStateIndex].shaderProgram = m_shaderProgram;
m_olderStates[m_oldStateIndex].texture = m_texture;
m_oldStateIndex++;
resetState();
} }
void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) void Painter::restoreSavedState()
{ {
if(dest.isEmpty() || src.isEmpty() || !texture->getId()) m_oldStateIndex--;
return; setProjectionMatrix(m_olderStates[m_oldStateIndex].projectionMatrix);
setTextureMatrix(m_olderStates[m_oldStateIndex].textureMatrix);
m_coordsBuffer.clear(); setColor(m_olderStates[m_oldStateIndex].color);
m_coordsBuffer.addQuad(dest, src); setOpacity(m_olderStates[m_oldStateIndex].opacity);
PainterShaderProgram *program = m_customProgram ? m_customProgram : m_drawTexturedProgram.get(); setCompositionMode(m_olderStates[m_oldStateIndex].compositionMode);
program->setTexture(texture); setClipRect(m_olderStates[m_oldStateIndex].clipRect);
drawProgram(program, m_coordsBuffer, PainterShaderProgram::TriangleStrip); setShaderProgram(m_olderStates[m_oldStateIndex].shaderProgram);
} setTexture(m_olderStates[m_oldStateIndex].texture);
void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
{
if(dest.isEmpty() || src.isEmpty() || !texture->getId())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addRepeatedRects(dest, src);
drawTextureCoords(m_coordsBuffer, texture);
}
void Painter::drawFilledRect(const Rect& dest)
{
if(dest.isEmpty())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addRect(dest);
drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram.get(), m_coordsBuffer);
}
void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth)
{
if(dest.isEmpty() || innerLineWidth == 0)
return;
m_coordsBuffer.clear();
m_coordsBuffer.addBoudingRect(dest, innerLineWidth);
drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram.get(), m_coordsBuffer);
} }
void Painter::setCompositionMode(Painter::CompositionMode compositionMode) void Painter::setCompositionMode(Painter::CompositionMode compositionMode)
{ {
switch(compositionMode) { if(m_compositionMode == compositionMode)
return;
m_compositionMode = compositionMode;
updateGlCompositionMode();
}
void Painter::setClipRect(const Rect& clipRect)
{
if(m_clipRect == clipRect)
return;
m_clipRect = clipRect;
updateGlClipRect();
}
void Painter::setTexture(Texture* texture)
{
if(m_texture == texture)
return;
m_texture = texture;
if(texture) {
m_glTextureId = texture->getId();
setTextureMatrix(texture->getTransformMatrix());
} else
m_glTextureId = 0;
m_texture = texture;
updateGlTexture();
}
void Painter::updateGlTexture()
{
glBindTexture(GL_TEXTURE_2D, m_glTextureId);
}
void Painter::updateGlCompositionMode()
{
glEnable(GL_BLEND);
switch(m_compositionMode) {
case CompositionMode_Normal: case CompositionMode_Normal:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break; break;
@ -133,50 +139,14 @@ void Painter::setCompositionMode(Painter::CompositionMode compositionMode)
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
break; break;
} }
m_compostionMode = compositionMode;
} }
void Painter::setClipRect(const Rect& clipRect) void Painter::updateGlClipRect()
{ {
if(m_clipRect == clipRect) if(m_clipRect.isValid()) {
return;
if(clipRect.isValid()) {
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glScissor(clipRect.left(), g_graphics.getViewportSize().height() - clipRect.bottom() - 1, clipRect.width(), clipRect.height()); glScissor(m_clipRect.left(), g_graphics.getViewportSize().height() - m_clipRect.bottom() - 1, m_clipRect.width(), m_clipRect.height());
} else { } else {
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }
m_clipRect = clipRect;
}
void Painter::saveAndResetState()
{
m_oldCustomProgram = m_customProgram;
m_oldProjectionMatrix = m_projectionMatrix;
m_oldColor = m_color;
m_oldOpacity = m_opacity;
m_oldCompostionMode = m_compostionMode;
m_oldClipRect = m_clipRect;
releaseCustomProgram();
resetClipRect();
setColor(Color::white);
setOpacity(1);
setCompositionMode(CompositionMode_Normal);
}
void Painter::restoreSavedState()
{
m_customProgram = m_oldCustomProgram;
setColor(m_oldColor);
setOpacity(m_oldOpacity);
setCompositionMode(m_oldCompostionMode);
setClipRect(m_oldClipRect);
m_oldCustomProgram = nullptr;
m_oldColor = Color::white;
m_oldOpacity = 1;
m_oldCompostionMode = CompositionMode_Normal;
m_oldClipRect = Rect();
} }

View File

@ -24,7 +24,6 @@
#define PAINTER_H #define PAINTER_H
#include "declarations.h" #include "declarations.h"
#include <framework/util/databuffer.h>
#include "coordsbuffer.h" #include "coordsbuffer.h"
#include "paintershaderprogram.h" #include "paintershaderprogram.h"
#include "texture.h" #include "texture.h"
@ -39,58 +38,90 @@ public:
CompositionMode_Replace, CompositionMode_Replace,
CompositionMode_DestBlending CompositionMode_DestBlending
}; };
enum DrawMode {
Triangles = GL_TRIANGLES,
TriangleStrip = GL_TRIANGLE_STRIP
};
void init(); struct PainterState {
void terminate(); Matrix3 projectionMatrix;
Matrix2 textureMatrix;
Color color;
float opacity;
Painter::CompositionMode compositionMode;
Rect clipRect;
Texture *texture;
PainterShaderProgram *shaderProgram;
};
void drawProgram(PainterShaderProgram *program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode = PainterShaderProgram::Triangles); Painter();
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); virtual ~Painter() { }
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); }
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_color = color; } virtual void bind() { refreshState(); }
Color getColor() { return m_color; } virtual void unbind() { }
void setOpacity(float opacity) { m_opacity = opacity; }
float getOpacity() { return m_opacity; }
void setClipRect(const Rect& clipRect);
Rect getClipRect() { return m_clipRect; }
void resetClipRect() { setClipRect(Rect()); }
void setCustomProgram(const PainterShaderProgramPtr& program) { m_customProgram = program.get(); }
void releaseCustomProgram() { m_customProgram = nullptr; }
void setCompositionMode(CompositionMode compositionMode);
void resetCompositionMode() { setCompositionMode(CompositionMode_Normal); }
void setProjectionMatrix(const Matrix3& projectionMatrix) { m_projectionMatrix = projectionMatrix; }
Matrix3 getProjectionMatrix() { return m_projectionMatrix; }
void resetState();
virtual void refreshState();
void saveAndResetState(); void saveAndResetState();
void restoreSavedState(); void restoreSavedState();
private: virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0;
PainterShaderProgramPtr m_drawTexturedProgram; virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0;
PainterShaderProgramPtr m_drawSolidColorProgram; virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
PainterShaderProgram *m_customProgram; void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); }
virtual void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
virtual void drawFilledRect(const Rect& dest) = 0;
virtual void drawBoundingRect(const Rect& dest, int innerLineWidth = 1) = 0;
virtual void setProjectionMatrix(const Matrix3& projectionMatrix) { m_projectionMatrix = projectionMatrix; }
virtual void setTextureMatrix(const Matrix2& textureMatrix) { m_textureMatrix = textureMatrix; }
virtual void setColor(const Color& color) { m_color = color; }
virtual void setOpacity(float opacity) { m_opacity = opacity; }
virtual void setCompositionMode(CompositionMode compositionMode);
virtual void setClipRect(const Rect& clipRect);
virtual void setShaderProgram(PainterShaderProgram *shaderProgram) { m_shaderProgram = shaderProgram; }
virtual void setTexture(Texture *texture);
void setShaderProgram(const PainterShaderProgramPtr& shaderProgram) { setShaderProgram(shaderProgram.get()); }
void setTexture(const TexturePtr& texture) { setTexture(texture.get()); }
Matrix3 getProjectionMatrix() { return m_projectionMatrix; }
Matrix2 getTextureMatrix() { return m_textureMatrix; }
Color getColor() { return m_color; }
float getOpacity() { return m_opacity; }
CompositionMode getCompositionMode() { return m_compositionMode; }
Rect getClipRect() { return m_clipRect; }
PainterShaderProgram *getShaderProgram() { return m_shaderProgram; }
void resetColor() { setColor(Color::white); }
void resetOpacity() { setOpacity(1.0f); }
void resetClipRect() { setClipRect(Rect()); }
void resetCompositionMode() { setCompositionMode(CompositionMode_Normal); }
void resetShaderProgram() { setShaderProgram(nullptr); }
void resetTexture() { setTexture(nullptr); }
protected:
void updateGlTexture();
void updateGlCompositionMode();
void updateGlClipRect();
CoordsBuffer m_coordsBuffer;
Matrix3 m_projectionMatrix; Matrix3 m_projectionMatrix;
Matrix2 m_textureMatrix;
Color m_color; Color m_color;
float m_opacity; float m_opacity;
CompositionMode m_compostionMode; CompositionMode m_compositionMode;
CoordsBuffer m_coordsBuffer;
Rect m_clipRect; Rect m_clipRect;
Texture *m_texture;
PainterShaderProgram *m_shaderProgram;
PainterShaderProgram *m_oldCustomProgram; PainterState m_olderStates[10];
Matrix3 m_oldProjectionMatrix; int m_oldStateIndex;
Color m_oldColor;
float m_oldOpacity; GLuint m_glTextureId;
Rect m_oldClipRect;
CompositionMode m_oldCompostionMode;
}; };
extern Painter g_painter; extern Painter *g_painter;
#endif #endif

View File

@ -0,0 +1,243 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 "painterogl1.h"
#include "graphics.h"
PainterOGL1 *g_painterOGL1 = nullptr;
PainterOGL1::PainterOGL1()
{
m_matrixMode = GL_PROJECTION;
resetState();
}
void PainterOGL1::refreshState()
{
Painter::refreshState();
updateGlColor();
updateGlMatrixMode();
updateGlProjectionMatrix();
updateGlTextureMatrix();
}
void PainterOGL1::bind()
{
Painter::bind();
// vertex and texture coord arrays are always enabled
// to avoid massive enable/disables, thus improving frame rate
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
}
void PainterOGL1::unbind()
{
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
{
int vertexCount = coordsBuffer.getVertexCount();
if(vertexCount == 0)
return;
bool textured = coordsBuffer.getTextureCoordCount() != 0;
if(textured)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
// use vertex arrays if possible, much faster
if(g_graphics.canUseDrawArrays()) {
// update coords buffer hardware caches if enabled
coordsBuffer.updateCaches();
bool hardwareCached = coordsBuffer.isHardwareCached();
// only set texture coords arrays when needed
if(textured) {
if(hardwareCached) {
coordsBuffer.getHardwareTextureCoordArray()->bind();
glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
} else
glTexCoordPointer(2, GL_FLOAT, 0, coordsBuffer.getTextureCoordArray());
}
// set vertex array
if(hardwareCached) {
coordsBuffer.getHardwareVertexArray()->bind();
glVertexPointer(2, GL_FLOAT, 0, nullptr);
} else
glVertexPointer(2, GL_FLOAT, 0, coordsBuffer.getVertexArray());
if(hardwareCached)
HardwareBuffer::unbind(HardwareBuffer::VertexBuffer);
// draw the element in coords buffers
glDrawArrays(drawMode, 0, vertexCount);
} else {
int verticesSize = vertexCount*2;
float *vertices = coordsBuffer.getVertexArray();
float *texCoords = coordsBuffer.getTextureCoordArray();
// use glBegin/glEnd, this is not available in OpenGL ES
// and is considered much slower then glDrawArrays,
// but this code is executed in really old graphics cards
glBegin(drawMode);
for(int i=0;i<verticesSize;i+=2) {
if(textured)
glTexCoord2f(texCoords[i], texCoords[i+1]);
glVertex2f(vertices[i], vertices[i+1]);
}
glEnd();
}
}
void PainterOGL1::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
{
if(!texture->getId())
return;
setTexture(texture.get());
drawCoords(coordsBuffer);
}
void PainterOGL1::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
{
if(dest.isEmpty() || src.isEmpty() || !texture->getId())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addQuad(dest, src);
setTexture(texture.get());
drawCoords(m_coordsBuffer, TriangleStrip);
}
void PainterOGL1::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
{
if(dest.isEmpty() || src.isEmpty() || !texture->getId())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addRepeatedRects(dest, src);
setTexture(texture.get());
drawCoords(m_coordsBuffer);
}
void PainterOGL1::drawFilledRect(const Rect& dest)
{
if(dest.isEmpty())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addRect(dest);
setTexture(nullptr);
drawCoords(m_coordsBuffer);
}
void PainterOGL1::drawBoundingRect(const Rect& dest, int innerLineWidth)
{
if(dest.isEmpty() || innerLineWidth == 0)
return;
m_coordsBuffer.clear();
m_coordsBuffer.addBoudingRect(dest, innerLineWidth);
setTexture(nullptr);
drawCoords(m_coordsBuffer);
}
void PainterOGL1::setMatrixMode(PainterOGL1::MatrixMode matrixMode)
{
if(m_matrixMode == matrixMode)
return;
m_matrixMode = matrixMode;
updateGlMatrixMode();
}
void PainterOGL1::setProjectionMatrix(const Matrix3& projectionMatrix)
{
m_projectionMatrix = projectionMatrix;
updateGlProjectionMatrix();
}
void PainterOGL1::setTextureMatrix(const Matrix2& textureMatrix)
{
m_textureMatrix = textureMatrix;
updateGlTextureMatrix();
}
void PainterOGL1::setColor(const Color& color)
{
if(m_color == color)
return;
m_color = color;
updateGlColor();
}
void PainterOGL1::setOpacity(float opacity)
{
if(m_opacity == opacity)
return;
m_opacity = opacity;
updateGlColor();
}
void PainterOGL1::updateGlColor()
{
glColor4f(m_color.rF(), m_color.gF(), m_color.bF(), m_color.aF() * m_opacity);
}
void PainterOGL1::updateGlMatrixMode()
{
glMatrixMode(m_matrixMode);
}
void PainterOGL1::updateGlProjectionMatrix()
{
float glProjectionMatrix[] = {
m_projectionMatrix(1,1), m_projectionMatrix(1,2), 0.0f, m_projectionMatrix(1,3),
m_projectionMatrix(2,1), m_projectionMatrix(2,2), 0.0f, m_projectionMatrix(2,3),
0.0f, 0.0f, 1.0f, 0.0f,
m_projectionMatrix(3,1), m_projectionMatrix(3,2), 0.0f, m_projectionMatrix(3,3),
};
setMatrixMode(MatrixProjection);
glLoadMatrixf(glProjectionMatrix);
}
void PainterOGL1::updateGlTextureMatrix()
{
float glTextureMatrix[] = {
m_textureMatrix(1,1), m_textureMatrix(1,2), 0.0f, 0.0f,
m_textureMatrix(2,1), m_textureMatrix(2,2), 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
setMatrixMode(MatrixTexture);
glLoadMatrixf(glTextureMatrix);
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 PAINTEROGL1_H
#define PAINTEROGL1_H
#include "painter.h"
/**
* Painter using OpenGL 1.0 fixed-function rendering pipeline,
* compatible with OpenGL ES 1.0 and intended to be used on
* older graphics cards. Shaders are not available
* for this painter engine.
*/
class PainterOGL1 : public Painter
{
public:
enum MatrixMode {
MatrixProjection = GL_PROJECTION,
MatrixTexture = GL_TEXTURE
};
PainterOGL1();
void bind();
void unbind();
void refreshState();
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
void drawTextureCoords(CoordsBuffer& coordsBuffer, 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);
void setMatrixMode(MatrixMode matrixMode);
void setProjectionMatrix(const Matrix3& projectionMatrix);
void setTextureMatrix(const Matrix2& textureMatrix);
void setColor(const Color& color);
void setOpacity(float opacity);
private:
void updateGlColor();
void updateGlMatrixMode();
void updateGlProjectionMatrix();
void updateGlTextureMatrix();
GLenum m_matrixMode;
};
extern PainterOGL1 *g_painterOGL1;
#endif

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 "painterogl2.h"
#include "texture.h"
#include "paintershadermanager.h"
PainterOGL2 *g_painterOGL2 = nullptr;
PainterOGL2::PainterOGL2()
{
m_drawProgram = nullptr;
resetState();
g_shaders.init();
}
PainterOGL2::~PainterOGL2()
{
g_shaders.terminate();
}
void PainterOGL2::bind()
{
Painter::bind();
// vertex and texture coord attributes are always enabled
// to avoid massive enable/disables, thus improving frame rate
PainterShaderProgram::enableAttributeArray(PainterShaderProgram::VERTEX_ATTR);
PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
}
void PainterOGL2::unbind()
{
PainterShaderProgram::disableAttributeArray(PainterShaderProgram::VERTEX_ATTR);
PainterShaderProgram::disableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
PainterShaderProgram::release();
}
void PainterOGL2::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
{
int vertexCount = coordsBuffer.getVertexCount();
if(vertexCount == 0)
return;
bool textured = coordsBuffer.getTextureCoordCount() > 0;
// update shader with the current painter state
m_drawProgram->bind();
m_drawProgram->setProjectionMatrix(m_projectionMatrix);
if(textured)
m_drawProgram->setTextureMatrix(m_textureMatrix);
m_drawProgram->setOpacity(m_opacity);
m_drawProgram->setColor(m_color);
m_drawProgram->updateTime();
// update coords buffer hardware caches if enabled
coordsBuffer.updateCaches();
bool hardwareCached = coordsBuffer.isHardwareCached();
// only set texture coords arrays when needed
if(textured) {
if(hardwareCached) {
coordsBuffer.getHardwareTextureCoordArray()->bind();
m_drawProgram->setAttributeArray(PainterShaderProgram::TEXCOORD_ATTR, nullptr, 2);
} else
m_drawProgram->setAttributeArray(PainterShaderProgram::TEXCOORD_ATTR, coordsBuffer.getTextureCoordArray(), 2);
}
// set vertex array
if(hardwareCached) {
coordsBuffer.getHardwareVertexArray()->bind();
m_drawProgram->setAttributeArray(PainterShaderProgram::VERTEX_ATTR, nullptr, 2);
HardwareBuffer::unbind(HardwareBuffer::VertexBuffer);
} else
m_drawProgram->setAttributeArray(PainterShaderProgram::VERTEX_ATTR, coordsBuffer.getVertexArray(), 2);
// draw the element in coords buffers
glDrawArrays(drawMode, 0, vertexCount);
}
void PainterOGL2::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
{
if(!texture->getId())
return;
setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawTexturedProgram().get());
setTexture(texture);
drawCoords(coordsBuffer);
}
void PainterOGL2::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
{
if(dest.isEmpty() || src.isEmpty() || !texture->getId())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addQuad(dest, src);
setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawTexturedProgram().get());
setTexture(texture);
drawCoords(m_coordsBuffer, TriangleStrip);
}
void PainterOGL2::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
{
if(dest.isEmpty() || src.isEmpty() || !texture->getId())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addRepeatedRects(dest, src);
setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawTexturedProgram().get());
setTexture(texture);
drawCoords(m_coordsBuffer);
}
void PainterOGL2::drawFilledRect(const Rect& dest)
{
if(dest.isEmpty())
return;
m_coordsBuffer.clear();
m_coordsBuffer.addRect(dest);
setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawSolidColorProgram().get());
drawCoords(m_coordsBuffer);
}
void PainterOGL2::drawBoundingRect(const Rect& dest, int innerLineWidth)
{
if(dest.isEmpty() || innerLineWidth == 0)
return;
m_coordsBuffer.clear();
m_coordsBuffer.addBoudingRect(dest, innerLineWidth);
setDrawProgram(m_shaderProgram ? m_shaderProgram : g_shaders.getDrawSolidColorProgram().get());
drawCoords(m_coordsBuffer);
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 PAINTEROGL2_H
#define PAINTEROGL2_H
#include "painter.h"
/**
* Painter using OpenGL 2.0 programmable rendering pipeline,
* compatible with OpenGL ES 2.0. Only recent cards support
* this painter engine.
*/
class PainterOGL2 : public Painter
{
public:
PainterOGL2();
~PainterOGL2();
void bind();
void unbind();
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
void drawTextureCoords(CoordsBuffer& coordsBuffer, 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 setDrawProgram(PainterShaderProgram *drawProgram) { m_drawProgram = drawProgram; }
private:
PainterShaderProgram *m_drawProgram;
};
extern PainterOGL2 *g_painterOGL2;
#endif

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 const std::string glslMainVertexShader = "\n\
highp vec4 calculatePosition();\n\
void main() {\n\
gl_Position = calculatePosition();\n\
}\n";
static const std::string glslMainWithTexCoordsVertexShader = "\n\
attribute highp vec2 a_texCoord;\n\
uniform highp mat2 textureMatrix;\n\
varying highp vec2 texCoord;\n\
highp vec4 calculatePosition();\n\
void main()\n\
{\n\
gl_Position = calculatePosition();\n\
texCoord = textureMatrix * a_texCoord;\n\
}\n";
static std::string glslPositionOnlyVertexShader = "\n\
attribute highp vec2 a_vertex;\n\
uniform highp mat3 projectionMatrix;\n\
highp vec4 calculatePosition() {\n\
return vec4(projectionMatrix * vec3(a_vertex.xy, 1), 1);\n\
}\n";
static const std::string glslMainFragmentShader = "\n\
uniform lowp float opacity;\n\
lowp vec4 calculatePixel();\n\
void main()\n\
{\n\
gl_FragColor = calculatePixel();\n\
gl_FragColor.a *= opacity;\n\
}\n";
static const std::string glslTextureSrcFragmentShader = "\n\
varying mediump vec2 texCoord;\n\
uniform lowp vec4 color;\n\
uniform sampler2D tex0;\n\
lowp vec4 calculatePixel() {\n\
return texture2D(tex0, texCoord) * color;\n\
}\n";
static const std::string glslSolidColorFragmentShader = "\n\
uniform lowp vec4 color;\n\
lowp vec4 calculatePixel() {\n\
return color;\n\
}\n";

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 "paintershadermanager.h"
#include "painterogl2.h"
#include "texture.h"
#include "painterogl2_shadersources.h"
#include "paintershaderprogram.h"
#include "shaderprogram.h"
#include "graphics.h"
PainterShaderManager g_shaders;
void PainterShaderManager::init()
{
m_drawTexturedProgram = createShader();
assert(m_drawTexturedProgram);
m_drawTexturedProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
m_drawTexturedProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader);
m_drawTexturedProgram->link();
m_drawSolidColorProgram = createShader();
assert(m_drawSolidColorProgram);
m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader);
m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader);
m_drawSolidColorProgram->link();
}
void PainterShaderManager::terminate()
{
m_drawTexturedProgram = nullptr;
m_drawSolidColorProgram = nullptr;
}
PainterShaderProgramPtr PainterShaderManager::createShader()
{
if(!g_graphics.canUseShaders())
return nullptr;
return PainterShaderProgramPtr(new PainterShaderProgram);
}
PainterShaderProgramPtr PainterShaderManager::createTexturedFragmentShader(const std::string& shaderFile)
{
PainterShaderProgramPtr shader = createShader();
if(!shader)
return nullptr;
shader->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
shader->addShaderFromSourceFile(Shader::Fragment, shaderFile);
if(!shader->link())
return nullptr;
return shader;
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 PAINTERSHADERMANAGER_H
#define PAINTERSHADERMANAGER_H
#include "paintershaderprogram.h"
class PainterShaderManager
{
public:
void init();
void terminate();
PainterShaderProgramPtr createShader();
PainterShaderProgramPtr createTexturedFragmentShader(const std::string& shaderFile);
const PainterShaderProgramPtr& getDrawTexturedProgram() { return m_drawTexturedProgram; }
const PainterShaderProgramPtr& getDrawSolidColorProgram() { return m_drawSolidColorProgram; }
private:
PainterShaderProgramPtr m_drawTexturedProgram;
PainterShaderProgramPtr m_drawSolidColorProgram;
};
extern PainterShaderManager g_shaders;
#endif

View File

@ -32,8 +32,6 @@ PainterShaderProgram::PainterShaderProgram()
m_opacity = 1; m_opacity = 1;
m_color = Color::white; m_color = Color::white;
m_time = 0; m_time = 0;
m_lastTexture = -1;
m_textures.fill(0);
} }
bool PainterShaderProgram::link() bool PainterShaderProgram::link()
@ -43,7 +41,7 @@ bool PainterShaderProgram::link()
bindAttributeLocation(TEXCOORD_ATTR, "a_texCoord"); bindAttributeLocation(TEXCOORD_ATTR, "a_texCoord");
if(ShaderProgram::link()) { if(ShaderProgram::link()) {
bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "projectionMatrix");
bindUniformLocation(TEXTURE_TRANSFORM_MATRIX_UNIFORM, "texTransformMatrix"); bindUniformLocation(TEXTURE_MATRIX_UNIFORM, "textureMatrix");
bindUniformLocation(COLOR_UNIFORM, "color"); bindUniformLocation(COLOR_UNIFORM, "color");
bindUniformLocation(OPACITY_UNIFORM, "opacity"); bindUniformLocation(OPACITY_UNIFORM, "opacity");
bindUniformLocation(TIME_UNIFORM, "time"); bindUniformLocation(TIME_UNIFORM, "time");
@ -52,15 +50,13 @@ bool PainterShaderProgram::link()
bind(); bind();
setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix); setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix);
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, m_textureTransformMatrix); setUniformValue(TEXTURE_MATRIX_UNIFORM, m_textureMatrix);
setUniformValue(COLOR_UNIFORM, m_color); setUniformValue(COLOR_UNIFORM, m_color);
setUniformValue(OPACITY_UNIFORM, m_opacity); setUniformValue(OPACITY_UNIFORM, m_opacity);
setUniformValue(TIME_UNIFORM, m_time); setUniformValue(TIME_UNIFORM, m_time);
setUniformValue(TEX0_UNIFORM, 0); setUniformValue(TEX0_UNIFORM, 0);
setUniformValue(TEX1_UNIFORM, 1); setUniformValue(TEX1_UNIFORM, 1);
release();
enableAttributeArray(PainterShaderProgram::VERTEX_ATTR);
enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
return true; return true;
} }
return false; return false;
@ -76,6 +72,16 @@ void PainterShaderProgram::setProjectionMatrix(const Matrix3& projectionMatrix)
m_projectionMatrix = projectionMatrix; m_projectionMatrix = projectionMatrix;
} }
void PainterShaderProgram::setTextureMatrix(const Matrix2& textureMatrix)
{
if(textureMatrix == m_textureMatrix)
return;
bind();
setUniformValue(TEXTURE_MATRIX_UNIFORM, textureMatrix);
m_textureMatrix = textureMatrix;
}
void PainterShaderProgram::setColor(const Color& color) void PainterShaderProgram::setColor(const Color& color)
{ {
if(color == m_color) if(color == m_color)
@ -96,68 +102,13 @@ void PainterShaderProgram::setOpacity(float opacity)
m_opacity = opacity; m_opacity = opacity;
} }
void PainterShaderProgram::setTexture(const TexturePtr& texture, int index) void PainterShaderProgram::updateTime()
{ {
assert(index >= 0 && index <= 1); float time = g_clock.timeElapsed(m_startTime);
if(m_time == time)
uint texId = texture ? texture->getId() : 0;
if(m_textures[index] == texId)
return; return;
m_textures[index] = texId;
m_lastTexture = std::max(m_lastTexture, index);
if(texture && index == 0) {
const Matrix2& textureTransformMatrix = texture->getTransformMatrix();
if(m_textureTransformMatrix != textureTransformMatrix) {
bind(); bind();
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix);
m_textureTransformMatrix = textureTransformMatrix;
}
}
}
void PainterShaderProgram::draw(CoordsBuffer& coordsBuffer, DrawMode drawMode)
{
bind();
float time = g_clock.timeElapsed(m_startTime);
if(m_time != time) {
setUniformValue(TIME_UNIFORM, time); setUniformValue(TIME_UNIFORM, time);
m_time = time; m_time = time;
} }
int vertexCount = coordsBuffer.getVertexCount();
if(vertexCount == 0)
return;
coordsBuffer.updateCaches();
bool hardwareCached = coordsBuffer.isHardwareCached();
if(hardwareCached)
coordsBuffer.getHardwareVertexBuffer()->bind();
setAttributeArray(PainterShaderProgram::VERTEX_ATTR, hardwareCached ? 0 : coordsBuffer.getVertexBuffer(), 2);
bool hasTexture = coordsBuffer.getTextureVertexCount() != 0;
if(hasTexture) {
if(hardwareCached)
coordsBuffer.getHardwareTextureVertexBuffer()->bind();
setAttributeArray(PainterShaderProgram::TEXCOORD_ATTR, hardwareCached ? 0 : coordsBuffer.getTextureVertexBuffer(), 2);
}
if(hardwareCached)
HardwareBuffer::unbind(HardwareBuffer::VertexBuffer);
if(m_lastTexture == 0) {
glBindTexture(GL_TEXTURE_2D, m_textures[0]);
} else {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_textures[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textures[0]);
}
glDrawArrays(drawMode, 0, vertexCount);
}

View File

@ -29,11 +29,12 @@
class PainterShaderProgram : public ShaderProgram class PainterShaderProgram : public ShaderProgram
{ {
protected:
enum { enum {
VERTEX_ATTR = 0, VERTEX_ATTR = 0,
TEXCOORD_ATTR = 1, TEXCOORD_ATTR = 1,
PROJECTION_MATRIX_UNIFORM = 0, PROJECTION_MATRIX_UNIFORM = 0,
TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1, TEXTURE_MATRIX_UNIFORM = 1,
COLOR_UNIFORM = 2, COLOR_UNIFORM = 2,
OPACITY_UNIFORM = 3, OPACITY_UNIFORM = 3,
TIME_UNIFORM = 4, TIME_UNIFORM = 4,
@ -42,34 +43,28 @@ class PainterShaderProgram : public ShaderProgram
//TEX2_UNIFORM = 7, //TEX2_UNIFORM = 7,
//TEX3_UNIFORM = 8, //TEX3_UNIFORM = 8,
}; };
public:
enum DrawMode {
Triangles = GL_TRIANGLES,
TriangleStrip = GL_TRIANGLE_STRIP
};
friend class PainterOGL2;
public:
PainterShaderProgram(); PainterShaderProgram();
bool link(); bool link();
void setProjectionMatrix(const Matrix3& projectionMatrix); void setProjectionMatrix(const Matrix3& projectionMatrix);
void setTextureMatrix(const Matrix2& textureMatrix);
void setColor(const Color& color); void setColor(const Color& color);
void setOpacity(float opacity); void setOpacity(float opacity);
void setTexture(const TexturePtr& texture, int index = 0); void updateTime();
void setUniformTexture(int location, const TexturePtr& texture, int index);
void draw(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
private: private:
DrawMode m_drawMode;
float m_startTime; float m_startTime;
std::array<uint, 2> m_textures;
Color m_color; Color m_color;
float m_opacity; float m_opacity;
Matrix3 m_projectionMatrix; Matrix3 m_projectionMatrix;
Matrix2 m_textureTransformMatrix; Matrix2 m_textureMatrix;
float m_time; float m_time;
int m_lastTexture;
}; };
#endif #endif

View File

@ -45,14 +45,14 @@ Particle::Particle(const Point& pos, const Size& startSize, const Size& finalSiz
void Particle::render() void Particle::render()
{ {
g_painter.setColor(m_color); g_painter->setColor(m_color);
if(!m_texture) if(!m_texture)
g_painter.drawFilledRect(m_rect); g_painter->drawFilledRect(m_rect);
else { else {
g_painter.setCompositionMode(m_compositionMode); g_painter->setCompositionMode(m_compositionMode);
g_painter.drawTexturedRect(m_rect, m_texture); g_painter->drawTexturedRect(m_rect, m_texture);
g_painter.setCompositionMode(Painter::CompositionMode_Normal); g_painter->setCompositionMode(Painter::CompositionMode_Normal);
} }
} }

View File

@ -44,8 +44,8 @@ public:
static void release(); static void release();
std::string log(); std::string log();
void disableAttributeArray(int location) { glDisableVertexAttribArray(location); } static void disableAttributeArray(int location) { glDisableVertexAttribArray(location); }
void enableAttributeArray(int location) { glEnableVertexAttribArray(location); } static void enableAttributeArray(int location) { glEnableVertexAttribArray(location); }
void disableAttributeArray(const char *name) { glDisableVertexAttribArray(getAttributeLocation(name)); } void disableAttributeArray(const char *name) { glDisableVertexAttribArray(getAttributeLocation(name)); }
void enableAttributeArray(const char *name) { glEnableVertexAttribArray(getAttributeLocation(name)); } void enableAttributeArray(const char *name) { glEnableVertexAttribArray(getAttributeLocation(name)); }

View File

@ -99,20 +99,23 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
void Texture::generateMipmaps() void Texture::generateMipmaps()
{ {
if(g_graphics.canGenerateHardwareMipmaps()) if(!generateHardwareMipmaps()) {
generateHardwareMipmaps();
else {
// fallback to software mipmaps generation, this can be slow // fallback to software mipmaps generation, this can be slow
//FIXME: disable because mipmaps size needs to be in base of 2, //FIXME: disabled because mipmaps size needs to be in base of 2,
// and the current algorithmn does not support that // and the current algorithmn does not support that
//generateSoftwareMipmaps(getPixels()); //generateSoftwareMipmaps(getPixels());
} }
} }
void Texture::generateHardwareMipmaps() bool Texture::generateHardwareMipmaps()
{ {
if(!g_graphics.canGenerateHardwareMipmaps()) if(!g_graphics.canUseHardwareMipmaps())
return; return false;
#ifndef OPENGL_ES2
if(!GLEW_ARB_framebuffer_object)
return false;
#endif
bind(); bind();
@ -122,6 +125,7 @@ void Texture::generateHardwareMipmaps()
} }
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
return true;
} }
void Texture::setSmooth(bool smooth) void Texture::setSmooth(bool smooth)
@ -146,10 +150,10 @@ std::vector<uint8> Texture::getPixels()
FrameBufferPtr fb(new FrameBuffer(m_size)); FrameBufferPtr fb(new FrameBuffer(m_size));
fb->bind(); fb->bind();
fb->clear(Color::alpha); fb->clear(Color::alpha);
g_painter.saveAndResetState(); g_painter->saveAndResetState();
g_painter.drawTexturedRect(Rect(0,0,m_size), shared_from_this()); g_painter->drawTexturedRect(Rect(0,0,m_size), shared_from_this());
glReadPixels(0, 0, m_size.width(), m_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); glReadPixels(0, 0, m_size.width(), m_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
g_painter.restoreSavedState(); g_painter->restoreSavedState();
fb->release(); fb->release();
#else #else
// copy pixels from opengl memory // copy pixels from opengl memory

View File

@ -36,15 +36,16 @@ public:
/// Tries to generate mipmaps via hardware, otherwise fallback to software implementation /// Tries to generate mipmaps via hardware, otherwise fallback to software implementation
void generateMipmaps(); void generateMipmaps();
/// Generate mipmaps via hardware /// Generate mipmaps via hardware if supported
void generateHardwareMipmaps(); bool generateHardwareMipmaps();
/// Generate mipmaps via software, which has a special algorithm for combining alpha pixels /// Generate mipmaps via software, which has a special algorithm for combining alpha pixels
void generateSoftwareMipmaps(std::vector<uint8> inPixels); void generateSoftwareMipmaps(std::vector<uint8> inPixels);
/// Activate texture altialising /// Activate texture anti-aliasing giving a better look when they are resized
void setSmooth(bool smooth); void setSmooth(bool smooth);
GLuint getId() { return m_textureId; } GLuint getId() { return m_textureId; }
/// Return actual texture pixels
std::vector<uint8> getPixels(); std::vector<uint8> getPixels();
int getWidth() { return m_size.width(); } int getWidth() { return m_size.width(); }

View File

@ -47,7 +47,7 @@ void UIFrameCounter::drawSelf()
} }
m_frameCount++; m_frameCount++;
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
m_font->drawText(m_fpsText, m_rect, m_align); m_font->drawText(m_fpsText, m_rect, m_align);
} }

View File

@ -53,9 +53,9 @@ void UITextEdit::drawSelf()
int textLength = m_text.length(); int textLength = m_text.length();
const TexturePtr& texture = m_font->getTexture(); const TexturePtr& texture = m_font->getTexture();
g_painter.setColor(m_color); g_painter->setColor(m_color);
for(int i=0;i<textLength;++i) for(int i=0;i<textLength;++i)
g_painter.drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]); g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
// render cursor // render cursor
if(isExplicitlyEnabled() && (isActive() || m_alwaysActive) && m_cursorPos >= 0) { if(isExplicitlyEnabled() && (isActive() || m_alwaysActive) && m_cursorPos >= 0) {
@ -69,7 +69,7 @@ void UITextEdit::drawSelf()
cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight()); cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight());
else else
cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight()); cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight());
g_painter.drawFilledRect(cursorRect); g_painter->drawFilledRect(cursorRect);
} else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) { } else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) {
m_cursorTicks = g_clock.ticks(); m_cursorTicks = g_clock.ticks();
} }

View File

@ -54,19 +54,19 @@ UIWidget::~UIWidget()
void UIWidget::draw(const Rect& visibleRect) void UIWidget::draw(const Rect& visibleRect)
{ {
if(m_clipping) if(m_clipping)
g_painter.setClipRect(visibleRect); g_painter->setClipRect(visibleRect);
drawSelf(); drawSelf();
if(m_children.size() > 0) { if(m_children.size() > 0) {
if(m_clipping) if(m_clipping)
g_painter.setClipRect(visibleRect.intersection(getClippingRect())); g_painter->setClipRect(visibleRect.intersection(getClippingRect()));
drawChildren(visibleRect); drawChildren(visibleRect);
} }
if(m_clipping) if(m_clipping)
g_painter.resetClipRect(); g_painter->resetClipRect();
} }
void UIWidget::drawSelf() void UIWidget::drawSelf()
@ -97,22 +97,22 @@ void UIWidget::drawChildren(const Rect& visibleRect)
continue; continue;
// store current graphics opacity // store current graphics opacity
float oldOpacity = g_painter.getOpacity(); float oldOpacity = g_painter->getOpacity();
// decrease to self opacity // decrease to self opacity
if(child->getOpacity() < oldOpacity) if(child->getOpacity() < oldOpacity)
g_painter.setOpacity(child->getOpacity()); g_painter->setOpacity(child->getOpacity());
child->draw(childVisibleRect); child->draw(childVisibleRect);
// debug draw box // debug draw box
if(g_ui.isDrawingDebugBoxes()) { if(g_ui.isDrawingDebugBoxes()) {
g_painter.setColor(Color::green); g_painter->setColor(Color::green);
g_painter.drawBoundingRect(child->getRect()); g_painter->drawBoundingRect(child->getRect());
} }
//g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Color::red); //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Color::red);
g_painter.setOpacity(oldOpacity); g_painter->setOpacity(oldOpacity);
} }
} }

View File

@ -323,8 +323,8 @@ void UIWidget::drawBackground(const Rect& screenCoords)
drawRect.translate(m_backgroundRect.topLeft()); drawRect.translate(m_backgroundRect.topLeft());
if(m_backgroundRect.isValid()) if(m_backgroundRect.isValid())
drawRect.resize(m_backgroundRect.size()); drawRect.resize(m_backgroundRect.size());
g_painter.setColor(m_backgroundColor); g_painter->setColor(m_backgroundColor);
g_painter.drawFilledRect(drawRect); g_painter->drawFilledRect(drawRect);
} }
} }
@ -332,31 +332,31 @@ void UIWidget::drawBorder(const Rect& screenCoords)
{ {
// top // top
if(m_borderWidth.top > 0) { if(m_borderWidth.top > 0) {
g_painter.setColor(m_borderColor.top); g_painter->setColor(m_borderColor.top);
Rect borderRect(screenCoords.topLeft(), screenCoords.width(), m_borderWidth.top); Rect borderRect(screenCoords.topLeft(), screenCoords.width(), m_borderWidth.top);
g_painter.drawFilledRect(borderRect); g_painter->drawFilledRect(borderRect);
} }
// right // right
if(m_borderWidth.right > 0) { if(m_borderWidth.right > 0) {
g_painter.setColor(m_borderColor.right); g_painter->setColor(m_borderColor.right);
Rect borderRect(screenCoords.topRight() - Point(m_borderWidth.right - 1, 0), m_borderWidth.right, screenCoords.height()); Rect borderRect(screenCoords.topRight() - Point(m_borderWidth.right - 1, 0), m_borderWidth.right, screenCoords.height());
g_painter.drawFilledRect(borderRect); g_painter->drawFilledRect(borderRect);
} }
// bottom // bottom
if(m_borderWidth.bottom > 0) { if(m_borderWidth.bottom > 0) {
g_painter.setColor(m_borderColor.bottom); g_painter->setColor(m_borderColor.bottom);
Rect borderRect(screenCoords.bottomLeft() - Point(0, m_borderWidth.bottom - 1), screenCoords.width(), m_borderWidth.bottom); Rect borderRect(screenCoords.bottomLeft() - Point(0, m_borderWidth.bottom - 1), screenCoords.width(), m_borderWidth.bottom);
g_painter.drawFilledRect(borderRect); g_painter->drawFilledRect(borderRect);
} }
// left // left
if(m_borderWidth.left > 0) { if(m_borderWidth.left > 0) {
g_painter.setColor(m_borderColor.left); g_painter->setColor(m_borderColor.left);
Rect borderRect(screenCoords.topLeft(), m_borderWidth.left, screenCoords.height()); Rect borderRect(screenCoords.topLeft(), m_borderWidth.left, screenCoords.height());
g_painter.drawFilledRect(borderRect); g_painter->drawFilledRect(borderRect);
} }
} }
@ -372,8 +372,8 @@ void UIWidget::drawIcon(const Rect& screenCoords)
drawRect.resize(m_icon->getSize()); drawRect.resize(m_icon->getSize());
drawRect.moveCenter(screenCoords.center()); drawRect.moveCenter(screenCoords.center());
} }
g_painter.setColor(m_iconColor); g_painter->setColor(m_iconColor);
g_painter.drawTexturedRect(drawRect, m_icon); g_painter->drawTexturedRect(drawRect, m_icon);
} }
} }

View File

@ -167,8 +167,8 @@ void UIWidget::drawImage(const Rect& screenCoords)
m_imageTexture->setSmooth(m_imageSmooth); m_imageTexture->setSmooth(m_imageSmooth);
g_painter.setColor(m_imageColor); g_painter->setColor(m_imageColor);
g_painter.drawTextureCoords(m_imageCoordsBuffer, m_imageTexture); g_painter->drawTextureCoords(m_imageCoordsBuffer, m_imageTexture);
} }
void UIWidget::setImageSource(const std::string& source) void UIWidget::setImageSource(const std::string& source)

View File

@ -87,8 +87,8 @@ void UIWidget::drawText(const Rect& screenCoords)
m_font->calculateDrawTextCoords(m_textCoordsBuffer, m_drawText, screenCoords.translated(m_textOffset), m_textAlign); m_font->calculateDrawTextCoords(m_textCoordsBuffer, m_drawText, screenCoords.translated(m_textOffset), m_textAlign);
} }
g_painter.setColor(m_color); g_painter->setColor(m_color);
g_painter.drawTextureCoords(m_textCoordsBuffer, m_font->getTexture()); g_painter->drawTextureCoords(m_textCoordsBuffer, m_font->getTexture());
} }
void UIWidget::onTextChange(const std::string& text, const std::string& oldText) void UIWidget::onTextChange(const std::string& text, const std::string& oldText)

View File

@ -23,7 +23,16 @@
#ifndef __COMPILER_H__ #ifndef __COMPILER_H__
#define __COMPILER_H__ #define __COMPILER_H__
#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#error "sorry, you need gcc 4.6 or greater to compile"
#endif
#if !defined(__GXX_EXPERIMENTAL_CXX0X__)
#error "sorry, you must enable C++0x to compile"
#endif
// hack to enable std::thread on mingw32 4.6 // hack to enable std::thread on mingw32 4.6
/*
#if !defined(_GLIBCXX_HAS_GTHREADS) && defined(__GNUG__) #if !defined(_GLIBCXX_HAS_GTHREADS) && defined(__GNUG__)
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
@ -45,5 +54,6 @@ namespace std {
using boost::condition_variable_any; using boost::condition_variable_any;
} }
#endif #endif
*/
#endif #endif

View File

@ -40,12 +40,11 @@ typedef int32_t int32;
typedef int16_t int16; typedef int16_t int16;
typedef int8_t int8; typedef int8_t int8;
// note that on 32 bit platforms the max ticks will overflow for valeus above 2,147,483,647 // note that on 32 bit platforms the max ticks will overflow for values above 2,147,483,647
// thus this means that the app may crash after running 24 days without restarting // thus this means that the app may cause unknown behavior after running 24 days without restarting
typedef long ticks_t; typedef long ticks_t;
typedef std::function<void()> SimpleCallback; typedef std::function<void()> SimpleCallback;
typedef std::function<bool()> BooleanCallback;
// boolean with default value initializer // boolean with default value initializer
template<bool def> template<bool def>

View File

@ -40,7 +40,7 @@ void AnimatedText::draw(const Point& dest, const Rect& visibleRect)
if(visibleRect.contains(rect)) { if(visibleRect.contains(rect)) {
//TODO: cache into a framebuffer //TODO: cache into a framebuffer
g_painter.setColor(m_color); g_painter->setColor(m_color);
m_font->drawText(m_text, rect, Fw::AlignLeft); m_font->drawText(m_text, rect, Fw::AlignLeft);
} }
} }

View File

@ -34,7 +34,7 @@
#include <framework/core/clock.h> #include <framework/core/clock.h>
#include <framework/graphics/paintershaderprogram.h> #include <framework/graphics/paintershaderprogram.h>
#include <framework/graphics/paintershadersources.h> #include <framework/graphics/painterogl2_shadersources.h>
#include <framework/graphics/texturemanager.h> #include <framework/graphics/texturemanager.h>
#include <framework/graphics/framebuffer.h> #include <framework/graphics/framebuffer.h>
#include "spritemanager.h" #include "spritemanager.h"
@ -59,25 +59,27 @@ Creature::Creature() : Thing()
m_informationFont = g_fonts.getFont("verdana-11px-rounded"); m_informationFont = g_fonts.getFont("verdana-11px-rounded");
} }
/*
PainterShaderProgramPtr outfitProgram; PainterShaderProgramPtr outfitProgram;
int HEAD_COLOR_UNIFORM = 10; int HEAD_COLOR_UNIFORM = 10;
int BODY_COLOR_UNIFORM = 11; int BODY_COLOR_UNIFORM = 11;
int LEGS_COLOR_UNIFORM = 12; int LEGS_COLOR_UNIFORM = 12;
int FEET_COLOR_UNIFORM = 13; int FEET_COLOR_UNIFORM = 13;
int MASK_TEXTURE_UNIFORM = 14; int MASK_TEXTURE_UNIFORM = 14;
*/
void Creature::draw(const Point& dest, float scaleFactor, bool animate) void Creature::draw(const Point& dest, float scaleFactor, bool animate)
{ {
Point animationOffset = animate ? m_walkOffset : Point(0,0); Point animationOffset = animate ? m_walkOffset : Point(0,0);
if(m_showTimedSquare && animate) { if(m_showTimedSquare && animate) {
g_painter.setColor(m_timedSquareColor); g_painter->setColor(m_timedSquareColor);
g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 3)*scaleFactor, Size(28, 28)*scaleFactor), std::max((int)(2*scaleFactor), 1)); g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 3)*scaleFactor, Size(28, 28)*scaleFactor), std::max((int)(2*scaleFactor), 1));
} }
if(m_showStaticSquare && animate) { if(m_showStaticSquare && animate) {
g_painter.setColor(m_staticSquareColor); g_painter->setColor(m_staticSquareColor);
g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 1)*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor), std::max((int)(2*scaleFactor), 1)); g_painter->drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 1)*scaleFactor, Size(Otc::TILE_PIXELS, Otc::TILE_PIXELS)*scaleFactor), std::max((int)(2*scaleFactor), 1));
} }
internalDrawOutfit(dest + animationOffset * scaleFactor, scaleFactor, animate, animate, m_direction); internalDrawOutfit(dest + animationOffset * scaleFactor, scaleFactor, animate, animate, m_direction);
@ -86,7 +88,8 @@ void Creature::draw(const Point& dest, float scaleFactor, bool animate)
void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction) void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction)
{ {
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
/*
if(!outfitProgram) { if(!outfitProgram) {
outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram);
outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
@ -97,6 +100,7 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor");
outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor");
} }
*/
int xPattern = 0, yPattern = 0, zPattern = 0; int xPattern = 0, yPattern = 0, zPattern = 0;
@ -124,13 +128,15 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1)))) if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1))))
continue; continue;
g_painter.setCustomProgram(outfitProgram); /*
g_painter->setShaderProgram(outfitProgram);
outfitProgram->bind(); outfitProgram->bind();
outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor());
outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor());
outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor());
outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor());
*/
for(int h = 0; h < getDimensionHeight(); h++) { for(int h = 0; h < getDimensionHeight(); h++) {
for(int w = 0; w < getDimensionWidth(); w++) { for(int w = 0; w < getDimensionWidth(); w++) {
@ -140,14 +146,14 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, animationPhase); int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, animationPhase);
maskTex = g_sprites.getSpriteTexture(maskId); maskTex = g_sprites.getSpriteTexture(maskId);
} }
outfitProgram->setTexture(maskTex, 1); //outfitProgram->setTexture(maskTex, 1);
internalDraw(dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor, internalDraw(dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor,
scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase); scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase);
} }
} }
g_painter.releaseCustomProgram(); //g_painter->resetShaderProgram();
} }
// outfit is a creature imitating an item or the invisible effect // outfit is a creature imitating an item or the invisible effect
} else { } else {
@ -182,12 +188,12 @@ void Creature::drawOutfit(const Rect& destRect, bool resize)
if(!outfitBuffer) if(!outfitBuffer)
outfitBuffer = FrameBufferPtr(new FrameBuffer(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS))); outfitBuffer = FrameBufferPtr(new FrameBuffer(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS)));
g_painter.saveAndResetState(); g_painter->saveAndResetState();
outfitBuffer->bind(); outfitBuffer->bind();
outfitBuffer->clear(Color::alpha); outfitBuffer->clear(Color::alpha);
internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South); internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South);
outfitBuffer->release(); outfitBuffer->release();
g_painter.restoreSavedState(); g_painter->restoreSavedState();
if(resize) { if(resize) {
Rect srcRect; Rect srcRect;
@ -227,26 +233,26 @@ void Creature::drawInformation(const Point& point, bool useGray, const Rect& par
healthRect.setWidth((m_healthPercent / 100.0) * 25); healthRect.setWidth((m_healthPercent / 100.0) * 25);
// draw // draw
g_painter.setColor(Color::black); g_painter->setColor(Color::black);
g_painter.drawFilledRect(backgroundRect); g_painter->drawFilledRect(backgroundRect);
g_painter.setColor(fillColor); g_painter->setColor(fillColor);
g_painter.drawFilledRect(healthRect); g_painter->drawFilledRect(healthRect);
if(m_informationFont) if(m_informationFont)
m_informationFont->drawText(m_name, textRect, Fw::AlignTopCenter); m_informationFont->drawText(m_name, textRect, Fw::AlignTopCenter);
if(m_skull != Otc::SkullNone && m_skullTexture) { if(m_skull != Otc::SkullNone && m_skullTexture) {
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
g_painter.drawTexturedRect(Rect(point.x + 12, point.y + 5, m_skullTexture->getSize()), m_skullTexture); g_painter->drawTexturedRect(Rect(point.x + 12, point.y + 5, m_skullTexture->getSize()), m_skullTexture);
} }
if(m_shield != Otc::ShieldNone && m_shieldTexture && m_showShieldTexture) { if(m_shield != Otc::ShieldNone && m_shieldTexture && m_showShieldTexture) {
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
g_painter.drawTexturedRect(Rect(point.x, point.y + 5, m_shieldTexture->getSize()), m_shieldTexture); g_painter->drawTexturedRect(Rect(point.x, point.y + 5, m_shieldTexture->getSize()), m_shieldTexture);
} }
if(m_emblem != Otc::EmblemNone && m_emblemTexture) { if(m_emblem != Otc::EmblemNone && m_emblemTexture) {
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
g_painter.drawTexturedRect(Rect(point.x + 12, point.y + 16, m_emblemTexture->getSize()), m_emblemTexture); g_painter->drawTexturedRect(Rect(point.x + 12, point.y + 16, m_emblemTexture->getSize()), m_emblemTexture);
} }
} }

View File

@ -29,7 +29,7 @@
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/paintershaderprogram.h> #include <framework/graphics/paintershaderprogram.h>
#include <framework/graphics/paintershadersources.h> #include <framework/graphics/painterogl2_shadersources.h>
Item::Item() : Thing() Item::Item() : Thing()
{ {
@ -50,9 +50,10 @@ ItemPtr Item::create(int id)
return item; return item;
} }
/*
PainterShaderProgramPtr itemProgram; PainterShaderProgramPtr itemProgram;
int ITEM_ID_UNIFORM = 10; int ITEM_ID_UNIFORM = 10;
*/
void Item::draw(const Point& dest, float scaleFactor, bool animate) void Item::draw(const Point& dest, float scaleFactor, bool animate)
{ {
if(m_id == 0) if(m_id == 0)
@ -165,6 +166,7 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate)
} }
// setup item drawing shader // setup item drawing shader
/*
if(!itemProgram) { if(!itemProgram) {
itemProgram = PainterShaderProgramPtr(new PainterShaderProgram); itemProgram = PainterShaderProgramPtr(new PainterShaderProgram);
itemProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); itemProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
@ -172,15 +174,16 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate)
itemProgram->link(); itemProgram->link();
itemProgram->bindUniformLocation(ITEM_ID_UNIFORM, "itemId"); itemProgram->bindUniformLocation(ITEM_ID_UNIFORM, "itemId");
} }
g_painter.setCustomProgram(itemProgram); g_painter->setShaderProgram(itemProgram);
//itemProgram->bind(); //itemProgram->bind();
//itemProgram->setUniformValue(ITEM_ID_UNIFORM, (int)m_id); //itemProgram->setUniformValue(ITEM_ID_UNIFORM, (int)m_id);
*/
// now we can draw the item // now we can draw the item
internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase); internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase);
// release draw shader // release draw shader
g_painter.releaseCustomProgram(); g_painter->resetShaderProgram();
} }
void Item::setId(uint32 id) void Item::setId(uint32 id)

View File

@ -24,8 +24,7 @@
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/framebuffer.h> #include <framework/graphics/framebuffer.h>
#include <framework/graphics/paintershaderprogram.h> #include <framework/graphics/paintershadermanager.h>
#include <framework/graphics/paintershadersources.h>
#include "creature.h" #include "creature.h"
#include "map.h" #include "map.h"
#include "tile.h" #include "tile.h"
@ -34,8 +33,6 @@
#include "missile.h" #include "missile.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
//int AWARE_AREA_UNIFORM = 10;
MapView::MapView() MapView::MapView()
{ {
m_viewMode = NEAR_VIEW; m_viewMode = NEAR_VIEW;
@ -47,11 +44,7 @@ MapView::MapView()
m_framebuffer = FrameBufferPtr(new FrameBuffer()); m_framebuffer = FrameBufferPtr(new FrameBuffer());
setVisibleDimension(Size(15, 11)); setVisibleDimension(Size(15, 11));
m_shaderProgram = PainterShaderProgramPtr(new PainterShaderProgram); m_shaderProgram = g_shaders.createTexturedFragmentShader("/game_shaders/map.frag");
m_shaderProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
m_shaderProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/map.frag");
m_shaderProgram->link();
//m_shaderProgram->bindUniformLocation(AWARE_AREA_UNIFORM, "awareArea");
} }
void MapView::draw(const Rect& rect) void MapView::draw(const Rect& rect)
@ -78,16 +71,15 @@ void MapView::draw(const Rect& rect)
Size tileSize = Size(1,1) * m_tileSize; Size tileSize = Size(1,1) * m_tileSize;
if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) { if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) {
g_painter.saveAndResetState();
m_framebuffer->bind(); m_framebuffer->bind();
if(m_mustCleanFramebuffer) { if(m_mustCleanFramebuffer) {
Rect clearRect = Rect(0, 0, m_drawDimension * m_tileSize); Rect clearRect = Rect(0, 0, m_drawDimension * m_tileSize);
// drawing a black rect is actually faster than FrameBuffer::clear() // drawing a black rect is actually faster than FrameBuffer::clear()
g_painter.setColor(Color::black); g_painter->setColor(Color::black);
g_painter.drawFilledRect(clearRect); g_painter->drawFilledRect(clearRect);
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
// m_framebuffer->clear(Color::black); // m_framebuffer->clear(Color::black);
} }
@ -105,8 +97,8 @@ void MapView::draw(const Rect& rect)
if(!m_drawMinimapColors) if(!m_drawMinimapColors)
tile->draw(transformPositionTo2D(tile->getPosition()), scaleFactor, drawFlags); tile->draw(transformPositionTo2D(tile->getPosition()), scaleFactor, drawFlags);
else { else {
g_painter.setColor(tile->getMinimapColor()); g_painter->setColor(tile->getMinimapColor());
g_painter.drawFilledRect(Rect(transformPositionTo2D(tile->getPosition()), tileSize)); g_painter->drawFilledRect(Rect(transformPositionTo2D(tile->getPosition()), tileSize));
} }
} }
@ -118,7 +110,6 @@ void MapView::draw(const Rect& rect)
} }
m_framebuffer->release(); m_framebuffer->release();
g_painter.restoreSavedState();
// generating mipmaps each frame can be slow in older cards // generating mipmaps each frame can be slow in older cards
//m_framebuffer->getTexture()->generateHardwareMipmaps(); //m_framebuffer->getTexture()->generateHardwareMipmaps();
@ -126,7 +117,7 @@ void MapView::draw(const Rect& rect)
m_mustDrawVisibleTilesCache = false; m_mustDrawVisibleTilesCache = false;
} }
g_painter.setCustomProgram(m_shaderProgram); //g_painter->setShaderProgram(m_shaderProgram);
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize; Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
if(m_followingCreature) if(m_followingCreature)
@ -139,39 +130,20 @@ void MapView::draw(const Rect& rect)
drawOffset.y += (srcVisible.height() - srcSize.height()) / 2; drawOffset.y += (srcVisible.height() - srcSize.height()) / 2;
Rect srcRect = Rect(drawOffset, srcSize); Rect srcRect = Rect(drawOffset, srcSize);
/*
// pass aware area to the shader program
Rect awareRect;
if(m_followingCreature) {
Point awareOffset = transformPositionTo2D(m_followingCreature->getPosition().translated(-Otc::AWARE_X_LEFT_TILES + 1, -Otc::AWARE_Y_TOP_TILES + 1));
awareOffset += m_followingCreature->getWalkOffset() * scaleFactor;
awareRect.setTopLeft(awareOffset);
awareRect.resize(Otc::VISIBLE_X_TILES * m_tileSize, Otc::VISIBLE_Y_TILES * m_tileSize);
}
m_shaderProgram->bind();
m_shaderProgram->setUniformValue(AWARE_AREA_UNIFORM,
awareRect.left()/(float)m_framebuffer->getSize().width(),
awareRect.top()/(float)m_framebuffer->getSize().height(),
awareRect.right()/(float)m_framebuffer->getSize().width(),
awareRect.bottom()/(float)m_framebuffer->getSize().height());
*/
#if 0 #if 0
// debug source area // debug source area
g_painter.saveAndResetState(); g_painter->saveAndResetState();
m_framebuffer->bind(); m_framebuffer->bind();
g_painter.setColor(Color::green); g_painter->setColor(Color::green);
g_painter.drawBoundingRect(srcRect, 2); g_painter->drawBoundingRect(srcRect, 2);
m_framebuffer->release(); m_framebuffer->release();
g_painter.restoreSavedState(); g_painter->restoreSavedState();
m_framebuffer->draw(rect); m_framebuffer->draw(rect);
#else #else
m_framebuffer->draw(rect, srcRect); m_framebuffer->draw(rect, srcRect);
#endif #endif
g_painter.releaseCustomProgram(); g_painter->resetShaderProgram();
// this could happen if the player position is not known yet // this could happen if the player position is not known yet
if(!cameraPosition.isValid()) if(!cameraPosition.isValid())
@ -231,9 +203,9 @@ void MapView::draw(const Rect& rect)
Rect hRect(0, 0, 10, 2); Rect hRect(0, 0, 10, 2);
vRect.moveCenter(rect.center()); vRect.moveCenter(rect.center());
hRect.moveCenter(rect.center()); hRect.moveCenter(rect.center());
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
g_painter.drawFilledRect(vRect); g_painter->drawFilledRect(vRect);
g_painter.drawFilledRect(hRect); g_painter->drawFilledRect(hRect);
} }
} }

View File

@ -137,7 +137,7 @@ TexturePtr SpriteManager::loadSpriteTexture(int id)
TexturePtr spriteTex(new Texture(32, 32, 4, &pixels[0])); TexturePtr spriteTex(new Texture(32, 32, 4, &pixels[0]));
spriteTex->setSmooth(true); spriteTex->setSmooth(true);
if(g_graphics.canGenerateMipmaps()) if(g_graphics.canUseMipmaps())
spriteTex->generateSoftwareMipmaps(pixels); spriteTex->generateSoftwareMipmaps(pixels);
return spriteTex; return spriteTex;

View File

@ -40,7 +40,7 @@ void StaticText::draw(const Point& dest, const Rect& parentRect)
// draw only if the real center is not too far from the parent center, or its a yell // draw only if the real center is not too far from the parent center, or its a yell
if((boundRect.center() - rect.center()).length() < parentRect.width() / 15 || isYell()) { if((boundRect.center() - rect.center()).length() < parentRect.width() / 15 || isYell()) {
//TODO: cache into a framebuffer //TODO: cache into a framebuffer
g_painter.setColor(m_color); g_painter->setColor(m_color);
m_font->drawText(m_text, boundRect, Fw::AlignCenter); m_font->drawText(m_text, boundRect, Fw::AlignCenter);
} }
} }

View File

@ -82,8 +82,8 @@ void Thing::internalDraw(const Point& dest, float scaleFactor, int w, int h, int
int spriteId = getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animationPhase); int spriteId = getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animationPhase);
if(spriteId) { if(spriteId) {
Rect drawRect(dest - getDisplacement()*scaleFactor, Size(scaledSize, scaledSize)); Rect drawRect(dest - getDisplacement()*scaleFactor, Size(scaledSize, scaledSize));
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
g_painter.drawTexturedRect(drawRect, g_sprites.getSpriteTexture(spriteId)); g_painter->drawTexturedRect(drawRect, g_sprites.getSpriteTexture(spriteId));
} }
} }

View File

@ -29,7 +29,7 @@ void UICreature::drawSelf()
UIWidget::drawSelf(); UIWidget::drawSelf();
if(m_creature) { if(m_creature) {
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
Rect drawRect = getClippingRect(); Rect drawRect = getClippingRect();
m_creature->drawOutfit(drawRect, !m_fixedCreatureSize); m_creature->drawOutfit(drawRect, !m_fixedCreatureSize);
} }

View File

@ -41,12 +41,12 @@ void UIItem::drawSelf()
dest += (1 - scaleFactor)*32; dest += (1 - scaleFactor)*32;
dest += m_item->getDisplacement() * scaleFactor; dest += m_item->getDisplacement() * scaleFactor;
g_painter.setColor(Color::white); g_painter->setColor(Color::white);
m_item->draw(dest, scaleFactor, true); m_item->draw(dest, scaleFactor, true);
if(m_font && m_item->isStackable() && m_item->getCount() > 1) { if(m_font && m_item->isStackable() && m_item->getCount() > 1) {
std::string count = Fw::tostring(m_item->getCount()); std::string count = Fw::tostring(m_item->getCount());
g_painter.setColor(Color(231, 231, 231)); g_painter->setColor(Color(231, 231, 231));
m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight); m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight);
} }
//m_font->drawText(Fw::tostring(m_item->getId()), m_rect, Fw::AlignBottomRight); //m_font->drawText(Fw::tostring(m_item->getId()), m_rect, Fw::AlignBottomRight);

View File

@ -49,9 +49,10 @@ void UIMap::drawSelf()
UIWidget::drawSelf(); UIWidget::drawSelf();
// draw map border // draw map border
g_painter.setColor(Color::black); g_painter->setColor(Color::black);
g_painter.drawBoundingRect(m_mapRect.expanded(1)); g_painter->drawBoundingRect(m_mapRect.expanded(1));
g_painter->setColor(Color::white);
m_mapView->draw(m_mapRect); m_mapView->draw(m_mapRect);
} }