3D shader Question

i need to use a shader as a fog type thing in my 3d game

I would like to make it so that anything around the camera is light but the further away it is the darker it gets

I do not understand how to apply the shader to the map. I’ve tried researching it but have found no documentation thus far and would be gratified if you could help me!

Thanks in advance!

-Toxyn

The shader

function setup()
    m=mesh()
    img=readImage("Small World:Icon")
    m:addRect(0,0,img.width*3,img.height*3)
    m:setColors(color(255))
    m.texture=img
    m.shader=shader(DistanceShader.vertexShader,DistanceShader.fragmentShader)
    parameter.number("distance",0,2000,1000)
    parameter.boolean("Fog",true)
    dist={z=200} --we have to use a table of pairs with tweens
    
    output.clear()
    print("Adjust fog (or dark) based on distance")   
    print("The distance slider sets the distance where everything becomes invisible")                                 
end
 
function draw()
    if Fog then background(162, 162, 162, 255) else background(0) end
    perspective()
    camera(0,0,0,0,0,-1000)
    m.shader.visibility = 1 - math.min(1,dist.z/distance)
    m.shader.fog=Fog
    pushMatrix()
      translate(0,0,-dist.z)
      m:draw()
    popMatrix()
end
 
DistanceShader = {
 
vertexShader = [[
 
uniform mat4 modelViewProjection;
uniform float visibility;
uniform bool fog;
 
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
 
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
 
void main()
{
    if (fog) vColor=vec4( color.rgb, color.a ) * visibility;
    else vColor=vec4( color.rgb * visibility, color.a );
    vTexCoord = texCoord;
    gl_Position = modelViewProjection * position;
}
 
]],
 
fragmentShader = [[
 
precision highp float;
 
uniform lowp sampler2D texture;
 
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
 
void main()
{
    lowp vec4 col = texture2D( texture, vTexCoord)*vColor;
    gl_FragColor = col;
}
 
]]}                                       

My code

--# Main


-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
function setup()
    music("A Hero's Quest:Dungeon", true)
    stick = Stick()
    anglex=0
    angley=0
    pylon = Wall("Documents:grate")
    wall = Wall("Documents:marble")
    floor = Floor("Documents:white floor")

sprite("Documents:BG_Gradient")
    world = World()
    hero = Hero(3,3)
    time = 0
    TO_DEG = 180/math.pi


end

-- This function gets called once every frame
function draw()

    background(76, 76, 76, 255)


    font("Arial-BoldMT")
    fill(255, 0, 236, 255)
    fontSize(20)
    time = time +0.02
    
    local TO_DEG = TO_DEG
    local hero = hero
    perspective(60)
     a=math.rad(anglex)
    x, z=math.sin(a) *1000, -math.cos(a)*1000
     b=math.rad(angley)
    y=math.sin(b) *1000, -math.cos(b)*1000
    camera(hero.x,0,hero.z,  x,y,z)

   pushMatrix()
    world:draw()
    popMatrix()

-- Draw hero



    -- roll animation
    if stick.active then
        rotate(-ElapsedTime*10*TO_DEG/2, 0, 0, 1)
    end

    scale(.25, .25, .25)
    hero:draw()

-- Restore orthographic projection
    ortho()
    viewMatrix(matrix())
    resetMatrix()

    --fade out overlay
    sprite("Cargo Bot:Background Fade", WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)


    if stick.active then
        local ceil = math.ceil
        stick:draw()

        -- move hero if stick is used
       
        local mvt = (vec2(hero.x-x,hero.z-z):normalize())/50 * stick.dist
        hero.x = hero.x + 0-mvt.x
        hero.z = hero.z + 0-mvt.y

        -- convert to table coordinates
        hero.px = ceil(hero.x - .5)
        hero.py = ceil(hero.z - .5)

        -- lazy collision check
        if world.data[hero.py][hero.px] ~= 0 then
            hero.x = hero.x + mvt.x
            hero.z = hero.z + mvt.y
            hero.px = ceil(hero.x + .5)
            hero.py = ceil(hero.z + .5)
        end
    end
end

function touched(touch)

    if touch.x<WIDTH/2 then stick:touched(touch) else
     anglex = anglex +touch.deltaX/3
        angley = angley + touch.deltaY/3
    end
end



--# World
World = class()

