Ondas de calor
Ruído empurrando a UV da tela, mascarado para a metade de baixo para a diferença ficar fácil de ver.
O editor acima está rodando este projeto. Mude uma linha e ele recarrega.
Classes do Godot usadas
ColorRectNoiseTexture2DCanvasLayer
O código
scripts/main.gd
extends Node
func _ready() -> void:
_add_environment()
_add_light()
_add_ground()
for i in 7:
_add_pillar(Vector3(-6.0 + i * 2.0, 0, -2.0 - float(i % 3) * 3.0), float(i) / 7.0)
var camera: Camera3D = Camera3D.new()
camera.position = Vector3(0, 2.2, 8)
add_child(camera)
camera.look_at(Vector3(0, 1.4, 0), Vector3.UP)
camera.current = true
var layer: CanvasLayer = CanvasLayer.new()
layer.layer = 10
add_child(layer)
var material: ShaderMaterial = ShaderMaterial.new()
material.shader = Get.shader('haze')
material.set_shader_parameter('noise_texture', _make_noise())
var screen: ColorRect = ColorRect.new()
screen.material = material
layer.add_child(screen)
screen.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
print('the lower half wobbles, the top stays put so the difference is visible')
func _make_noise() -> NoiseTexture2D:
var noise: FastNoiseLite = FastNoiseLite.new()
noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
noise.frequency = 0.02
var texture: NoiseTexture2D = NoiseTexture2D.new()
texture.noise = noise
texture.seamless = true
texture.width = 256
texture.height = 256
return texture
func _add_pillar(at: Vector3, hue: float) -> void:
var mesh: BoxMesh = BoxMesh.new()
mesh.size = Vector3(1.1, 3.2, 1.1)
var material: StandardMaterial3D = StandardMaterial3D.new()
material.albedo_color = Color.from_hsv(hue * 0.15 + 0.05, 0.6, 0.95)
material.roughness = 0.6
var pillar: MeshInstance3D = MeshInstance3D.new()
pillar.mesh = mesh
pillar.material_override = material
pillar.position = at + Vector3(0, 1.6, 0)
add_child(pillar)
func _add_ground() -> void:
var mesh: PlaneMesh = PlaneMesh.new()
mesh.size = Vector2(60, 60)
var material: StandardMaterial3D = StandardMaterial3D.new()
material.albedo_color = Color('#3a2f26')
material.roughness = 0.95
var ground: MeshInstance3D = MeshInstance3D.new()
ground.mesh = mesh
ground.material_override = material
add_child(ground)
func _add_environment() -> void:
var sky_material: ProceduralSkyMaterial = ProceduralSkyMaterial.new()
sky_material.sky_top_color = Color(0.25, 0.35, 0.6)
sky_material.sky_horizon_color = Color(0.8, 0.7, 0.5)
sky_material.ground_bottom_color = Color(0.2, 0.16, 0.12)
sky_material.ground_horizon_color = Color(0.6, 0.5, 0.38)
var sky: Sky = Sky.new()
sky.sky_material = sky_material
var env: Environment = Environment.new()
env.background_mode = Environment.BG_SKY
env.sky = sky
env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
env.ambient_light_energy = 1.0
var world: WorldEnvironment = WorldEnvironment.new()
world.environment = env
add_child(world)
func _add_light() -> void:
var light: DirectionalLight3D = DirectionalLight3D.new()
light.rotation_degrees = Vector3(-60, -40, 0)
light.light_energy = 1.5
add_child(light)shaders/haze.gdshader
shader_type canvas_item;
uniform sampler2D screen_texture: hint_screen_texture, filter_linear;
uniform sampler2D noise_texture;
uniform float strength = 0.012;
uniform float speed = 0.35;
uniform float band_top = 0.25;
void fragment() {
vec2 flow = SCREEN_UV * vec2(2.0, 1.0) + vec2(0.0, -TIME * speed);
vec2 offset = texture(noise_texture, flow).rg * 2.0 - 1.0;
// only the lower band distorts, the top stays as a reference
float mask = smoothstep(band_top, band_top + 0.25, SCREEN_UV.y);
COLOR = vec4(texture(screen_texture, SCREEN_UV + offset * strength * mask).rgb, 1.0);
}