我正在嘗試爲iOS編寫一個小型的,便攜式的2D引擎來學習C++和OpenGL。現在我正在嘗試顯示已加載的紋理。使用CoreGraphic庫加載時,我已成功顯示紋理,但現在我試圖使用fread和libpng在C++中加載文件,並且我看到的只是一個白色的盒子。使用C++在OpenGL ES中顯示紋理故障
我的紋理是64x64,所以它不是2問題的力量。我也啓用了GL_TEXTURE_2D。
第一塊代碼用於加載png,將png轉換爲圖像數據,並將數據加載到OpenGL中。
void AssetManager::loadImage(const std::string &filename)
{
Texture texture(filename);
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_bytep *row_pointers = NULL;
int bitDepth, colourType;
FILE *pngFile = fopen(std::string(Game::environmentData.basePath + "/" + filename).c_str(), "rb");
if(!pngFile)
return;
png_byte sig[8];
fread(&sig, 8, sizeof(png_byte), pngFile);
rewind(pngFile);//so when we init io it won't bitch
if(!png_check_sig(sig, 8))
return;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
if(!png_ptr)
return;
if(setjmp(png_jmpbuf(png_ptr)))
return;
info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr)
return;
png_init_io(png_ptr, pngFile);
png_read_info(png_ptr, info_ptr);
bitDepth = png_get_bit_depth(png_ptr, info_ptr);
colourType = png_get_color_type(png_ptr, info_ptr);
if(colourType == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
/*if(colourType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)
png_set_gray_1_2_4_to_8(png_ptr);*/
if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
if(bitDepth == 16)
png_set_strip_16(png_ptr);
else if(bitDepth < 8)
png_set_packing(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &texture.width, &texture.height,
&bitDepth, &colourType, NULL, NULL, NULL);
int components = GetTextureInfo(colourType);
if(components == -1)
{
if(png_ptr)
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return;
}
GLubyte *pixels = (GLubyte *)malloc(sizeof(GLubyte) * (texture.width * texture.height * components));
row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * texture.height);
for(int i = 0; i < texture.height; ++i)
row_pointers[i] = (png_bytep)(pixels + (i * texture.width * components));
png_read_image(png_ptr, row_pointers);
png_read_end(png_ptr, NULL);
// make it
glGenTextures(1, &texture.name);
// bind it
glBindTexture(GL_TEXTURE_2D, texture.name);
GLuint glcolours;
switch (components) {
case 1:
glcolours = GL_LUMINANCE;
break;
case 2:
glcolours = GL_LUMINANCE_ALPHA;
break;
case 3:
glcolours = GL_RGB;
break;
case 4:
glcolours = GL_RGBA;
break;
}
glTexImage2D(GL_TEXTURE_2D, 0, components, texture.width, texture.height, 0, glcolours, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(pngFile);
free(row_pointers);
free(pixels);
textures.push_back(texture);
}
這裏是我的紋理類的代碼:
class Texture
{
public:
Texture(const std::string &filename) { this->filename = filename; }
unsigned int name;
unsigned int size;
unsigned int width;
unsigned int height;
std::string filename;
};
這裏是我安裝我的看法如何:
void Renderer::Setup(Rectangle rect, CameraType cameraType)
{
_viewRect = rect;
glViewport(0,0,_viewRect.width,_viewRect.height);
if(cameraType == Renderer::Orthographic)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(_viewRect.x,_viewRect.width,_viewRect.y,_viewRect.height,kZNear,kZFar);
glMatrixMode(GL_MODELVIEW);
}
else
{
GLfloat size = kZNear * tanf(DegreesToRadians(kFieldOfView)/2.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustumf(-size, size, -size/(_viewRect.width/_viewRect.height), size/(_viewRect.width/_viewRect.height), kZNear, kZFar);
glMatrixMode(GL_MODELVIEW);
}
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE, GL_SRC_COLOR);
glEnable(GL_BLEND);
}
現在,這裏是我畫的質地:
void Renderer::DrawTexture(int x, int y, Texture &texture)
{
GLfloat vertices[] = {
x, _viewRect.height - y, 0.0,
x, _viewRect.height - (y + texture.height), 0.0,
x + texture.width, _viewRect.height - y, 0.0,
x + texture.width, _viewRect.height - (y + texture.height), 0.0
};
static const GLfloat normals[] = {
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0
};
GLfloat texCoords[] = {
0.0, 1.0,
0.0, 0.0,
1.0, 1.0,
1.0, 0.0
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.0);
glBindTexture(GL_TEXTURE_2D, texture.name);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glNormalPointer(GL_FLOAT, 0, normals);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
U PDATE:
我改變了我用來生成紋理的功能。它現在創建一個隨機測試紋理。無論如何,我仍然看到一個白色的質地。要繼續挖掘我如何renderering。
這裏的新功能:
void AssetManager::CreateNoisyTexture(const char * key)
{
Texture texture(key, 64, 64);
const unsigned int components = 4;
GLubyte *pixels = (GLubyte *)malloc(sizeof(GLubyte) * (texture.width * texture.height * components));
GLubyte *pitr1 = pixels;
GLubyte *pitr2 = pixels + (texture.width * texture.height * components);
while (pitr1 != pitr2) {
*pitr1 = rand() * 0xFF;
*(pitr1 + 1) = rand() * 0xFF;
*(pitr1 + 2) = rand() * 0xFF;
*(pitr1 + 3) = 0xFF;
pitr1 += 4;
}
glGenTextures(1, &texture.name);
glBindTexture(GL_TEXTURE_2D, texture.name);
glTexImage2D(GL_TEXTURE_2D, 0, components, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
free(pixels);
printf("Created texture with key: %s name: %d", texture.key, texture.name);
textures.push_back(texture);
}
您確定PNG解壓縮工作正常嗎?我會先在內存中生成一個RGBA紋理,然後嘗試先使用它。一些簡單的像半紅和半綠色的工作。它應該有助於縮小問題所在。 – IronMensan
幾個nits:'Texture'的'name'成員應該是'GLuint',而不是'unsigned int'。你可以將'GL_TEXTURE_MIN_FILTER'設置爲'GL_LINEAR',因爲之後立即將它改爲'GL_NEAREST'。 – IronMensan
感謝您的反饋!今晚我會給你一個鏡頭,讓你知道。 – Meroon