EDIT ajout nouvelle texture minaret, differse correction, reglage de l'environnement et postfx,...

This commit is contained in:
osquallo 2020-04-08 14:38:05 +02:00
parent 894f4d732c
commit 403742b1ad
35 changed files with 377 additions and 63 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 MiB

Binary file not shown.

View file

@ -85,13 +85,13 @@ vec3 hsv2rgb(vec3 c)
void vertex() void vertex()
{ {
v_index = mod(VERTEX.x, 1024.0/200.0);
base_uv=UV*uv1_scale.xy+uv1_offset.xy; base_uv=UV*uv1_scale.xy+uv1_offset.xy;
rotated_uv = rotateUVmatrinx(base_uv, vec2(0.5), (VERTEX.x)); rotated_uv = rotateUVmatrinx(base_uv, vec2(0.5), (v_index));
// rotated_uv = base_uv; // rotated_uv = base_uv;
rotated_uv_mask = rotateUVmatrinx(UV, vec2(0.5), (VERTEX.x+10.0)); rotated_uv_mask = rotateUVmatrinx(UV, vec2(0.5), (v_index));
// rotated_uv_mask = UV; // rotated_uv_mask = UV;
v_index = mod(VERTEX.x, 10.0);
} }
@ -107,7 +107,7 @@ void fragment()
vec4 dirt_height_tex = texture(texture_dirt_height,base_uv); vec4 dirt_height_tex = texture(texture_dirt_height,base_uv);
vec4 dirt_height_hsv_tex = texture(texture_dirt_height,rotated_uv_mask); vec4 dirt_height_hsv_tex = texture(texture_dirt_height,rotated_uv_mask);
vec4 hsv_mask_tex = texture(texture_hsv_mask,UV); vec4 hsv_mask_tex = texture(texture_hsv_mask,UV);
vec4 hsv2_mask_tex = texture(texture_hsv2_mask,UV*vec2(5.0,5.0)); vec4 hsv2_mask_tex = texture(texture_hsv2_mask,UV*vec2(1.0,1.0));
vec4 albedo_mix_tex; vec4 albedo_mix_tex;
// if ( abs(v_index) > 1.28 ) // if ( abs(v_index) > 1.28 )
// { // {
@ -118,25 +118,26 @@ void fragment()
albedo_mix_tex = texture(texture_albedo_mix,UV); albedo_mix_tex = texture(texture_albedo_mix,UV);
} }
vec4 mix_gradiant_tex = texture(texture_mix_gradiant,vec2( albedo_mix_tex.r, albedo_mix_tex.r )); vec4 mix_gradiant_tex = texture(texture_mix_gradiant,vec2( albedo_mix_tex.r, albedo_mix_tex.r ));
vec4 albedo_mix_tex_low = texture(texture_albedo_mix,UV*vec2(5.0,5.0)); vec4 albedo_mix_tex_low = texture(texture_albedo_mix,UV*vec2(50.0,50.0));
vec4 mix_gradiant_low_tex = texture(texture_mix_gradiant,vec2( albedo_mix_tex_low.r, albedo_mix_tex_low.r )); vec4 mix_gradiant_low_tex = texture(texture_mix_gradiant,vec2( albedo_mix_tex_low.r, albedo_mix_tex_low.r ));
vec4 mix_gradiant_border = texture(texture_mix_border,vec2( albedo_mix_tex_low.r, albedo_mix_tex_low.r )); vec4 mix_gradiant_border = texture(texture_mix_border,vec2( albedo_mix_tex_low.r, albedo_mix_tex_low.r ));
vec4 albedo_mix_tex2 = texture(texture_albedo_mix2,base_uv); vec4 albedo_mix_tex2 = texture(texture_albedo_mix2,base_uv);
vec4 mix_gradiant2_tex = texture(texture_mix_gradiant,vec2( albedo_mix_tex2.r, albedo_mix_tex2.r )); vec4 mix_gradiant2_tex = texture(texture_mix_gradiant,vec2( albedo_mix_tex2.r, albedo_mix_tex2.r ));
ALBEDO = albedo.rgb * grass_tex.rgb; // ALBEDO = albedo.rgb * grass_tex.rgb;
//
vec3 hsv_albedo = rgb2hsv(ALBEDO); // vec3 hsv_albedo = rgb2hsv(ALBEDO);
vec3 hsv_mask = rgb2hsv( hsv_mask_tex.rgb ); vec3 hsv_mask = rgb2hsv( hsv_mask_tex.rgb );
vec3 hsv2_mask = rgb2hsv( hsv2_mask_tex.rgb ); vec3 hsv2_mask = rgb2hsv( hsv2_mask_tex.rgb );
hsv_albedo.x *= hsv.x; // hsv_albedo.x *= hsv.x;
hsv_albedo.y = hsv.y; // hsv_albedo.y = hsv.y;
hsv_albedo.z *= hsv.z * (hsv_mask.z * hsv2_mask.z*2.0); // hsv_albedo.z *= hsv.z * (hsv_mask.z * hsv2_mask.z*2.0);
ALBEDO = hsv2rgb( hsv_albedo ); // ALBEDO = hsv2rgb( hsv_albedo );
vec4 mix_mix = mix( mix_gradiant_tex, mix_gradiant2_tex, 0.5 ); vec4 mix_mix = mix( mix_gradiant_tex, mix_gradiant_border, 0.5 );
float mix_level = clamp( mix_gradiant_tex.r*mix_gradiant_border.r-grass_level, 0.0, 1.0 ); float mix_level = clamp( mix_gradiant_tex.r-grass_level, 0.0, 1.0 );
// float mix_level = clamp( mix_gradiant_tex.r*mix_gradiant_border.r-grass_level, 0.0, 1.0 );
// if ( grass_height_tex.r > 0.5 ) // if ( grass_height_tex.r > 0.5 )
// { // {
@ -150,37 +151,57 @@ void fragment()
{ {
if ( grass_height_tex.r < dirt_height_tex.r ) if ( grass_height_tex.r < dirt_height_tex.r )
{ {
mix_level = 1.0; // mix_level = 0.0;
} }
else else
{ {
mix_level = 0.0; // mix_level = 1.0;
} }
} }
mix_level *= mix_level; // mix_level *= mix_level;
mix_level *= mix_level; // mix_level *= mix_level;
mix_level *= mix_level; // mix_level *= mix_level;
vec3 hsv_dirt = rgb2hsv(dirt_tex.rgb); vec3 hsv_dirt = rgb2hsv(dirt_tex.rgb);
vec3 hsv_dirt_height = rgb2hsv(dirt_height_hsv_tex.rgb); // hsv_dirt.x += (hsv_mask.z)*0.1;
hsv_dirt.y = hsv.y*hsv_mask.z; hsv_dirt.y = hsv.y*(hsv_mask.z * hsv2_mask.z *2.0);
hsv_dirt.z *= hsv.z*hsv_mask.z; hsv_dirt.z *= hsv.z*(hsv_mask.z * hsv2_mask.z *2.0);
dirt_tex.rgb = hsv2rgb( hsv_dirt ); dirt_tex.rgb = hsv2rgb( hsv_dirt );
vec3 hsv_grass = rgb2hsv(grass_tex.rgb);
// hsv_grass.x *= hsv.x;
hsv_grass.y = hsv.y*(hsv_mask.z * hsv2_mask.z *2.0);
hsv_grass.z *= hsv.z*(hsv_mask.z * hsv2_mask.z *2.0);
grass_tex.rgb = hsv2rgb( hsv_grass );
vec3 hsv_grass_25 = rgb2hsv(grass_25_tex.rgb);
hsv_grass_25.y = hsv.y*(hsv_mask.z * hsv2_mask.z *2.0);
hsv_grass_25.z *= hsv.z*(hsv_mask.z * hsv2_mask.z *2.0);
grass_25_tex.rgb = hsv2rgb( hsv_grass_25 );
ALBEDO = dirt_tex.rgb;
if ( mix_level >= 1.0 ) if ( mix_level >= 1.0 )
{ {
ALBEDO = mix( ALBEDO, dirt_tex.rgb, mix_level ); // ALBEDO = mix( ALBEDO, grass_tex.rgb, mix_level);
} }
else if ( mix_level >= 0.1 ) else if ( mix_level >= 0.5 )
{ {
// ALBEDO = mix( ALBEDO, grass_25_tex.rgb, mix_gradiant_border.r*mix_level );
ALBEDO = mix( ALBEDO, grass_25_tex.rgb, mix_level ); ALBEDO = mix( ALBEDO, grass_25_tex.rgb, mix_level );
} }
else
{
// ALBEDO = mix( ALBEDO, grass_25_tex.rgb, mix_level );
}
ALBEDO = mix( ALBEDO, grass_tex.rgb, mix_level*mix_level*mix_level*mix_level);
METALLIC = metallic; METALLIC = metallic;
vec4 final_roughness = mix( texture(texture_roughness,base_uv),texture(texture_roughness_dirt,base_uv), mix_level ); vec4 final_roughness = mix( texture(texture_roughness_dirt,base_uv),texture(texture_roughness,base_uv), mix_level );
ROUGHNESS = dot(final_roughness, roughness_texture_channel) * roughness; ROUGHNESS = dot(final_roughness, roughness_texture_channel) * roughness;
SPECULAR = specular; SPECULAR = specular;
vec4 final_normal = mix( texture(texture_normal,base_uv), texture(texture_normal_dirt,base_uv), mix_level ); vec4 final_normal = mix( texture(texture_normal_dirt,base_uv),texture(texture_normal,base_uv), mix_level );
NORMALMAP = final_normal.rgb; NORMALMAP = final_normal.rgb;
NORMALMAP_DEPTH = normal_scale; NORMALMAP_DEPTH = normal_scale;
vec4 final_ao = mix( texture(texture_ambient_occlusion,base_uv), texture(texture_ambient_occlusion_dirt,base_uv), mix_level ); vec4 final_ao = mix( texture(texture_ambient_occlusion_dirt,base_uv), texture(texture_ambient_occlusion,base_uv), mix_level );
AO = dot(final_ao,ao_texture_channel); AO = dot(final_ao,ao_texture_channel);
AO_LIGHT_AFFECT = ao_light_affect; AO_LIGHT_AFFECT = ao_light_affect;
} }

Binary file not shown.

View file

@ -0,0 +1,60 @@
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_disabled,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : hint_color;
uniform sampler2D texture_hue : hint_albedo;
uniform sampler2D texture_lightness : hint_white;
uniform sampler2D texture_saturation : hint_white;
uniform sampler2D texture_alpha : hint_black;
uniform float specular;
uniform float metallic;
uniform float roughness : hint_range(0,1);
uniform float point_size : hint_range(0,128);
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
uniform vec3 uv2_scale;
uniform vec3 uv2_offset;
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void vertex() {
UV=UV*uv1_scale.xy+uv1_offset.xy;
VERTEX.x += cos(TIME)*VERTEX.y/4.0;
VERTEX.z += sin(TIME)*VERTEX.y/4.0;
}
void fragment() {
vec2 base_uv = UV;
vec4 hue_tex = texture(texture_hue,base_uv);
vec4 lightness_tex = texture(texture_lightness,base_uv);
vec4 saturation_tex = texture(texture_saturation,base_uv);
vec4 alpha_tex = texture(texture_alpha,base_uv);
ALBEDO = albedo.rgb;
vec3 hsv = vec3( hue_tex.r, saturation_tex.r, lightness_tex.r );
ALBEDO *= hsv2rgb(hsv);
METALLIC = metallic;
ROUGHNESS = roughness;
SPECULAR = specular;
ALPHA = albedo.a * alpha_tex.r;
ALPHA_SCISSOR = 0.1;
}

