Jump to content

Minecraft's Excessively-Complex Rendering Engine


jakj

Recommended Posts

After walking my way through the block-rendering code of vanilla 1.2.5, Kaevator's Super Slopes, and Thaumcraft's new crystal block...and then being forcibly ejected by the sheer pressing mass of code...I realized something.

[img width=150]

So, I'm wondering if anyone here has any advice for me. What I want to create is the simplest possible function for rendering that can then be applied in a nicely-abstracted way to draw pretty much anything desired in Minecraft. It's the good old tried-and-true 3D algorithm: Draw a triangle.

Basically, what I want to be able to do is specify an oriented triangle (meaning either three x|y|z vertices with the active side determined either clockwise or counterclockwise, or three x|y vertices on a plane with rotation u|v|w) and a texture (with offset, scale, whatever is useful).

In layspeak, it would be like this:

Triangle vertex 1: 0.5 , 0.5 , 0.5

Triangle vertex 2: 0.5 , 0.8 , 0.5

Triangle vertex 3: 0.5 , 0.5 , 0.8

Texture offset X: 64

Texture offset Y: 16

In its most basic and simple form.

But the sheer amount of code required to do this very simple thing is absolutely staggering. I mean, come on: Just rendering the simplest full-sized cube in minecraft is hundreds of lines of code, with six separate functions for each face, as well as container functions for whether or not ambient occlusion (smooth lighting) is on or not.

Can anyone help with this idea, or is the answer basically "Gonna have to do it the hard-as-fuck way or give up."?

Link to comment
Share on other sites

Well at it's core it's OpenGL, if you don't know much about OpenGL then yes it's going to be rather abstruse.

Minecraft does add complexity on top of it but really it's not too far removed. I think LWGJL has some tutorials (good luck finding them... their wiki is... well a wiki) and there's always the OpenGL red book, I have a print copy but you can certainly find it online for free & legal even (Google gave me http://fly.cc.fer.hr/~unreal/theredbook/ which looks like it). Or the NeHe stuff though it's been years since I looked at any of that (http://nehe.gamedev.net/).

p.s. I consider myself a competent programmer or at least I get paid to be one, but I've never been able to really wrap my head around OpenGL, DirectX or any sort of graphics programming. So don't feel horrible if it's like about as easy as a really difficult thing, you're not alone.

Link to comment
Share on other sites

Is it any different to what has been done with perhaps the book on the enchanting table and the end-crystalthings, or do they work differently as they are not 'static' entities?

I see what you are trying to do, but java is just the wrong damn language. If someone were to, I dunno, spend all of half an hour moving it to C++... (not me, someone else, digging up link now).

Link to comment
Share on other sites

Upon further examination, it looks like lighting is really the sticking point, because the physical act of drawing was only a bit at the end. I"m going to look at the links you've provided and start experimenting without worrying about lighting, and see how far that gets me. :-)

Link to comment
Share on other sites

  • 3 weeks later...

I was working on an improved version of Kaevator's Slopes. Gave up for now because the lighting was pissing me off (and Diablo).

I actually figured out a way for you to provide any arbitrary 3D model for a block via an external file, but I did not get far enough into the coding to figure out whether or not Minecraft's architecture would support it without immense overhead.

The basic idea was to store a model ID in the tile entity via nbt, then store the actual model data in the world file itself (just like EE stores the alch-bag data). That would make worlds exchangeable as long as both had the mod.

But the lighting is basically and totally impossible unless I were to dedicate the next year of my life to it. The only option would be very simple lighting like minecraft used to have, where the whole block is colored based on the light level.

Link to comment
Share on other sites

  • 2 weeks later...

Right, I'm sick of this, I recon that there should be a modding project to basically fix notch's stupid lighting code, who's with me?

Good luck with that, champ. If we can't even get every Minecraft mod-user to install Forge (or even ModLoader, for pity's sake), I'd love to see how many people you convince to install and use your lighting system+API (not to mention getting modders to support it). No way in hell would you ever be able to rewrite Minecraft lighting in such a way that it wouldn't break existing mods, unless you kept your changes so small as to be irrelevant.

Link to comment
Share on other sites

  • Forum Administrators

But the lighting is basically and totally impossible unless I were to dedicate the next year of my life to it. The only option would be very simple lighting like minecraft used to have, where the whole block is colored based on the light level.

Isn't this how redpower does it with its microblocks? It's fairly minor all things considered. Kev's slopes where a favorite of mine but fell to the wayside because there wasn't room nor was it compatible early on. Dunno if things have changed.

Link to comment
Share on other sites

Isn't this how redpower does it with its microblocks? It's fairly minor all things considered. Kev's slopes where a favorite of mine but fell to the wayside because there wasn't room nor was it compatible early on. Dunno if things have changed.

