PageRenderTime 46ms CodeModel.GetById 26ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

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