Binary file not shown.

View file

@ -0,0 +1,13 @@
# Blender MTL File: 'grass_01.blend'
# Material Count: 1
newmtl grass_card_01
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_d D:\\projets\\khanat\\khanat-asset-sources\\textures\\terrain\\grass_card_01_alpha.png

View file

@ -0,0 +1,77 @@
# Blender v2.82 (sub 7) OBJ File: 'grass_01.blend'
# www.blender.org
mtllib grass_01.mtl
o Grass_01
v 0.044276 -0.000001 0.019583
v 0.022358 -0.000001 -0.007932
v -0.007311 0.309181 -0.049808
v 0.022589 0.313134 -0.023535
v 0.059781 -0.000001 -0.001409
v -0.007605 -0.000000 0.013815
v -0.014160 0.285551 0.040648
v 0.065340 0.285550 -0.001433
v -0.043797 -0.000000 -0.009238
v -0.037235 -0.000001 -0.045960
v -0.026157 0.202063 -0.059532
v -0.032602 0.202064 0.001215
v -0.010460 -0.000001 -0.020205
v -0.071450 -0.000001 -0.079450
v -0.052179 0.321421 -0.089446
v -0.020042 0.321422 -0.015236
v 0.018498 -0.000001 -0.093125
v -0.002777 -0.000001 -0.073942
v 0.005995 0.230458 -0.011340
v 0.007487 0.233504 -0.042697
vt 0.010300 0.000000
vt 0.176357 0.000000
vt 0.176357 1.000000
vt 0.010300 1.000000
vt 0.718206 0.000000
vt 0.986606 0.000000
vt 0.986606 1.000000
vt 0.718206 1.000000
vt 0.377415 -0.001700
vt 0.537998 -0.001700
vt 0.537998 0.996200
vt 0.377415 0.996200
vt 0.718206 0.000000
vt 0.986606 0.000000
vt 0.986606 1.000000
vt 0.718206 1.000000
vt 0.010300 0.000000
vt 0.176357 0.000000
vt 0.176357 1.000000
vt 0.010300 1.000000
vn 0.7727 -0.0135 -0.6346
vn 0.7821 -0.0093 -0.6230
vn 0.6725 -0.0535 -0.7382
vn 0.6632 -0.0568 -0.7462
vn -0.2687 0.0719 -0.9605
vn -0.2195 0.0863 -0.9718
vn -0.4316 0.0211 -0.9018
vn -0.4678 0.0090 -0.8838
vn 0.9856 -0.0455 0.1629
vn 0.9835 -0.0421 0.1757
vn 0.9918 -0.0583 0.1137
vn 0.9926 -0.0604 0.1053
vn 0.7378 -0.0493 -0.6732
vn 0.6953 -0.0640 -0.7158
vn 0.8907 0.0177 -0.4543
vn 0.9171 0.0335 -0.3972
vn -0.7024 0.2039 -0.6820
vn -0.6530 0.2216 -0.7242
vn -0.9941 -0.0157 -0.1078
vn -0.9980 -0.0361 -0.0510
g Grass_01_Grass_01_grass_card_01
usemtl grass_card_01
s 1
f 1/1/1 2/2/2 3/3/3
f 3/3/3 4/4/4 1/1/1
f 5/5/5 6/6/6 7/7/7
f 7/7/7 8/8/8 5/5/5
f 9/9/9 10/10/10 11/11/11
f 11/11/11 12/12/12 9/9/9
f 13/13/13 14/14/14 15/15/15
f 15/15/15 16/16/16 13/13/13
f 17/17/17 18/18/18 19/19/19
f 19/19/19 20/20/20 17/17/17

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

