Show Posts
|
|
Pages: [1]
|
|
1
|
Discussions / Java Gaming Wiki / Smoothing Algorithm Question
|
on: 2013-05-28 02:57:32
|
|
COULD SOMEONE MOVE THIS TO THE GENERAL DISCUSSION SECTION. @_@
Hello! This is a question that's for all ya'll who have more experience in graphics and algorithms than myself. I'm working on a project (For work, and I did get permission to ask around) that requires the smoothing of a large set of data.
The basics of is that there is a data set that is a 3D matrix filled with 'slowness' values which is basically 'When moving through this cell how many units do you move per time step?' Initially, these values are filled in with a interpolated gradient from some min at the top to some max at the bottom. Then, this data set has a function applied to it repeatedly that takes the data set and another set of inputs, and updates certain cells in the matrix to new values. The updated data set is then fed back into the algorithm again and again until it converges or some maximum number of iterations is achieved.
This is where the major problems begin. For the most part, the function expects that there is some degree of smoothness to the data set, IE- there is some finite, but unknown, allowed difference between values in adjacent cells for which the algorithm will produce meaningful data. This is due to the fact that there is no guarantee that each application of the function will touch the same cells, only that it should touch cells that are close to those touched in the prior step. Due to the fact that the starting estimation (The gradient) is so bad the updates result in large discrepancies between updated and unupdated cells. To help combat this a filtering operation, namely a smoothing, is applied to the the entire data set before it is fed back into the algorithm. Currently, the smoothing operation is a Sliding Windowed Mean with the window size that changes as the iterations continue and as the estimation becomes more exact. Typically it starts out at a window size that is the size of the data set with a slide of 1 (In each direction).
For the size of data set that we're typically work on, this takes a large portion of time (Think a data set that's about 100x50x50, with a sliding windowed mean of 100x50x50 and a slide of in the (x,y,z) direction). This has two major problems: First, it takes a long time to perform this operations, and Second, at least in early iterations there is a 'large' contribution to the value of cells from those that are relatively far away.
So, while it would be nice to figure out a better initial data set, IE- One that will result in a smaller degree in discrepancies between early applications of the function, I've been asked to work on the problem of making the filtering itself more efficient. So many, I'm asking about various filters and whether anyone has any resources for the use of them in 3D (As in smooth across depth instead of just height and width) resources, anything about how to figure out when the application of a filter will result in little-to-no change (IE- figuring out when I can exclude a cell from having the filter applied to it) and things like that?
|
|
|
|
|
2
|
Discussions / Java Gaming Wiki / Complex number cookbook
|
on: 2013-03-14 17:44:34
|
By representing an orientation (or rotation) by a complex number instead of an explicit angle we can drop a fair number of expensive operations. So instead of storing angle 'a', we store complex number (cos(a), sin(a)). Another potential advantage is the algebra framework (just manipulating algebra) and reasoning. Algebra's like complex number, vectors, quaternions, etc allow thinking in terms of relative information which can greatly simplify the process. We will assume that standard mathematical convention of the X axis pointing the to right and the Y axis pointing up. Additionally we will assume that the reference orientation of objects is pointing straight right. Combining these together when thinking about some specific entity, we can think in terms of its center being at the origin and its facing straight down the X axis. NOTE: Although angles are talked about, this is for understanding and thinking purposes and not computation. Basic examples in code: Common definitionsCapital letter are complex number and small are scalars. X=(a,b) Y=(c,d) P=(x,y) R=(cos(a), sin(a)) S=(cos(b), sin(b)) Complex number basicsComplex numbers are represented by two numbers, which we will denote as a pair (a,b). The first number we will call 'x' and the second 'y'. ConjugateX* = (a,b)* = (a,-b)R* = (cos(a),sin(a))* = (cos(a),-sin(a)) = (cos(-a),sin(-a))
So the conjugate reflects ( wikipedia) about the X axis, which is the same as negating the angular information. (SEE: Trig identities: Symmetry) Addition/Subtraction X+Y = (a,b)+(c,d) = (a+c,b+d) X-Y = (a,b)-(c,d) = (a-c,b-d)Operation is component-wise. Can represent translation. Product XY = (a,b)(c,d) = (ac-bd, ad+bc) RP = (cos(a), sin(a))(x,y) = (x cos(a) - y sin(a), y cos(a) + x sin(a)) RS = (cos(a), sin(a))(cos(b), sin(b)) = (cos(a)cos(b) - sin(a)sin(b), cos(b)sin(a) + cos(a)sin(b)) = (cos(a+b), sin(a+b))So the product sums the angular information of the two inputs. (SEE: Trig identities: angle sum) SEE: C2D.mul(C2D)Product combined with conjugate X*Y = (a,b)*(c,d) = (a,-b)(c,d) = (ac+bd, ad-bc) R*S = (cos(a),sin(a))*(cos(b),sin(b)) = (cos(-a),sin(-a))(cos(b),sin(b)) = (cos(a)cos(b)+sin(a)sin(b), -cos(b)sin(a)+cos(a)sin(b)) = (cos(b-a),sin(b-a))Since we can add angles with the product and can negate an angle with the conjugate, the two together allow us to subtract angles. (AKA get relative angular information) SEE: C2D.mulc(C2D) & C2D.cmul(C2D)Magnitude (L2 norm)|X| = |XX*| = |(a,b)(a,-b)| = sqrt(a2+b2)Notice that we're not calling this length. Complex numbers, vectors, etc do not have lengths (nor positions). What they represent in a give instance might have a length equal to its magnitude. Unit complex and trig formUnit complex numbers have a magnitude of one and can be written in 'trig form': (cos(t),sin(t)). Since scale factors can be pulled out (see scalar product) all complex numbers can also be written in 'trig form': m(cos(t),sin(t)). Scalar productsX = s(a,b) = (s,0)(a,b) = (sa, sb)This can be reversed, so all scale factors can be pulled out. Inverse 1/X = X*/(XX*) = (a,-b)/(a2+b2) 1/R = (cos(-a),sin(-a))/(cos(a)2+sin(a)2) = (cos(-a),sin(-a)) = R*The multiplicative inverse of a unit complex is the same as its conjugate. SEE: C2D.inv()Counterclockwise rotation of point about the originFalls directly out of the product. Given rotation (R) and point (P), the point after rotation (P'): P' = RP = (cos(a), sin(a))(x,y) = (x cos(a) - y sin(a), y cos(a) + x sin(a))Example: P = (3,3) R = (cos(pi/4), sin(pi/4)) = (.707107, .707107) P' = (3,3)(.707107, .707107) = (0, 4.24264)How do I find rotation of A into BSolve the above. Assuming A & B are unit vectors: RA = B R = B(1/A) R = BA*Example: A = (0.809017, 0.587785) B = (0.5, -0.866025) R = BA* = (0.5, -0.866025)(0.809017, 0.587785)* = (0.5, -0.866025)(0.809017, -0.587785) = (-0.104528, -0.994522)Counterclockwise rotation of point about arbitrary pointWe can rotate about the origin, to rotate about an arbitrary point (C) translate the system to the origin, perform the rotation and then undo the translation. P' = R(P-C)+C = RP-RC+C = RP+C-RC = RP+C(1-R) = RP+Twhere T = C(1-R). Look at the last line. It is telling you that the rotation R about point C is equivalent to a rotation about the origin R followed by a translation T. And C is recoverable from T & R: C = T/(1-R) (assuming R isn't 1...or no rotation). Composition of rotationsFalls directly out of the product. Given rotation (R) followed by rotation (S): RS = (cos(a+b), sin(a+b))Orthogonal directionTo find a direction orthogonal in a right-handed sense is the same as rotating by pi/2 radians (90 degrees), which is to multiply by (cos[pi/2], sin[pi/2) = (0,1). ortho(X) = ortho((a,b)) = (a,b)(0,1) = (-b,a)Relation to dot and cross productsFalls directly from the product where one is conjugated: X*Y = (a,b)*(c,d) = (a,-b)(c,d) = (ac+bd, ad-bc)dot(X,Y) = ac+bdcross(X,Y) = ad-bcThe dot product is the parallel projection and the cross is the orthogonal projection. Cross product is related to dot product by: cross(X,Y) = dot(ortho(X),Y). Basic geometryOn which side of a line is a point?A line can be represented by a direction (L) and a point on the line (A). The simplest case is a line which coincides with the X axis, L=(1,0) & P=(0,0), in which case we can simply examine the 'y' value of a test point (P). If 'y' is positive, then it is above, zero on the line and if negative then it is below. Moreover the value is the orthogonal distance of the point from the line. Next let's consider an arbitrary line through the origin with unit direction L. We can simply rotate the system such that the line coincides with the X axis as above and we're done. Our modified test point becomes: P'=PL*. Now the 'y' of P' is exactly the same as above. To fully generalize we simply need to move the line to the origin which give us: P'=(P-A)L*. If we were to plug in symbolic values: P=(px,py), L=(lx,ly) & A=(ax,ay) and expand we would see that we have unused intermediate values. This is because we are ultimately only examining a single component..we're only examining the orthogonal projection of the point into the line (SEE: cross product above). Additionally the direction of the line does not need to be normalized if we're only interested in above, on or below line question. The reason is because we only care about the sign of the result to answer our question. So the 'which side' question reduces to: cross(L,P-A), which expands to the following pseudo-code: return lx*(py-ay)-ly*(px-ax) Aside: the previous can be expanded to cross(L,P)-cross(L,A) = cross(L,P)-m. The scalar 'm' can be stored instead of the point 'A' to represent the line. This value 'm' is commonly called the 'moment about the origin'. Basic examplesAt the top we say we can represent an entity by its position and orientation and think about its center as being at the origin and facing straight down the X axis (the reason for this is because that's the entity's local coordinate frame). Let's call it's position E and orientation F and we have some test point P. We can translate the system to the origin (P-E) and then we can undo the rotation of the system by multiplying by F*, which gives us: (P-E)F*. So P in the reference frame of our entity is: P' = (P-E)F*Example: P = (100,100) E = (200,200) F = (.92388, .382683) <- Pi/8 or 22.5 degrees P' = ((200,200)-(100,100))(.92388, -.382683) = (130.656, 54.1196)If you've ever worked with vectors, this should seem similar: find the delta distance and perform the dot and/or cross product. The above equation is finding the delta distance and then effectively computing both. (Obviously you only compute one if only need one). So the dot product is simply the 'x' coordinate in the local coordinate frame (parallel projection) and the cross is the 'y' coordinate (orthogonal projection). What's my unit direction vector?It's pretending the unit complex number of the orientation is a unit vector. It has the same numeric values for 'x' & 'y'. Is it behind me?As noted above the dot product is 'x' in the local coordinate frame, so the sign of the dot product. If negative it's behind the center point with respect to facing and positive if forward. Turn clockwise or counterclockwise?As noted above the cross product is 'y' in the local coordinate frame, so the sign of the cross product. If positive the shortest turn is counter clockwise, if negative it's clockwise and if zero it's straight ahead. Turn toward point with constant angular velocityAgain, the sign of cross product tells the minimum direction. Take a constant angular velocity, store as a unit complex number 'A'. If the sign of the cross product is negative, we need to conjugate A (negate it's 'y' component). Multiply the current facing 'F' by the potentially modified 'A'. Take our new 'F' and cross again. If the sign has changed, we've overshot the target. Is point within field of viewGiven an entity in its local coordinate frame: image some field of view (<= Pi or 180 degrees), which become a pair of line segments symmetric about the X-axis (or triangle or cone). We can immediately note a couple of things. The first is that if our x component of a test point P=(px,py) is negative that it cannot be inside. The second is that given the symmetry about the X-axis, P and P * will always return the same results. Given the second we can form a new test point P'=(px,|py|). Now the problem is identical to on which side a point falls with respect to a line through the origin and we the first observation isn't required to compute the result. Since we're asking 'below' the line, we negate the result to convert into the convention of positive is inside, yielding the following pseudo-code: return ly*px-lx*Math.abs(py);As with the point to line test, our direction L does not need to be normalized and L is half of the field-of-view. Which unit direction forms the minimum angle with the local X axis.Although related to point/line and view-of-view, this case reduces to simply the direction with the greatest x component. Bounce reflectionGiven a vector (v) of something that hits a surface with normal (n) the resulting vector (v') has the same orthogonal part and the parallel part is negated. The parallel part is dot(n,v), so v-n(dot(n,v)) removes the parallel part and v-2n(dot(n,v)) results in the parallel part being negated. For point reflections: negate the bounce reflection equation. SEE: C2D.uref (this is point refection implementation)
|
|
|
|
|
3
|
Discussions / Java Gaming Wiki / Forms of Randomness
|
on: 2012-12-08 23:46:42
|
Forms of Randomness
I. Random Number Generatorsi. IntroductionRandom number generators create a sequence of random bits. The client to a random number generator class can request the raw bits directly or interpreted data derived from the bit sequence (floats, doubles, values between two other values, values with a certain distribution, etc.) Random number generators produce bits in a sequence and have a state. It may not be possible to achieve random access to a number in the sequence produced by an RNG. Random numbers are also not be suited for applications with data in multiple dimensions stretching to infinity or finite grids that are too large to store in RAM. If you need random data as a function of one or more variables, you can use a hash function or an RNG seeded from the value of a hash function. 1. RNG SeedA value called a seed can be used to derive the initial state of a Pseudo Random Number Generator. If you provide the same seed to a PRNG, it will produce the same sequence of numbers every time (but only for the same algorithm). This is useful for creating reproducible procedurally created content, synchronizing random number sequences between multiple computers, or any other scenario require consistency or reproducibility. 2. RNG StateThe state of a PRNG is normally hidden to the user of the object. You can create a PRNG that lets you copy it's state into a different object, so you can create identical sequences starting from the middle of a sequence (instead of just the beginning using a seed) and so you can save and restore the state of the PRNG in the middle of a sequence. All pseudo random number generators have a state. PRNGs are deterministic and do not return truly random sequences. ii. Cryptographic Random Number GeneratorsCryptographic random number generators have special properties useful for security related applications. They exploit properties of number systems that can be used for private communication, authentication, and zero knowledge proofs. They work with large numbers and may be too slow for applications that do not require them, such as simulations or games. If you think you need one in your game but don't know how it works or what it's used for, then you probably don't need one. iii. Non-Deterministic Random NumbersYou don't need true random number generators for the same reason you don't need cryptographically secure random number generators. Cryptographic PRNGs may benefit from keys derived from real world noise in order to prevent some attacks, but a game won't have to worry about such attacks. To get this type of randomness, computers use input from the physical world that can be considered random. The "state" of this RNG is the state of the real world. It does not have the useful properties of PRNGs other than the appearance of randomness. Computers might utilize this source of randomness or user inputted key to seed a cryptographic PRNG instead of a timer to prevent certain side channel attacks. If you're not using cryptography, don't look for this type of randomness. II. Hash Functioni. IntroductionHash functions take a sequence of bits and transform them to a new sequence of bits, usually of some fixed length. The function for Java Objects produces a 32 bit output. Hash functions are sometimes (that is, very rarely) referred to as compression functions because they take a sequence of bytes and shorten it to a smaller sequence. One way to do this is to simply truncate the sequence (for example "Java Gaming" could be hashed to "Java"), but it's generally better to have some type of random output. This way "Java Gaming" and "Java Programming Language" don't create a hash collision. One good reason to never call a hash function a compression function is that it can easily be confused with a compression algorithm. A compression algorithm also shortens a sequence of bits, but in a way that is meant to be reversible. In a way, hash functions work the opposite of a random number generator. A random number generator may take a 32 bit seed and be used to create a much larger sequence of random numbers. A hash function takes a long sequence of bytes and can convert it to a "random" 32 bit hash. A PRNG always produces the same output sequence given the same seed. And a hash function always produces the same hash given the same input. This article uses H(X) = Y to represent a generic hash function. X is the input and Y is the output, or "hash," or "hash value." 1. Cascade Effect and Relation to PRNGsThe cascade effect says that if you change one bit of the input to a hash function, then about half the bits of the output should change, too, on average. This means that H("StringA"), H("StringB"), and H("StringC") all produce very different output. A random number generator where each output bit had a uniform probably of being zero or one will produce a similar outcome. One way a cryptographic PRGN can be created is to take the hash of a counter using a cryptographic hash function, although this would be too slow to use in a video game. Some general purpose PRNGs operate in the form where f(x) is a one-to-one hash function. Special care must be taken to ensure that f(x) has a long enough period for all valid states and that its sequence still appears random. iii. Randomness, collisions, and Hash TablesHash tables take advantage of hash functions to make make fast searches for key values. Java's hashCode() function compresses the data represented by an Object (such as a String, which can be much longer than 32 bits) so that it can be manipulated as an int. The first location the hash table looks for an object is at array index key.hashCode() % arraySize |
If different values map to the same array index (or hash value if not further compressed using %, then those two values are said to cause a collision using that hash function, which makes look up slower. Collisions in hash functions used in procedural content generation may create visual artifacts. Good hash functions are unpredictable, have the cascade effect, and are statistically as likely to produce one value as any other, so that the chance of collision is minimized. iv. Procedural Content, Salting, and Spatial HashingHash functions are useful for generating random values that can be found without sequential access or a look up table. For example, if I had a randomly generated RPG world but if I wanted the same people to appear, I could combine a hash function and RNG to generate similar characters with the same name in alternate realities. In this example Bob may be a character with brown hair, a green shirt, blue pants, black shoes, and no glasses. In other save file, he might look the same but have brown hair. Or have glasses in a third save file. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public static Character createCharacter(String characterName, String worldId) { Rng rng = new Rng(characterName.hashCode()); Character c = new Character(characterName);
c.setHairColor(rng.nextInt(0, MaxHairColorId)); c.setShirtColor(rng.nextInt(0, MaxShirtColorId)); c.setPantsColor(rng.nextInt(0, MaxPantsColorId)); c.setShoeColor(rng.nextInt(0, MaxShoeColorId)); c.setGlasses(rng.nextBoolean); c.setGlassesColor(rng.nextInt(0, MaxGlassesColorId));
rng.reset((characterName + ":" + worldId).hashCode()); switch(rng.nextInt(0, 5) { case 0: c.setHairColor(rng.nextInt(0, MaxHairColorId)); break; case 1: c.setShirtColor(rng.nextInt(0, MaxShirtColorId)); break; case 2: c.setPantsColor(rng.nextInt(0, MaxPantsColorId)); break; case 3: c.setShoeColor(rng.nextInt(0, MaxShoeColorId)); break; case 4: c.setGlasses(!c.hasGlasses()); break; case 5: c.setGlassesColor(rng.nextInt(0, MaxGlassesColorId)); break; } return c; } |
Another way to use hash functions is to hash x-y coordinates. Separate your game world into grids and randomly generate content in a grid one grid at a time. You can generate them all ahead of time, or you can generate them on the fly by using a hash function H(x, y) to seed the RNG in that grid location. When the player leaves that area, you can forget about that grid cell and recreate the exact same area the next time the player goes to that area. One potential problem with this approach is that if a person replays the game, all maps will be the same. This may be desirable. (And it may be helpful. Procedurally created worlds may let you distribute a small binary file and no extra resources (Java4k?) and still have consistent user experience.) One way to change the output of a hash function is to add a "salt" value. You could store the salt in the player's save file or derive one from their username. Modifying the salt is like modifying the RNG seed. Utilizing String's hashcode function again, you could have a salt-less version of a hash function that returns (x + ", " + y).hashCode() |
and a salted version that returns (playerName + "..." + x + ", " + y).hashCode() |
. Spatial hashing is one you take a point in multidimensional space, determine what grid cell (square, hexagonal, cubic, or whatever) it is in, and convert the position of that cell to a value. III. Other sequencesOther sequences may be used that look random to humans and provide certain properties, but aren't actually. Halton and Sobol sequences are examples of low discrepancy sequences and are also called quasi-random sequences. IV. NoiseNoise combines one or more of the above forms of randomness and algorithms to produce a desired affect. Perlin noise, for example, requires a grid of random values, which can either be derived ahead of time using an RNG (for small grids) or on the fly at any point using a hash function (for large or infinite grids,) and interpolates between those values for other locations. White noise in the real world represents a signal with many many frequencies present over an entire spectrum of frequencies. The intensity of the noise is completely random. You could convert the output of an RNG to a PCM sound data to produce (1D) white noise sound or set the brightness of each pixel in a black and white image to the output of an RNG to produce a (2D) white noise image. White noise generally isn't very useful. Noise may be generated with specific aesthetic, frequency spectrum, or structural properties instead. See other articles for descriptions of types of noise, noise algorithms, and applications of noise.
|
|
|
|
|
4
|
Discussions / Java Gaming Wiki / GLSL tricks
|
on: 2012-12-07 05:44:28
|
Todays GPUs are very powerful but it's important to understand the limitations of the hardware of GPUs. For example, branching in GLSL is very expensive due to the way that the stream processors on GPUs work. In many cases branching causes both branches to be executed and the correct result is then picked afterwards. A general tip when coding shaders is to use the built-in functions as much as possible. They are always faster than manually doing the calculations. - Never manually normalize a vector by calculating the length of it using a square root and dividing it by it. Always use normalize().
- Don't use branching to clamp values. Use min(), max() and clamp() for that.
- A very common function is linear blending and there's a function called mix() for it.
Generating random numbers Generating random numbers on a GPU in a traditional way is impossible since we can't use a global seed (well, we can in OGL4+ using atomic counters, but I wouldn't count on good performance). Random numbers can be useful to introduce noise to counter banding in algorithms like HBAO (randomly rotate the sampling ray) or volumetric lighting (random offsets) to trade banding for noise which is much harder to spot and looks better when blurred. This one-line function is a pretty simple noise function seeded with a 2D position (you can use the screen position or texture coordinates as the seed). Generating random numbers on the GPU presents a couple of challenges. The first is that from a practical standpoint you start with some non-random data (say a texture coordinate) which needs to be hashed to give a "random" starting value. The second is that most GPUs currently in use are very slow at integer computations which are invaluable in hashing and generating PRNGs. The results needing to perform very hacky hashing and random number generation entirely in floating point until your low end target has full-speed integer support.1 2 3
| float rand(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); } |
Permutation polynomials. In use examples: ( Local value noise, gradient and simplex noise) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } vec2 permute(vec2 x) { return mod289(((x*34.0)+1.0)*x); } vec2 rng(vec2 x) { return fract(x*1.0/41.0); }
float bar(vec2 x) { float h, r; vec2 m = mod289(x); h = permute(permute(m.x)+m.y); r = rng(h); ... h = permute(h); r = rng(h); } |
Dot products The dot() function is used to calculate the dot-product of two vectors, which is the same as multiplying the vectors component-wise and then adding them together. For a 3D vector, that means that dot(v1, v2) = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z |
. This is a very useful function for doing many things. For example, calculating the distance between two points using Pythagoras' theorem: 1 2 3 4 5 6 7 8
| vec3 p1; vec3 p2;
vec3 delta = p1-p2; float distSqrd = dot(delta, delta); float dist = sqrt(distSqrd); |
Converting a color to grayscale: 1 2 3 4 5
| vec3 color;
float grayscale = dot(color, vec3(0.21, 0.71, 0.07)); |
Shadow mapping Shadow mapping is basically a software depth test against a shadow map. The shadow map coordinates are interpolated as a vec4, so we need to do a w-divide per pixel, get the shadow map depth at that coordinate and compare it to the pixel's depth. A simple implementation does this: 1 2 3 4 5 6 7 8 9
| uniform sampler2D shadowMap;
float shadow(){ vec3 wDivShadowCoord = shadowCoord.xyz / shadowCoord.w; float distanceFromLight = texture(shadowMap, wDivShadowCoord.xy).z; return distanceFromLight < wDivShadowCoord.z ? 0.0 : 1.0; } |
This is not optimal. By using the function called step() we can eliminate the branch by just writing return step(wDivShadowCoord.z, distanceFromLight); |
instead. Even better, the GPU can do the shadow test for us in hardware with some basic shadow filtering if we use a sampler2DShadow instead of a normal sampler2D. That way we just feed in the xyz w-divided shadow coordinates into it. On the shadow map, set up the following parameter to enable hardware shadow testing: GL11.glTexParameteri(GL_TEXTURE_2D, GL14.GL_TEXTURE_COMPARE_MODE, GL14.GL_COMPARE_R_TO_TEXTURE); |
and change the sampler type to sampler2DShadow. It's also possible to enable GL_LINEAR as the texture filter and get 4-tap PCF bilinear filtering. There is one final optimization. Not only can the GPU do the shadow test in hardware with filtering, it can also do the w-divide in hardware using ! It can't get better than that! 1 2 3
| float shadow(){ return textureProj(sampler, shadowCoord); } |
We get better performance, better image quality thanks to the PCF filtering AND a simpler shader. However, the first shader is extremely fast anyway, so why optimize it this much? Shadow filtering. To get smoother shadow edges you do lots of shadow tests on nearby pixels in the shadow map, usually 8 to 16 of them. In that case we would've gotten 16 branches, not just one, so eliminating them means a lot here. Using hardware filtering also gives you 4 samples per texture lookup instead of just one, allowing you to sample a bigger area. GLSL Gotchas- Array declaration is broken on Mac Snow Leopard[1]
|
|
|
|
|
5
|
Discussions / Java Gaming Wiki / Uniform feature points
|
on: 2012-12-05 16:27:32
|
Main/Procedural contentSTUB (YEAH, I'M MAKING LOTS OF THESE) TO REMIND MYSELF TO DO A WRITE-UP. Uniform Feature PointsLet us imagine that we have a 100x100 meter field and in this field we what there to be, on average, two flowers per meter squared. So we could create an array with 100x100x2 = 20,000 elements to explicitly store the positions of each flower. Using a seeded uniform random number generator we could then fill the array with repeatable coordinates for each. If we were to examine the placement of flowers we would notice that there would be regions with none and areas where they are clummped up. 1 2 3 4 5 6 7
| rng.setSeed(someValue);
for(int i=0; i<100*100*2; i++) { float x = 100*rng.nextFloat(); float y = 100*rng.nextFloat(); doMyFlower(x,y); } |
Now if were to examine each square meter (or some other regular chunk) and count the number of flowers it contains, then the "distribution" of the counts approaches the Poisson distribution ( Wikipedia, MathWorld). So instead of precomputing a explicit list of "features", the space in question can be broken down into parts. For each part one computes a poisson random number to determine the number of features inside it. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public static final int poisson(float eMean) { int r = 1; float t = rng.nextFloat(); while (t > eMean) { r++; t *= rng.nextFloat(); } return r-1; }
private static final float FLOWER_POWER = (float)Math.exp(-2);
private void doSomeCellFlowerThing(...) { rng.setSeed(hashOfThisCell);
int num = poisson(FLOWER_POWER);
for(int i=0; i<num; i++) { float x = rng.nextFloat(); float y = rng.nextFloat(); ... } } |
Assuming that the chosen hashing function does a reasonable job, then the "look" of the localized vs. global versions should be similar. Up until now I've avoided too much techo-speak but some definitions are required. All of the above rng.nextFloat() calls are assume to return a uniformly distributed random number on [0,1) which is the standard base contract for a uniform floating point result (actually the inclusion/exclusion of the end-points may vary, but I'm assuming the presented). In probability a uniform distribution ( Wikipedia, MathWorld) means that all results on the range are equally probable...like in a single fair die roll. So in the examples above the 'x' coordinate of each flower is completely independent of 'y', which should be expected. Moreover the coordinates of each flower is independent of any other. This leads to the previously mentioned empty and clumpped up areas. This result, like many from probability, is likely to seem counter-intuitive. Most likely "uniform" will tend to invoke notions of uniformly (or evenly) covered areas. This is a radially different notion of uniform as implies that all of the values are related to each other rather than independent. Note that these two different notions of uniform approach one another as the number of features (or event) increase.
|
|
|
|
|
6
|
Discussions / Java Gaming Wiki / Orders of magnitude
|
on: 2012-11-27 14:22:32
|
BANGED OUT QUICK -- MIGHT BE MISTAKESProgrammers daily work with 32 and 64 bit quantities so it's sometimes easy to loose sight of scale. Additionally humans are better at thinking in terms of linear changes and have difficult with fast growing functions. Likewise once number get bigger/smaller beyond some point, any additional bigger/smaller has less and less meaning to to point where changes become somewhat meaningless. Distances (in meters) greater than 10 6 are officially termed "Astronomical", which is ~2 23. The following table list some powers-of-two along with the bounding factorials and some quantities of that scale: | Number | Relation of scale to real world | 12! < 232 < 13! | - The diameter of the sun is ~230m.
- The number of people alive today (~2^32).
| 20! < 264 < 21! | - The number of people whom have ever lived: ~237
- Thickness of the Milky Way's gaseous disk ~255Km
- The distance from the sun to Proxima Centauri is ~255m
- The age of the universe is ~259 seconds.
| 34! < 2128 < 35! | - The observable universe has an estimated radius of 93 billion lightyears which is ~2119 nanometers.
| 57! < 2256 < 58! | | 98! < 2512 < 99! | - The number of atoms in the observable universe is ~2266.
| 170! < 21024 < 171! | |
Notice to reach a mere 2 614 we are measuring the incomprehensibly large in terms of the incomprehensibly small. Now consider the value of 2 64-2 32. Without stopping to think you might be tempted say that this is ~2 32, when actually the value is ~2 64-2-32 or ~2 63.999999999664. Since we're programmers it is probably more useful to consider computation. Real world examples below are using FLOPS measurements. - AMD 7970 system which can perform ~244 computations per second and ~268 per year.
- The Cray Titan which can perform ~254 computations per second and ~279 per year.
- It's estimated super computers will reach ~260 per second by 2018.
- It's estimated super computers will reach ~270 per second around 2030.
- Imagine an atom which is a quantum computer that can perform one computation per Plank's time (5.39106*10-44s). Then this atom computer can perform ~2144 computations per second and ~2169 per year.
- Imagine a supercomputer made of all the atoms in the observable universe which is ~1080, each of which is one of the above, resulting in ~2410 computations per second and ~2435 per year.
We'll also define a time scale BB which is equal 4.339*10 17s, the amount of time from the big bang until now. The Titan can perform 2 64 computations in ~17 minutes and 2 128 in ~2 16 BB. The atom computer could perform 2 128 computations in ~15 milliseconds and 2 256 in ~2 53 BB. The universe could perform 2 256 computations in less than one Plank time and 2 512 in ~2 43 BB. It would take the Titan ~2 65 years to perform one second of the atom computer. The big bang was merely ~2 34 years ago. It would take the atom computer ~2 241 years to perform one second of the "universe" super computer.
|
|
|
|
|
7
|
Discussions / Java Gaming Wiki / Pseudo random number generators
|
on: 2012-11-15 17:40:51
|
VERY ROUGH WORK IN PROGRESS..NO REAL USEFUL INFORMATION AS OF YET. OverviewThe purpose of this page is to give an rough overview of how pseudo random number generators (PRNG) work and a rough idea of how to choose ones which are adequate for a game runtime. Rules of thumb- Never use the same instance of a generator in more than one thread.
- Never create static utility methods which call a generator unless single threaded (same as previous).
- XXX
XXX Use different generators if you need a more expensive one for a sub-set of tasks...oh, and don't really worry about any of this stuff if you just don't generate many random numbers. Everything below this point can (and should) be ignored unless you are generating a large numbers of random numbers per frame OR you tempted to use OR are using a "good" random number generator especially one with a period greater than 2 64. Again this page is only dealing with PRNGs for game runtimes where "real" money is not directly involved. IntroductionThe vast majority of PRNGs all work in the same way. They take some state-data in the form of a sequence of bits and perform computations which mix the bits. Notice that hashing and random number generation are very similar. A given generator will have a period which is the number of unique values the state will assume before wrapping around and repeating itself. Yeah, that was clear. OK, let's pretend like we're using a 2-bit integer for our state data, so our 2-bit integer can have values of: {0,1,2,3}. For our random number generator we want to produce some permutation ( MathWorld, Wikipedia) of that set which appears random. The number of permutations of a set with n elements is Factorial[n], so we have 24 choices for our 2-bit integer. Limiting the set to those that start with '0' (all the remaining are rotations), we have: {0,1,2,3},{0,1,3,2},{0,2,1,3},{0,2,3,1},{0,3,1,2},{0,3,2,1}. Now obviously none of the above permutation choices look very random but this is exactly how random number generators work. The problem here is that there just aren't enough unique values that any of the permutations appear random. Luckily factorials explode and if we were talking about only 8-bits then there would be approximately 8.6x10 506 choices and 16-bits is ~5.2x10 287193. Other than some very narrow special cases (like in GLSL, when attempting to avoid using integers) there's no reason to use generators with less than 32-bits. An implication of this is that the period can be at most 2 n, where 'n' is the number of bits. On this page we will only consider "full period generators" which will have a period of either 2 n or 2 n-1. The minus one comes into play for generators for which zero is an invalid state. This does not imply that PRNGs with longer periods are superior in quality than those that are shorter. PeriodAs mentioned above the period of a PRNG is the length of the sequence that it generates. Once the period is exhausted, the sequence wraps-around and starts to repeat itself. For scientific usage long periods are important. The reason for this is that statistically they will begin show defects if in "single computation" more than sqrt(T) random numbers are used, where T is the period. Note that the sqrt(T) = T1/2. Even more important is because one can break a problem across multiple CPUs/servers/whatever to attack a single problem and the longer the period, the lower the probability that the individual computation units will be using overlapping parts of the sequence. Note the "single computation" part. There's the mistaken notion in games that one needs a period long enough that it never repeats during gameplay. Not at all, it simply should be long enough that every single computation has more than enough values to complete. So what about the period? Do we need to think in terms of T or sqrt(T)? The question is more or less moot. As noted above there's no reason to use a generator with a period shorter than ~2 32, so you should feel safe if any single problem needs no more than 2 16 or 65536 random numbers, which seems highly unlikely. At the opposite end of the spectrum (SEE: url=http://www.java-gaming.org/topics/orders-of-magnitude/27917/view.html]orders of magnitude[/url]) it would take the Cray Titan more than 17 minutes to generate 2 64 random numbers and an infinite amount of time to generate 2 128. Sticking the sqrt(T) rule of thumb this means you never need a generator with a period greater than 2 128. DimensionsHumm...any ideas here kids, other than don't worry about dimensions. Just don't use a LCG for more than 2. QualityPRNGs do not attempt to create sequences which appear random. Instead they are attempting to simulate statistical randomness. For our purposes the main usefulness of having a generator which passes the majority to all of XXXX XX note uniform distribution XX Write something somehow convincing about how quality a la. diehard and various crushes shouldn't matter. Old SkoolPermutation PolynomialsSEE: GLSL TricksWeyl Generators--STUB AGAIN -- stuck in place since I mentioned them in the GLSL tricks page This family is based on the equidistribution theorem (properties of irrational numbers). Quality varies widely depending on formulation and precision. Like permutation polynomials they can be computed purely in floating point and are currently useful on the GPU. The simplest version looks like: un = na mod 1 = (un-1+a) mod 1where: 'a' is a fixed irrational number mod 1. 'n' is the number in the sequence (0,1,2...) Common variants include nested: un = n(na mod 1) mod 1and shuffled nested (where 'm' is a fixed large integer): vn = m(n(na mod 1) mod 1)+1/2 un = (vn(vn a mod 1)) mod 11 2 3 4 5 6 7 8
| vec3 weyli(vec3 s, vec3 a) { return fract(s+a); } vec3 weyl(vec3 n, vec3 a) { return fract(n*a); } vec3 weyln(vec3 n, vec3 a) { return fract(n*fract(n*a)); } vec3 weylns(vec3 n, vec3 a) { n = m*fract(n*fract(n*a))+0.5; return fract(n*fract(n*a)); } |
XXXX Linear Congruent GeneratorsLinear congruent generatorsMention some mod-power-of-two LCGs here. Non-power-of-two just ain't worthwhile. Nor are IHMO sub-cycle generators. New kids on the blockMention some cheap LSFRs here SummaryReferenceBlah, blah
|
|
|
|
|
8
|
Discussions / Java Gaming Wiki / World save system
|
on: 2012-08-27 18:04:35
|
|
Hello, i'm new on the forum :p, I want to do a world save system but i have no idea of how to do this. I use a sprite system for my game. Can you help me ? Thx, Brian22950
PS : I'm french
|
|
|
|
|
9
|
Discussions / Java Gaming Wiki / How do I start Java Game Development?
|
on: 2012-08-22 22:37:44
|
Java game development is not for the faint of heart. Like everything else, it requires patience, comprehension, and practice. These paragraphs are part of a tried-and-true track of experience levels that would be very beneficial to your growth. You don't have to start at the beginning, but can jump in at any spot you know you are in. Beginner, the most important and *required* step: -For now since you are a beginner, learning Java syntax, core classes, and command line stuff is very important and should be your first priority. Do not jump straight into graphics. Make basic command line games using ASCII art. Make almost any game you can think of for the command line. Eclipse is a very useful and powerful tool and as much as you may like it too, I also recommend you to start with the command line. Write an entire command line app using just notepad, compile it, and run it. Start using packages and experience the pain and confusion of compiling and running programs that are in packages. *OPTIONAL*. Nowadays, it is best to start with LibGDX. Slick2D is another library with a slightly easier learning curve, but it's buggy, no longer maintained, and many years old. -When you feel you know and understand Java well enough, jump into graphics using Java2D. Java2D is the java.awt packages and subpackages. These allow you to do custom drawing and offer very, very powerful tools for making 2D graphical apps and games. Also you may learn Swing, Java's GUI widget toolkit. It offers nice tools for making GUIs (Graphical User Interface). -While you are becoming proficient with Java2D, you will learn and accept one grave and heart-breaking truth: Java2D is slow and unsuitable for professional and graphically expensive games. However, despite this shortcoming, it is the perfect playground for gaming beginners. I advise you to not advance until you have learned basic game systems, designs, code architectural organization, etc...*OPTIONAL*-Finally, when you notice you are ready for hard-core, speed-hungry games, you may jump into the OpenGL bandwagon. OpenGL is a portable high-level API to interface with graphics cards. It is portable in the sense that it works on almost all graphics cards and all systems, and high level since it abstracts away the differences in graphics card functions and drivers. This means you get to skip the slowness of Java2D and be able to directly access the power and performance of raw graphics card awesomeness. This may all seem neat and amazing but there is 1 drawback......its API is written in C (another language). This means you can't really access it directly from Java without writing native code doing a lot of complicated stuff. Well fear not, a bunch of really cool people wrote a library that lets you access these functions and more, and these cool people named it the Lightweight Java Game Library (LWJGL). There is also another group of cool people who wrote a similar library and called it JOGL. They are both almost exactly the same and the only difference is in your perception of it and your choice. However, it seems the LWJGL community is far bigger than the JOGL community and there is a lot more support for it. -Slick2D is an open-source library whose API looks very similar to Java2D yet uses LWJGL underneath. So it lets you make 2D games without worrying about the details underneath. However, it is best if you understand the underlying inner workings so you can gain experience and be able to understand any problems you run into. -There are some libraries that try to simplify your life when making 2D/3D games and GUIs using OpenGL. Such tools include: -libGDX: open-source library that easily allows you to make OpenGL applications on PCs, HTML5, iOS and Android -Java Monkey Engine (JME): fully featured Java 3D engine built on LWJGL that has tons of tools for making professional-looking games -jPCT: Another 3D engine built on LWJGL that to some is simpler and easier than JME yet isn't as powerful. -Ardor3D: A recently emerging 3D engine also built on LWJGL that looks very promising, from what I've heard it combines the ease of jPCT and the power of JME. -Themable Widget Toolkit (TWL): A GUI widget toolkit. It is very powerful and allows for full customization of your widgets. This is the "Swing" version of OpenGL  These tools and engines are nice to use if you don't want to get too much into the details of OpenGL. However, it is better if you do because it is just nicer to understand what is going on behind the scenes and will help you debug any problems you run into. These libraries just ease the lives of those who already understand OpenGL, rather than helping ignorant impatient programmers who want to get their hands dirty in 3D designing. Well this was a long post, and I hope you now understand the current situation of Java gaming and have a basic timeline of your future  If you need any help or assistance, we are always here to guide and point you along the way, not to spoon feed you with code. Remember, we're all a bunch of chill dudes sacrificing our time to help newbies because we enjoy it  You can also join us at the #lwjgl channel on the Freenode IRC network for more help, but know that if no one responds, do idle since we are all on different timezones (half of them live in Europe!). Good luck!!!! LINKS: -Ultimate Java tutorials: http://tinyurl.com/cqp4as -Java Resources: http://www.java-gaming.org/index.php?action=resources - OpenGL tutorials - Java ports
|
|
|
|
|
12
|
Discussions / Java Gaming Wiki / Noise (bandpassed white)
|
on: 2012-08-10 10:42:04
|
Main/Procedural content/NoiseOverviewThe purpose of this page is to give an overview of how noise functions in this family work and the various tradeoffs that can be made in implementation choices. How to use noise to create and modify content is a huge topic...BLAH, BLAH add links. WebGL demo: http://glsl.heroku.com/e#7967.0Top to bottom: value noise, gradient noise and value noise. Right-to-left: single sample, 3-sample fBn, 3-sample turbulence. Cells are purposefully aligned. IntroductionThis family of noise functions are incredibly useful tools for creating and modifying content. According to CG industry lore it was informally observed in the 90s that "90% of 3D rendering time is spent in shading, and 90% of that time is spent computing Perlin (gradient) noise". Regardless of the truth of this observation, this family of noise functions are certainly one of the most important techniques not only in procedurally generated content but in CG as a whole. Increases in CPU speed and the relatively new addition of GPU computation allow for runtime evaluation of the cheaper of these methods in realtime graphics. Attempting to give any detailed descriptions of how to "use" noise functions to create or modify content is well beyond the scope of any short description. The goal here is to outline some basics of core generation techniques and to provide links to more detailed information in specific areas of interest. For the local discussion, we'll assume that noise accepts floating point input for a sample coordinate and returns a floating point value (usually either on [0,1] or [-1,1]). It will provide some sketches of 2D implementations to (hopefully) aid in understanding. Noise functions are evaluated in some number of dimensions (typically 1,2,3 or 4). This is simply to say that you provide some input coordinate and noise returns the corresponding fixed value at that position, just like any other multi-dimensional function. From a signal processing perspective this family can be described as an attempt to approximate band-pass filtering of white noise. Perhaps a simpler description would be that they are attempts at coherent pseudo-random number generators (PRNG). Regular PRNGs attempt to create a fixed sequence (from some initial state data...frequently termed the 'seed') of values that appear to be statistically independent. White noise can be created from a PRNG as in the following sketch (in 2D): 1 2 3 4 5 6
| float eval(float x, float y) { long seed = mix(x,y); prng.setSeed(seed); return prng.nextFloat(); } |
Unfortunately raw white noise is of very little use. If you were to create a 2D texture from white noise, regardless of how you walk through the 'noise' function the result would be virtually identical. The result would be like what you'd see on an old broadcast TV tuned to a channel without a signal. What's really needed to be useful are random values that are coherent: which roughly says that sample points far apart are like PRNG values, appear to be independent, and the set of all sample points close to one another vary continuously (or smoothly in less formal speak). Value noiseValue noise is the one of the original attempts at this style of noise generation. It is very often miscalled Perlin noise. Evaluation is very cheap, but it burden with serious defects and is very poor at band-pass filtering. Quality can be improved, but even the most basic improvements make it more expensive than gradient noise. So a general guideline for using this technique is to only use a very cheap version and only when some existing content can be minorly modified by one or two evaluations. Value noise is computed by forming a regular grid, computing random values at each vertex and blending the values to produce a result. Sketch in 2D: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| float eval(float x, float y) { int ix = (int)Math.floor(x); int iy = (int)Math.floor(y);
float dx = x - ix; float dy = y - iy;
float r00 = mix(ix, iy); float r10 = mix(ix+1, iy); float r01 = mix(ix, iy+1); float r11 = mix(ix+1, iy+1);
return blend(r00,r10,r01,r11,dx,dy); } |
So to compute value noise in 'n' dimensions, the work required is related to n 2 (1D = line segment or 2 vertices, 2D = square or 4 verts, 3D = cube and 8, etc). The problems with value noise stem from the fact that at each evaluation point, the result only depends on blended data interior the cell that its within. This results in sample points close to one another, but in different cells, to not vary continuously. This results in very obvious defects along cell boundaries. Early attempts to fix this major problem included visiting further away cells and using more complex blending functions...which drastically increase complexity. The introduction of gradient noise made these solutions obsolete. However value noise is far from useless. Its very cheap computational cost can make it a good choice when many noise samples are required and is what you will most often find used in "demoscene" style shaders. ReferencesPerlin gradient noiseCreated in 1983 by Ken Perlin, this Oscar award winning technique is a clever way to minorly modify value noise to drastically improve the output quality. Usually when one is (correctly) calling a noise function "Perlin" noise, this is the technique being discussed. The clever addition is to choose a vector associated with each vertex (gradient vector). Then to calculate the vector from the vertex to the sample point. The dot product between these two vectors gives a weighting to modify the value at each vertex. It was quickly noted that this last step is not really useful and that the dot product itself is more than a sufficiently random value (dropping one multiply). Next the dot product results at the vertices are interpolated to generate a final result. Although the dot product drastically reduces defects along the cell boundaries, it introduces a new defect. Specifically the dot product will always approach zero as the sample point approaches one of the cell vertices. Notice that like value noise, the output entirely depends on the evaluation of a single cell and has the same complexity in the number of dimensions. The difference here is that the random vector helps to smooth out values across neighboring cells...much in the same way that Gouraud shading improves over flat shading. Sketch in 2D: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| float eval(float x, float y) { int ix = (int)Math.floor(x); int iy = (int)Math.floor(y);
x -= ix; y -= iy;
int h00 = mix(ix, iy); int h10 = mix(ix+1, iy); int h01 = mix(ix, iy+1); int h11 = mix(ix+1, iy+1);
float r00 = dotRandVect(h00, x, y); float r10 = dotRandVect(h10, x-1, y); float r01 = dotRandVect(h01, x, y-1); float r11 = dotRandVect(h11, x-1, y-1);
x = weight(x); y = weight(y);
float xb = lerp(x, r00, r10); float xt = lerp(x, r01, r11);
return lerp(y, xb, xt); } |
Note that there have been numerous improvements made to gradient noise over the years, so some references may be referring to older versions. And, of course, authors may make minor tweaks (for better or worse) to their specific implementation. Variants of note: - Originally the vectors were randomly generated unit vectors. Creating these on the fly is rather expensive. In days of yore a precomputed table of random vectors was an option (less so today given memory access overhead). The reduced number of random vectors introduces some very minor directional defects.
Perlin later noted that using a small set of vectors (all the permutations of vector components of zero and +/-one, but not all zero) drastically reduced computational cost. Specifically this drops 1 multiply per dimension per vertex (2*4 in 2D, 3*8 in 3D). This significantly increases directional defects (SEE: Defects below). Some GPU implementations use more mathematically complex selection to address this issue. - Two ease functions: Perlin uses a weight function which he terms either ease or s-curve. The original function was: 3t2-2t3. This function is continuous but its derivative is not. This was later replaced by the more expensive: 10t3-15t4 + 6t5 which is C2 continuous.
References Yeah...add tons of stuff here Perlin simplex noiseIn 2002 Ken Perlin introduced a new noise function that is a drastic change in direction. The purpose was to create a function which could be cheaply implemented in hardware and addresses some of the defects in gradient noise. Although designed for hardware it is a better fit for modern CPU and GPU architectures. The first major change is how cells are formed. Instead of regular breaking up of space, the input is skewed into a simplex (SEE: Stefan Gustavon's paper for details). This drops the number of vertices needed from n 2 to (n+1), where 'n' is the number of dimensions. The second major change is instead of calculating values and each vertex and blending the results to compute the final result, the result is instead a summation of contributions from each. This lowers the dependency chain and can increase throughput. For example in 2D, in value and gradient noise, one might first blend in "X": the top edge, then the bottom (these two are independent), then take those results and blend in "Y" to get a final result. In 2D simplex noise, the contribution from the three vertices are independently computed and summed to produce the result. As a rule of thumb, if you need noise (of this variety) in three or four dimensions, then simplex noise is the way to go. ReferencesDefectsNoise is one of those area's where science and art collide. As such the various listed defects only really have meaning if they have a negative impact on the desired result. - hash function:
- gradient vector selection:
- aligned cell structure:
The cheapest way to attempt to hide these defects is to insure that the grid structures of multiple noise evaluations are not aligned with one another. BLAH, BLAH Isotropic and anisotropicIsotropic is math-speak for uniform in all directions and anisotropic is, well, not...the thing in question isn't uniform in all directions. The goal of all the above noise functions is to be isotropic. All, however, have directional defects which make this not quite true. Getting anisotropic results from isotropic noise simply involves applying a non-uniform scale factor when sampling. Periodic noiseThe sketches above are for noise functions without a period. It is commonly desirable to have noise be periodic, or in other words to wrap at specific boundaries. Well, there's good and there's bad news. The first bad news is that most "methods" to make noise periodic are very expensive and don't really work (SEE: Matt Zucker's FAQ above for an example). The first good news is that it's simple to perform cheaply, assuming that wrapping at integer boundaries and in particular power-of-two boundaries is an acceptable limitation. Making a minor modification to the vertex computation allows this to happen..masking in the case of power-of-two and "faking" an integer modulo in other cases. This requires modifying the base noise function (having special cases, dynamic code generations, etc.) Another option is to use a noise function in (potentially) a higher dimension higher than desired and to "walk" that space in such a way that you reach the same coordinate at boundary points. This later happens someway naturally if computation is performed at runtime on the GPU. As an example to apply noise to a sphere (or any other 3D object), one simply samples a 3D noise function at a scaled and/or translated coordinate of the object's surface (or 4D function if the noise is to be animated in time). OptimizationsNoise functions tend to be expensive as many calls are usually required to create a specific effect. As such speed is pretty important when computated at runtime. Given the nature of noise it is a very good candidate for running on the GPU...blah, blah Pre-computation vs. runtimeBlah, Blah. Other noise functionsThere are many other noise functions, many of which are too complex to be evaluated at runtime, but may have game usage for pre-generated content. BLAH BLAH: - Anisotropic noise
- Gabor noise: not the same family, but can generate similar results.
- Sparse convolution noise: realtime variants potentially reasonable on the GPU
- Wavelet noise
References
|
|
|
|
|
13
|
Discussions / Java Gaming Wiki / Concurrency
|
on: 2012-08-03 16:45:04
|
Here is a good tutorial on Java concurrency : ConcurrencyThe most common way of way of handling concurrent modifications is by using the synchronized key word, but that is not the only way to do it. There is also methods based on message passing like the actor model and there is atomic variable. The 5 levels of thread safety. It defines objects that are the best/easiest to use in a multi-threaded environment to the worst/hardest. 1. Immutable : The object can't be modified once created. This is the most safe level. No matter how many threads access this object you won't run into any problems. 2. Thread-safe : The object contains enough internal synchronization (synchronized method) to be used without problems by multiple threads. 3. Conditionally thread-safe : Same as thread-safe except that under some circumstances, you will need to provide external synchronization (outside of that object) 4. Thread-Compatible : Can be used in multi-threaded environment but it is up to the programmer to do the synchronization 5. Thread-hostile : Can't be used in multi-threaded envrionment (Ex.: Thread.stop() - That method was deprecated because it releases the lock when it is called. Hence it could leave an object into an invalid state) People usually think that the method Collections.synchronizedList(new ArrayList()) will return a thread-safe collection. But that is not true. It is conditionnaly thread-safe. That is true for almost all Java default ''synchronized'' collections. Here is a list of collections that are Thread-safe : Concurrent CollectionsVectors are conditionally thread-safe. That means that most of the time you don't need to provide external synchronization but in some cases you might. One case where you need external synchronization is when iterating over the Vector and modifying it. Collection.getSynchronizedCollection() - (or something like that) are also conditionnally thread-safe : meaning that you have to provide external synchronization for some operation. ArrayList is thread compatible : meaning that if you want to use it in a multi-threaded environment you have to provide all the synchronization The Best Advice On Using Concurrency... is to avoid using concurrency at all if you can help it. Threads are extremely difficult to debug, behaving and interacting in very complex ways that are often counterintuitive or seemingly completely indeterministic. They are also not nearly as effective as you'd like to hope in a typical SMP desktop system: two threads does not equal twice the computation, typically. You'll be lucky to achieve a fraction of an increase, for a great deal of extra complexity.
|
|
|
|
|
14
|
Discussions / Java Gaming Wiki / ArrayList vs LinkedList
|
on: 2012-08-03 03:17:00
|
ArrayList and LinkedList are both very similar. They're used in the exact same way, but have very different performance characteristics. Even if you're using the right one for the job, you might still be using the list in a bad way leading to bad performance. A very important thing to consider when choosing which one to use is how they scale for large lists. How lists (and algorithms in general) scale with their size can be described using Big O notation. For example, ArrayList.get(int index) method always returns in O(1) time. The time it takes to find an object is always the same. It does not get slower as the list grows, since it's just simple array access in this case. LinkedList.get(int index) however is O(n). Finding the i'th object requires it to follow the linked list to the i'th. As the list gets longer, get(int index) ON AVERAGE gets slower. Finding the first object is obviously fast, O(1), but finding the last object is O(n) where n is the length of the list. On average, finding an object is O(n/2). However, the /2 is irrelevant in big O notation since it only describes how the list SCALES. LinkedList.get(int index) on average scales linearly with the list's length, so it's therefore O(n). ArrayList: - Adding objects is O(1). - Getting objects is O(1). - Removing objects is O(n). Double the size and the (average) access time doubles too. Note that remove(0) is the worse case scenario as a remove forces a copy of all following objects to fill the first spot that was left empty. - contains(object) is O(n) since the whole list has to be traversed to check if the object is in the list. LinkedList: - Adding objects is O(1) - Random access (getting using indices) is O(n). Getting objects in order using an iterator is O(1). - Removing objects is O(n) when using indices or references to remove objects. Removing objects with an iterator is O(1). - contains(object) is O(n) since the whole list has to be traversed to check if the object is in the list. Which should I use for my game objects? Looking at the above makes it's easy to conclude that LinkedList is the most flexible one. Adding objects is O(1), iterating over objects in order is O(1) and removing objects as we iterate over them is O(1). ArrayList is very similar, but is O(n) for removing. Game objects will die and be removed as the game progresses, so LinkedList scales the best. Even though LinkedList scales better, it does not necessarily have to be the fastest option for a certain use case. The problem with LinkedList is that it creates an Entry object which it wraps in each object added to store the next and previous entries. This allocation (and later garbage collection) makes it a lot slower to add and remove stuff than ArrayList in most use cases. Big O notation says nothing about the actual performance of these two. Adding objects is O(1) for both lists, but is still a lot slower for LinkedLists. Basically, for "small" lists ArrayList will always be faster, but for "large" lists LinkedList is faster. The exact point where you should start using LinkedList also depends on how you use the list, so it's impossible to give an exact number. ArrayList is most almost always the best choice for a game object list. Even when you have lots of stuff to remove, ArrayList can be a good choice. A good solution might be to use TWO ArrayLists and pingpong your objects between them. By doing that you can avoid all shifting while still getting fast (and random) access to all objects. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| ArrayList<GameObject> currentList, nextList;
while(true){
update(); render(); }
private void update(){ for(int i = 0; i < currentList.size(); i++){ GameObject go = currentList.get(i); go.update(); if(go.isAlive()){ nextList.add(go); } } currentList.clear(); ArrayList<GameObject> temp = nextList; nextList = currentList; currentList = temp; } |
|
|
|
|
|
16
|
Discussions / Java Gaming Wiki / HotSpot Intrinsics
|
on: 2012-08-02 13:49:43
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
| java.lang.Object.hashCode(); java.lang.Object.getClass(); java.lang.Object.clone();
java.lang.Math.abs(double); java.lang.Math.sin(double); java.lang.Math.cos(double); java.lang.Math.tan(double); java.lang.Math.atan2(double, double); java.lang.Math.sqrt(double); java.lang.Math.log(double); java.lang.Math.log10(double); java.lang.Math.pow(double, double); java.lang.Math.exp(double) java.lang.Math.min(int, int); java.lang.Math.max(int, int);
java.lang.Float.floatToRawIntBits(float); java.lang.Float.floatToIntBits(float); java.lang.Float.intBitsToFloat(int);
java.lang.Double.doubleToRawLongBits(double); java.lang.Double.doubleToLongBits(double); java.lang.Double.longBitsToDouble(long);
java.lang.Integer.numberOfLeadingZeros(int); java.lang.Long.numberOfLeadingZeros(long);
java.lang.Integer.numberOfTrailingZeros(int); java.lang.Long.numberOfTrailingZeros(long);
java.lang.Integer.bitCount(int); java.lang.Long.bitCount(long);
java.lang.Integer.reverseBytes(int); java.lang.Long.reverseBytes(long); java.lang.Character.reverseBytes(char); java.lang.Short.reverseBytes(short);
java.lang.System.identityHashCode(Object); java.lang.System.currentTimeMillis(); java.lang.System.nanoTime(); java.lang.System.arraycopy(....); java.lang.Thread.isInterrupted(....); java.lang.Thread.currentThread();
java.lang.Class.isAssignableFrom(Class) java.lang.Class.isInstance(Object) java.lang.Class.getModifiers() java.lang.Class.isInterface() java.lang.Class.isArray() java.lang.Class.isPrimitive() java.lang.Class.getSuperclass() java.lang.Class.getComponentType()
sun.reflect.Reflection.getClassAccessFlags(Class) java.lang.reflect.Array.getLength(Object)
sun.reflect.Reflection.getCallerClass()
java.lang.reflect.Array.newArray
java.util.Arrays.copyOf
java.util.Arrays.copyOfRange java.util.Arrays.equals java.lang.String.compareTo(String) java.lang.String.indexOf java.lang.String.equals(Object) java.nio.Buffer.checkIndex(int)
java.lang.ref.Reference.get()
sun.misc.AtomicLongCSImpl.get() sun.misc.AtomicLongCSImpl.attemptUpdate
sun.misc.Unsafe.allocateInstance sun.misc.Unsafe.copyMemory sun.misc.Unsafe.park sun.misc.Unsafe.unpark
sun.misc.Unsafe.getObject sun.misc.Unsafe.getBoolean sun.misc.Unsafe.getByte sun.misc.Unsafe.getShort sun.misc.Unsafe.getChar sun.misc.Unsafe.getInt sun.misc.Unsafe.getLong sun.misc.Unsafe.getFloat sun.misc.Unsafe.getDouble sun.misc.Unsafe.putObject sun.misc.Unsafe.putBoolean sun.misc.Unsafe.putByte sun.misc.Unsafe.putShort sun.misc.Unsafe.putChar sun.misc.Unsafe.putInt sun.misc.Unsafe.putLong sun.misc.Unsafe.putFloat sun.misc.Unsafe.putDouble sun.misc.Unsafe.getObjectVolatile sun.misc.Unsafe.getBooleanVolatile sun.misc.Unsafe.getByteVolatile sun.misc.Unsafe.getShortVolatile sun.misc.Unsafe.getCharVolatile sun.misc.Unsafe.getIntVolatile sun.misc.Unsafe.getLongVolatile sun.misc.Unsafe.getFloatVolatile sun.misc.Unsafe.getDoubleVolatile sun.misc.Unsafe.putObjectVolatile sun.misc.Unsafe.putBooleanVolatile sun.misc.Unsafe.putByteVolatile sun.misc.Unsafe.putShortVolatile sun.misc.Unsafe.putCharVolatile sun.misc.Unsafe.putIntVolatile sun.misc.Unsafe.putLongVolatile sun.misc.Unsafe.putFloatVolatile sun.misc.Unsafe.putDoubleVolatile sun.misc.Unsafe.getByte sun.misc.Unsafe.getShort sun.misc.Unsafe.getChar sun.misc.Unsafe.getInt sun.misc.Unsafe.getLong sun.misc.Unsafe.getFloat sun.misc.Unsafe.getDouble sun.misc.Unsafe.getAddress sun.misc.Unsafe.putByte sun.misc.Unsafe.putShort sun.misc.Unsafe.putChar sun.misc.Unsafe.putInt sun.misc.Unsafe.putLong sun.misc.Unsafe.putFloat sun.misc.Unsafe.putDouble sun.misc.Unsafe.putAddress sun.misc.Unsafe.compareAndSwapObject sun.misc.Unsafe.compareAndSwapLong sun.misc.Unsafe.compareAndSwapInt sun.misc.Unsafe.putOrderedObject sun.misc.Unsafe.putOrderedLong sun.misc.Unsafe.putOrderedInt sun.misc.Unsafe.prefetchRead sun.misc.Unsafe.prefetchWrite sun.misc.Unsafe.prefetchReadStatic sun.misc.Unsafe.prefetchWriteStatic
java.lang.Throwable.fillInStackTrace
java.lang.StringBuilder, object.initializer, void.method.signature java.lang.StringBuilder, object.initializer, int.void.signature java.lang.StringBuilder, object.initializer, string.void.signature
java.lang.StringBuilder.append(char) java.lang.StringBuilder.append(int) java.lang.StringBuilder.append(String) java.lang.StringBuilder.toString()
java.lang.StringBuffer, object.initializer, void.method.signature java.lang.StringBuffer, object.initializer, int.void.signature java.lang.StringBuffer, object.initializer, string.void.signature java.lang.StringBuffer.append(char) java.lang.StringBuffer.append(int) java.lang.StringBuffer.append(String) java.lang.StringBuffer.toString()
java.lang.Integer.toString(int)
java.lang.String, object.initializer, string.void.signature java.lang.Object, object.initializer, void.method.signature
java.lang.reflect.Method.invoke, object.object.array.object.signature
java.lang.invoke.MethodHandleNatives, checkSpreadArgument, checkSpreadArgument.signature java.lang.invoke.MethodHandle, invokeExact, object.array.object.signature java.lang.invoke.MethodHandle, invokeGeneric, object.array.object.signature java.lang.invoke.MethodHandle, invokeVarargs, object.array.object.signature java.lang.invoke.InvokeDynamic, star, object.array.object.signature
java.lang.invoke.MethodHandleImpl.selectAlternative, selectAlternative.signature
java.lang.Boolean.booleanValue java.lang.Byte.byteValue java.lang.Character.charValue java.lang.Short.shortValue java.lang.Integer.intValue java.lang.Long.longValue java.lang.Float.floatValue java.lang.Double.doubleValue
java.lang.Boolean.valueOf java.lang.Byte.valueOf java.lang.Character.valueOf java.lang.Short.valueOf java.lang.Integer.valueOf java.lang.Long.valueOf java.lang.Float.valueOf java.lang.Double.valueOf |
|
|
|
|
|
17
|
Discussions / Java Gaming Wiki / HotSpot Optimization
|
on: 2012-08-02 13:48:26
|
compiler tactics:proof-based techniques:flow-sensitive rewrites:language-specific techniques:- class hierarchy analysis
- devirtualization
- symbolic constant propagation
- autobox elimination
- escape analysis
- scalar replacement
- lock elision
- lock fusion
- de-reflection
speculative (profile-based) techniques:- optimistic nullness assertions
- optimistic type assertions
- optimistic type strengthening
- optimistic array length strengthening
- untaken branch pruning
- optimistic N-morphic inlining
- branch frequency prediction
- call frequency prediction
memory and placement transformation:- expression hoisting
- expression sinking
- redundant store elimination
- adjacent store fusion
- card-mark elimination
- merge-point splitting
loop transformations:global code shaping:- inlining (graph integration)
- global code motion
- heat-based code layout
- switch balancing
- throw inlining
control flow graph transformation:
|
|
|
|
|
20
|
Discussions / Miscellaneous Topics / Unrolled Linked List - Experiment
|
on: 2012-08-02 07:33:52
|
Community work - second try This time we must implement an Unrolled Linked List. Everyone can make as many modification as he wants. The goal is to get the best data structure that we can in term of performance and flexibility. It should implements the following interfaces : Cloneable, Collection, List, RandomAccess, Serializable You can find information on unrolled linked list here and hereGood luck community 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
| import java.io.Serializable; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.RandomAccess;
public class UnrolledLinkedList implements Cloneable, Collection, List, RandomAccess, Serializable {
@Override public void add(int arg0, Object arg1) { }
@Override public boolean addAll(int arg0, Collection arg1) { return false; }
@Override public Object get(int arg0) { return null; }
@Override public int indexOf(Object arg0) { return 0; }
@Override public int lastIndexOf(Object arg0) { return 0; }
@Override public ListIterator listIterator() { return null; }
@Override public ListIterator listIterator(int arg0) { return null; }
@Override public Object remove(int arg0) { return null; }
@Override public Object set(int arg0, Object arg1) { return null; }
@Override public List subList(int arg0, int arg1) { return null; }
@Override public boolean add(Object arg0) { return false; }
@Override public boolean addAll(Collection arg0) { return false; }
@Override public void clear() { }
@Override public boolean contains(Object arg0) { return false; }
@Override public boolean containsAll(Collection arg0) { return false; }
@Override public boolean isEmpty() { return false; }
@Override public Iterator iterator() { return null; }
@Override public boolean remove(Object arg0) { return false; }
@Override public boolean removeAll(Collection arg0) { return false; }
@Override public boolean retainAll(Collection arg0) { return false; }
@Override public int size() { return 0; }
@Override public Object[] toArray() { return null; }
@Override public Object[] toArray(Object[] arg0) { return null; }
} |
|
|
|
|
|
22
|
Discussions / Java Gaming Wiki / Java Data structures
|
on: 2012-07-24 09:08:26
|
General data structure types and interfaces
- Collection General bag of stuff. Lets you add, remove and iterate when you don't really care what the underlying structure is.
- List Ordered list of stuff. Use when you want objects kept in order, but you don't care what the underlying structure is.
- Set. A collection that does not allow duplicates. Use when having the same object twice in your collection is an error.
- Map. Map of key-value pairs. Use when you want fast lookups from some kind of identifying key to another object.
Lists & queues- ArrayList Growable list, implemented with an array that is resized under the hood.
- LinkedList Doubly linked list. Faster insertion and removal than an ArrayList, but slower to iterate over.
- PriorityQueue Ordered list where objects are sorted by a priority value.
- Unrolled linked list
Lookup tablesOrdered collectionsThread-safe collectionsMost containers can be wrapped to create thread safe versions using the methods in Collections. Eg. Collections.synchronizedList(new ArrayList<Type>()) More specialised containers can be found in java.util.concurrent. - ConcurrentHashMap. Map with non-blocking get(), useful for caches which may be populated from a loader thread.
- ConcurrentLinkedQueue. Non-blocking queue, useful for multithreaded pipelines where producers and consumers may share a common queue.
General Advice- Always declare using the most general type you need. This isn't so important for locals, but it makes a huge difference for fields, as this allows you to swap the implementation of a datastructure without breaking code, that may otherwise already have dependencies on the explicitly defined implementation. For example:
1 2 3 4 5 6 7
| ArrayList<Foo> foos = new ArrayList<Foo>(); HashMap<Foo,Bar> foobar = new HashMap<Foo,Bar>();
List<Foo> foos = new ArrayList<Foo>(); Map<Foo,Bar> foobar = new HashMap<Foo,Bar>(); |
References
- Interactive applet. Visualization tool that walks through the steps of: BST, AVL, B-tree, AA Tree, Red Black, Skiplist, Max & Min Heap, Treap, Scapegoat and Splay.
|
|
|
|
|
23
|
Discussions / Java Gaming Wiki / Gameloop experiment
|
on: 2012-07-20 06:18:35
|
Hello, To celebrate the start of the new wiki we will try to create a gameloop together as a community. Since this is a bit of an easy task and there are many gameloop around I will ask to not copy paste any existing gameloop. Instead, to get a wiki feel to that experiment, each person contributing can only add, remove or modify a few lines. Good luck community! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class GameLoopExperiment implements Runnable {
private boolean running = true; private final int framerate = 60; private final long frameIntervalNanos = 1_000_000_000L / framerate;
public void logic(int deltaTime) { for(int i=0; i<entities.size(); i++) { entities[i].processTick(deltaTime); } }
public void render() { for(int i=0; i<entities.size(); i++) { entities[i].draw(); } }
public boolean isRunning() { return running; } public void exit() { running = false; }
public void run() { long lastFrameNanos = System.nanoTime(); while ( this.isRunning() ) { long now = System.nanoTime(); long deltaTime = now - lastFrameNanos; lastFrameNanos = now; logic((int)deltaTime); render(); } } } |
|
|
|
|
|
24
|
Discussions / Java Gaming Wiki / Topic Request
|
on: 2012-07-20 05:13:48
|
While writing these topics willy-nilly as we think them up will be useful (Everyone has their own specialized area of interest where they're probably highly knowledgeable and informative), there should probably be a spot for us to make requests for topics which we're interested in, but not knowledgeable, that the rest of the community might be able to fill in. If you write a Wiki-Post in response to a given request, please update the list with the link to it (Just in case the topic isn't immediately obvious). Requests
|
|
|
|
|
25
|
Discussions / Java Gaming Wiki / Java Gaming Resources
|
on: 2012-07-20 03:08:22
|
Recommended BooksGame TutorialsFull Game Source Code- The entire source code to Revenge of the Titans! (Please respect the fact that it is copyright and use for educational purposes only)
Game Libraries2D Engines and Libraries- Slick2D (Hardware Accelerated 2D Games Library)
- PulpCore (2D Games Engine, especially good for Applets)
- LibGDX (2D and 3D OpenGL library, both desktop and Android support, and more)
3D Engines and Libraries- Ardor3D (Java based 3D engine)
- JMonkeyEngine (Java based 3D engine)
- jPCT (Java based 3D engine)
- LibGDX (2D and 3D OpenGL library, both desktop and Android support, and more)
- Clyde (For creating action-oriented networked 3D games in Java.)
- Xith3D (Java based 3D engine)
- Ogre4J (Java binding to the popular C++ engine Ogre3D)
- 3DzzD (Java based 3D engine for webpages)
- Java 3D (scene graph based 3D application programming interface)
Graphics and Sound Bindings- LWJGL (OpenGL, OpenAL, OpenCL, JInput)
- JogAmp (OpenGL, OpenAL, OpenCL, OpenMAX, JInput For JogAmp)
Sound LibrariesPhysics Libraries- JBox2D (2D physics engine, straight port of the C++ Box2D engine)
- Fizzy (2D physics engine, based on JBox2D. Presents a more familiar environment to Java programmers)
- JBullet (3D physics engine)
- dyn4j (A 100% Java 2D collision detection and physics engine)
Network Libraries- KryoNet (clean and simple API for efficient TCP and UDP client/server network communication using NIO)
- RedDwarf (RedDwarf is a server side technology written in Java that radically simplifies the development of online games and lowers the barrier to entry into the MMOG market)
- Narya (The Narya library provides various facilities for making networked multiplayer games.)
GUI Libraries- TWL (TWL is a GUI library built on top of OpenGL and provides all the standard widgets like labels, edit fields, tables, popups, tooltips, frames and a lot more.)
- Nifty (Nifty GUI is a Library for games or similar applications. The configuration of the GUI are stored in xml files with little supporting Java code.)
- Feng GUI (FengGUI is built on OpenGL and provides all typical GUI components.)
- PureSwing (Reimplementation of Swing)
Java Game Portals- GameJolt - Upload Java Games and make money
- Games4J - Upload Java Games and make money
- FunOrb - Java Games Portal
- Java4K - The site for the annual Java4k contest, upload & play Java4K games
- Java Game Tome - Showcase your java games online
- Pogo - Online Games Portal
- Chrome Web Store - Google's App Store allows Java Games (You can even sell them)
Featured Misc.
|
|
|
|
|
26
|
Discussions / Java Gaming Wiki / Test topic
|
on: 2012-07-19 22:25:27
|
 Test message  [size=10pt]Hello mum! I miss u : ( [/size] Sandwiches with delicious mayonassie mustard french Russian radish mayonnaise. Oh it doesn't do what I thought it did. Ah yes it does. So perhaps this feature might have a checkbox on it to turn it on and off. For the sake of cute fluffy bunnies, can somebody modify the post, so I can check whether revisions work?
 my ass is on fire! once upon a time... there is a bunny... Erm, Why does a fluffy bunny own a flaming donkey? Because of the fire fox.  Gimby says: all your base are belong to us! An Error Has Occurred! You aren't allowed to modify just any post.  I'm a furry goat apple which only knows how to speak in burp-toung and say the words supercalifragilisticexpialidocious along with antidisestablishmentarianism . 
|
|
|
|
|
27
|
Discussions / Java Gaming Wiki / How to: JGO Wiki
|
on: 2012-07-19 22:20:35
|
[size=16pt] Welcome to the JGO Wiki![/size] IntroductionOn this board you can start new topics or reply to others just like elsewhere on the forum. You might notice that once you posted a new topic, the author of the post will not be you, but our always friendly Wiki Duke. You will always be the credited author of the original content, as each post and modification will be saved as a revision in which the author is stored. Rules for the creation of articlesAnything goes, but please do not create a new article to request more information about a subject. Rules of engagementEverybody is entitled to their opinion, but should also respect the opinion of others. Differences of opinions should be discussed in the replies, not through frantic modifications of the wiki article. If no agreement is reached, both opinions should be expressed in the article. As the article will be editable by any member of JGO, it will be subject to rollbacks and/or temporary bans if members behave malliciously. Final notes- Due to the shared ownership of content, wiki articles cannot receive medals. Appreciation can be expressed by awarding a medal to a reply of the intended member in that topic, if such a reply exists.
- Concurrent modification of a wiki article will cause the latest posted revision to replace the other(s). Merging of updates will have to be handled manually.
- After making a (significant) modification, you're encouraged to add a reply to the topic stating the reason of the edit. This serves both as additional context and to 'bump' the topic on the board and making others aware of your contribution through the 'unread posts' listing.
|
|
|
|
|
28
|
Discussions / Java Gaming Wiki / Applet FAQ
|
on: 2009-04-25 15:08:55
|
I think an applet FAQ would be awesome. It would be great also to have a section just dedicated to applets as their a lot of special considerations like bugs, tutorials, sizes, offline testing, focus. It seems like java for games could really take off by taking some of the flash market share. As a beginner here are a list of the questions I have. I've answered what I've could, but I'm sure there are a ton more. Flash v Java: advantages and disadvantages?Warning! Reading this part might be a bit depressing, depending on your current time investment of Java. Flash is the king of the browser game market despite being proprietary and not as flavorful, smooth as Java. <a href=" http://www.java-gaming.org/topics/they-re-moving-to-flash-here-s-why/19373/view.html"> http://www.java-gaming.org/topics/they-re-moving-to-flash-here-s-why/19373/view.html</a> Browser Penetration: (Portability of Java is practically meaningless by looking at this stat) http://www.statowl.com/java.php Penetration: 54% with 1.6 + 19% with 1.5. Total 73%. http://www.statowl.com/flash.php Penetration: 54% with 9. + 40 with 10. Total 94% On a positive side, Java is going to allow you to move toward bigger and more complex games. What size should my applet be?According to this <a href=" http://www.hobo-web.co.uk/tips/25.htm">site</a>, the most common browsing resolution as of March 2009 is 1024x768. I used Photoshop on Windows XP to measure the maximum available browsing height with tabs and task bar up: On Firefox I only had 535 pixels. (Width seems mostly irrelevant.) According to the flash discussion <a href=" http://www.triquitips.com/viewtopic.php?f=25&t=617>here</a>, 640x480 seems to be the preference. Of course with vector graphics, flash may have more flexibility. According to this <a href=" https://www.mochiads.com/community/forum/topic/portals-and-game-sizes-list-of-portals-max-size>discussion</a> that lists several flash portals, 640x480 is the max for a few but many go much larger. Width doesn't seem to be much of an issue, often set at 800. Beware of large file sizes as it will hurt performance. Why is the size of the applet important? Try playing this amazing <a href=" http://www.rocksolidarcade.com/games/robokill/>game</a> on low resolution like 1024. Webstart versus Applet?Consensus says applet; however both do different things. Applets should be great for in browser gaming with fast loading and keeping the visitors harddrive clean. Webstart is great for keeping a game up-to-date and cleaning installing your application. The full discussion can be found <a href=" http://www.java-gaming.org/topics/applet-vs-webstart-what-do-you-prefer-as-a-end-user/20044/view.html>here</a>. How to double buffer with an applet?I've found three code samples I like. It would be wonderful if a Java Guru could chime in on the quality of these. http://www.naturalprogramming.com/javagui/BeatingHeartApplet.javahttp://www.gamedev.net/community/forums/topic.asp?topic_id=405663http://www.gamespp.com/java/gameProgrammingTutorial04.htmlWhich Java game frameworks support applets?<a href=" http://slick.cokeandcode.com/"> Slick </a> <a href=" http://lwjgl.org/">LWJGL</a> <a href=" http://www.interactivepulp.com/pulpcore/">PulpCore</a> <a href=" http://dzzd.net/">3DzzD</a> <a href=" http://www.goldenstudios.or.id/products/GTGE/">GTGE</a> http://www.jpct.net/forum2/topics/aplha-and-performance/1247/view.htmlJOGL --> Unknown. (any others?) How do I test my applet offline?<a href=" http://en.wikipedia.org/wiki/AppletViewer">AppletViewer</a> In an IDE, just add it to a frame. Something like this: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { SampleApplet applet = new SampleApplet(); Frame frame = new Frame(); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } });
frame.add(applet); frame.setSize(800,600); frame.show(); applet.init(); applet.start(); } |
In a browser, for a single class, 1
| <applet code="SampleApplet.class" width="800" height="600"></applet> |
In a browser, from a Jar: 1
| <applet code="SampleApplet.class" archive="SampleJar.jar" width="800" height="600"></applet> |
How to add files (images and sound) to a JAR?In NetBeans, right click on the project. Select properties. Select the category named "Sources." Click "Add Folder" under the Source Package Folder Section. Select your directories. The default is *.*. Hit okay. How to load files (images and sound) from a URL?(need help) How to load files (images and sound) from a jar on a URL?(need help) How to setup your code to load from a hard drive or URL?(need help) What is the best sound player for uncompressed files?Use AudioClip. Clip seems to be buggy. What is the best sound player for compressed files like Ogg and MP3?(need help) How do I add my own art to the Java Loading screen?https://jdk6.dev.java.net/plugin2/#LOADING_SCREENHow can I drive traffic to my game?<a href=" http://jayisgames.com/>http://jayisgames.com/</a> <a href=" http://www.123spill.no/>http://www.123spill.no/</a> <a href=" http://www.javagametome.com"> http://www.javagametome.com</a> <a href=" http://digg.com/"> http://digg.com/</a> http://www.greatgamesexperiment.com/games/Where can I attempt to sell my game to a portal?http://www.heavygames.com/http://www.freearcade.com/http://www.miniclip.com/http://www.arcadepod.com/java/Not interested in money, just want to get the game out there to be played.<a href=" http://gamejolt.com"> http://gamejolt.com</a> http://www.jars.com/http://www.javashareware.com/ What are the know bugs?Mac users have a tough time with 1.6. Is there an explanation of the major browser crash bug? I know David Brackeen's framework resolves this but his code was a bit over my head. What is the difference between Applet and JApplet? Which to use?On person says, Applet is the HeavyWeight component, just use Applet everywhere and forget about JApplet. However, when I use a canvas for double buffer and use Applet, I get a nasty 8 pixel bar along the top of my application. JApplet does not have this issue. Has Oracle's purchase of Sun doomed Java Games?http://www.java-gaming.org/topics/oracle-buying-sun/20314/view.htmlHow to write to a server for things like high scores, save data, etc?This allows folks to communicate with perl etc on the server side. http://www.javaworld.com/javatips/jw-javatip34.html
|
|
|
|
|
|
Add your game by posting it in the WIP section,
or publish it in Showcase.
The first screenshot will be displayed as a thumbnail.
|
|