api independet base texture class
I have been fighting with this thing several times but I can't seem to find a good solution for it..
what I want is to have an API independent texture class as base class something like this:
class CTexture {...};
class CTextureGL : public CTexture { ... };
class CTextureD3D : public CTexture { ... };
I would like to be able to have the texture as a Surface which I can render to, and depth maps.
the problems is the "binding" of the texture, I can't figure out how I can manage the binding of a texture..
I could do it by using a virtual bind function for the texture so it would be a call like this:
pTexture->Bind([some parameters like texcoordset]);
but I want to bind it like this:
pRenderCore->BindTexture( id, pTexture, pVertexBuffer->GetTexCoordSet(1) );
becouse that would fit my way of programming, altough I don't how I can store the OpenGL/D3D specefic stuff for that texture..
// base interfacestruct ITexture : public IBase { VIRTUAL bool Make(ImageData&) END_VIRTUAL; VIRTUAL void Bind(unsigned int stage) END_VIRTUAL; VIRTUAL void UnBind(unsigned int stage) END_VIRTUAL;};bool IsPowerOfTwo(unsigned int w){ if (w==2||w==4||w==8||w==16||w==32||w==64||w==128|| w==256||w==512||w==1024||w==2048) { return true; } return false;}// openGLstruct IGL_Texture : public ITexture { /// ctor IGL_Texture(); /// dtor ~IGL_Texture(); void Bind(unsigned int stage); void UnBind(unsigned int stage); bool Make(ImageData&); /// the texture ID unsigned int m_ID;};void IGL_Texture::Bind(unsigned int stage){ glActiveTextureARB( GL_TEXTURE0_ARB + stage ); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,m_ID);}void IGL_Texture::UnBind(unsigned int stage){ glActiveTextureARB( GL_TEXTURE0_ARB + stage ); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);}bool IGL_Texture::Make(ImageData& img) { GLenum Format,IFormat; if(!IsPowerOfTwo(img.w)||!IsPowerOfTwo(img.h)) return false; switch(img.bpp) { case 3: case 24: img.bpp=3; Format=GL_RGB; IFormat=GL_RGB8; break; case 4: case 32: img.bpp=4; Format=GL_RGBA; IFormat=GL_RGBA8; break; default: break; } glPixelStorei (GL_UNPACK_ALIGNMENT, 1); /* set the current texture to the one just created */ glBindTexture (GL_TEXTURE_2D, m_ID); /* repeat the texture in both directions */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); /* use bi-linear filtering to smooth the texture nicely. */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);#if 1 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D,img.bpp,img.w,img.h,Format,GL_UNSIGNED_BYTE,img.pixels);#else glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D,0,IFormat,img.w,img.h,0,Format,GL_UNSIGNED_BYTE,img.pixels);#endif return true;}// DirectXstruct ID3D_Texture : public ITexture { /// ctor ID3D_Texture(); /// dtor ~ID3D_Texture(); void Bind(unsigned int stage); void UnBind(unsigned int stage); bool Make(ImageData&); /// A pointer to the D3D texture LPDIRECT3DTEXTURE9 m_TheTex;};ID3D_Texture::ID3D_Texture() { m_TheTex=0;}ID3D_Texture::~ID3D_Texture() { if(m_TheTex) m_TheTex->Release(); m_TheTex=0;}void ID3D_Texture::Bind(unsigned int stage){ if(m_TheTex) { g_pd3dDevice->SetTexture( stage, m_TheTex ); g_pd3dDevice->SetTextureStageState( stage, D3DTSS_COLOROP, D3DTOP_MODULATE ); g_pd3dDevice->SetTextureStageState( stage, D3DTSS_COLORARG1, D3DTA_TEXTURE ); g_pd3dDevice->SetTextureStageState( stage, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); g_pd3dDevice->SetTextureStageState( stage, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); }}void ID3D_Texture::UnBind(unsigned int stage){ g_pd3dDevice->SetTexture( stage, 0 );}// __________________________________________________________________________________________________// LoadTexture// calls filterdown which will trash _pBuffer as temp storage for mips//LPDIRECT3DTEXTURE9 CreateTexture2D(unsigned char* buffer, const unsigned int width, const unsigned int height,const unsigned int bpp){ DWORD *pBuffer = (DWORD *)buffer; LPDIRECT3DTEXTURE9 pTexture; HRESULT hr; unsigned int bpp_=bpp; unsigned char* ptemp=0; if(bpp==4 || bpp == 32) { // flip texture from RGBA to ARGB unsigned char* p = buffer; unsigned char* e = p + (width*height*4); for( ; p != e; p+=4 ) { unsigned char r = p[0]; unsigned char g = p[1]; unsigned char b = p[2]; unsigned char a = p[3]; p[0] = a; p[1] = r; p[2] = g; p[3] = b; } bpp_ = 4; hr = g_pd3dDevice->CreateTexture(width, height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL); } else if(bpp==3 || bpp == 24) { // flip texture from RGBA to ARGB unsigned char* p = new unsigned char[ width*height*4 ]; ptemp=p; unsigned char* pp = buffer; unsigned char* e = pp + (width*height*3); for( ; pp != e; pp += 3, p += 4 ) { unsigned char r = pp[0]; unsigned char g = pp[1]; unsigned char b = pp[2]; unsigned char a = 255; p[2] = r; p[1] = g; p[0] = b; p[3] = a; } bpp_ = 4; hr = g_pd3dDevice->CreateTexture(width, height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL); } if(FAILED(hr)) return 0; D3DLOCKED_RECT Lock; pTexture->LockRect(0,&Lock,NULL,0); memcpy(Lock.pBits,ptemp,width*4*height); pTexture->UnlockRect(0); delete [] ptemp; pTexture->GenerateMipSubLevels(); return pTexture;}bool ID3D_Texture::Make(ImageData& img) { if(!IsPowerOfTwo(img.w)||!IsPowerOfTwo(img.h)) return false; if(m_TheTex) { m_TheTex->Release(); m_TheTex=0; } m_TheTex = CreateTexture2D(img.pixels,img.w,img.h,img.bpp); return m_TheTex!=0;}
Quote:Original post by superpig
What data does each API need in order to bind the texture?
I create the texture by passing the following structure to the Make method.
struct ImageData {
unsigned char* pixels;
unsigned int w;
unsigned int h;
unsigned int bpp;
};
DX9 needs an LPDIRECT3DTEXTURE9 for the texture, openGL needs the texture object number. I keep those in the derived classes and just call the abstract bind method to run the API specific binding.
Overload it in the sub-class. For instance, some of the DX-based APIs that I use require the texture to set itself as the current texture. Therefore, I simply derive that into my base Texture class. Pretty easy, really. It's just a matter of putting an interface between your code and whatever API you're using.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement