CylinderLine
extends Node3D
# 控制
@export var enable: bool = true:
set(value):
var was_enabled = enable
enable = value
if ready_called and enable != was_enabled:
if enable:
engage()
else:
disengage()
# 导出变量
@export var mainline: CharacterBody3D
@export var camera: Camera3D
@export var cylinder_tail_parent: Node3D
@export_group("Cylinder Settings")
@export var cylinder_reference_node: Node3D
@export var auto_update_cylinder: bool = true
@export var cylinder_radius: float = 14.5
@export var cylinder_center_offset: Vector3 = Vector3.ZERO
@export var cylinder_axis_direction: Vector3 = Vector3(1, 0, -1)
@export_group("Transform Offsets")
@export var position_offset: Vector3 = Vector3.ZERO
@export var rotation_offset: Vector3 = Vector3.ZERO
@export var initial_angle_degrees: float = 0.0
@export_group("Update Settings")
@export var update_per_frame: bool = true
@export_group("Spiral Motion Settings")
@export_enum("Fixed Angular Speed", "Fixed Pitch") var spiral_mode: int = 1
@export var spiral_angular_speed: float = 1.0
@export var spiral_pitch: float = 15.0
@export var spiral_enabled: bool = true
@export var use_independent_speed: bool = false
@export var forward_speed: float = 5.0
@export_group("Trail Settings")
@export var map_trails: bool = true
@export var trail_color: Color = Color.WHITE
@export var trail_emission: bool = false
@export var trail_emission_color: Color = Color.WHITE
@export var trail_emission_energy: float = 1.0
@export var min_segment_length: float = 0.01
# 内部变量
var cylinder_axis_point: Vector3
var cylinder_axis: Vector3
var last_mainline_position: Vector3
var current_angle: float = 0.0
var current_axial_progress: float = 0.0
var target_transform: Transform3D
var reference_direction: Vector3
var perpendicular_direction: Vector3
var current_cylinder_line: MeshInstance3D = null
var line_start_position: Vector3
var is_drawing: bool = false
var mainline_tail_node: Node3D = null
var last_mapped_position: Vector3
var has_last_mapped_position: bool = false
var cylinder_bend_shader: Shader
var cylinder_bend_material: ShaderMaterial
# 偏移变换
var rotation_offset_basis: Basis
# 螺旋运动相关
var spiral_direction: float = 1.0
# 状态标记
var ready_called: bool = false
var engage_flag: bool = false
var resources_initialized: bool = false
var last_cylinder_reference_position: Vector3
# 缓存的计算结果
var _cached_local_rotation: Basis
var _cached_two_pi_div_pitch: float
var _movement_threshold_squared: float = 0.0001 # 0.01^2
# 优化:缓存信号连接状态
var _signals_connected: bool = false
func _ready():
ready_called = true
# 预计算常用值
_cached_local_rotation = Basis.from_euler(Vector3(deg_to_rad(90), deg_to_rad(90), 0))
if spiral_pitch > 0.001:
_cached_two_pi_div_pitch = TAU / spiral_pitch
func _init_resources():
if resources_initialized:
return
if not mainline:
return
cylinder_bend_shader = load("res://cylinder_bend.gdshader")
if not cylinder_bend_shader:
return
if not camera:
camera = get_viewport().get_camera_3d()
if not cylinder_tail_parent:
cylinder_tail_parent = Node3D.new()
cylinder_tail_parent.name = "CylinderTail"
get_tree().current_scene.add_child(cylinder_tail_parent)
_update_offset_transform()
setup_cylinder()
last_cylinder_reference_position = cylinder_axis_point
create_base_material()
var scene_root = get_tree().current_scene
if scene_root and scene_root.has_node("tail"):
mainline_tail_node = scene_root.get_node("tail")
resources_initialized = true
func _update_offset_transform():
rotation_offset_basis = Basis.from_euler(Vector3(
deg_to_rad(rotation_offset.x),
deg_to_rad(rotation_offset.y),
deg_to_rad(rotation_offset.z)
))
func _enter_tree():
if mainline and engage_flag and not _signals_connected:
_connect_signals()
func _exit_tree():
if _signals_connected:
_disconnect_signals()
func _connect_signals():
if not mainline or _signals_connected:
return
if mainline.has_signal("onturn"):
mainline.onturn.connect(_on_mainline_turn)
if mainline.has_signal("new_line1"):
mainline.new_line1.connect(_on_mainline_new_line)
if mainline.has_signal("on_sky"):
mainline.on_sky.connect(_on_mainline_on_sky)
_signals_connected = true
func _disconnect_signals():
if not mainline or not _signals_connected:
return
if mainline.has_signal("onturn") and mainline.onturn.is_connected(_on_mainline_turn):
mainline.onturn.disconnect(_on_mainline_turn)
if mainline.has_signal("new_line1") and mainline.new_line1.is_connected(_on_mainline_new_line):
mainline.new_line1.disconnect(_on_mainline_new_line)
if mainline.has_signal("on_sky") and mainline.on_sky.is_connected(_on_mainline_on_sky):
mainline.on_sky.disconnect(_on_mainline_on_sky)
_signals_connected = false
func engage():
if not ready_called:
return
if not resources_initialized:
_init_resources()
if not resources_initialized:
return
engage_flag = true
if not _signals_connected:
_connect_signals()
current_angle = deg_to_rad(initial_angle_degrees)
initialize_mapping()
if map_trails and has_last_mapped_position:
is_drawing = true
create_new_cylinder_line()
func disengage():
if not engage_flag:
return
engage_flag = false
_disconnect_signals()
stop_drawing_trails()
func stop_drawing_trails():
is_drawing = false
current_cylinder_line = null
func manual_clear_trails():
clear_cylinder_trails()
func setup_cylinder():
var reference_position: Vector3
if cylinder_reference_node and is_instance_valid(cylinder_reference_node):
reference_position = cylinder_reference_node.global_position
elif camera:
reference_position = camera.global_position
else:
return
cylinder_axis_point = reference_position + cylinder_center_offset
cylinder_axis = cylinder_axis_direction.normalized()
reference_direction = Vector3.UP.cross(cylinder_axis)
if reference_direction.length_squared() < 0.000001: # 使用 length_squared 避免开方
reference_direction = Vector3.RIGHT.cross(cylinder_axis)
reference_direction = reference_direction.normalized()
perpendicular_direction = cylinder_axis.cross(reference_direction).normalized()
func create_base_material():
cylinder_bend_material = ShaderMaterial.new()
cylinder_bend_material.shader = cylinder_bend_shader
cylinder_bend_material.set_shader_parameter("cylinder_axis_point", cylinder_axis_point)
cylinder_bend_material.set_shader_parameter("cylinder_axis", cylinder_axis)
cylinder_bend_material.set_shader_parameter("cylinder_radius", cylinder_radius)
cylinder_bend_material.set_shader_parameter("albedo_color", trail_color)
cylinder_bend_material.set_shader_parameter("use_emission", trail_emission)
cylinder_bend_material.set_shader_parameter("emission_color", trail_emission_color)
cylinder_bend_material.set_shader_parameter("emission_energy", trail_emission_energy)
func initialize_mapping():
if not mainline or not engage_flag:
return
last_mainline_position = mainline.global_position
var to_mainline = mainline.global_position - cylinder_axis_point
current_axial_progress = to_mainline.dot(cylinder_axis)
var virtual_position = cylinder_axis_point + cylinder_axis * current_axial_progress
map_position_to_cylinder(virtual_position, -mainline.transform.basis.z)
func _on_mainline_turn():
if not engage_flag:
return
spiral_direction = -spiral_direction # 优化:直接取反
func _on_mainline_new_line():
if not engage_flag:
return
if target_transform:
last_mapped_position = target_transform.origin
has_last_mapped_position = true
if map_trails:
is_drawing = true
create_new_cylinder_line()
func _on_mainline_on_sky():
if not engage_flag:
return
if target_transform:
last_mapped_position = target_transform.origin
has_last_mapped_position = true
is_drawing = false
current_cylinder_line = null
func _process(delta):
if not engage_flag or not mainline:
return
if auto_update_cylinder:
_auto_update_cylinder_position()
if update_per_frame:
var current_pos = mainline.global_position
var forward = -mainline.transform.basis.z
var axial_movement: float
if use_independent_speed:
axial_movement = forward_speed * delta
else:
var movement = current_pos - last_mainline_position
axial_movement = movement.dot(cylinder_axis)
if spiral_enabled:
if spiral_mode == 0:
update_spiral_motion_angular_speed(axial_movement, forward, delta)
else:
update_spiral_motion_fixed_pitch(axial_movement, forward)
# 优化:使用 distance_squared_to 避免开方
if current_pos.distance_squared_to(last_mainline_position) > _movement_threshold_squared:
last_mainline_position = current_pos
if map_trails and is_drawing and current_cylinder_line and is_instance_valid(current_cylinder_line):
update_cylinder_trail()
func _auto_update_cylinder_position():
var reference_position: Vector3
if cylinder_reference_node and is_instance_valid(cylinder_reference_node):
reference_position = cylinder_reference_node.global_position
elif camera:
reference_position = camera.global_position
else:
return
var new_axis_point = reference_position + cylinder_center_offset
# 优化:使用 distance_squared_to
if new_axis_point.distance_squared_to(last_cylinder_reference_position) > 0.000001:
cylinder_axis_point = new_axis_point
last_cylinder_reference_position = new_axis_point
if cylinder_bend_material:
cylinder_bend_material.set_shader_parameter("cylinder_axis_point", cylinder_axis_point)
_update_all_trails_cylinder_params()
func _update_all_trails_cylinder_params():
if not cylinder_tail_parent:
return
# 优化:批量更新,减少函数调用
var children = cylinder_tail_parent.get_children()
for child in children:
if child is MeshInstance3D:
var line_material = child.get_surface_override_material(0)
if line_material and line_material is ShaderMaterial:
# 一次性设置多个参数
line_material.set_shader_parameter("cylinder_axis_point", cylinder_axis_point)
line_material.set_shader_parameter("cylinder_axis", cylinder_axis)
line_material.set_shader_parameter("cylinder_radius", cylinder_radius)
line_material.set_shader_parameter("reference_direction", reference_direction)
line_material.set_shader_parameter("perpendicular_direction", perpendicular_direction)
func update_spiral_motion_angular_speed(axial_movement: float, forward_direction: Vector3, delta: float):
current_axial_progress += axial_movement
current_angle += spiral_angular_speed * spiral_direction * delta
var virtual_position = cylinder_axis_point + cylinder_axis * current_axial_progress
map_position_to_cylinder(virtual_position, forward_direction)
func update_spiral_motion_fixed_pitch(axial_movement: float, forward_direction: Vector3):
current_axial_progress += axial_movement
if spiral_pitch > 0.001:
# 优化:使用预计算的值
var angle_increment = axial_movement * _cached_two_pi_div_pitch
current_angle += angle_increment * spiral_direction
var virtual_position = cylinder_axis_point + cylinder_axis * current_axial_progress
map_position_to_cylinder(virtual_position, forward_direction)
func map_position_to_cylinder(mainline_pos: Vector3, _forward_direction: Vector3):
var to_mainline = mainline_pos - cylinder_axis_point
var axial_distance = to_mainline.dot(cylinder_axis)
var axial_position = cylinder_axis_point + cylinder_axis * axial_distance
var radial_direction = get_radial_direction_from_angle(current_angle)
var surface_position = axial_position + radial_direction * cylinder_radius
# 应用位置偏移
surface_position += position_offset
var tangent_direction = cylinder_axis.cross(radial_direction).normalized()
if spiral_direction < 0:
tangent_direction = -tangent_direction
var rotation_basis = Basis()
rotation_basis.z = -tangent_direction
rotation_basis.y = cylinder_axis
rotation_basis.x = rotation_basis.y.cross(rotation_basis.z).normalized()
rotation_basis = rotation_basis.orthonormalized()
# 应用旋转偏移
rotation_basis = rotation_offset_basis * rotation_basis
# 优化:使用缓存的局部旋转
target_transform = Transform3D()
target_transform.origin = surface_position
target_transform.basis = rotation_basis * _cached_local_rotation
last_mapped_position = surface_position
has_last_mapped_position = true
func create_new_cylinder_line():
if not engage_flag or not cylinder_tail_parent:
return
if not has_last_mapped_position:
return
current_cylinder_line = MeshInstance3D.new()
# 优化:复用 BoxMesh 实例(如果需要大量创建,可以使用对象池)
var box_mesh = BoxMesh.new()
box_mesh.size = Vector3(1, 1, 1)
box_mesh.subdivide_width = 2
box_mesh.subdivide_height = 2
box_mesh.subdivide_depth = 20
current_cylinder_line.mesh = box_mesh
var line_material = cylinder_bend_material.duplicate()
line_start_position = last_mapped_position
# 批量设置 shader 参数
line_material.set_shader_parameter("line_start_position", line_start_position)
line_material.set_shader_parameter("line_end_position", line_start_position)
line_material.set_shader_parameter("line_length", 0.01)
line_material.set_shader_parameter("reference_direction", reference_direction)
line_material.set_shader_parameter("perpendicular_direction", perpendicular_direction)
current_cylinder_line.set_surface_override_material(0, line_material)
current_cylinder_line.global_transform = Transform3D.IDENTITY
current_cylinder_line.name = "CylinderLine"
current_cylinder_line.extra_cull_margin = 16384.0
current_cylinder_line.visibility_range_end_margin = 0.0
cylinder_tail_parent.add_child(current_cylinder_line)
func update_cylinder_trail():
if not engage_flag or not current_cylinder_line or not is_instance_valid(current_cylinder_line):
return
var current_pos = target_transform.origin
var offset = current_pos - line_start_position
var distance_squared = offset.length_squared() # 优化:先用平方比较
if distance_squared < min_segment_length * min_segment_length:
return
var line_material = current_cylinder_line.get_surface_override_material(0)
if line_material and line_material is ShaderMaterial:
var distance = sqrt(distance_squared) # 只在需要时才开方
line_material.set_shader_parameter("line_end_position", current_pos)
line_material.set_shader_parameter("line_length", distance)
last_mapped_position = current_pos
@warning_ignore("shadowed_variable")
func get_radial_direction_from_angle(angle: float) -> Vector3:
# 优化:内联计算,减少临时变量
var cos_a = cos(angle)
var sin_a = sin(angle)
return (reference_direction * cos_a + perpendicular_direction * sin_a).normalized()
func project_vector_to_cylinder_plane(vec: Vector3) -> Vector3:
var projection_on_axis = vec.dot(cylinder_axis) * cylinder_axis
var projected = vec - projection_on_axis
return projected.normalized() if projected.length_squared() > 0.000001 else Vector3.ZERO
func project_point_to_cylinder_plane(point: Vector3) -> Vector3:
var to_point = point - cylinder_axis_point
var projection_on_axis = to_point.dot(cylinder_axis)
return point - cylinder_axis * projection_on_axis
func get_mapping_info() -> Dictionary:
return {
"enabled": enable,
"engaged": engage_flag,
"spiral_mode": "固定角速度" if spiral_mode == 0 else "固定螺距",
"speed_mode": "独立速度" if use_independent_speed else "跟随mainline",
"forward_speed": forward_speed,
"spiral_direction": "顺时针" if spiral_direction > 0 else "逆时针",
"angle_degrees": rad_to_deg(current_angle),
"angle_radians": current_angle,
"axial_progress": current_axial_progress,
"surface_position": target_transform.origin,
"cylinder_axis_point": cylinder_axis_point,
"cylinder_reference": "自定义节点" if cylinder_reference_node else "相机",
"auto_update": auto_update_cylinder,
"cylinder_radius": cylinder_radius,
"spiral_pitch": spiral_pitch,
"spiral_angular_speed": spiral_angular_speed,
"position_offset": position_offset,
"rotation_offset": rotation_offset,
"initial_angle_degrees": initial_angle_degrees,
"distance_to_axis": target_transform.origin.distance_to(
cylinder_axis_point + cylinder_axis * current_axial_progress
) if engage_flag else 0.0,
"is_drawing": is_drawing,
"active_lines": cylinder_tail_parent.get_child_count() if cylinder_tail_parent else 0,
"current_line_length": (target_transform.origin - line_start_position).length() if is_drawing and has_last_mapped_position else 0.0
}
func clear_cylinder_trails():
if not cylinder_tail_parent:
return
# 优化:直接获取子节点并删除,避免创建临时数组
var children = cylinder_tail_parent.get_children()
for child in children:
if is_instance_valid(child):
child.queue_free()
# 如果需要立即清理,可以等待一帧
if children.size() > 0:
await get_tree().process_frame
cylinderTP.gd
extends Node
@export var cylinder_mapper: Node3D
func _ready():
if not cylinder_mapper:
push_error("CylinderTP: 需要指定 cylinder_mapper 引用!")
return
func flip_to_opposite_side():
if not cylinder_mapper:
push_warning("CylinderTP: cylinder_mapper 未设置")
return
if cylinder_mapper.is_drawing and cylinder_mapper.current_cylinder_line:
cylinder_mapper.is_drawing = false
cylinder_mapper.current_cylinder_line = null
cylinder_mapper.current_angle += PI
if cylinder_mapper.engage_flag and cylinder_mapper.mainline:
var forward = -cylinder_mapper.mainline.transform.basis.z
var virtual_position = cylinder_mapper.cylinder_axis_point + cylinder_mapper.cylinder_axis * cylinder_mapper.current_axial_progress
cylinder_mapper.map_position_to_cylinder(virtual_position, forward)
cylinder_mapper.last_mapped_position = cylinder_mapper.target_transform.origin
cylinder_mapper.has_last_mapped_position = true
if cylinder_mapper.map_trails:
cylinder_mapper.is_drawing = true
cylinder_mapper.create_new_cylinder_line()
cylinder_bend.gdshader
shader_type spatial;
render_mode unshaded;
// 圆柱体参数
uniform vec3 cylinder_axis_point = vec3(0.0, 0.0, 0.0); // 圆柱体轴线上的点
uniform vec3 cylinder_axis = vec3(0.707, 0.0, -0.707); // 圆柱体轴线方向(归一化)
uniform float cylinder_radius = 14.5; // 圆柱体半径
// 线段参数
uniform vec3 line_start_position; // 线段起点(世界坐标)
uniform vec3 line_end_position; // 线段终点(世界坐标)
uniform float line_length = 1.0; // 线段长度
// 圆柱体坐标系
uniform vec3 reference_direction = vec3(0.0, 1.0, 0.0); // 参考方向
uniform vec3 perpendicular_direction = vec3(1.0, 0.0, 0.0); // 垂直方向
// 材质参数
uniform vec4 albedo_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable;
uniform float metallic : hint_range(0.0, 1.0) = 0.0;
uniform float roughness : hint_range(0.0, 1.0) = 1.0;
uniform bool use_emission = false;
uniform vec4 emission_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float emission_energy : hint_range(0.0, 16.0) = 1.0;
// 计算点到轴线的投影
vec3 project_to_axis(vec3 point, vec3 axis_point, vec3 axis_dir) {
vec3 to_point = point - axis_point;
float axial_distance = dot(to_point, axis_dir);
return axis_point + axis_dir * axial_distance;
}
// 计算径向方向
vec3 get_radial_direction(vec3 point, vec3 axis_point, vec3 axis_dir) {
vec3 projection = project_to_axis(point, axis_point, axis_dir);
vec3 radial = point - projection;
float len = length(radial);
return len > 0.001 ? radial / len : vec3(0.0, 1.0, 0.0);
}
// 从角度获取径向方向(使用圆柱体坐标系)
vec3 get_radial_from_angle(float angle, vec3 ref_dir, vec3 perp_dir) {
return normalize(ref_dir * cos(angle) + perp_dir * sin(angle));
}
// 计算点在圆柱体上的角度
float get_angle_on_cylinder(vec3 point, vec3 axis_point, vec3 axis_dir, vec3 ref_dir, vec3 perp_dir) {
vec3 projection = project_to_axis(point, axis_point, axis_dir);
vec3 radial = point - projection;
float len = length(radial);
if (len < 0.001) {
return 0.0;
}
radial = radial / len;
float cos_angle = dot(radial, ref_dir);
float sin_angle = dot(radial, perp_dir);
return atan(sin_angle, cos_angle);
}
// 将点映射到圆柱体表面(保持在圆柱体表面上)
vec3 map_to_cylinder_surface(vec3 point, vec3 axis_point, vec3 axis_dir, float radius, vec3 ref_dir, vec3 perp_dir) {
// 1. 获取轴向投影
vec3 axial_projection = project_to_axis(point, axis_point, axis_dir);
// 2. 获取角度
float angle = get_angle_on_cylinder(point, axis_point, axis_dir, ref_dir, perp_dir);
// 3. 从角度计算径向方向
vec3 radial_dir = get_radial_from_angle(angle, ref_dir, perp_dir);
// 4. 映射到表面
return axial_projection + radial_dir * radius;
}
// 计算圆柱体表面的法线
vec3 calculate_cylinder_normal(vec3 surface_point, vec3 axis_point, vec3 axis_dir) {
vec3 axial_projection = project_to_axis(surface_point, axis_point, axis_dir);
vec3 radial = surface_point - axial_projection;
float len = length(radial);
return len > 0.001 ? radial / len : vec3(0.0, 1.0, 0.0);
}
// 在圆柱体表面插值两点
vec3 interpolate_on_cylinder(vec3 start_pos, vec3 end_pos, float t, vec3 axis_point, vec3 axis_dir, float radius, vec3 ref_dir, vec3 perp_dir) {
// 获取起点和终点的角度和轴向位置
float start_angle = get_angle_on_cylinder(start_pos, axis_point, axis_dir, ref_dir, perp_dir);
float end_angle = get_angle_on_cylinder(end_pos, axis_point, axis_dir, ref_dir, perp_dir);
// 处理角度跨越 -π 到 π 的情况
float angle_diff = end_angle - start_angle;
if (angle_diff > 3.14159) {
start_angle += 6.28318;
} else if (angle_diff < -3.14159) {
end_angle += 6.28318;
}
// 插值角度
float interpolated_angle = mix(start_angle, end_angle, t);
// 获取轴向位置
vec3 start_axial = project_to_axis(start_pos, axis_point, axis_dir);
vec3 end_axial = project_to_axis(end_pos, axis_point, axis_dir);
// 插值轴向位置
vec3 interpolated_axial = mix(start_axial, end_axial, t);
// 从插值后的角度获取径向方向
vec3 radial_dir = get_radial_from_angle(interpolated_angle, ref_dir, perp_dir);
// 返回圆柱体表面上的点
return interpolated_axial + radial_dir * radius;
}
void vertex() {
// 获取顶点在模型空间的位置
vec3 local_pos = VERTEX;
// 计算沿线段的进度 (0.0 到 1.0)
// 假设线段沿 Z 轴,范围从 -0.5 到 +0.5
float t = local_pos.z + 0.5;
t = clamp(t, 0.0, 1.0);
// 在圆柱体表面上插值起点和终点
vec3 curved_center = interpolate_on_cylinder(
line_start_position,
line_end_position,
t,
cylinder_axis_point,
cylinder_axis,
cylinder_radius,
reference_direction,
perpendicular_direction
);
// 计算该点的切线方向(用于横向偏移)
float epsilon = 0.01;
float t_before = clamp(t - epsilon, 0.0, 1.0);
float t_after = clamp(t + epsilon, 0.0, 1.0);
vec3 point_before = interpolate_on_cylinder(
line_start_position,
line_end_position,
t_before,
cylinder_axis_point,
cylinder_axis,
cylinder_radius,
reference_direction,
perpendicular_direction
);
vec3 point_after = interpolate_on_cylinder(
line_start_position,
line_end_position,
t_after,
cylinder_axis_point,
cylinder_axis,
cylinder_radius,
reference_direction,
perpendicular_direction
);
// 计算切线方向
vec3 tangent_dir = normalize(point_after - point_before);
// 计算该点的径向方向(法线方向)
vec3 radial_dir = calculate_cylinder_normal(curved_center, cylinder_axis_point, cylinder_axis);
// 计算横向方向(垂直于切线和径向)
vec3 lateral_dir = normalize(cross(tangent_dir, radial_dir));
// 应用偏移
// local_pos.x: 横向偏移(沿着 lateral_dir)
// local_pos.y: 径向偏移(沿着 radial_dir,用于线条厚度)
vec3 final_position = curved_center + lateral_dir * local_pos.x + radial_dir * local_pos.y;
// 更新顶点位置(转回局部空间)
VERTEX = (inverse(MODEL_MATRIX) * vec4(final_position, 1.0)).xyz;
// 计算法线
// 对于线条,法线应该是径向方向
vec3 final_normal = radial_dir;
NORMAL = normalize((inverse(transpose(mat3(MODEL_MATRIX))) * final_normal));
// 传递 UV 坐标
UV = UV;
}
void fragment() {
// 基础颜色
vec4 tex_color = texture(texture_albedo, UV);
ALBEDO = albedo_color.rgb * tex_color.rgb;
ALPHA = albedo_color.a * tex_color.a;
// 材质属性
METALLIC = metallic;
ROUGHNESS = roughness;
// 自发光
if (use_emission) {
EMISSION = emission_color.rgb * emission_energy;
}
}
本文来自博客园,作者:meny,转载请注明原文链接:https://www.cnblogs.com/mmme/p/19560199

浙公网安备 33010602011771号