#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib, "glew32.lib")
#include <GL/glew.h>
#include <GL/freeglut/freeglut.h>
#include <string>
#define WIDTH 320
#define HEIGHT 240
//各種構造体
typedef struct _DDPixelFormat
{
GLuint size;
GLuint flgas;
GLuint fourCC;
GLuint bpp;
GLuint redMask;
GLuint greenMask;
GLuint blueMask;
GLuint alphaMask;
} DDPixelFormat;
typedef struct _DDSCaps
{
GLuint caps;
GLuint caps2;
GLuint caps3;
GLuint caps4;
} DDSCaps;
typedef struct _DDColorKey
{
GLuint lowVal;
GLuint highVal;
} DDColorKey;
typedef struct _DDSurfaceDesc
{
GLuint size;
GLuint flags;
GLuint height;
GLuint width;
GLuint pitch;
GLuint depth;
GLuint mipMapLevels;
GLuint alphaBitDepth;
GLuint reserved;
GLuint surface;
DDColorKey ckDestOverlay;
DDColorKey ckDestBlt;
DDColorKey ckSrcOverlay;
DDColorKey ckSrcBlt;
DDPixelFormat format;
DDSCaps caps;
GLuint textureStage;
} DDSurfaceDesc;
//DDSクラス
class DDSImage
{
protected:
GLenum format;
GLuint internalFormat;
GLuint bpp;
GLuint numMipmaps;
public:
GLuint ID;
GLuint imageSize;
GLubyte *imageData;
GLuint width;
GLuint height;
DDSImage();
~DDSImage();
void DecompressDDS();
bool ReadDDS(const char *filename);
GLuint Load(const char *filename);
};
//コンストラクタ
DDSImage::DDSImage()
{
imageSize = 0;
imageData = NULL;
format = GL_RGB;
internalFormat = GL_RGB;
width = 0;
height = 0;
bpp = 0;
ID = 0;
numMipmaps = 0;
}
//デストラクタ
DDSImage::~DDSImage()
{
if ( imageData )
{
delete [] imageData;
imageData = NULL;
}
}
//DDSファイルの読み込み
bool DDSImage::ReadDDS(const char *filename)
{
FILE *fp;
char magic[4];
int mipmapFactor;
long curr, end;
DDSurfaceDesc ddsd;
// ファイルを開く
fp = fopen(filename, "rb");
if ( !fp )
{
printf("ファイルを開けませんでした\n");
return false;
}
// マジックを読み取り
fread(&magic, sizeof(char), 4, fp);
// マジックをチェック
if ( strncmp(magic, "DDS ", 4 ) != 0 )
{
printf("DDSファイルではありません\n");
fclose(fp);
return false;
}
// ヘッダーを読み取り
fread(&ddsd, sizeof(ddsd), 1, fp);
// 幅・高さを格納
height = ddsd.height;
width = ddsd.width;
numMipmaps = ddsd.mipMapLevels;
// フォーマット判別
switch ( ddsd.format.fourCC )
{
case '1TXD':
// DXT1
format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
internalFormat = 3;
mipmapFactor = 2;
break;
case '3TXD':
// DXT3
format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
internalFormat = 4;
mipmapFactor = 4;
break;
case '5TXD':
// DXT5
format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
internalFormat = 4;
mipmapFactor = 4;
break;
default:
printf("未対応の形式です\n");
return false;
}
// テクセルデータのサイズを算出
curr = ftell(fp);
fseek(fp, 0, SEEK_END);
end = ftell(fp);
fseek(fp, curr, SEEK_SET);
imageSize = end - curr;
imageData = new GLubyte [imageSize];
// ピクセルデータの読み込み
fread(imageData, sizeof(GLubyte), imageSize, fp);
// ファイルを閉じる
fclose(fp);
return true;
}
//S3TC圧縮の解凍作業
void DDSImage::DecompressDDS()
{
int blockSize;
int offset = 0;
GLsizei mWidth = width, mHeight = height, mSize = 0;
// DXT1
if ( format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
blockSize = 8;
// DXT3, DXT5
else
blockSize = 16;
// 解凍
for ( int i=0; i<(int)numMipmaps; i++ )
{
mSize = ( (mWidth+3)/4 ) * ( (mHeight+3)/4 ) * blockSize;
glCompressedTexImage2D(GL_TEXTURE_2D, i, format, mWidth, mHeight, 0,
mSize, imageData + offset );
if ( mWidth >> 1 ) mWidth = (mWidth >> 1);
else mWidth = 1;
if ( mHeight >> 1 ) mHeight = (mHeight >> 1);
else mHeight = 1;
offset += mSize;
}
}
//DDSファイルを読み込み,テクスチャを生成する
GLuint DDSImage::Load(const char *filename)
{
// ファイルの読み込み
if ( !ReadDDS(filename) )
return 0;
// テクスチャを生成
glGenTextures(1, &ID);
// テクスチャをバインド
glBindTexture(GL_TEXTURE_2D, ID);
// 拡大・縮小する方法の指定
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
// テクスチャ環境の設定
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// 解凍作業
DecompressDDS();
if ( imageData )
{
delete [] imageData;
imageData = NULL;
}
glBindTexture(GL_TEXTURE_2D, 0);
// 生成したテクスチャ番号を返す
return ID;
}
DDSImage texture;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0.0, WIDTH, HEIGHT, 0.0, -1.0, 1.0);
glEnable(GL_TEXTURE_2D);//テクスチャ有効
glBindTexture(GL_TEXTURE_2D, texture.ID);
glEnable(GL_ALPHA_TEST);//アルファテスト開始
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 1.0f); glVertex2d(10 , 230);//左下
glTexCoord2f(0.0f, 0.0f); glVertex2d(10 , 10);//左上
glTexCoord2f(1.0f, 0.0f); glVertex2d( 310 , 10);//右上
glTexCoord2f(1.0f, 1.0f); glVertex2d( 310 , 230);//右下
glEnd();
glDisable(GL_ALPHA_TEST);//アルファテスト終了
glDisable(GL_TEXTURE_2D);//テクスチャ無効
glutSwapBuffers();
}
void idle(void)
{
glutPostRedisplay();
}
void Init(){
//GLEWの初期化
if(glewInit() != GLEW_OK)printf("GLEWの初期化に失敗しました\n");
glClearColor(0.0, 0.0, 0.0, 1.0);
glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);
texture.Load("sample.dds");
}
int main(int argc, char *argv[])
{
glutInitWindowPosition(100, 100);
glutInitWindowSize(WIDTH, HEIGHT);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("画像を読み込んで表示");
glutDisplayFunc(display);
glutIdleFunc(idle);
Init();
glutMainLoop();
return 0;
}
|