Controls: A and S to change ambient lighting. Z and X to change color blend.Use arrow keys to change size of lights and blocks.1 and 2 to change between light placing mode and block placing mode respectively.Click to selected and move a light/block Control + Right Click to add light.Control + Left Click to add block.

And here is a screen to show.

Now the lights will not look like openGL type lights mainly because java2D cannot do hardware additive blending.

This is the way the current api works.

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

//create the lightmap with the screen width and height. The third arg is the lightmap scale reduction. 1 is no reductionlightmap = newLightMap(window.getWidth(),window.getHeight(),1);lightmap.setAmbientColor(Themes.getColor(Themes.GREEN));lightmap.setAmbientLuminosity(luma);lightmap.setColorBlend(colorBlend);lightmap.setAmbientLight(ambLight);

//add a light with location and size. Fifth arg is a color. By not passing in a BufferedImage as a fifth arg to use as a light, it will use a default one. Lightl = newLight(0,0,size,size, Themes.getColor(Themes.CYAN));//there are some vars and methods that will make the light do stuff. l.jump(window.mouseX, window.mouseY);l.decay = 0;l.intensity = 1;// and add the light to the lightmaplightmap.addLight(l);

//Then update the lightmaplightmap.update();//and finally render everything that will be effected by the lightmap first and then render the lightmapGraphics2Dg2d = window.begin();//draw stufflightmap.render(g2d);//render stuff not lit hereg2d.dispose();window.end();

The only thing that is left is to add blocks to the lightmap via

1

lightmap.cullers.add(newBlock(x,y,width,hieght)

These could be walls or a set of blocks for a player or other things.

Circle cullers are actually cheaper and the code has been done but they don't play well with blocks but for a player or sprite they would work great. If people want I can post the source in the shared code section and explain a little more on how it is done.

Like you say, generally Java2D is not a good way to go for this, but it's a nice learning experience. And it could give you some insight later down the road if you need to use HTML5 canvas or another platform that doesn't support shaders.

I'll piggyback on your thread by posting another approach in Java2D that I did for a school project. It's very basic, but fast enough.

The "falloff" is created with RadialGradientPaint. The trick is to just treat each entity as a circle. Alternatively, you could use classic "shadow boundary" technique described by Orangy Tang to get a more accurate geometry; in brief it looks like this:https://gist.github.com/mattdesl/5287255

Basic idea is finding the corner points of the squares and creating a polygon from that based on the points angle to the light. Cool thing is that this supports baking lights. Basically, find the shadows, bake to BufferedImage, and render said image. This is a huge performance boost as you lose the fully dynamic lights but gain static fake dynamic lights.

The Idea I chose was to, from the light source and the picture contour, create a polygon in real time and in an intermediate volatileimage, remove the polygon to the light sprite with the AlphaComposite.SRC_OUT. If you are interested in some details just ask me

Absolutely! That is so close to what I am doing. How are you creating the polygon from the image contours? How fast is it? How many lights can you have? Are you using an image as the light or drawing a gradient? Right now I can do 200 lights that are 256x256 in size where after I hit a fillrate limit. So basically, no limit on the number of lights.

Once you have the light source location and the location of the polygon, you can create these fake shadows for each facet of the polygon. I optimized this by just creating a complex polygon which is composed by all the exposed object facets plus the shdow projection. If I have time I will try to clean up some code and post it here

After some thinking and optimizations you can reach nice performance. Not 300 lights of course, but maybe 5-6 lights with a few tens of objects in screen is feasible (on a mid-end card). The biggest limitation here is the shadow rendering, (not the calculation, just the "drawpolygon"). If you have to render 10 shadows per light, you will become limited by fillrate, specially on lowend cards like intedl HD3000 (I works sooo bad with java2D).

For the light I use an existing image, as you did in your older posts about this. It works fine.

Also, you can get smoother shadows by doing the following, it is like a "cheap" antialias. It draws a traslucent shadow contour several time before drawing the shadow.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

privatevoidpaintShadow(Graphics2Dgbsombras){

//"remove" contains the shadow polygon//"gbsombras" is the target graphics2D

So how to you cast the shadow? Right now I am using the java Area class which is very slow for constructing the shadow. Please do post code. I also would love to see how you create these polygons. Are they done in real time? or pre-computed.

That anti-aliasing is not cheap. Java can draw quite a few Images fast. Things like polygon fills, and gradients, are much slower. I have an idea for softish shadows that will be truly free. Need to test it. I can confirm that normally finding shadows is fast but drawing them is slow. I fixed this with volatile images. Now, very little to no penalty for size or number of objects.

On my laptop which I think is HD 3000 I have the most Fing weird bugs because the drivers are such shit. I have solved most and know what is going on but it pisses me off. On that one, I can get 100+ lights.

Do you combine all the shadows as you find them? This could allow you to cull things out if they are already blocked by a shadow caster but in my tests it is faster to just draw each shadow as you find it. Also, how did you solve the shadows of one gear not clipping on to another?

I cast the shadow using some trigonometry. If you know the location of a polygon point and the location of the light source, you can get the expression of the line that connects them. This line is one of the rays casted by the shadow.

I use polygons, not areas. I just add points to that Polygon and then I send the polygon to render. Pretty fast and simple.

I calculate all the shadow polygons in real time, it is not very resource consuming. This is some graphical sample of what I do. lines p3-p4 and p2-p4 are ignored as they are in the back of the object.

I agree with you that

This is part of the code (removed some non important stuff) . It is a mess and it is full of spanish variable names, so it may be quite confusing for you. I will try to fix this some day. Anyways I hope that you will get the general idea.

//I call this method n times for each light, where n is the number of objects inside the scene

//ii: object number ii of the scene//luz_baseX,int luz_base, screen location of the light//distancia_fuera: distance of shadow trail//lightScale: scale of the light//gsombras: volatileimage where I store all the shadows//dimMaxMedia: size/ of the light

//for each point of the polygonwhile(cont<quita.npoints){booleanactual_shadow=true;

//move point 2 to point 1pto1_x=pto2_x;pto1_y=pto2_y;

//read a new point from the polygonif (pos<quita.npoints-1) {pto2_x=((quita_baseX+quita.xpoints[pos+1]));pto2_y=((quita_baseY+quita.ypoints[pos+1]));}else {pto2_x=((quita_baseX+quita.xpoints[0]));pto2_y=((quita_baseY+quita.ypoints[0]));}

//the line between these two points creales a line. is this line in the front side of the object or in the back side//if it is in the back side it should not project a light (useless)

//we calculate the bisector and we move us 4 pixels from the middle of the line to the line in the direction of the bisector.//is we are inside the polygon we don't project a shadow, othwerwise we project it

Sweet. I am not sure if you do this already but give the lights a max radius and check if a shadow caster is inside before you add its shadow. You cull out points but you could drop the whole shape much faster.

I do the exact same thing with circles and squares. I only used areas with general polys as I could not solve the issue where a object casts a light on its self. I can get the front or back facing polys very very fast. The issues is when the object has an edge that could occlude an inner part of itself. Normally you project the points furthest (perpendicular from the center point of the shape and light point) out; p2 and p3 in your picture. But if you get some edge that protrudes out. Ray casting deals with these but requires checking if a ray intersects the shape and the point of said intersection to form the polygon shadow.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org