View file

@ -15,6 +15,8 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 2 )
[node name="camera" type="Camera" parent="spring_arm"] [node name="camera" type="Camera" parent="spring_arm"]
transform = Transform( 0.999983, -0.00572465, 0, 0.00553979, 0.967694, 0.252069, -0.00144301, -0.252065, 0.967709, 0, -1.19209e-07, 1.19209e-07 ) transform = Transform( 0.999983, -0.00572465, 0, 0.00553979, 0.967694, 0.252069, -0.00144301, -0.252065, 0.967709, 0, -1.19209e-07, 1.19209e-07 )
near = 0.01
far = 10000.0
[node name="model_static" parent="." instance=ExtResource( 1 )] [node name="model_static" parent="." instance=ExtResource( 1 )]
visible = false visible = false

View file

@ -0,0 +1,65 @@
[gd_scene load_steps=14 format=2]
[ext_resource path="res://scenes/decors/terrains/demo/ground_big.tscn" type="PackedScene" id=1]
[ext_resource path="res://assets/decors/terrains/demo/water/textures/Water_UV.png" type="Texture" id=2]
[ext_resource path="res://assets/decors/terrains/demo/water/textures/Foam.png" type="Texture" id=3]
[ext_resource path="res://assets/decors/terrains/demo/water/textures/Water_N_B.png" type="Texture" id=4]
[ext_resource path="res://assets/decors/terrains/demo/water/textures/Water_N_A.png" type="Texture" id=5]
[ext_resource path="res://assets/decors/terrains/demo/water/water.shader" type="Shader" id=6]
[ext_resource path="res://scenes/decors/buildings/minaret/minaret.tscn" type="PackedScene" id=7]
[ext_resource path="res://assets/decors/vegets/grass/grass_particle.material" type="Material" id=8]
[ext_resource path="res://assets/decors/vegets/grass/grass.material" type="Material" id=9]
[ext_resource path="res://scenes/decors/terrains/demo/grass.gd" type="Script" id=11]
[ext_resource path="res://assets/decors/vegets/grass/grass_01.obj" type="ArrayMesh" id=12]
[sub_resource type="ShaderMaterial" id=1]
shader = ExtResource( 6 )
shader_param/wave_speed = 0.0
shader_param/wave_a = Plane( 1, 1, 0.35, 3 )
shader_param/wave_b = Plane( 1, 0.6, 0.3, 1.55 )
shader_param/wave_c = Plane( 1, 1.3, 0.25, 0.9 )
shader_param/sampler_scale = Vector2( 0.25, 0.25 )
shader_param/sampler_direction = Vector2( 0.05, 0.04 )
shader_param/uv_sampler_scale = Vector2( 0.25, 0.25 )
shader_param/uv_sampler_strength = 0.04
shader_param/foam_level = 0.5
shader_param/refraction = 0.075
shader_param/color_deep = Color( 0, 0.360784, 0.486275, 1 )
shader_param/color_shallow = Color( 1, 1, 1, 1 )
shader_param/beers_law = 2.0
shader_param/depth_offset = -0.75
shader_param/projector = null
shader_param/uv_sampler = ExtResource( 2 )
shader_param/normalmap_a_sampler = ExtResource( 5 )
shader_param/normalmap_b_sampler = ExtResource( 4 )
shader_param/foam_sampler = ExtResource( 3 )
[sub_resource type="PlaneMesh" id=2]
material = SubResource( 1 )
size = Vector2( 200, 200 )
[node name="demo_2" type="Spatial"]
[node name="ground_big" parent="." instance=ExtResource( 1 )]
[node name="water" type="MeshInstance" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.32202, 0 )
mesh = SubResource( 2 )
material/0 = null
[node name="minaret" parent="." instance=ExtResource( 7 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -45.3431, 19.9739, -51.4872 )
[node name="grass" type="Particles" parent="."]
material_override = ExtResource( 9 )
cast_shadow = 2
use_in_baked_light = true
amount = 40000
explosiveness = 1.0
visibility_aabb = AABB( -18, -50, -18, 36, 100, 36 )
local_coords = false
process_material = ExtResource( 8 )
draw_pass_1 = ExtResource( 12 )
script = ExtResource( 11 )
rows = 200.0
spacing = 0.18

View file

@ -0,0 +1,39 @@
extends Particles
export var rows = 64.0 setget set_rows, get_rows
func set_rows( value ):
rows = value
amount = rows * rows
update_aabb()
if process_material:
process_material.set_shader_param( "rows", rows )
func get_rows():
return rows
export var spacing = 1.0 setget set_spacing, get_spacing
func set_spacing( value ):
spacing = value
update_aabb()
if process_material:
process_material.set_shader_param( "spacing", spacing )
func get_spacing():
return spacing
func update_aabb():
var size = self.rows * self.spacing
self.visibility_aabb = AABB( -Vector3(0.5*size, 50.0, 0.5*size), Vector3(size, 100.0, size) )
func _ready():
self.set_rows( self.rows )
self.set_spacing( self.spacing )
func _process( delta ):
var viewport = self.get_viewport()
var camera = viewport.get_camera()
if camera:
var pos = camera.global_transform.origin
pos.y = 0.0
self.global_transform.origin = pos

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,13 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://assets/decors/vegets/grass/grass.material" type="Material" id=1]
[sub_resource type="QuadMesh" id=1]
size = Vector2( 0.18, 1 )
[node name="grass_card_01" type="Spatial"]
[node name="quad" type="MeshInstance" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0 )
mesh = SubResource( 1 )
material/0 = ExtResource( 1 )

View file

@ -94,6 +94,12 @@ func _process( delta ):
$trauma_fx.get_surface_material( 0 ).set_shader_param( "mist_level", trauma_value ) $trauma_fx.get_surface_material( 0 ).set_shader_param( "mist_level", trauma_value )
$sky/viewport/sky.day_time_hours += delta*((6.0/24.0)/3600.0)
if $sky/viewport/sky.day_time_hours >= 24.0:
$sky/viewport/sky.day_time_hours = $sky/viewport/sky.day_time_hours-24.0
func load_player( filename ): func load_player( filename ):
$creatures/player.load_creature( filename ) $creatures/player.load_creature( filename )

File diff suppressed because one or more lines are too long

View file

@ -15,6 +15,10 @@ enabled = true
[node name="ra" parent="model" instance=ExtResource( 2 )] [node name="ra" parent="model" instance=ExtResource( 2 )]
[node name="camera" parent="model/ra/spring_arm" index="0"]
near = 0.01
far = 10000.0
[node name="collision" parent="model/ra" index="3"] [node name="collision" parent="model/ra" index="3"]
transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0.831027, 0 ) transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0.831027, 0 )