Add texture abstract class

This commit is contained in:
Henrique Santiago 2013-03-03 03:32:49 -03:00 committed by Eduardo Bart
parent ab9351196c
commit b3b849000d
13 changed files with 318 additions and 230 deletions

View File

@ -26,6 +26,7 @@
#include <framework/graphics/framebuffermanager.h>
#include <framework/graphics/painter.h>
#include <framework/graphics/image.h>
#include <framework/graphics/ogl/textureogl.h>
enum {
MAX_LIGHT_INTENSITY = 8,
@ -61,7 +62,7 @@ TexturePtr LightView::generateLightBubble(float centerFactor)
}
}
TexturePtr tex = TexturePtr(new Texture(lightImage, true));
TexturePtr tex = TexturePtr(new TextureOGL(lightImage, true));
tex->setSmooth(true);
return tex;
}

View File

@ -29,6 +29,7 @@
#include <framework/graphics/painter.h>
#include <framework/graphics/image.h>
#include <framework/graphics/framebuffermanager.h>
#include <framework/graphics/ogl/textureogl.h>
#include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h>
#include <zlib.h>
@ -65,7 +66,7 @@ void MinimapBlock::update()
if(shouldDraw) {
if(!m_texture) {
m_texture = TexturePtr(new Texture(image, true));
m_texture = TexturePtr(new TextureOGL(image, true));
} else {
m_texture->uploadPixels(image, true);
}

View File

@ -28,6 +28,7 @@
#include <framework/graphics/graphics.h>
#include <framework/graphics/texture.h>
#include <framework/graphics/image.h>
#include <framework/graphics/ogl/textureogl.h>
#include <framework/graphics/texturemanager.h>
#include <framework/core/filestream.h>
#include <framework/otml/otml.h>
@ -283,7 +284,7 @@ const TexturePtr& ThingType::getTexture(int animationPhase)
}
}
}
animationPhaseTexture = TexturePtr(new Texture(fullImage, true));
animationPhaseTexture = TexturePtr(new TextureOGL(fullImage, true));
animationPhaseTexture->setSmooth(true);
}
return animationPhaseTexture;

View File

@ -459,6 +459,8 @@ if(FRAMEWORK_GRAPHICS)
${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.h
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.h
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/textureogl.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/textureogl.h
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.h
${CMAKE_CURRENT_LIST_DIR}/graphics/vertexarray.h

View File

@ -30,6 +30,7 @@
#include <framework/graphics/particlemanager.h>
#include <framework/graphics/texturemanager.h>
#include <framework/graphics/painter.h>
#include <framework/graphics/ogl/textureogl.h>
#ifdef FW_SOUND
#include <framework/sound/soundmanager.h>
@ -232,7 +233,7 @@ void GraphicalApplication::resize(const Size& size)
m_onInputEvent = false;
if(g_graphics.canCacheBackbuffer()) {
m_foreground = TexturePtr(new Texture(size));
m_foreground = TexturePtr(new TextureOGL(size));
m_foreground->setUpsideDown(true);
}
m_mustRepaint = true;

View File

@ -24,14 +24,15 @@
#include "graphics.h"
#include <framework/core/eventdispatcher.h>
#include "ogl/textureogl.h"
AnimatedTexture::AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps, bool compress)
AnimatedTexture::AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps)
{
if(!setupSize(size, buildMipmaps))
return;
for(uint i=0;i<frames.size();++i) {
m_frames.push_back(new Texture(frames[i], buildMipmaps, compress));
m_frames.push_back(new TextureOGL(frames[i], buildMipmaps));
}
m_framesDelay = framesDelay;

View File

@ -29,7 +29,7 @@
class AnimatedTexture : public Texture
{
public:
AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps = false, bool compress = false);
AnimatedTexture(const Size& size, std::vector<ImagePtr> frames, std::vector<int> framesDelay, bool buildMipmaps = false);
virtual ~AnimatedTexture();
virtual bool buildHardwareMipmaps();

View File

@ -26,6 +26,7 @@
#include <framework/platform/platformwindow.h>
#include <framework/core/application.h>
#include <framework/graphics/ogl/textureogl.h>
uint FrameBuffer::boundFbo = 0;
@ -61,7 +62,7 @@ void FrameBuffer::resize(const Size& size)
if(m_texture && m_texture->getSize() == size)
return;
m_texture = TexturePtr(new Texture(size));
m_texture = TexturePtr(new TextureOGL(size));
m_texture->setSmooth(m_smooth);
m_texture->setUpsideDown(true);
@ -75,7 +76,7 @@ void FrameBuffer::resize(const Size& size)
internalRelease();
} else {
if(m_backuping) {
m_screenBackup = TexturePtr(new Texture(size));
m_screenBackup = TexturePtr(new TextureOGL(size));
m_screenBackup->setUpsideDown(true);
}
}

