Is there a way to make a fog effect with shaders, where the farther away a mesh is, the more fuzzy and less visible it is?
Could you specify a bit more, do you mean the device, or a part of the program
I think he means the picture gets less clear, into the distance, if the air is foggy - like in real life
This needs a shader that uses the distance to set the strength of the fuzzy effect. Unfortunately, I don’t know how to do that.
I am not sure how to use shaders yet but from what I know I made this code it does work like fog.
You could do the beautification of it if you want but here’s the concept. I have one question how can we post videos out here? BTW this ones for 3D I don’t think there can be fog for 2D. I copy pasted from shader demo and added a moving effect but I have no idea how it works.
--# Main
function setup()
img = readImage("Cargo Bot:Codea Icon")
w,h = img.width/2,img.height/2
m = mesh()
m.vertices = {vec3(-w,-h,0),vec3(-w,h,0),vec3(w,-h,0),
vec3(-w,h,0),vec3(w,-h,0),vec3(w,h,0)}
m.texCoords = {vec2(0,0),vec2(0,1),vec2(1,0),vec2(0,1),vec2(1,0),vec2(1,1)}
m.texture = img
w,h = WIDTH/2,HEIGHT/2
fogg = readImage("Platformer Art:Cloud 3")
fog = mesh()
fog.vertices = {vec2(0,0),vec2(0,h),vec2(w,0),vec2(w,0),vec2(0,h),vec2(w,h)}
fog.texCoords = {vec2(0,0),vec2(0,1),vec2(1,0),vec2(1,0),vec2(0,1),vec2(1,1)}
fog.texture = fogg
Ex,Ey,Ez = 0,0,0
parameter.watch("dist")
end
function draw()
--fog,Position = vec3(0,0,-2000)
--ourPosition = vec3(Ex,Ey,Ez)
distance = vec3(Ex,Ey,Ez) - vec3(0,0,-2000)
dist = distance:len()/8
background(0, 0, 0, 255)
fill(255)
perspective(45,WIDTH/HEIGHT)
Ez = Ez-5
camera(Ex,Ey,Ez,0,0,-2000,0,1,0)
pushMatrix()
translate(0,0,-2000)
m:draw()
popMatrix()
ortho()
viewMatrix(matrix())
fog:setColors(255,255,255,dist)
pushMatrix()
translate(WIDTH-200,HEIGHT/2)
rotate(180)
fog:draw()
popMatrix()
pushMatrix()
translate(WIDTH/2-200,HEIGHT/2)
fog:draw()
popMatrix()
end
Or an Easier method. I think this one looks better if you don’t want to put much effort make the fog look better and you know more foggy with patches here and there. But I don’t know how to make the mesh blurry with distance.
--# Main
function setup()
img = readImage("Cargo Bot:Codea Icon")
w,h = img.width/2,img.height/2
m = mesh()
m.vertices = {vec3(-w,-h,0),vec3(-w,h,0),vec3(w,-h,0),
vec3(-w,h,0),vec3(w,-h,0),vec3(w,h,0)}
m.texCoords = {vec2(0,0),vec2(0,1),vec2(1,0),vec2(0,1),vec2(1,0),vec2(1,1)}
m.texture = img
m.shader = shader("Effects:Ripple")
Ex,Ey,Ez = 0,0,0
end
function draw()
--fog,Position = vec3(0,0,-2000)
--ourPosition = vec3(Ex,Ey,Ez)
distance = vec3(Ex,Ey,Ez) - vec3(0,0,-2000)
dist = distance:len()/8
background(0, 0, 0, 255)
fill(255)
perspective(45,WIDTH/HEIGHT)
Ez = Ez-5
camera(Ex,Ey,Ez,0,0,-2000,0,1,0)
pushMatrix()
translate(0,0,-2000)
m:setColors(255,255,255,255-dist)
m.shader.time = ElapsedTime
m.shader.freq = dist/600
m:draw()
popMatrix()
end
No, I had double pasted by mistake so the code got messed up I edited it and I couldn’t use the shader effect in first code where there was fog so I wrote it in the second code. Shader effect is only in second code. And how can I post a video out here?
I think you left out the fog class, and the shader
iif you record it in Codea and save it to your photo album, you can post it to Youtube straight from there
But how should I post it here on the forum?
YouTube will give you a link to your video which you can post on the forum
The way I do it is to upload the video to Youtube from the photo library, then when I’m asked if I want I share it, I choose email, which gives me a draft email with the link in it, then I copy the URL out of there.
Thanks Saurabh!
So, it appears that shaders are unique to each individual mesh.
That means you couldn’t have a generic “fog shader” in a certain location, and any mesh that passes behind it looks like it’s in fog. Right?
Yeah that’s the way I know about. Hope it helped.
Guess what, my first shader - for fog
There is only one setting, the z distance at which everything disappears. This is used in DrawMesh to mix the normal image and my fog image (mostly white). A random number is used to create a bit of swirl
The shader mixes the normal image and fog image together, but only for pixels which are not blank.
--# Main
function setup()
vanishZ=800 --z value at which fog makes things invisible
fog=CreateFog(128,10,1000)
m={}
m[1] = createImageMesh("Planet Cute:Character Princess Girl")
m[2] = createImageMesh("Planet Cute:Character Boy")
m[3] = createImageMesh("Planet Cute:Character Pink Girl")
count=0
end
function CreateFog(s)
local img=image(s,s)
setContext(img)
fill(220,220,220,240)
rect(1,1,s,s)
setContext()
return img
end
function createImageMesh(i,d)
local img = readImage(i)
local w,h = img.width/2,img.height/2
local m = mesh()
m.vertices = {vec3(-w,-h,0),vec3(-w,h,0),vec3(w,-h,0),
vec3(-w,h,0),vec3(w,-h,0),vec3(w,h,0)}
m.texCoords = {vec2(0,0),vec2(0,1),vec2(1,0),vec2(0,1),vec2(1,0),vec2(1,1)}
m.texture = img
m.shader= shader(fogShader.vertexShader, fogShader.fragmentShader)
--m.shader.texture2=fog
return m
end
function draw()
count=count+1
background(220)
fill(255)
perspective(45,WIDTH/HEIGHT)
camera(0,200,200,0,0,-800,0,1,0)
drawMesh(1,-100,200+count/3)
drawMesh(2,0,500-count/3)
drawMesh(3,150,800-count/3)
end
function drawMesh(i,x,z)
pushMatrix()
translate(x,0,-z)
m[i].shader.texture2=fog
m[i].shader.mixAmount=math.min(1,z/vanishZ+math.random()*.05)
m[i]:draw()
popMatrix()
end
--# Fog
fogShader = {
vertexShader = [[
//
// A basic vertex shader
//
//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;
//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
//Pass the mesh color to the fragment shader
vColor = color;
vTexCoord = texCoord;
//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
//
// A basic fragment shader
//
//Default precision qualifier
precision highp float;
//This represents the current texture on the mesh
uniform lowp sampler2D texture;
//This texture will be rendered atop the first
uniform lowp sampler2D texture2;
//This is the amount to mix the two textures
uniform float mixAmount;
//The interpolated vertex color for this fragment
varying lowp vec4 vColor;
//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;
void main()
{
//Sample the texture at the interpolated coordinate
lowp vec4 col1 = texture2D( texture, vTexCoord );
lowp vec4 col2 = texture2D( texture2, vTexCoord );
if (col1.a>0.)
gl_FragColor = mix(col1, col2, mixAmount);
else gl_FragColor = col1;
}
]]}
Actually, it is just the code for the blend (2 images together) shader, with a one line change (3rd from the bottom above). Instead of blending the two images for every pixel, it only does it if the alpha is non zero (so it only puts fog on the used part of your images, not on the transparent pixels around them, otherwise you get gray rectangles).
Then all you need to do is vary the mix of the two images (which the shader already let you do) in your draw function, so the fog is greater with distance.
So it’s not actually too difficult (or else I couldn’t have done it). I will write this up soon, because I’m starting to think mere mortals like me can maybe write simple shaders. Maybe.
Yeah, all this graphics stuff is a bit scary. But like most things, if you keep working at it, it gets easier.
Darn, that’s awesome
Here’s a shader that flips the image horizontally depending on the parameter value
--# Main
function setup()
parameter.boolean("Flip",false)
m = createImageMesh("Planet Cute:Character Princess Girl")
end
function createImageMesh(i,d)
local img = readImage(i)
local w,h = img.width/2,img.height/2
local m = mesh()
m.vertices = {vec3(-w,-h,0),vec3(-w,h,0),vec3(w,-h,0),
vec3(-w,h,0),vec3(w,-h,0),vec3(w,h,0)}
m.texCoords = {vec2(0,0),vec2(0,1),vec2(1,0),vec2(0,1),vec2(1,0),vec2(1,1)}
m.texture = img
m.shader= shader(flipShader.vertexShader, flipShader.fragmentShader)
m.shader.flipper=0
return m
end
function draw()
background(220)
fill(255)
perspective(45,WIDTH/HEIGHT)
camera(0,200,200,0,0,-400,0,1,0)
pushMatrix()
translate(0,0,-300)
if Flip==true then m.shader.flip=1 else m.shader.flip=0 end
m:draw()
popMatrix()
end
function drawMesh(i,x,z)
end
--# Flip
flipShader = {
vertexShader = [[
//
// A basic vertex shader
//
//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;
//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
uniform float flip;
//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
//Pass the mesh color to the fragment shader
vColor = color;
if (flip == 1.)
vTexCoord = vec2(1.-texCoord.x,texCoord.y);
else
vTexCoord = texCoord;
//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
//
// A basic fragment shader
//
//Default precision qualifier
precision highp float;
//uniform float flip;
//This represents the current texture on the mesh
uniform lowp sampler2D texture;
//The interpolated vertex color for this fragment
varying lowp vec4 vColor;
//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;
void main()
{
//Sample the texture at the interpolated coordinate
lowp vec4 col1 = texture2D( texture, vTexCoord );
gl_FragColor = col1;
}
]]}
I am writing a post about the little I know about shaders, I should have it done in the next day with several examples like this