Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Global illumination in 2D

edited September 2017 in Code Sharing Posts: 105

If you happen to be working on a 2D top-down game and want some global illumination on top of that, say no more! Actually, if you find something to be terribly wrong or confusing in the code then please tell me!

This project bakes diffuse global illumination for your scene where you define the resolution of the lightmap. It supports as many lightbounces as you like from sky, sun and emissive objects. The algorithm is based on path tracing and accelerated with a distance field in order to reduce waiting times and avoid crashing the program.

The code includes a tab called "ReadMe", read it!
Potential questions that you might have:
Q: Why does the lighting sometimes look bugged when I have calculated 1 bounce of light?
A: Calculate 1-2 more bounces and it will disappear!

Q: In my game the lighting is really dark, why?
A: Two words, gamma correction! Essentially our screens does not display light in a linear form, so when displaying colors we need to compensate.

Instead of:
gl_FragColor=vec4(Color,1.);
do
gl_FragColor=vec4(pow(Color,vec3(0.45)),1.);
This is correct!

Code:
https://github.com/firelava135/GIDF2D/blob/master/Code.txt

Here is an example:

Comments

  • Posts: 722

    Did anyone save this code? Link doesn’t work...

  • Posts: 588

    @UberGoober couldn't you just set up a 3d craft scene, but put all the objects on a plane. The light source could be above the plane.

  • Posts: 83

    @piinthesky can you make a boilerplate showing using an image on a plane?

  • Posts: 588

    @skar not sure exactly what you are after, but this illustrates what i was imagining: a plane with 3D objects sitting on it (cubes in this example) and the standard craft Sun lighting.....


    -- Demo plane with 3D cubes -- PiInTheSky, 3/4/21 -- requires orbitViewer from Cameras library function setup() parameter.integer("ambientIntensity",0,255,200) parameter.number("sunIntensity",0,10,5.0) -- Create a new craft scene scene = craft.scene() v=scene.camera:add(OrbitViewer,vec3(0,0,0), 1000, HEIGHT/2, 2000) v.camera.farPlane=3000 scene.ambientColor=color(ambientIntensity,ambientIntensity,ambientIntensity,255) sunLight=scene.sun:get(craft.light) -- sunLight.position=vec3(WIDTH/2, 1000,0) sunLight.intensity=sunIntensity -- create plane (a flat cube) yellow=color(233, 204, 80) planeSize=500 plane=createCube(vec3(0,0,0), vec3(planeSize*2,1, planeSize*2),yellow ) -- create many cubes for i=1,1000 do col=color(math.random()*255, math.random()*255, math.random()*255) cubeSize=20*math.random() y=cubeSize/2 createCube(vec3(math.random(-planeSize,planeSize),y,math.random(-planeSize,planeSize)), vec3(1,1,1)*cubeSize, col) end end function createCube(pos,size,col) local c=scene:entity() c.position=vec3(pos.x,pos.y,pos.z) c.model = craft.model.cube(size) -- c.material = craft.material("Materials:Specular") c.material = craft.material(asset.builtin.Materials.Standard) c.material.diffuse=col return c end function update(dt) scene.ambientColor=color(ambientIntensity,ambientIntensity,ambientIntensity,255) sunLight.intensity=sunIntensity scene:update(dt) end function draw() update(DeltaTime) scene:draw() end function touched(touch) v:touched(touch) end
  • Posts: 83

    I’m trying to find ways to do lighting in 2D not 3D, but I thought you meant to put a 2D image as a texture onto a plane and use the 3D lights on it, but that’s not going to work in the desired way.

    https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6

  • Posts: 588

    @skar gotcha, here is a little demo of lighting effects using the inbuilt surfaces: Basic Bricks, Stone Brick and Desert Cliff. Quite fun to see the effect of the varying the different parameters. I expect with Shade one could do a lot more.

    -- Demo textures
    -- PiInTheSky, 3/4/21
    -- requires orbitViewer from Cameras library
    
    function setup()
        stoneBrick=true
        basicBricks=false
        desertCliff=false
    
        parameter.integer("ambientIntensity",0,255,200)
        parameter.number("sunIntensity",0,10,5.0)     
    
        parameter.number("opacity",0,1,1.0)
        parameter.number("normalScale",0,10,1.0)
        parameter.number("roughness",0,10,1.0)
        parameter.number("metalness",0,10,1.0)
        parameter.number("aoMapIntensity",0,10,1.0)
        parameter.number("displacementScale",0,10,1.0)
    
    -- Create a new craft scene    
        scene = craft.scene()   
        v=scene.camera:add(OrbitViewer,vec3(0,0,0), 1000, HEIGHT/2, 2000)
        v.camera.farPlane=3000
    
        scene.ambientColor=color(ambientIntensity,ambientIntensity,ambientIntensity,255)
        sunLight=scene.sun:get(craft.light)
    --    sunLight.position=vec3(WIDTH/2, 1000,0)
        sunLight.intensity=sunIntensity
    
    -- create plane (a flat cube)
        yellow=color(233, 204, 80)
        planeSize=500
        e=createCube(vec3(0,0,0), vec3(planeSize*2, planeSize*2, 1), yellow )
    
        -- Load the standard material (physically based rendering)
        m = craft.material(asset.builtin.Materials.Standard)
    --    m = craft.material(asset.builtin.Materials.Specular)
        e.material = m
    
        -- Surface color
        m.diffuse = color(255, 255, 255)
        -- Opacity (0.0 fully transparent, 1.0 fully opaque)
        m.blendMode=NORMAL
        m.opacity = opacity
    
        if basicBricks then 
            -- Surface color texture map
            m.map = "Surfaces:Basic Bricks Color"
            -- Normal map for small scale surface details
            m.normalMap = "Surfaces:Basic Bricks Normal"
            -- A texture that controls the roughness
            m.roughnessMap = "Surfaces:Basic Bricks Roughness"
            -- The ambient occlusion map, used for self-occluding shadows
            m.aoMap = "Surfaces:Basic Bricks AO"
            -- A texture that controls how metallic the surface is
            m.metalnessMap = nil
            -- The displacement map which modifies vertex positions based on normals
            m.displacementMap = nil
        end
    
        if stoneBrick then 
            -- Surface color texture map
            m.map = "Surfaces:Stone Brick Color"
            -- Normal map for small scale surface details
            m.normalMap = "Surfaces:Stone Brick Normal"
            -- A texture that controls the roughness
            m.roughnessMap = "Surfaces:Stone Brick Roughness"
            -- The ambient occlusion map, used for self-occluding shadows
            m.aoMap = "Surfaces:Stone Brick AO"
            -- A texture that controls how metallic the surface is
            m.metalnessMap = "Surfaces:Stone Brick Metalness"
            -- The displacement map which modifies vertex positions based on normals
            m.displacementMap = "Surfaces:Stone Brick Height"
        end    
    
        if desertCliff then
            -- Surface color texture map
            m.map = "Surfaces:Desert Cliff Color"
            -- Normal map for small scale surface details
            m.normalMap = "Surfaces:Desert Cliff Normal"
            -- A texture that controls the roughness
            m.roughnessMap = "Surfaces:Desert Cliff Roughness"
            -- The ambient occlusion map, used for self-occluding shadows
            m.aoMap = "Surfaces:Desert Cliff AO"
            -- A texture that controls how metallic the surface is
            m.metalnessMap = "Surfaces:Desert Cliff Metalness"
            -- The displacement map which modifies vertex positions based on normals
            m.displacementMap = "Surfaces:Desert Cliff Height"
        end
    
        -- The environment map (a CubeTexture), specular illumination
        m.envMap = nil
    
        -- Texture map offset and repeat (tiling)
        m.offsetRepeat = vec4(0.0, 0.0, 3.0, 3.0)
        -- Base offset of the displacement map
        m.displacementBias = 0
        -- Scale of the displacement map
        m.displacementScale = displacementScale
    
    end
    
    function createCube(pos,size,col)
        local c=scene:entity()
        c.position=vec3(pos.x,pos.y,pos.z)
        c.model = craft.model.cube(size)
    --    c.material = craft.material("Materials:Specular")
        c.material = craft.material(asset.builtin.Materials.Standard)
        c.material.diffuse=col
        return c
    end
    
    function update(dt)  
        scene.ambientColor=color(ambientIntensity,ambientIntensity,ambientIntensity,255)
        sunLight.intensity=sunIntensity
    
        -- Opacity (0.0 fully transparent, 1.0 fully opaque)
        m.opacity = opacity  
        -- How intense the normal map effect is in tangent space (also used for flipping)
        m.normalScale = vec2(1, 1)*normalScale
        -- How rough the material is
        m.roughness = roughness
        -- How metallic the material is
        m.metalness = metalness
        -- How intense the aoMap is
        m.aoMapIntensity = aoMapIntensity
        -- Scale of the displacement map
        m.displacementScale = displacementScale
    
        e.material = m
    
        scene:update(dt)
    end   
    
    function draw()
        update(DeltaTime)
        scene:draw()   
    end
    
    function touched(touch)  
        v:touched(touch) 
    end
    
    
  • Posts: 83

    This is really great, thanks for setting it up. It’s as I thought though, this solution probably is not what i want to do. I’ll have to play with it some to see if it’s the best solution but it seems to me we should be able to use Mesh and Shader to have a 2D light effect without having to use craft 3D

Sign In or Register to comment.