PageRenderTime 63ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/newcode/src/com/prupe/mcpatcher/hd/FancyDial.java

https://bitbucket.org/prupe/mcpatcher
Java | 668 lines | 595 code | 67 blank | 6 comment | 122 complexity | 253dfd48c4ec66b673107d4f262d07ad MD5 | raw file
  1. package com.prupe.mcpatcher.hd;
  2. import com.prupe.mcpatcher.Config;
  3. import com.prupe.mcpatcher.MCLogger;
  4. import com.prupe.mcpatcher.MCPatcherUtils;
  5. import com.prupe.mcpatcher.mal.resource.BlendMethod;
  6. import com.prupe.mcpatcher.mal.resource.GLAPI;
  7. import com.prupe.mcpatcher.mal.resource.PropertiesFile;
  8. import com.prupe.mcpatcher.mal.resource.TexturePackAPI;
  9. import com.prupe.mcpatcher.mal.tile.IconAPI;
  10. import com.prupe.mcpatcher.mal.util.InputHandler;
  11. import net.minecraft.src.*;
  12. import org.lwjgl.input.Keyboard;
  13. import org.lwjgl.opengl.*;
  14. import org.lwjgl.util.glu.GLU;
  15. import javax.imageio.ImageIO;
  16. import java.awt.image.BufferedImage;
  17. import java.io.File;
  18. import java.nio.ByteBuffer;
  19. import java.nio.IntBuffer;
  20. import java.util.*;
  21. public class FancyDial {
  22. private static final MCLogger logger = MCLogger.getLogger(MCPatcherUtils.CUSTOM_ANIMATIONS, "Animation");
  23. private static final double ANGLE_UNSET = Double.MAX_VALUE;
  24. private static final int NUM_SCRATCH_TEXTURES = 3;
  25. private static final boolean fboSupported = GLContext.getCapabilities().GL_EXT_framebuffer_object;
  26. private static final boolean gl13Supported = GLContext.getCapabilities().OpenGL13;
  27. private static final boolean enableCompass = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "fancyCompass", true);
  28. private static final boolean enableClock = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "fancyClock", true);
  29. private static final boolean useGL13 = gl13Supported && Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "useGL13", true);
  30. private static final boolean useScratchTexture = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "useScratchTexture", true);
  31. private static final int glAttributes;
  32. private static boolean initialized;
  33. private static boolean active;
  34. private static final int drawList = GL11.glGenLists(1);
  35. private static final Map<TextureAtlasSprite, ResourceLocation> setupInfo = new IdentityHashMap<TextureAtlasSprite, ResourceLocation>();
  36. private static final Map<TextureAtlasSprite, FancyDial> instances = new IdentityHashMap<TextureAtlasSprite, FancyDial>();
  37. private static int warnCount;
  38. private final TextureAtlasSprite icon;
  39. private final PropertiesFile properties;
  40. private final String name;
  41. private final int x0;
  42. private final int y0;
  43. private final int width;
  44. private final int height;
  45. private final ByteBuffer scratchBuffer;
  46. private final FBO[] scratchFBO = new FBO[NUM_SCRATCH_TEXTURES];
  47. private FBO itemsFBO;
  48. private int scratchIndex;
  49. private Map<Double, ByteBuffer> itemFrames = new TreeMap<Double, ByteBuffer>();
  50. private int outputFrames;
  51. private boolean ok;
  52. private double lastAngle = ANGLE_UNSET;
  53. private boolean lastItemFrameRenderer;
  54. private final List<Layer> layers = new ArrayList<Layer>();
  55. private InputHandler keyboard;
  56. private static final float STEP = 0.01f;
  57. private float scaleXDelta;
  58. private float scaleYDelta;
  59. private float offsetXDelta;
  60. private float offsetYDelta;
  61. static {
  62. logger.config("fbo: supported=%s", fboSupported);
  63. logger.config("GL13: supported=%s, enabled=%s", gl13Supported, useGL13);
  64. int bits = GL11.GL_VIEWPORT_BIT | GL11.GL_SCISSOR_BIT | GL11.GL_DEPTH_BITS | GL11.GL_LIGHTING_BIT;
  65. if (useGL13) {
  66. bits |= GL13.GL_MULTISAMPLE_BIT;
  67. }
  68. glAttributes = bits;
  69. GL11.glNewList(drawList, GL11.GL_COMPILE);
  70. drawBox();
  71. GL11.glEndList();
  72. }
  73. public static void setup(TextureAtlasSprite icon) {
  74. if (!fboSupported) {
  75. return;
  76. }
  77. String name = IconAPI.getIconName(icon).replaceFirst("^minecraft:items/", "");
  78. if (icon instanceof TextureClock && name.equals("compass")) { // 1.5 bug
  79. name = "clock";
  80. }
  81. if ("compass".equals(name)) {
  82. if (!enableCompass) {
  83. return;
  84. }
  85. } else if ("clock".equals(name)) {
  86. if (!enableClock) {
  87. return;
  88. }
  89. } else {
  90. logger.warning("ignoring custom animation for %s not compass or clock", name);
  91. return;
  92. }
  93. ResourceLocation resource = TexturePackAPI.newMCPatcherResourceLocation("/misc/" + name + ".properties", "dial/" + name + ".properties");
  94. if (TexturePackAPI.hasResource(resource)) {
  95. logger.fine("found custom %s (%s)", name, resource);
  96. setupInfo.put(icon, resource);
  97. active = true;
  98. }
  99. }
  100. public static boolean update(TextureAtlasSprite icon, boolean itemFrameRenderer) {
  101. if (!initialized) {
  102. logger.finer("deferring %s update until initialization finishes", IconAPI.getIconName(icon));
  103. return false;
  104. }
  105. if (!active) {
  106. return false;
  107. }
  108. int oldFB = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT);
  109. if (oldFB != 0 && warnCount < 10) {
  110. logger.finer("rendering %s while non-default framebuffer %d is active", IconAPI.getIconName(icon), oldFB);
  111. warnCount++;
  112. }
  113. int oldTexture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
  114. try {
  115. FancyDial instance = getInstance(icon);
  116. return instance != null && instance.render(itemFrameRenderer);
  117. } finally {
  118. EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFB);
  119. GLAPI.glBindTexture(oldTexture);
  120. }
  121. }
  122. static void clearAll() {
  123. logger.finer("FancyDial.clearAll");
  124. if (initialized) {
  125. active = false;
  126. setupInfo.clear();
  127. }
  128. for (FancyDial instance : instances.values()) {
  129. if (instance != null) {
  130. instance.finish();
  131. }
  132. }
  133. instances.clear();
  134. initialized = true;
  135. }
  136. static void registerAnimations() {
  137. TextureObject texture = TexturePackAPI.getTextureObject(TexturePackAPI.ITEMS_PNG);
  138. if (texture instanceof TextureAtlas) {
  139. List<TextureAtlasSprite> animations = ((TextureAtlas) texture).animations;
  140. for (FancyDial instance : instances.values()) {
  141. instance.registerAnimation(animations);
  142. }
  143. }
  144. }
  145. void registerAnimation(List<TextureAtlasSprite> animations) {
  146. if (animations.contains(icon)) {
  147. return;
  148. }
  149. animations.add(icon);
  150. if (icon.animationFrames == null) {
  151. icon.animationFrames = new ArrayList<int[]>();
  152. }
  153. if (icon.animationFrames.isEmpty()) {
  154. int[] dummyRGB = new int[width * height];
  155. Arrays.fill(dummyRGB, 0xffff00ff);
  156. icon.animationFrames.add(dummyRGB);
  157. }
  158. logger.fine("registered %s animation", name);
  159. }
  160. private static FancyDial getInstance(TextureAtlasSprite icon) {
  161. if (instances.containsKey(icon)) {
  162. return instances.get(icon);
  163. }
  164. ResourceLocation resource = setupInfo.remove(icon);
  165. instances.put(icon, null);
  166. if (resource == null) {
  167. return null;
  168. }
  169. PropertiesFile properties = PropertiesFile.get(logger, resource);
  170. if (properties == null) {
  171. return null;
  172. }
  173. try {
  174. FancyDial instance = new FancyDial(icon, properties);
  175. if (instance.ok) {
  176. instances.put(icon, instance);
  177. return instance;
  178. }
  179. instance.finish();
  180. } catch (Throwable e) {
  181. e.printStackTrace();
  182. }
  183. return null;
  184. }
  185. private FancyDial(TextureAtlasSprite icon, PropertiesFile properties) {
  186. this.icon = icon;
  187. this.properties = properties;
  188. name = IconAPI.getIconName(icon);
  189. x0 = IconAPI.getIconX0(icon);
  190. y0 = IconAPI.getIconY0(icon);
  191. width = IconAPI.getIconWidth(icon);
  192. height = IconAPI.getIconHeight(icon);
  193. scratchBuffer = ByteBuffer.allocateDirect(4 * width * height);
  194. int itemsTexture = TexturePackAPI.getTextureIfLoaded(TexturePackAPI.ITEMS_PNG);
  195. if (itemsTexture < 0) {
  196. logger.severe("could not get items texture");
  197. return;
  198. }
  199. itemsFBO = new FBO(itemsTexture, x0, y0, width, height);
  200. if (useScratchTexture) {
  201. logger.fine("rendering %s to %dx%d scratch texture", name, width, height);
  202. for (int i = 0; i < scratchFBO.length; i++) {
  203. scratchFBO[i] = new FBO(width, height);
  204. }
  205. } else {
  206. logger.fine("rendering %s directly to atlas", name);
  207. }
  208. boolean debug = false;
  209. for (int i = 0; ; i++) {
  210. Layer layer = newLayer(properties, "." + i);
  211. if (layer == null) {
  212. if (i > 0) {
  213. break;
  214. }
  215. continue;
  216. }
  217. layers.add(layer);
  218. debug |= layer.debug;
  219. logger.fine(" new %s", layer);
  220. }
  221. keyboard = new InputHandler(name, debug);
  222. if (layers.size() < 2) {
  223. logger.error("custom %s needs at least two layers defined", name);
  224. return;
  225. }
  226. outputFrames = properties.getInt("outputFrames", 0);
  227. int glError = GL11.glGetError();
  228. if (glError != 0) {
  229. logger.severe("%s during %s setup", GLU.gluErrorString(glError), name);
  230. return;
  231. }
  232. ok = true;
  233. }
  234. private boolean render(boolean itemFrameRenderer) {
  235. if (!ok) {
  236. return false;
  237. }
  238. if (!itemFrameRenderer) {
  239. boolean changed = true;
  240. if (!keyboard.isEnabled()) {
  241. changed = false;
  242. } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD2)) {
  243. scaleYDelta -= STEP;
  244. } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD8)) {
  245. scaleYDelta += STEP;
  246. } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD4)) {
  247. scaleXDelta -= STEP;
  248. } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD6)) {
  249. scaleXDelta += STEP;
  250. } else if (keyboard.isKeyPressed(Keyboard.KEY_DOWN)) {
  251. offsetYDelta += STEP;
  252. } else if (keyboard.isKeyPressed(Keyboard.KEY_UP)) {
  253. offsetYDelta -= STEP;
  254. } else if (keyboard.isKeyPressed(Keyboard.KEY_LEFT)) {
  255. offsetXDelta -= STEP;
  256. } else if (keyboard.isKeyPressed(Keyboard.KEY_RIGHT)) {
  257. offsetXDelta += STEP;
  258. } else if (keyboard.isKeyPressed(Keyboard.KEY_MULTIPLY)) {
  259. scaleXDelta = scaleYDelta = offsetXDelta = offsetYDelta = 0.0f;
  260. } else {
  261. changed = false;
  262. }
  263. if (changed) {
  264. logger.info("");
  265. logger.info("scaleX %+f", scaleXDelta);
  266. logger.info("scaleY %+f", scaleYDelta);
  267. logger.info("offsetX %+f", offsetXDelta);
  268. logger.info("offsetY %+f", offsetYDelta);
  269. lastAngle = ANGLE_UNSET;
  270. }
  271. if (outputFrames > 0) {
  272. writeCustomImage();
  273. outputFrames = 0;
  274. }
  275. }
  276. double angle = getAngle(icon);
  277. if (!useScratchTexture) {
  278. // render directly to items.png
  279. if (angle != lastAngle) {
  280. renderToItems(angle);
  281. lastAngle = angle;
  282. }
  283. } else if (itemFrameRenderer) {
  284. // look in itemFrames cache first
  285. ByteBuffer buffer = itemFrames.get(angle);
  286. if (buffer == null) {
  287. logger.fine("rendering %s at angle %f for item frame", name, angle);
  288. buffer = ByteBuffer.allocateDirect(width * height * 4);
  289. renderToItems(angle);
  290. itemsFBO.read(buffer);
  291. itemFrames.put(angle, buffer);
  292. } else {
  293. itemsFBO.write(buffer);
  294. }
  295. lastItemFrameRenderer = true;
  296. } else if (lastAngle == ANGLE_UNSET) {
  297. // first time rendering - render all N copies
  298. for (FBO fbo : scratchFBO) {
  299. renderToFB(angle, fbo);
  300. }
  301. scratchFBO[0].read(scratchBuffer);
  302. itemsFBO.write(scratchBuffer);
  303. lastAngle = angle;
  304. scratchIndex = 0;
  305. } else if (lastItemFrameRenderer || angle != lastAngle) {
  306. // render to buffer i + 1
  307. // update items.png from buffer i
  308. int nextIndex = (scratchIndex + 1) % NUM_SCRATCH_TEXTURES;
  309. if (angle != lastAngle) {
  310. renderToFB(angle, scratchFBO[nextIndex]);
  311. scratchFBO[scratchIndex].read(scratchBuffer);
  312. }
  313. itemsFBO.write(scratchBuffer);
  314. lastAngle = angle;
  315. scratchIndex = nextIndex;
  316. lastItemFrameRenderer = false;
  317. }
  318. int glError = GL11.glGetError();
  319. if (glError != 0) {
  320. logger.severe("%s during %s update", GLU.gluErrorString(glError), name);
  321. ok = false;
  322. }
  323. return ok;
  324. }
  325. private void writeCustomImage() {
  326. try {
  327. BufferedImage image = new BufferedImage(width, outputFrames * height, BufferedImage.TYPE_INT_ARGB);
  328. IntBuffer intBuffer = scratchBuffer.asIntBuffer();
  329. int[] argb = new int[width * height];
  330. File path = MCPatcherUtils.getGamePath("custom_" + name + ".png");
  331. logger.info("generating %d %s frames", outputFrames, name);
  332. for (int i = 0; i < outputFrames; i++) {
  333. renderToItems(i * (360.0 / outputFrames));
  334. itemsFBO.read(scratchBuffer);
  335. intBuffer.position(0);
  336. for (int j = 0; j < argb.length; j++) {
  337. switch (MipmapHelper.TEX_FORMAT) {
  338. case GL12.GL_BGRA:
  339. int bgra = intBuffer.get(j);
  340. argb[j] = (bgra << 24) |
  341. ((bgra & 0xff00) << 8) |
  342. ((bgra & 0xff0000) >> 8) |
  343. (bgra >>> 24);
  344. break;
  345. default:
  346. if (i == 0 && j == 0) {
  347. logger.warning("unhandled texture format %d, color channels may be incorrect", MipmapHelper.TEX_FORMAT);
  348. }
  349. // fall through
  350. case GL11.GL_RGBA:
  351. argb[j] = Integer.rotateRight(intBuffer.get(j), 8);
  352. break;
  353. }
  354. }
  355. image.setRGB(0, i * height, width, height, argb, 0, width);
  356. }
  357. ImageIO.write(image, "png", path);
  358. logger.info("wrote %dx%d %s", image.getWidth(), image.getHeight(), path.getPath());
  359. } catch (Throwable e) {
  360. e.printStackTrace();
  361. }
  362. }
  363. private void renderToItems(double angle) {
  364. renderToFB(angle, itemsFBO);
  365. }
  366. private void renderToFB(double angle, FBO fbo) {
  367. if (fbo != null) {
  368. fbo.bind();
  369. renderImpl(angle);
  370. fbo.unbind();
  371. }
  372. }
  373. private void renderImpl(double angle) {
  374. for (Layer layer : layers) {
  375. layer.blendMethod.applyBlending();
  376. GL11.glPushMatrix();
  377. TexturePackAPI.bindTexture(layer.textureName);
  378. float offsetX = layer.offsetX;
  379. float offsetY = layer.offsetY;
  380. float scaleX = layer.scaleX;
  381. float scaleY = layer.scaleY;
  382. if (layer.debug) {
  383. offsetX += offsetXDelta;
  384. offsetY += offsetYDelta;
  385. scaleX += scaleXDelta;
  386. scaleY += scaleYDelta;
  387. }
  388. GL11.glTranslatef(offsetX, offsetY, 0.0f);
  389. GL11.glScalef(scaleX, scaleY, 1.0f);
  390. float layerAngle = (float) (angle * layer.rotationMultiplier + layer.rotationOffset);
  391. GL11.glRotatef(layerAngle, 0.0f, 0.0f, 1.0f);
  392. GL11.glCallList(drawList);
  393. GL11.glPopMatrix();
  394. }
  395. }
  396. private static void drawBox() {
  397. GL11.glBegin(GL11.GL_QUADS);
  398. GL11.glTexCoord2f(0.0f, 0.0f);
  399. GL11.glVertex3f(-1.0f, -1.0f, 0.0f);
  400. GL11.glTexCoord2f(1.0f, 0.0f);
  401. GL11.glVertex3f(1.0f, -1.0f, 0.0f);
  402. GL11.glTexCoord2f(1.0f, 1.0f);
  403. GL11.glVertex3f(1.0f, 1.0f, 0.0f);
  404. GL11.glTexCoord2f(0.0f, 1.0f);
  405. GL11.glVertex3f(-1.0f, 1.0f, 0.0f);
  406. GL11.glEnd();
  407. }
  408. private void finish() {
  409. for (int i = 0; i < scratchFBO.length; i++) {
  410. if (scratchFBO[i] != null) {
  411. scratchFBO[i].delete();
  412. scratchFBO[i] = null;
  413. }
  414. }
  415. if (itemsFBO != null) {
  416. itemsFBO.delete();
  417. itemsFBO = null;
  418. }
  419. itemFrames.clear();
  420. layers.clear();
  421. ok = false;
  422. }
  423. @Override
  424. public String toString() {
  425. return String.format("FancyDial{%s, %dx%d @ %d,%d}", name, width, height, x0, y0);
  426. }
  427. @Override
  428. protected void finalize() throws Throwable {
  429. finish();
  430. super.finalize();
  431. }
  432. private static double getAngle(Icon icon) {
  433. if (icon instanceof TextureCompass) {
  434. return ((TextureCompass) icon).currentAngle * 180.0 / Math.PI;
  435. } else if (icon instanceof TextureClock) {
  436. return ((TextureClock) icon).currentAngle * 360.0;
  437. } else {
  438. return 0.0;
  439. }
  440. }
  441. Layer newLayer(PropertiesFile properties, String suffix) {
  442. ResourceLocation textureResource = properties.getResourceLocation("source" + suffix, "");
  443. if (textureResource == null) {
  444. return null;
  445. }
  446. if (!TexturePackAPI.hasResource(textureResource)) {
  447. properties.error("could not read %s", textureResource);
  448. return null;
  449. }
  450. float scaleX = properties.getFloat("scaleX" + suffix, 1.0f);
  451. float scaleY = properties.getFloat("scaleY" + suffix, 1.0f);
  452. float offsetX = properties.getFloat("offsetX" + suffix, 0.0f);
  453. float offsetY = properties.getFloat("offsetY" + suffix, 0.0f);
  454. float angleMultiplier = properties.getFloat("rotationSpeed" + suffix, 0.0f);
  455. float angleOffset = properties.getFloat("rotationOffset" + suffix, 0.0f);
  456. String blend = properties.getString("blend" + suffix, "alpha");
  457. BlendMethod blendMethod = BlendMethod.parse(blend);
  458. if (blendMethod == null) {
  459. properties.error("unknown blend method %s", blend);
  460. return null;
  461. }
  462. boolean debug = properties.getBoolean("debug" + suffix, false);
  463. return new Layer(textureResource, scaleX, scaleY, offsetX, offsetY, angleMultiplier, angleOffset, blendMethod, debug);
  464. }
  465. private class Layer {
  466. final ResourceLocation textureName;
  467. final float scaleX;
  468. final float scaleY;
  469. final float offsetX;
  470. final float offsetY;
  471. final float rotationMultiplier;
  472. final float rotationOffset;
  473. final BlendMethod blendMethod;
  474. final boolean debug;
  475. Layer(ResourceLocation textureName, float scaleX, float scaleY, float offsetX, float offsetY, float rotationMultiplier, float rotationOffset, BlendMethod blendMethod, boolean debug) {
  476. this.textureName = textureName;
  477. this.scaleX = scaleX;
  478. this.scaleY = scaleY;
  479. this.offsetX = offsetX;
  480. this.offsetY = offsetY;
  481. this.rotationMultiplier = rotationMultiplier;
  482. this.rotationOffset = rotationOffset;
  483. this.blendMethod = blendMethod;
  484. this.debug = debug;
  485. }
  486. @Override
  487. public String toString() {
  488. return String.format("Layer{%s %f %f %+f %+f x%f}", textureName, scaleX, scaleY, offsetX, offsetY, rotationMultiplier);
  489. }
  490. }
  491. private static class FBO {
  492. private final int texture;
  493. private final boolean ownTexture;
  494. private final int x0;
  495. private final int y0;
  496. private final int width;
  497. private final int height;
  498. private final int frameBuffer;
  499. private boolean lightmapEnabled;
  500. private boolean deleted;
  501. FBO(int width, int height) {
  502. this(blankTexture(width, height), true, 0, 0, width, height);
  503. }
  504. FBO(int texture, int x0, int y0, int width, int height) {
  505. this(texture, false, x0, y0, width, height);
  506. }
  507. private FBO(int texture, boolean ownTexture, int x0, int y0, int width, int height) {
  508. this.texture = texture;
  509. this.ownTexture = ownTexture;
  510. this.x0 = x0;
  511. this.y0 = y0;
  512. this.width = width;
  513. this.height = height;
  514. frameBuffer = EXTFramebufferObject.glGenFramebuffersEXT();
  515. if (frameBuffer < 0) {
  516. throw new RuntimeException("could not get framebuffer object");
  517. }
  518. GLAPI.glBindTexture(texture);
  519. EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
  520. EXTFramebufferObject.glFramebufferTexture2DEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT, GL11.GL_TEXTURE_2D, texture, 0);
  521. }
  522. void bind() {
  523. EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
  524. GL11.glPushAttrib(glAttributes);
  525. GL11.glViewport(x0, y0, width, height);
  526. GL11.glEnable(GL11.GL_SCISSOR_TEST);
  527. GL11.glScissor(x0, y0, width, height);
  528. lightmapEnabled = false;
  529. if (gl13Supported) {
  530. GL13.glActiveTexture(GL13.GL_TEXTURE1);
  531. lightmapEnabled = GL11.glIsEnabled(GL11.GL_TEXTURE_2D);
  532. if (lightmapEnabled) {
  533. GL11.glDisable(GL11.GL_TEXTURE_2D);
  534. }
  535. GL13.glActiveTexture(GL13.GL_TEXTURE0);
  536. }
  537. GL11.glEnable(GL11.GL_TEXTURE_2D);
  538. GL11.glDisable(GL11.GL_DEPTH_TEST);
  539. GLAPI.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  540. GL11.glDisable(GL11.GL_LIGHTING);
  541. GL11.glEnable(GL11.GL_ALPHA_TEST);
  542. GLAPI.glAlphaFunc(GL11.GL_GREATER, 0.01f);
  543. if (useGL13) {
  544. GL11.glDisable(GL13.GL_MULTISAMPLE);
  545. }
  546. GLAPI.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  547. GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
  548. GL11.glMatrixMode(GL11.GL_PROJECTION);
  549. GL11.glPushMatrix();
  550. GL11.glLoadIdentity();
  551. GL11.glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
  552. GL11.glMatrixMode(GL11.GL_MODELVIEW);
  553. GL11.glPushMatrix();
  554. GL11.glLoadIdentity();
  555. }
  556. void unbind() {
  557. GL11.glPopAttrib();
  558. GL11.glMatrixMode(GL11.GL_PROJECTION);
  559. GL11.glPopMatrix();
  560. GL11.glMatrixMode(GL11.GL_MODELVIEW);
  561. GL11.glPopMatrix();
  562. if (lightmapEnabled) {
  563. GL13.glActiveTexture(GL13.GL_TEXTURE1);
  564. GL11.glEnable(GL11.GL_TEXTURE_2D);
  565. GL13.glActiveTexture(GL13.GL_TEXTURE0);
  566. }
  567. GL11.glEnable(GL11.GL_BLEND);
  568. GLAPI.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
  569. EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
  570. }
  571. void read(ByteBuffer buffer) {
  572. EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer);
  573. buffer.position(0);
  574. GL11.glReadPixels(x0, y0, width, height, MipmapHelper.TEX_FORMAT, MipmapHelper.TEX_DATA_TYPE, buffer);
  575. }
  576. void write(ByteBuffer buffer) {
  577. GLAPI.glBindTexture(texture);
  578. buffer.position(0);
  579. GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, x0, y0, width, height, MipmapHelper.TEX_FORMAT, MipmapHelper.TEX_DATA_TYPE, buffer);
  580. }
  581. void delete() {
  582. if (!deleted) {
  583. deleted = true;
  584. if (ownTexture) {
  585. GL11.glDeleteTextures(texture);
  586. }
  587. EXTFramebufferObject.glDeleteFramebuffersEXT(frameBuffer);
  588. }
  589. }
  590. @Override
  591. protected void finalize() throws Throwable {
  592. delete();
  593. super.finalize();
  594. }
  595. private static int blankTexture(int width, int height) {
  596. int texture = GL11.glGenTextures();
  597. MipmapHelper.setupTexture(texture, width, height, "scratch");
  598. return texture;
  599. }
  600. }
  601. }