View File

@ -0,0 +1,227 @@
/*
* Copyright (c) 2010-2013 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 "textureogl.h"
#include <framework/graphics/image.h>
#include <framework/core/application.h>
#include <framework/graphics/graphics.h>
TextureOGL::TextureOGL()
{
m_id = 0;
}
TextureOGL::TextureOGL(const Size& size)
{
m_id = 0;
if(!setupSize(size))
return;
createTexture();
bind();
setupPixels(0, m_glSize, nullptr, 4);
setupWrap();
setupFilters();
}
TextureOGL::TextureOGL(const ImagePtr& image, bool buildMipmaps)
{
m_id = 0;
if(!setupSize(image->getSize(), buildMipmaps))
return;
createTexture();
uploadPixels(image, buildMipmaps);
}
TextureOGL::~TextureOGL()
{
#ifndef NDEBUG
assert(!g_app.isTerminated());
#endif
// free texture from gl memory
if(g_graphics.ok() && m_id != 0)
glDeleteTextures(1, &m_id);
}
void TextureOGL::uploadPixels(const ImagePtr& image, bool buildMipmaps)
{
ImagePtr glImage = image;
if(m_size != m_glSize) {
glImage = ImagePtr(new Image(m_glSize, image->getBpp()));
glImage->paste(image);
} else
glImage = image;
bind();
if(buildMipmaps) {
int level = 0;
do {
setupPixels(level++, glImage->getSize(), glImage->getPixelData(), glImage->getBpp());
} while(glImage->nextMipmap());
m_hasMipmaps = true;
} else
setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp());
setupWrap();
setupFilters();
}
void TextureOGL::bind()
{
// must reset painter texture state
g_painter->setTexture(this);
glBindTexture(GL_TEXTURE_2D, m_id);
}
void TextureOGL::copyFromScreen(const Rect& screenRect)
{
bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height());
}
bool TextureOGL::buildHardwareMipmaps()
{
if(!g_graphics.canUseHardwareMipmaps())
return false;
bind();
if(!m_hasMipmaps) {
m_hasMipmaps = true;
setupFilters();
}
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
void TextureOGL::setSmooth(bool smooth)
{
if(smooth && !g_graphics.canUseBilinearFiltering())
return;
if(smooth == m_smooth)
return;
m_smooth = smooth;
bind();
setupFilters();
}
void TextureOGL::setRepeat(bool repeat)
{
if(m_repeat == repeat)
return;
m_repeat = repeat;
bind();
setupWrap();
}
void TextureOGL::setUpsideDown(bool upsideDown)
{
if(m_upsideDown == upsideDown)
return;
m_upsideDown = upsideDown;
setupTranformMatrix(m_glSize, m_size);
}
void TextureOGL::createTexture()
{
glGenTextures(1, &m_id);
assert(m_id != 0);
}
bool TextureOGL::setupSize(const Size& size, bool forcePowerOfTwo)
{
Size glSize;
if(!g_graphics.canUseNonPowerOfTwoTextures() || forcePowerOfTwo)
glSize.resize(stdext::to_power_of_two(size.width()), stdext::to_power_of_two(size.height()));
else
glSize = size;
// checks texture max size
if(std::max(glSize.width(), glSize.height()) > g_graphics.getMaxTextureSize()) {
g_logger.error(stdext::format("loading texture with size %dx%d failed, "
"the maximum size allowed by the graphics card is %dx%d,"
"to prevent crashes the texture will be displayed as a blank texture",
size.width(), size.height(), g_graphics.getMaxTextureSize(), g_graphics.getMaxTextureSize()));
return false;
}
m_size = size;
m_glSize = glSize;
setupTranformMatrix(m_glSize, m_size);
return true;
}
void TextureOGL::setupWrap()
{
int texParam;
if(!m_repeat && g_graphics.canUseClampToEdge())
texParam = GL_CLAMP_TO_EDGE;
else
texParam = GL_REPEAT;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
}
void TextureOGL::setupFilters()
{
int minFilter;
int magFilter;
if(m_smooth) {
minFilter = m_hasMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
magFilter = GL_LINEAR;
} else {
minFilter = m_hasMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
magFilter = GL_NEAREST;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
}
void TextureOGL::setupPixels(int level, const Size& size, uchar* pixels, int channels)
{
GLenum format = 0;
switch(channels) {
case 4:
format = GL_RGBA;
break;
case 3:
format = GL_RGB;
break;
case 2:
format = GL_LUMINANCE_ALPHA;
break;
case 1:
format = GL_LUMINANCE;
break;
}
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2010-2013 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 TEXTUREOGL_H
#define TEXTUREOGL_H
#include <framework/graphics/texture.h>
class TextureOGL : public Texture
{
public:
TextureOGL();
TextureOGL(const Size& size);
TextureOGL(const ImagePtr& image, bool buildMipmaps = false);
virtual ~TextureOGL();
void uploadPixels(const ImagePtr& image, bool buildMipmaps = false);
void bind();
void copyFromScreen(const Rect& screenRect);
virtual bool buildHardwareMipmaps();
virtual void setSmooth(bool smooth);
virtual void setRepeat(bool repeat);
void setUpsideDown(bool upsideDown);
protected:
void createTexture();
bool setupSize(const Size& size, bool forcePowerOfTwo = false);
void setupWrap();
void setupFilters();
void setupPixels(int level, const Size& size, uchar *pixels, int channels = 4);
};
#endif

View File

@ -33,223 +33,29 @@ Texture::Texture()
m_time = 0;
}
Texture::Texture(const Size& size)
{
m_id = 0;
m_time = 0;
if(!setupSize(size))
return;
createTexture();
bind();
setupPixels(0, m_glSize, nullptr, 4);
setupWrap();
setupFilters();
}
Texture::Texture(const ImagePtr& image, bool buildMipmaps, bool compress)
{
m_id = 0;
m_time = 0;
createTexture();
uploadPixels(image, buildMipmaps, compress);
}
Texture::~Texture()
{
#ifndef NDEBUG
assert(!g_app.isTerminated());
#endif
// free texture from gl memory
if(g_graphics.ok() && m_id != 0)
glDeleteTextures(1, &m_id);
}
void Texture::uploadPixels(const ImagePtr& image, bool buildMipmaps, bool compress)
bool Texture::setupSize(const Size& size, bool)
{
if(!setupSize(image->getSize(), buildMipmaps))
return;
ImagePtr glImage = image;
if(m_size != m_glSize) {
glImage = ImagePtr(new Image(m_glSize, image->getBpp()));
glImage->paste(image);
} else
glImage = image;
bind();
if(buildMipmaps) {
int level = 0;
do {
setupPixels(level++, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
} while(glImage->nextMipmap());
m_hasMipmaps = true;
} else
setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
setupWrap();
setupFilters();
}
void Texture::bind()
{
// must reset painter texture state
g_painter->setTexture(this);
glBindTexture(GL_TEXTURE_2D, m_id);
}
void Texture::copyFromScreen(const Rect& screenRect)
{
bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height());
}
bool Texture::buildHardwareMipmaps()
{
if(!g_graphics.canUseHardwareMipmaps())
return false;
bind();
if(!m_hasMipmaps) {
m_hasMipmaps = true;
setupFilters();
}
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
void Texture::setSmooth(bool smooth)
{
if(smooth && !g_graphics.canUseBilinearFiltering())
return;
if(smooth == m_smooth)
return;
m_smooth = smooth;
bind();
setupFilters();
}
void Texture::setRepeat(bool repeat)
{
if(m_repeat == repeat)
return;
m_repeat = repeat;
bind();
setupWrap();
}
void Texture::setUpsideDown(bool upsideDown)
{
if(m_upsideDown == upsideDown)
return;
m_upsideDown = upsideDown;
setupTranformMatrix();
}
void Texture::createTexture()
{
glGenTextures(1, &m_id);
assert(m_id != 0);
}
bool Texture::setupSize(const Size& size, bool forcePowerOfTwo)
{
Size glSize;
if(!g_graphics.canUseNonPowerOfTwoTextures() || forcePowerOfTwo)
glSize.resize(stdext::to_power_of_two(size.width()), stdext::to_power_of_two(size.height()));
else
glSize = size;
// checks texture max size
if(std::max(glSize.width(), glSize.height()) > g_graphics.getMaxTextureSize()) {
g_logger.error(stdext::format("loading texture with size %dx%d failed, "
"the maximum size allowed by the graphics card is %dx%d,"
"to prevent crashes the texture will be displayed as a blank texture",
size.width(), size.height(), g_graphics.getMaxTextureSize(), g_graphics.getMaxTextureSize()));
return false;
}
m_size = size;
m_glSize = glSize;
setupTranformMatrix();
setupTranformMatrix(size, size);
return true;
}
void Texture::setupWrap()
{
int texParam;
if(!m_repeat && g_graphics.canUseClampToEdge())
texParam = GL_CLAMP_TO_EDGE;
else
texParam = GL_REPEAT;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
}
void Texture::setupFilters()
{
int minFilter;
int magFilter;
if(m_smooth) {
minFilter = m_hasMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
magFilter = GL_LINEAR;
} else {
minFilter = m_hasMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
magFilter = GL_NEAREST;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
}
void Texture::setupTranformMatrix()
void Texture::setupTranformMatrix(const Size& textureSize, const Size& realSize)
{
if(m_upsideDown) {
m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
0.0f, -1.0f/m_glSize.height(), 0.0f,
0.0f, m_size.height()/(float)m_glSize.height(), 1.0f };
m_transformMatrix = { 1.0f/textureSize.width(), 0.0f, 0.0f,
0.0f, -1.0f/textureSize.height(), 0.0f,
0.0f, realSize.height()/(float)textureSize.height(), 1.0f };
} else {
m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
0.0f, 1.0f/m_glSize.height(), 0.0f,
0.0f, 0.0f, 1.0f };
m_transformMatrix = { 1.0f/textureSize.width(), 0.0f, 0.0f,
0.0f, 1.0f/textureSize.height(), 0.0f,
0.0f, 0.0f, 1.0f };
}
}
void Texture::setupPixels(int level, const Size& size, uchar* pixels, int channels, bool compress)
{
GLenum format = 0;
switch(channels) {
case 4:
format = GL_RGBA;
break;
case 3:
format = GL_RGB;
break;
case 2:
format = GL_LUMINANCE_ALPHA;
break;
case 1:
format = GL_LUMINANCE;
break;
}
GLenum internalFormat = GL_RGBA;
#ifdef OPENGL_ES
//TODO
#else
if(compress)
internalFormat = GL_COMPRESSED_RGBA;
#endif
glTexImage2D(GL_TEXTURE_2D, level, internalFormat, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
}

View File

@ -29,26 +29,25 @@ class Texture : public stdext::shared_object
{
public:
Texture();
Texture(const Size& size);
Texture(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
virtual ~Texture();
void uploadPixels(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
void bind();
void copyFromScreen(const Rect& screenRect);
virtual bool buildHardwareMipmaps();
virtual void setSmooth(bool) {}
virtual void setRepeat(bool) {}
virtual void setUpsideDown(bool) {}
virtual bool setupSize(const Size& size, bool);
virtual void copyFromScreen(const Rect&) {}
virtual bool buildHardwareMipmaps() { return false; }
virtual void uploadPixels(const ImagePtr&, bool) {}
virtual void setSmooth(bool smooth);
virtual void setRepeat(bool repeat);
void setUpsideDown(bool upsideDown);
void setTime(ticks_t time) { m_time = time; }
void setupTranformMatrix(const Size& textureSize, const Size& realSize);
uint getId() { return m_id; }
ticks_t getTime() { return m_time; }
int getWidth() { return m_size.width(); }
int getHeight() { return m_size.height(); }
const Size& getSize() { return m_size; }
const Size& getGlSize() { return m_glSize; }
const Matrix3& getTransformMatrix() { return m_transformMatrix; }
bool isEmpty() { return m_id == 0; }
bool hasRepeat() { return m_repeat; }
@ -56,13 +55,6 @@ public:
virtual bool isAnimatedTexture() { return false; }
protected:
void createTexture();
bool setupSize(const Size& size, bool forcePowerOfTwo = false);
void setupWrap();
void setupFilters();
void setupTranformMatrix();
void setupPixels(int level, const Size& size, uchar *pixels, int channels = 4, bool compress = false);
uint m_id;
ticks_t m_time;
Size m_size;

View File

@ -29,6 +29,7 @@
#include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h>
#include <framework/graphics/apngloader.h>
#include "ogl/textureogl.h"
TextureManager g_textures;
@ -146,7 +147,7 @@ TexturePtr TextureManager::loadTexture(std::stringstream& file)
texture = animatedTexture;
} else {
ImagePtr image = ImagePtr(new Image(imageSize, apng.bpp, apng.pdata));
texture = TexturePtr(new Texture(image));
texture = TexturePtr(new TextureOGL(image));
}
free_apng(&apng);
}