Well, there really aren't any issues of compatibility. And it can in fact be done with only one block ID, but it's non-trivial coding. Most of the coding is algorithms and data structures, though, and not actually dealing with Minecraft's classes at all other than the actual rendering and a few data-storage bits, so it's a very doable project, if the lighting issue is ignored as unimportant.

If I ever feel like modding again, I'll certainly give it a shot, but if in the mean time somebody else reliable and ambitious decides they want to try, I could make a lengthy and detailed forum posting with all of what I've discovered so far, and they can take it from there.

Link to comment
Share on other sites

Yes but if Someone was to make it it could be included in modloader along with the functions then forge modloader will steal it and problem solved.

My god, do your sentences ever make sense? The fuck...

Link to comment
Share on other sites

  • 3 weeks later...

jakj, were you able to get a block model to render without lighting? I've worked out the math for lighting triangular faces at arbitrary angles using Minecraft's methodology, but my test block comes out as invisible (it's a standard cube with faces divided into 2 triangles each). My source code is available on dropbox if you're interested.

I don't know how far you got with the lighting, but if you are curious, this is what I've found:

1) RGB color multipliers and brightness values are retrieved for each block immediately touching one of the corners of the block to be rendered.

2) The colors and brightness of the 4 adjacent blocks touching the corner of a face are averaged together. The color multipliers are then applied to the rendering block's color (white for regular blocks. Redstone and Grass use this to colorize their textures). So in total, there are 24 averaged points, 4 for each of the 6 faces.

3) The color and brightness values for a face are set before each corner's (x,y,z)+texture(u,v) is added to the tessellator buffer. Flags in the tessellator class tell it to add brightness, texture, color, and normal values to the buffer with the coordinates. Each point is 8 index points long with the order:

0 - x

1 - y

2 - z

3 - scaled texture x location (u)

4 - scaled texture y location (v)

5 - RGB color

6 - viewpoint normal vector? seems to be used for rendering inventory items only

7 - brightness

4) Supposedly the Tessellator.draw() method is called when the buffer is filled, but I don't see where that happens yet.

An easy way to demonstrate this with Kaevator's Superslopes code is to change the way the colors are averaged for the sloped faces. As is, the lighting for these faces is treated the same as a regular vertical face. To add a shadow gradient, average the "back" of the face that the slope slopes to. Then, when placing a solid cube to one side of the slope, the color for that back face darkens considerably, producing a smooth shadow towards the unblocked edge. I took this one step further with Smoothslopes and averaged all vector components of the color multipliers and brightness values at each cube corner above the plane normal to the triangular face instead of using the 4 block corners on the cube's face. I'll try to put together a picture showing what I mean if that's not clear.

Link to comment
Share on other sites

That's just for color-multiplier, though, and not even AO lighting. If you look at the comments Kaevator made about his own lighting code, you'll see that even it doesn't work right in the last version he officially supported, and he was frustrated and giving up.

I haven't done anything at all with this idea, having lost interest in Minecraft modding entirely due to the poisonous environment. I suggest creating a new thread for yourself and post your code there, in the Questions subforum if you just want some advice about your transparent blocks, or in the main Modding forum if you plan on making this into a full mod for Technic.

In terms of arbitrary block modeling in Minecraft, I can summarize the steps very easily:

  • You will need one ID for your custom block.
  • A block's model will be a set of triangles, just like standard 3D modeling. The standard way to specify which way the triangle faces is to decide either clockwise or counterclockwise means you're looking at the rendered side of it. An entire block's set of vertices should be stored as floating-point values from 0 to 1, picking an X/Z/Y direction to be the origin corner.
  • Model data should be input by text file, and you could also support file formats from programs like Blender if you're ambitious.
  • You can use WorldSavedData (look at how EE stores its data for Alchemical Bags) to keep model data with a world file after it's first loaded, so you don't have to keep the model file with the world. (You might be able to import texture files this way too, but I'm not sure. You could save a .png into the world and extract it into the player's .minecraft directory upon loading, but you might not be able to load the textures directly without doing that.)
  • Each triangle face would also have a texture associated with it. You would store the offset into the texture for each face along with the triangle's vertices. Trying to get textures to flow nicely from face to face would probably be too ridiculously difficult, so you'd never get that genuine "cloth wrapped around a wireframe" effect, but you could try if you want.
  • You would store the ID of the model a block uses, its scaling and rotation, and any other transformative information, in its NBT compound. It would be too expensive to load this information for every render frame, but what you do is cache that information in your mod, so every render frame, you load from the NBT compound only if the data are not cached.
  • You can use the blocks' 4 bits of metadata for anything you like, or just ignore them. You could use them for orientation if you don't want to support arbitrary-angle rotation, or you could do something with redstone, or you could allow grouping of similar models (like an antenna that is either retracted or extended), or even for animation states or rate.
  • Bonus points for using the vertex list to keep the block's hitbox minimal.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...