texture.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <X11/X.h>
  6. #include <X11/Xlib.h>
  7. #include <GL/glew.h>
  8. #include <GL/glx.h>
  9. #include <GL/glu.h>
  10. #include "utilities.h"
  11. #include "texture.h"
  12. #include <png.h>
  13. #include <setjmp.h>
  14. Texture* loadDataTexture(unsigned char* data, short width, short height) {
  15. Texture* dt;
  16. dt = (Texture*)malloc(sizeof(Texture));
  17. dt->width = width;
  18. dt->height = height;
  19. glEnable(GL_TEXTURE_2D);
  20. glGenTextures(1, &dt->tex_id);
  21. glBindTexture(GL_TEXTURE_2D, dt->tex_id);
  22. glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
  23. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  24. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  25. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  26. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  27. //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  28. // squash the data in
  29. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  30. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  31. glTexImage2D(GL_TEXTURE_2D, // target
  32. 0, // level, 0 = base, no minimap,
  33. GL_RED, // internalformat
  34. width,
  35. height,
  36. 0, // border
  37. GL_RGBA, // format
  38. GL_UNSIGNED_BYTE, // input type
  39. data);
  40. glBindTexture(GL_TEXTURE_2D, 0);
  41. return dt;
  42. }
  43. BitmapRGBA8* readPNG(char* path) {
  44. int ret;
  45. BitmapRGBA8* b = (BitmapRGBA8*)calloc(sizeof(BitmapRGBA8), 1);
  46. if(!b) return NULL;
  47. ret = readPNG2(path, b);
  48. if(ret) {
  49. if(b->data) free(b->data);
  50. free(b);
  51. return NULL;
  52. }
  53. return b;
  54. }
  55. int readPNG2(char* path, BitmapRGBA8* bmp) {
  56. FILE* f;
  57. png_byte sig[8];
  58. png_bytep* rowPtrs;
  59. int i;
  60. png_byte colorType;
  61. f = fopen(path, "rb");
  62. if(!f) {
  63. fprintf(stderr, "Could not open \"%s\" (readPNG).\n", path);
  64. return 1;
  65. }
  66. fread(sig, 1, 8, f);
  67. if(png_sig_cmp(sig, 0, 8)) {
  68. fprintf(stderr, "\"%s\" is not a valid PNG file.\n", path);
  69. fclose(f);
  70. return 1;
  71. }
  72. png_structp readStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  73. if (!readStruct) {
  74. fprintf(stderr, "Failed to load \"%s\". readPNG Error 1.\n", path);
  75. fclose(f);
  76. return 1;
  77. }
  78. png_infop infoStruct = png_create_info_struct(readStruct);
  79. if (!infoStruct) {
  80. fprintf(stderr, "Failed to load \"%s\". readPNG Error 2.\n", path);
  81. png_destroy_read_struct(&readStruct, (png_infopp)0, (png_infopp)0);
  82. fclose(f);
  83. return 1;
  84. };
  85. bmp->path = path;
  86. // exceptions are evil. the alternative with libPNG is a bit worse. ever heard of return codes libPNG devs?
  87. if (setjmp(png_jmpbuf(readStruct))) {
  88. fprintf(stderr, "Failed to load \"%s\". readPNG Error 3.\n", path);
  89. png_destroy_read_struct(&readStruct, (png_infopp)0, (png_infopp)0);
  90. if(bmp->data) free(bmp->data);
  91. free(bmp);
  92. fclose(f);
  93. return 1;
  94. }
  95. png_init_io(readStruct, f);
  96. png_set_sig_bytes(readStruct, 8);
  97. png_read_info(readStruct, infoStruct);
  98. bmp->width = png_get_image_width(readStruct, infoStruct);
  99. bmp->height = png_get_image_height(readStruct, infoStruct);
  100. colorType = png_get_color_type(readStruct, infoStruct);
  101. if (colorType == PNG_COLOR_TYPE_RGB) {
  102. png_set_add_alpha(readStruct, 0xff, PNG_FILLER_AFTER);
  103. }
  104. png_read_update_info(readStruct, infoStruct);
  105. bmp->data = (uint32_t*)malloc(bmp->width * bmp->height * sizeof(uint32_t));
  106. rowPtrs = (png_bytep*)malloc(sizeof(png_bytep) * bmp->height);
  107. for(i = 0; i < bmp->height; i++) {
  108. rowPtrs[i] = (png_bytep)(bmp->data + (bmp->width * i));
  109. }
  110. png_read_image(readStruct, rowPtrs);
  111. free(rowPtrs);
  112. png_destroy_read_struct(&readStruct, (png_infopp)0, (png_infopp)0);
  113. fclose(f);
  114. printf("Loaded \"%s\".\n", path);
  115. return 0;
  116. }
  117. Texture* loadBitmapTexture(char* path) {
  118. BitmapRGBA8* png;
  119. png = readPNG(path);
  120. if(!png) {
  121. fprintf(stderr, "could not load texture %s \n", path);
  122. return NULL;
  123. }
  124. Texture* dt;
  125. dt = (Texture*)malloc(sizeof(Texture));
  126. dt->width = png->width;
  127. dt->height = png->height;
  128. glGenTextures(1, &dt->tex_id);
  129. glActiveTexture(GL_TEXTURE0);
  130. glBindTexture(GL_TEXTURE_2D, dt->tex_id);
  131. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  132. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  133. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  134. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  135. // squash the data in
  136. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  137. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  138. glTexImage2D(GL_TEXTURE_2D, // target
  139. 0, // level, 0 = base, no minimap,
  140. GL_RGBA8, // internalformat
  141. png->width,
  142. png->height,
  143. 0, // border
  144. GL_RGBA, // format
  145. GL_UNSIGNED_BYTE, // input type
  146. png->data);
  147. glGenerateMipmap(GL_TEXTURE_2D);
  148. glBindTexture(GL_TEXTURE_2D, 0);
  149. glexit("failed to load texture");
  150. return dt;
  151. }
  152. // actually, the argument is a void**, but the compiler complains. stupid standards...
  153. size_t ptrlen(const void* a) {
  154. size_t i = 0;
  155. void** b = (void**)a;
  156. while(*b++) i++;
  157. return i;
  158. }
  159. TexArray* loadTexArray(char** files) {
  160. TexArray* ta;
  161. int len, i;
  162. char* source, *s;
  163. BitmapRGBA8** bmps;
  164. int w, h;
  165. len = ptrlen(files);
  166. bmps = malloc(sizeof(BitmapRGBA8*) * len);
  167. ta = calloc(sizeof(TexArray), 1);
  168. w = 0;
  169. h = 0;
  170. for(i = 0; i < len; i++) {
  171. bmps[i] = readPNG(files[i]);
  172. if(!bmps[1]) {
  173. printf("Failed to load %s\n", files[i]);
  174. continue;
  175. }
  176. w = MAX(w, bmps[i]->width);
  177. h = MAX(h, bmps[i]->height);
  178. }
  179. ta->width = w;
  180. ta->height = h;
  181. ta->depth = len;
  182. printf("len: %d\n", len);
  183. glGenTextures(1, &ta->tex_id);
  184. glBindTexture(GL_TEXTURE_2D, 0);
  185. glBindTexture(GL_TEXTURE_2D_ARRAY, ta->tex_id);
  186. glexit("failed to create texture array 1");
  187. // glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_GENERATE_MIPMAP, GL_FALSE);
  188. glexit("failed to create texture array 2");
  189. glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  190. glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  191. glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  192. glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  193. glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  194. glexit("failed to create texture array 3");
  195. // squash the data in
  196. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  197. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  198. glTexStorage3D(GL_TEXTURE_2D_ARRAY,
  199. 1, // mips, flat
  200. GL_RGBA8,
  201. w, h,
  202. len); // layers
  203. glexit("failed to create texture array 4");
  204. for(i = 0; i < len; i++) {
  205. if(!bmps[i]) continue;
  206. glTexSubImage3D(GL_TEXTURE_2D_ARRAY, // target
  207. 0, // mip level, 0 = base, no mipmap,
  208. 0, 0, i,// offset
  209. w, h,
  210. 1,
  211. GL_RGBA, // format
  212. GL_UNSIGNED_BYTE, // input type
  213. bmps[i]->data);
  214. glexit("could not load tex array slice");
  215. free(bmps[i]->data);
  216. free(bmps[i]);
  217. }
  218. free(bmps);
  219. return ta;
  220. }
  221. void Texture_Release(Texture* t) {
  222. printf("NYI: Texture_Release(), %s:%d\n", __FILE__, __LINE__);
  223. }