OFFICIAL Realtime 2D lighting - Part 2

Mike

nobody important
GMC Elder
The second part of the realtime 2D lighting Tech Blog is now live.

Realtime 2D Lighting in GameMaker Studio 2 - Part 2

"In the last post, I showed you how to create the fundamentals of a 2D lighting system, so in this one I want to carry on the current example and make it more like an actual point light. We'll also introduce a little shader use to help make things a little easier - yes shaders can be easy! - and then make the light coloured. "


http://www.yoyogames.com/blog/420
 

Andrey

Member
That's great, Mike!
And the continuation of the post will be?

The technology of light reflection is very interesting. Then it will be possible to make different materials: metal, stones and other and realistic lighting in 2d.
 

Attachments

Kyon

Member
Very nice tutorial! Thanks!
How hard / fpsconsuming will this be to do with objects instead of tiles, and more abstract shapes?
 

Le Don

Member
Hey, great tutorial overall, but I got stuck in the end and need some help - I hope, it's alright if I post this here. I'm stuck when setting up multiple lights and as great as the turial is, it gets unfortunately quite vague at the end. I couldn't manage to set a the right blend mode, after I tried every combination with gpu_set_blend_mode_ext and then I tried to change to handle every light to the shader and adjust it accordingly. But now it seems the shadows are casting shadows on each other.

Here's the code for my shader:
Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
varying vec2 v_vScreenPos;

const int counterLights = 4;

uniform vec3 u_fLightPositionRadius[counterLights];

uniform float  u_fLightPosX[counterLights];
uniform float  u_fLightPosY[counterLights];
uniform float  u_fLightRadius[counterLights];

void main() {
   float lightValue = 1.0;
   for (int i = 0; i < counterLights; i++) {
       float posX = u_fLightPosX[i];
       float posY = u_fLightPosY[i];
       float radius = u_fLightRadius[i];

       vec2 vect = vec2(v_vScreenPos.x - posX, v_vScreenPos.y - posY);
       float dist = sqrt(vect.x * vect.x + vect.y * vect.y);

       if (dist < radius) {
           float fallout = dist / radius;
         
           lightValue = min(lightValue, fallout);
       }
   }

   if (lightValue == 1.0) {
       gl_FragColor = vec4(0.0, 0.0, 0.0, 0.7);
   } else {
       gl_FragColor = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord);
       gl_FragColor = mix(gl_FragColor, vec4(0.0, 0.0, 0.0, 0.7), lightValue);
   }
}
and my Light Controller:
Code:
if( !surface_exists(surf) ){
    surf = surface_create(room_width,room_height);
}


surface_set_target(surf);
draw_clear_alpha(0,0);

vertex_begin(VBuffer, VertexFormat);


lightCounter = 0;
with (obj_light) {
   var lx = x + sprite_width / 2;       // the light position, based around the mouse location
   var ly = y + sprite_height / 2;
   var tile_size = 32;     // size of a tile
   var tilemap = layer_tilemap_get_id("Floor_1_Walls");

   var startx = floor((lx-rad)/tile_size);
   var endx = floor((lx+rad)/tile_size);
   var starty = floor((ly-rad)/tile_size);
   var endy = floor((ly+rad)/tile_size);

   /*other.lights[other.lightCounter, 0] = lx;
   other.lights[other.lightCounter, 1] = ly;
   other.lights[other.lightCounter, 2] = rad;*/
 
   other.lights[other.lightCounter] = lx;
   other.lights[other.lightCounter] = ly;
   other.lights[other.lightCounter] = rad;
 
   other.lightsX[other.lightCounter] = lx;
   other.lightsY[other.lightCounter] = ly;
   other.lightsR[other.lightCounter] = rad;
   other.lightCounter++;

   for(var yy=starty;yy<=endy;yy++)
   {
       for(var xx=startx;xx<=endx;xx++)
       {
           var tile = tilemap_get(tilemap,xx,yy);
           if( tile!=0 )
           {
               // get corners of the
               var px1 = xx*tile_size;     // top left
               var py1 = yy*tile_size;
               var px2 = px1+tile_size;    // bottom right
               var py2 = py1+tile_size;


               if( !SignTest( px1,py1, px2,py1, lx,ly) ){
                   ProjectShadow(other.VBuffer,  px1,py1, px2,py1, lx,ly );
               }
               if( !SignTest( px2,py1, px2,py2, lx,ly) ){
                   ProjectShadow(other.VBuffer,  px2,py1, px2,py2, lx,ly );
               }
               if( !SignTest( px2,py2, px1,py2, lx,ly) ){
                   ProjectShadow(other.VBuffer,  px2,py2, px1,py2, lx,ly );
               }
               if( !SignTest( px1,py2, px1,py1, lx,ly) ){
                   ProjectShadow(other.VBuffer,  px1,py2, px1,py1, lx,ly );                   
               }                 
           }
       }
   }
}

vertex_end(VBuffer); 
vertex_submit(VBuffer,pr_trianglelist,-1);
surface_reset_target();

shader_set(sh_shadow);
shader_set_uniform_f_array(LightPosRadius, lights);

shader_set_uniform_f_array(LightPosX, lightsX);
shader_set_uniform_f_array(LightPosY, lightsY);
shader_set_uniform_f_array(LightRadius, lightsR);

draw_surface(surf,0,0);
shader_reset();
It would be great, if some could nudge me in the right direction and I apologize, if that's not the right place to post this.

EDIT: I forgot the screenshot.
 

Attachments

A

almost

Guest
Hello , i love your engine, your tuto is very good but i can't follow all steps, i am french and sure its simple english but i am realy blocked, so i have start but the step of the end of part 1 , and part 2 is more dificult for me ( my english is not very good ) so i have take the code of that topic : https://www.reddit.com/r/gamemaker/comments/757u4y/cannot_figure_out_the_realtime_2d_lighting_in/
But sure it does'nt work ...
Plz it is possible to have all of the code ? and sure i will work a lot to know how your code work but now i cant :/ or a translate tuto in french :)
 
Top