无限网格
一个平面,没有任何纹理。fwidth 让每条线无论相机多远都保持一个像素宽。
上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。
用到的 Godot 类
PlaneMeshShaderMaterialCamera3D
代码
scripts/main.gd
extends Node
var camera: Camera3D
var elapsed: float = 0.0
func _ready() -> void:
_add_environment()
_add_light()
var mesh: PlaneMesh = PlaneMesh.new()
mesh.size = Vector2(120, 120)
var material: ShaderMaterial = ShaderMaterial.new()
material.shader = Get.shader('grid')
var floor_plane: MeshInstance3D = MeshInstance3D.new()
floor_plane.mesh = mesh
floor_plane.material_override = material
add_child(floor_plane)
for i in 5:
_add_marker(Vector3(cos(i * 1.25) * 6.0, 0.6, sin(i * 1.25) * 6.0), float(i) / 5.0)
camera = Camera3D.new()
camera.position = Vector3(0, 3.4, 10)
add_child(camera)
camera.look_at(Vector3(0, 0.5, 0), Vector3.UP)
camera.current = true
print('one plane, no texture: fwidth keeps the line one pixel wide at any distance')
func _process(delta: float) -> void:
elapsed += delta
camera.position = Vector3(sin(elapsed * 0.2) * 10.0, 3.4, cos(elapsed * 0.2) * 10.0)
camera.look_at(Vector3(0, 0.5, 0), Vector3.UP)
func _add_marker(at: Vector3, hue: float) -> void:
var mesh: BoxMesh = BoxMesh.new()
mesh.size = Vector3(1.2, 1.2, 1.2)
var material: StandardMaterial3D = StandardMaterial3D.new()
material.albedo_color = Color.from_hsv(hue, 0.5, 0.95)
material.roughness = 0.4
var marker: MeshInstance3D = MeshInstance3D.new()
marker.mesh = mesh
marker.material_override = material
marker.position = at
add_child(marker)
func _add_environment() -> void:
var env: Environment = Environment.new()
env.background_mode = Environment.BG_COLOR
env.background_color = Color(0.02, 0.02, 0.04)
env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
env.ambient_light_color = Color(0.12, 0.14, 0.2)
env.ambient_light_energy = 1.0
env.glow_enabled = true
var world: WorldEnvironment = WorldEnvironment.new()
world.environment = env
add_child(world)
func _add_light() -> void:
var light: DirectionalLight3D = DirectionalLight3D.new()
light.rotation_degrees = Vector3(-55, -30, 0)
light.light_energy = 1.0
add_child(light)shaders/grid.gdshader
shader_type spatial;
render_mode cull_disabled;
uniform vec3 line_color: source_color = vec3(0.55, 0.65, 0.95);
uniform vec3 floor_color: source_color = vec3(0.04, 0.05, 0.08);
uniform float cell_size = 1.0;
uniform float line_width = 1.4;
uniform float fade_distance = 40.0;
varying vec3 world_position;
float grid_line(vec2 position, float size) {
vec2 cell = abs(fract(position / size - 0.5) - 0.5) / fwidth(position / size);
return 1.0 - min(min(cell.x, cell.y) / line_width, 1.0);
}
void vertex() {
world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
void fragment() {
float thin = grid_line(world_position.xz, cell_size);
float thick = grid_line(world_position.xz, cell_size * 10.0);
float distance_fade = 1.0 - clamp(length(world_position.xz) / fade_distance, 0.0, 1.0);
float line = max(thin * 0.35, thick) * distance_fade;
ALBEDO = mix(floor_color, line_color, line);
EMISSION = line_color * line * 0.6;
ROUGHNESS = 0.9;
}