Jump to content
  • Advertisement
Sign in to follow this  
McZ

OpenGL api independet base texture class

This topic is 4946 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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..

Share this post


Link to post
Share on other sites
Advertisement

// base interface
struct 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;
}

// openGL
struct 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;
}

// DirectX
struct 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;
}


Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!