function World:init()

    -- define the world
    self.data =
    {
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
        {1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1},
        {1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1},
        {1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1},
        {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1},
        {1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1},
        {1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
        {1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1},
        {1, 1, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
        {1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}

    }
end

function World:draw()
    local floor, wall, pylon = floor, wall, pylon
    local offSet = 10
    local px, py = hero.px, hero.py

    -- look around the hero to draw whatever is around him
    translate(px - offSet, 0, py - offSet)
    for y = py - offSet, py + offSet do
        for x = px - offSet, px + offSet do
            if self.data[y] then
                local val = self.data[y][x]
                if val == 0 then
                    floor:draw()
                elseif val == 1 then
                    wall:draw()
                elseif val == 2 then
                    pylon:draw()
                end
            end
            translate(1,0,0)
        end
        translate(-(1 + 2 * offSet), 0, 1)
    end
end



--# Hero
Hero = class()

function Hero:init(x, z)
    self.x, self.y, self.z = x,0,z
    self.px, self.py = math.ceil(.5+x), math.ceil(.5+z)

    self.mdl = Wall("Documents:StoneTile")
    sprite("Documents:BG_Gradient")
end

function Hero:draw()
    self.mdl:draw()
end


--# Wall
Wall = class()


function Wall:init(tex)
    -- all the unique vertices that make up a cube
    local vertices =
    {
        vec3(-0.5, -0.5,  0.5), -- Left  bottom front
        vec3( 0.5, -0.5,  0.5), -- Right bottom front
        vec3( 0.5,  0.5,  0.5), -- Right top    front
        vec3(-0.5,  0.5,  0.5), -- Left  top    front
        vec3(-0.5, -0.5, -0.5), -- Left  bottom back
        vec3( 0.5, -0.5, -0.5), -- Right bottom back
        vec3( 0.5,  0.5, -0.5), -- Right top    back
        vec3(-0.5,  0.5, -0.5), -- Left  top    back
    }

    -- now construct a cube out of the vertices above
    local verts =
    {
        -- Front
        vertices[1], vertices[2], vertices[3],
        vertices[1], vertices[3], vertices[4],
        -- Right
        vertices[2], vertices[6], vertices[7],
        vertices[2], vertices[7], vertices[3],
        -- Back
        vertices[6], vertices[5], vertices[8],
        vertices[6], vertices[8], vertices[7],
        -- Left
        vertices[5], vertices[1], vertices[4],
        vertices[5], vertices[4], vertices[8],
        -- Top
        vertices[4], vertices[3], vertices[7],
        vertices[4], vertices[7], vertices[8],
       -- Bottom
        vertices[5], vertices[6], vertices[2],
        vertices[5], vertices[2], vertices[1],
    }

    -- all the unique texture positions needed
    local texvertices =
    {
        vec2(0,0),
        vec2(1,0),
        vec2(0,1),
        vec2(1,1)
    }

    -- apply the texture coordinates to each triangle
    local texCoords =
    {
        -- Front
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Right
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Back
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Left
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Top
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Bottom
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
    }

    self.model = mesh()
    self.model.vertices = verts
    self.model.texture = tex
    self.model.texCoords = texCoords
    self.model:setColors(255,255,255,255)
end

function Wall:draw()
    self.model:draw()
end

--# Floor
Floor = class()

function Floor:init(tex)
    -- all the unique vertices that make up a cube
    local vertices =
    {
        vec3( 0.5,  -0.5,  0.5), -- Right top    front
        vec3(-0.5,  -0.5,  0.5), -- Left  top    front
        vec3( 0.5,  -0.5, -0.5), -- Right top    back
        vec3(-0.5,  -0.5, -0.5), -- Left  top    back
    }


    -- now construct a cube out of the vertices above
    local verts =
    {
        -- Bottom
        vertices[3], vertices[4], vertices[2],
        vertices[3], vertices[2], vertices[1],
    }

    -- all the unique texture positions needed
    local texvertices =
    {
        vec2(0,0),
        vec2(1,0),
        vec2(0,1),
        vec2(1,1)
    }

    -- apply the texture coordinates to each triangle
    local texCoords =
    {
        -- Bottom
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
    }

    self.model = mesh()
    self.model.vertices = verts
    self.model.texture = tex
    self.model.texCoords = texCoords
    self.model:setColors(255,255,255,255)
end

function Floor:draw()
    self.model:draw()
end


--# Stick
Stick = class()

function Stick:init()
    self.direction = 0
    self.dist = 0

    self.active = false
    self.origin = vec2(150, 150)
    self.center = self.origin
    self.pos = self.origin

    self.stick_bg = readImage("Space Art:Eclipse")
    self.stick = readImage("SpaceCute:Collision Circle")
    self.vec=vec2(0,0)
end

function Stick:draw()
    sprite(self.stick_bg, self.center.x, self.center.y)
    sprite(self.stick, self.pos.x, self.pos.y)
end

function Stick:touched(touch)
    if touch.state == BEGAN then
        self.center = vec2(touch.x, touch.y)
        self.active = true
    end

    self.pos = vec2(touch.x, touch.y)
    self.direction = math.atan2(self.pos.y - self.center.y, self.pos.x - self.center.x)
    self.dist = math.min(2, self.pos:dist(self.center)/32)
    self.vec=(self.center-self.pos):normalize()
    print(self.vec)
    if touch.state == ENDED then
        self.center = self.origin
        self.pos = self.center
        self.active = false
    end


end

bump

Look at the shader posts on my blog, or my ebook on shaders

@Ignatz I read your ebook. Is you blog the coolcodea thing?

if you read my ebook, it has an example of a fog shader

That’s the fog shader I’m using but I don’t know how to apply it to an area around the character

The area needs to be a mesh, then you attach the shader to the mesh as shown in my example. Everything affected by the fog needs to be drawn using the shader.

I think I understand how to do it, I’ll have to fiddle around with its giblets and see if I can do it! Thanks!