// split out of png_encode to simplify resource cleanup and avoid // "dtor / setjmp interaction" warning. static Status png_encode_impl(Tex* t, png_structp png_ptr, png_infop info_ptr, DynArray* da) { const png_uint_32 w = (png_uint_32)t->w, h = (png_uint_32)t->h; const size_t pitch = w * t->bpp / 8; int colour_type; switch(t->flags & (TEX_GREY|TEX_ALPHA)) { case TEX_GREY|TEX_ALPHA: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case TEX_GREY: colour_type = PNG_COLOR_TYPE_GRAY; break; case TEX_ALPHA: colour_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: colour_type = PNG_COLOR_TYPE_RGB; break; } png_set_write_fn(png_ptr, da, io_write, io_flush); png_set_IHDR(png_ptr, info_ptr, w, h, 8, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); u8* data = tex_get_data(t); std::vector<RowPtr> rows = tex_codec_alloc_rows(data, h, pitch, t->flags, TEX_TOP_DOWN); // PNG is native RGB. const int png_transforms = (t->flags & TEX_BGR)? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY; png_set_rows(png_ptr, info_ptr, (png_bytepp)&rows[0]); png_write_png(png_ptr, info_ptr, png_transforms, 0); return INFO::OK; }
/////////////////////////////////////////////////////////////////// // Load all sky textures void SkyManager::LoadSkyTextures() { for (size_t i = 0; i < ARRAY_SIZE(m_SkyTexture); ++i) { VfsPath path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(s_imageNames[i])+L".dds"); CTextureProperties textureProps(path); textureProps.SetWrap(GL_CLAMP_TO_EDGE); CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps); texture->Prefetch(); m_SkyTexture[i] = texture; } glGenTextures(1, &m_SkyCubeMap); glBindTexture(GL_TEXTURE_CUBE_MAP, m_SkyCubeMap); int types[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y }; const wchar_t* images[numTextures+1] = { L"front", L"back", L"right", L"left", L"top", L"top" }; for (size_t i = 0; i < numTextures+1; ++i) { VfsPath path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(images[i])+L".dds"); shared_ptr<u8> file; size_t fileSize; g_VFS->LoadFile(path, file, fileSize); Tex tex; tex_decode(file, fileSize, &tex); tex_transform_to(&tex, (tex.flags | TEX_BOTTOM_UP | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS)); u8* data = tex_get_data(&tex); if (types[i] == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y || types[i] == GL_TEXTURE_CUBE_MAP_POSITIVE_Y) { std::vector<u8> rotated(tex.dataSize); for (size_t y = 0; y < tex.h; ++y) { for (size_t x = 0; x < tex.w; ++x) { size_t invx = y, invy = tex.w-x-1; rotated[(y*tex.w + x) * 4 + 0] = data[(invy*tex.w + invx) * 4 + 0]; rotated[(y*tex.w + x) * 4 + 1] = data[(invy*tex.w + invx) * 4 + 1]; rotated[(y*tex.w + x) * 4 + 2] = data[(invy*tex.w + invx) * 4 + 2]; rotated[(y*tex.w + x) * 4 + 3] = data[(invy*tex.w + invx) * 4 + 3]; } } glTexImage2D(types[i], 0, GL_RGB, tex.w, tex.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &rotated[0]); } else { glTexImage2D(types[i], 0, GL_RGB, tex.w, tex.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); } tex_free(&tex); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); }