PageRenderTime 41ms CodeModel.GetById 24ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/newcode/src/com/prupe/mcpatcher/ctm/RenderPass.java

https://bitbucket.org/SevenBits/mcpatcher
Java | 342 lines | 297 code | 42 blank | 3 comment | 58 complexity | 9e8b87acd88985c480dd581b59b609d8 MD5 | raw file
  1package com.prupe.mcpatcher.ctm;
  2
  3import com.prupe.mcpatcher.*;
  4import com.prupe.mcpatcher.mal.block.BlockAPI;
  5import com.prupe.mcpatcher.mal.block.RenderPassAPI;
  6import net.minecraft.src.*;
  7import org.lwjgl.opengl.GL11;
  8
  9import java.util.*;
 10
 11public class RenderPass {
 12    private static final MCLogger logger = MCLogger.getLogger(MCPatcherUtils.BETTER_GLASS);
 13
 14    private static final ResourceLocation RENDERPASS_PROPERTIES = TexturePackAPI.newMCPatcherResourceLocation("renderpass.properties");
 15
 16    private static final Map<Block, Integer> baseRenderPass = new IdentityHashMap<Block, Integer>();
 17    private static final Map<Block, Integer> extraRenderPass = new IdentityHashMap<Block, Integer>();
 18    private static final Map<Block, Integer> renderPassBits = new IdentityHashMap<Block, Integer>();
 19    private static final Set<Block> customRenderPassBlocks = new HashSet<Block>();
 20
 21    private static BlendMethod blendMethod;
 22    private static ResourceLocation blendBlankResource;
 23    private static boolean enableLightmap;
 24    private static boolean enableColormap;
 25    private static final boolean[] backfaceCulling = new boolean[RenderPassAPI.NUM_RENDER_PASSES];
 26
 27    private static int currentRenderPass = -1;
 28    private static int maxRenderPass = 1;
 29    private static boolean canRenderInThisPass;
 30    private static boolean hasCustomRenderPasses;
 31    private static boolean ambientOcclusion;
 32
 33    private static final int COLOR_POS_0 = 3;
 34    private static final int COLOR_POS_1 = COLOR_POS_0 + 7;
 35    private static final int COLOR_POS_2 = COLOR_POS_1 + 7;
 36    private static final int COLOR_POS_3 = COLOR_POS_2 + 7;
 37
 38    private static int saveColor0;
 39    private static int saveColor1;
 40    private static int saveColor2;
 41    private static int saveColor3;
 42
 43    static {
 44        RenderPassAPI.instance = new RenderPassAPI() {
 45            @Override
 46            public boolean skipDefaultRendering(Block block) {
 47                return currentRenderPass > MAX_BASE_RENDER_PASS;
 48            }
 49
 50            @Override
 51            public boolean skipThisRenderPass(Block block, int pass) {
 52                if (currentRenderPass < 0) {
 53                    return pass > MAX_BASE_RENDER_PASS;
 54                }
 55                if (pass < 0) {
 56                    pass = RenderPassMap.instance.getDefaultRenderPass(block);
 57                }
 58                return pass != currentRenderPass;
 59            }
 60
 61            @Override
 62            public boolean useColorMultiplierThisPass(Block block) {
 63                return currentRenderPass != OVERLAY_RENDER_PASS || enableColormap;
 64            }
 65
 66            @Override
 67            public boolean useLightmapThisPass() {
 68                return currentRenderPass != OVERLAY_RENDER_PASS || enableLightmap;
 69            }
 70
 71            @Override
 72            public void clear() {
 73                canRenderInThisPass = false;
 74                maxRenderPass = MAX_BASE_RENDER_PASS - 1;
 75                baseRenderPass.clear();
 76                extraRenderPass.clear();
 77                renderPassBits.clear();
 78                customRenderPassBlocks.clear();
 79
 80                blendMethod = BlendMethod.ALPHA;
 81                blendBlankResource = blendMethod.getBlankResource();
 82                if (blendBlankResource == null) {
 83                    blendBlankResource = BlendMethod.ALPHA.getBlankResource();
 84                }
 85                enableLightmap = true;
 86                enableColormap = false;
 87                Arrays.fill(backfaceCulling, true);
 88                backfaceCulling[RenderPassAPI.BACKFACE_RENDER_PASS] = false;
 89
 90                for (Block block : BlockAPI.getAllBlocks()) {
 91                    baseRenderPass.put(block, RenderPassMap.instance.getDefaultRenderPass(block));
 92                }
 93            }
 94
 95            @Override
 96            public void refreshBlendingOptions() {
 97                Properties properties = TexturePackAPI.getProperties(RENDERPASS_PROPERTIES);
 98                if (properties != null) {
 99                    properties = remapProperties(properties);
100                    String method = properties.getProperty("blend.overlay", "alpha").trim().toLowerCase();
101                    blendMethod = BlendMethod.parse(method);
102                    if (blendMethod == null) {
103                        logger.error("%s: unknown blend method '%s'", RENDERPASS_PROPERTIES, method);
104                        blendMethod = BlendMethod.ALPHA;
105                    }
106                    blendBlankResource = blendMethod.getBlankResource();
107                    if (blendBlankResource == null) {
108                        blendBlankResource = BlendMethod.ALPHA.getBlankResource();
109                    }
110                    enableLightmap = MCPatcherUtils.getBooleanProperty(properties, "enableLightmap.overlay", !blendMethod.isColorBased());
111                    enableColormap = MCPatcherUtils.getBooleanProperty(properties, "enableColormap.overlay", false);
112                    backfaceCulling[RenderPassAPI.OVERLAY_RENDER_PASS] = MCPatcherUtils.getBooleanProperty(properties, "backfaceCulling.overlay", true);
113                    backfaceCulling[RenderPassAPI.CUTOUT_RENDER_PASS] = backfaceCulling[RenderPassMap.instance.getCutoutRenderPass()] = MCPatcherUtils.getBooleanProperty(properties, "backfaceCulling.cutout", true);
114                    backfaceCulling[RenderPassAPI.CUTOUT_MIPPED_RENDER_PASS] = MCPatcherUtils.getBooleanProperty(properties, "backfaceCulling.cutout_mipped", backfaceCulling[RenderPassAPI.CUTOUT_RENDER_PASS]);
115                    backfaceCulling[RenderPassAPI.TRANSLUCENT_RENDER_PASS] = MCPatcherUtils.getBooleanProperty(properties, "backfaceCulling.translucent", true);
116                }
117            }
118
119            private Properties remapProperties(Properties properties) {
120                Properties newProperties = new Properties();
121                for (Map.Entry<Object, Object> entry : properties.entrySet()) {
122                    String key = (String) entry.getKey();
123                    key = key.replaceFirst("\\.3$", ".overlay");
124                    key = key.replaceFirst("\\.2$", ".backface");
125                    if (!key.equals(entry.getKey())) {
126                        logger.warning("%s: %s is deprecated in 1.8.  Use %s instead", RENDERPASS_PROPERTIES, entry.getKey(), key);
127                    }
128                    newProperties.put(key, entry.getValue());
129                }
130                return newProperties;
131            }
132
133            @Override
134            public void setRenderPassForBlock(Block block, int pass) {
135                if (block == null || pass < 0) {
136                    return;
137                }
138                String name;
139                if (pass <= MAX_BASE_RENDER_PASS) {
140                    baseRenderPass.put(block, pass);
141                    name = "base";
142                } else {
143                    extraRenderPass.put(block, pass);
144                    name = "extra";
145                }
146                logger.fine("%s %s render pass -> %s",
147                    BlockAPI.getBlockName(block), name, RenderPassAPI.instance.getRenderPassName(pass)
148                );
149                customRenderPassBlocks.add(block);
150                maxRenderPass = Math.max(maxRenderPass, pass);
151            }
152
153            @Override
154            public ResourceLocation getBlankResource(int pass) {
155                return pass == OVERLAY_RENDER_PASS ? blendBlankResource : super.getBlankResource(pass);
156            }
157
158            @Override
159            public ResourceLocation getBlankResource() {
160                return getBlankResource(currentRenderPass);
161            }
162        };
163
164        TexturePackChangeHandler.register(new TexturePackChangeHandler(MCPatcherUtils.BETTER_GLASS, 4) {
165            @Override
166            public void beforeChange() {
167            }
168
169            @Override
170            public void afterChange() {
171                for (Block block : BlockAPI.getAllBlocks()) {
172                    int bits = 0;
173                    Integer i = baseRenderPass.get(block);
174                    if (i != null && i >= 0) {
175                        bits |= (1 << i);
176                    }
177                    i = extraRenderPass.get(block);
178                    if (i != null && i >= 0) {
179                        bits |= (1 << i);
180                    }
181                    renderPassBits.put(block, bits);
182                }
183            }
184        });
185    }
186
187    public static void start(int pass) {
188        currentRenderPass = RenderPassMap.instance.vanillaToMCPatcher(pass);
189        CTMUtils.setBlankResource();
190    }
191
192    public static void finish() {
193        currentRenderPass = -1;
194        CTMUtils.setBlankResource();
195    }
196
197    public static boolean skipAllRenderPasses(boolean[] skipRenderPass) {
198        return skipRenderPass[0] && skipRenderPass[1] && skipRenderPass[2] && skipRenderPass[3];
199    }
200
201    public static boolean checkRenderPasses(Block block, boolean moreRenderPasses) {
202        int bits = renderPassBits.get(block) >>> currentRenderPass;
203        canRenderInThisPass = (bits & 1) != 0;
204        hasCustomRenderPasses = customRenderPassBlocks.contains(block);
205        return moreRenderPasses || (bits >>> 1) != 0;
206    }
207
208    public static boolean canRenderInThisPass(boolean canRender) {
209        return hasCustomRenderPasses ? canRenderInThisPass : canRender;
210    }
211
212    // pre-14w02a
213    public static boolean shouldSideBeRendered(Block block, IBlockAccess blockAccess, int i, int j, int k, int face) {
214        if (BlockAPI.shouldSideBeRendered(block, blockAccess, i, j, k, face)) {
215            return true;
216        } else if (!extraRenderPass.containsKey(block)) {
217            Block neighbor = BlockAPI.getBlockAt(blockAccess, i, j, k);
218            return extraRenderPass.containsKey(neighbor);
219        } else {
220            return false;
221        }
222    }
223
224    // 14w02a+
225    public static boolean shouldSideBeRendered(Block block, IBlockAccess blockAccess, Position position, Direction direction) {
226        if (block.shouldSideBeRendered(blockAccess, position, direction)) {
227            return true;
228        } else if (!extraRenderPass.containsKey(block)) {
229            Block neighbor = blockAccess.getBlock(position);
230            return extraRenderPass.containsKey(neighbor);
231        } else {
232            return false;
233        }
234    }
235
236    public static boolean setAmbientOcclusion(boolean ambientOcclusion) {
237        RenderPass.ambientOcclusion = ambientOcclusion;
238        return ambientOcclusion;
239    }
240
241    public static float getAOBaseMultiplier(float multiplier) {
242        return RenderPassAPI.instance.useLightmapThisPass() ? multiplier : 1.0f;
243    }
244
245    public static boolean useBlockShading() {
246        return RenderPassAPI.instance.useLightmapThisPass();
247    }
248
249    // *sigh* Mojang removed the "unshaded" model face buffer in 14w11a, making this hack necessary again
250    public static void unshadeBuffer(int[] b) {
251        if (!useBlockShading()) {
252            saveColor0 = b[COLOR_POS_0];
253            saveColor1 = b[COLOR_POS_1];
254            saveColor2 = b[COLOR_POS_2];
255            saveColor3 = b[COLOR_POS_3];
256            b[COLOR_POS_0] = b[COLOR_POS_1] = b[COLOR_POS_2] = b[COLOR_POS_3] = -1;
257        }
258    }
259
260    public static void reshadeBuffer(int[] b) {
261        if (!useBlockShading()) {
262            b[COLOR_POS_0] = saveColor0;
263            b[COLOR_POS_1] = saveColor1;
264            b[COLOR_POS_2] = saveColor2;
265            b[COLOR_POS_3] = saveColor3;
266        }
267    }
268
269    public static boolean preRenderPass(int pass) {
270        currentRenderPass = pass;
271        if (pass > maxRenderPass) {
272            return false;
273        }
274        switch (pass) {
275            case RenderPassAPI.SOLID_RENDER_PASS:
276            case RenderPassAPI.CUTOUT_MIPPED_RENDER_PASS:
277            case RenderPassAPI.CUTOUT_RENDER_PASS:
278            case RenderPassAPI.TRANSLUCENT_RENDER_PASS:
279            case RenderPassAPI.BACKFACE_RENDER_PASS:
280                if (!backfaceCulling[pass]) {
281                    GL11.glDisable(GL11.GL_CULL_FACE);
282                }
283                break;
284
285            case RenderPassAPI.OVERLAY_RENDER_PASS:
286                GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
287                GL11.glPolygonOffset(-2.0f, -2.0f);
288                GL11.glEnable(GL11.GL_POLYGON_OFFSET_FILL);
289                if (backfaceCulling[pass]) {
290                    GL11.glEnable(GL11.GL_CULL_FACE);
291                } else {
292                    GL11.glDisable(GL11.GL_CULL_FACE);
293                }
294                if (ambientOcclusion) {
295                    GL11.glShadeModel(GL11.GL_SMOOTH);
296                }
297                blendMethod.applyBlending();
298                break;
299
300            default:
301                break;
302        }
303        return true;
304    }
305
306    public static int postRenderPass(int value) {
307        switch (currentRenderPass) {
308            case RenderPassAPI.SOLID_RENDER_PASS:
309            case RenderPassAPI.CUTOUT_MIPPED_RENDER_PASS:
310            case RenderPassAPI.CUTOUT_RENDER_PASS:
311            case RenderPassAPI.TRANSLUCENT_RENDER_PASS:
312            case RenderPassAPI.BACKFACE_RENDER_PASS:
313                if (!backfaceCulling[currentRenderPass]) {
314                    GL11.glEnable(GL11.GL_CULL_FACE);
315                }
316                break;
317
318            case RenderPassAPI.OVERLAY_RENDER_PASS:
319                GL11.glPolygonOffset(0.0f, 0.0f);
320                GL11.glDisable(GL11.GL_POLYGON_OFFSET_FILL);
321                if (!backfaceCulling[currentRenderPass]) {
322                    GL11.glEnable(GL11.GL_CULL_FACE);
323                }
324                GL11.glDisable(GL11.GL_BLEND);
325                GL11.glShadeModel(GL11.GL_FLAT);
326                break;
327
328            default:
329                break;
330        }
331        currentRenderPass = -1;
332        return value;
333    }
334
335    public static void enableDisableLightmap(EntityRenderer renderer, double partialTick) {
336        if (RenderPassAPI.instance.useLightmapThisPass()) {
337            renderer.enableLightmap(partialTick);
338        } else {
339            renderer.disableLightmap(partialTick);
340        }
341    }
342}