Skip to content

Commit 0cbc6bc

Browse files
authored
Version 1.0.1
1 parent 61e586f commit 0cbc6bc

14 files changed

+848
-1
lines changed

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21-
SOFTWARE.
21+
SOFTWARE.

grass.gd

+296
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# grass.gd
2+
# This file is part of: SimpleGrassTextured
3+
# Copyright (c) 2023 IcterusGames
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining
6+
# a copy of this software and associated documentation files (the
7+
# "Software"), to deal in the Software without restriction, including
8+
# without limitation the rights to use, copy, modify, merge, publish,
9+
# distribute, sublicense, and/or sell copies of the Software, and to
10+
# permit persons to whom the Software is furnished to do so, subject to
11+
# the following conditions:
12+
#
13+
# The above copyright notice and this permission notice shall be
14+
# included in all copies or substantial portions of the Software.
15+
#
16+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+
24+
@tool
25+
@icon ("icon.png")
26+
class_name SimpleGrassTextured extends MultiMeshInstance3D
27+
28+
@export var mesh : Mesh = null : set = _on_set_mesh
29+
@export var player_pos := Vector3(1000000, 1000000, 1000000) : set = _on_set_player_pos
30+
@export var player_radius := 0.5 : set = _on_set_player_radius
31+
@export_color_no_alpha var albedo := Color.WHITE : set = _on_set_albedo
32+
@export var texture_albedo : Texture = preload("textures/grassbushcc008.png") : set = _on_set_texture_albedo
33+
@export var alpha_scissor_threshold := 0.5 : set = _on_set_alpha_scissor_threshold
34+
@export var scale_h := 1.0 : set = _on_set_scale_h
35+
@export var scale_w := 1.0 : set = _on_set_scale_w
36+
@export var scale_var := -0.25 : set = _on_set_scale_var
37+
@export_range(0.0, 1.0) var grass_strength := 0.8 : set = _on_set_grass_strength
38+
@export var wind_dir := Vector3.RIGHT : set = _on_set_wind_dir
39+
@export var wind_strength := 0.03 : set = _on_set_wind_strength
40+
@export var wind_speed := 1.0 : set = _on_set_wind_speed
41+
@export var optimization_by_distance := false : set = _on_set_optimization_by_distance
42+
@export var optimization_level := 7.0 : set = _on_set_optimization_level
43+
44+
var dist_min : float = 0.0
45+
46+
var _default_mesh : Mesh = null
47+
var _buffer_add : Array[Transform3D] = []
48+
var _material := preload("materials/grass.material").duplicate() as ShaderMaterial
49+
50+
51+
func _init():
52+
_default_mesh = _build_default_mesh()
53+
54+
55+
func _ready():
56+
if Engine.is_editor_hint():
57+
set_process(true)
58+
else:
59+
set_process(false)
60+
if multimesh == null:
61+
multimesh = MultiMesh.new()
62+
multimesh.transform_format = MultiMesh.TRANSFORM_3D
63+
if multimesh.mesh == null:
64+
if mesh != null:
65+
multimesh.mesh = mesh
66+
else:
67+
multimesh.mesh = _default_mesh
68+
for isur in range(multimesh.mesh.get_surface_count()):
69+
multimesh.mesh.surface_set_material(isur, _material)
70+
_on_set_player_pos(player_pos)
71+
_on_set_player_radius(player_radius)
72+
_on_set_texture_albedo(texture_albedo)
73+
_on_set_alpha_scissor_threshold(alpha_scissor_threshold)
74+
_on_set_scale_h(scale_h)
75+
_on_set_scale_w(scale_w)
76+
_on_set_scale_var(scale_var)
77+
_on_set_grass_strength(grass_strength)
78+
_on_set_wind_dir(wind_dir)
79+
_on_set_wind_strength(wind_strength)
80+
_on_set_wind_speed(wind_speed)
81+
_on_set_optimization_by_distance(optimization_by_distance)
82+
_on_set_optimization_level(optimization_level)
83+
84+
85+
func _process(_delta : float):
86+
if _buffer_add.size() == 0:
87+
return
88+
_update_multimesh()
89+
90+
91+
func add_grass(pos : Vector3, normal : Vector3, scale : Vector3):
92+
var trans := Transform3D()
93+
trans = trans.rotated(Vector3.UP, TAU * randf())
94+
trans.basis.y = normal
95+
trans = trans.scaled(scale)
96+
trans = trans.translated(pos)
97+
if dist_min > 0:
98+
for trans_prev in _buffer_add:
99+
if trans.origin.distance_to(trans_prev.origin) <= dist_min:
100+
return
101+
_buffer_add.append(trans)
102+
103+
104+
func erase(pos : Vector3, radius : float):
105+
var multi_new := MultiMesh.new()
106+
var array : Array[Transform3D] = []
107+
multi_new.transform_format = MultiMesh.TRANSFORM_3D
108+
if mesh != null:
109+
multi_new.mesh = mesh
110+
else:
111+
multi_new.mesh = _default_mesh
112+
for i in range(multimesh.instance_count):
113+
var trans := multimesh.get_instance_transform(i)
114+
if trans.origin.distance_to(pos) > radius:
115+
array.append(trans)
116+
multi_new.instance_count = array.size()
117+
for i in range(array.size()):
118+
multi_new.set_instance_transform(i, array[i])
119+
multimesh = multi_new
120+
if _material != null:
121+
for isur in range(multimesh.mesh.get_surface_count()):
122+
multimesh.mesh.surface_set_material(isur, _material)
123+
124+
125+
func _update_multimesh():
126+
if multimesh == null:
127+
return
128+
var multi_new := MultiMesh.new()
129+
var count_prev := multimesh.instance_count
130+
multi_new.transform_format = MultiMesh.TRANSFORM_3D
131+
if mesh != null:
132+
multi_new.mesh = mesh
133+
else:
134+
multi_new.mesh = _default_mesh
135+
if _buffer_add.size() > 0 and dist_min > 0:
136+
for i in range(multimesh.instance_count):
137+
var trans := multimesh.get_instance_transform(i)
138+
for trans_add in _buffer_add:
139+
if trans_add.origin.distance_to(trans.origin) <= dist_min:
140+
_buffer_add.erase(trans_add)
141+
break
142+
multi_new.instance_count = count_prev + _buffer_add.size()
143+
for i in range(multimesh.instance_count):
144+
multi_new.set_instance_transform(i, multimesh.get_instance_transform(i))
145+
for i in range(_buffer_add.size()):
146+
multi_new.set_instance_transform(i + count_prev, _buffer_add[i])
147+
multimesh = multi_new
148+
if _material != null:
149+
for isur in range(multimesh.mesh.get_surface_count()):
150+
multimesh.mesh.surface_set_material(isur, _material)
151+
_buffer_add.clear()
152+
153+
154+
func _build_default_mesh() -> Mesh:
155+
var array_mesh := ArrayMesh.new()
156+
var vertices := PackedVector3Array()
157+
var normals := PackedVector3Array()
158+
var uvs := PackedVector2Array()
159+
var index := PackedInt32Array()
160+
161+
vertices.push_back(Vector3(-0.5, 1, 0))
162+
vertices.push_back(Vector3(0.5, 0, 0))
163+
vertices.push_back(Vector3(-0.5, 0, 0))
164+
vertices.push_back(Vector3(0.5, 1, 0))
165+
vertices.push_back(Vector3(0, 1, -0.5))
166+
vertices.push_back(Vector3(0, 0, 0.5))
167+
vertices.push_back(Vector3(0, 0, -0.5))
168+
vertices.push_back(Vector3(0, 1, 0.5))
169+
normals.push_back(Vector3(0, 0, 1))
170+
normals.push_back(Vector3(0, 0, 1))
171+
normals.push_back(Vector3(0, 0, 1))
172+
normals.push_back(Vector3(0, 0, 1))
173+
normals.push_back(Vector3(-1, 0, 0))
174+
normals.push_back(Vector3(-1, 0, 0))
175+
normals.push_back(Vector3(-1, 0, 0))
176+
normals.push_back(Vector3(-1, 0, 0))
177+
uvs.push_back(Vector2(0, 0))
178+
uvs.push_back(Vector2(1, 1))
179+
uvs.push_back(Vector2(0, 1))
180+
uvs.push_back(Vector2(1, 0))
181+
uvs.push_back(Vector2(0, 0))
182+
uvs.push_back(Vector2(1, 1))
183+
uvs.push_back(Vector2(0, 1))
184+
uvs.push_back(Vector2(1, 0))
185+
index.push_back(0)
186+
index.push_back(1)
187+
index.push_back(2)
188+
index.push_back(3)
189+
index.push_back(1)
190+
index.push_back(0)
191+
index.push_back(4)
192+
index.push_back(5)
193+
index.push_back(6)
194+
index.push_back(7)
195+
index.push_back(5)
196+
index.push_back(4)
197+
198+
var arrays := []
199+
arrays.resize(Mesh.ARRAY_MAX)
200+
arrays[Mesh.ARRAY_VERTEX] = vertices
201+
arrays[ArrayMesh.ARRAY_NORMAL] = normals
202+
arrays[ArrayMesh.ARRAY_TEX_UV] = uvs
203+
arrays[ArrayMesh.ARRAY_INDEX] = index
204+
205+
array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
206+
return array_mesh
207+
208+
209+
func _on_set_mesh(value : Mesh):
210+
mesh = value
211+
if Engine.is_editor_hint() and is_inside_tree():
212+
_update_multimesh()
213+
214+
215+
func _on_set_player_pos(value : Vector3):
216+
player_pos = value
217+
if _material != null:
218+
_material.set_shader_parameter("player_pos", player_pos)
219+
220+
221+
func _on_set_player_radius(value : float):
222+
player_radius = value
223+
if _material != null:
224+
_material.set_shader_parameter("player_radius", player_radius)
225+
226+
227+
func _on_set_albedo(value : Color):
228+
albedo = value;
229+
if _material != null:
230+
_material.set_shader_parameter("albedo", albedo)
231+
232+
233+
func _on_set_texture_albedo(value : Texture):
234+
texture_albedo = value
235+
if _material != null:
236+
_material.set_shader_parameter("texture_albedo", texture_albedo)
237+
238+
239+
func _on_set_alpha_scissor_threshold(value : float):
240+
alpha_scissor_threshold = value
241+
if _material != null:
242+
_material.set_shader_parameter("alpha_scissor_threshold", alpha_scissor_threshold)
243+
244+
245+
func _on_set_scale_h(value : float):
246+
scale_h = value
247+
if _material != null:
248+
_material.set_shader_parameter("scale_h", scale_h)
249+
250+
251+
func _on_set_scale_w(value : float):
252+
scale_w = value
253+
if _material != null:
254+
_material.set_shader_parameter("scale_w", scale_w)
255+
256+
257+
func _on_set_scale_var(value : float):
258+
scale_var = value
259+
if _material != null:
260+
_material.set_shader_parameter("scale_var", scale_var)
261+
262+
263+
func _on_set_grass_strength(value : float):
264+
grass_strength = value
265+
if _material != null:
266+
_material.set_shader_parameter("grass_strength", grass_strength)
267+
268+
269+
func _on_set_wind_dir(value : Vector3):
270+
wind_dir = value
271+
if _material != null:
272+
_material.set_shader_parameter("wind_dir", wind_dir)
273+
274+
275+
func _on_set_wind_strength(value : float):
276+
wind_strength = value
277+
if _material != null:
278+
_material.set_shader_parameter("wind_strength", wind_strength)
279+
280+
281+
func _on_set_wind_speed(value : float):
282+
wind_speed = value
283+
if _material != null:
284+
_material.set_shader_parameter("wind_speed", wind_speed)
285+
286+
287+
func _on_set_optimization_by_distance(value : bool):
288+
optimization_by_distance = value
289+
if _material != null:
290+
_material.set_shader_parameter("optimization_by_distance", optimization_by_distance)
291+
292+
293+
func _on_set_optimization_level(value : float):
294+
optimization_level = value
295+
if _material != null:
296+
_material.set_shader_parameter("optimization_level", optimization_level)

icon.png

7.54 KB
Loading

icon.png.import

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://bydmhs1jeab4x"
6+
path="res://.godot/imported/icon.png-19fbba19af0b6f102089d0f09a582f5a.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://addons/simplegrasstextured/icon.png"
14+
dest_files=["res://.godot/imported/icon.png-19fbba19af0b6f102089d0f09a582f5a.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/lossy_quality=0.7
20+
compress/hdr_compression=1
21+
compress/bptc_ldr=0
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1

images/pointer.png

22.3 KB
Loading

images/pointer.png.import

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://35qfdmr0xvq3"
6+
path="res://.godot/imported/pointer.png-292374924e7ba5a25097927bb55f262e.ctex"
7+
metadata={
8+
"vram_texture": false
9+
}
10+
11+
[deps]
12+
13+
source_file="res://addons/simplegrasstextured/images/pointer.png"
14+
dest_files=["res://.godot/imported/pointer.png-292374924e7ba5a25097927bb55f262e.ctex"]
15+
16+
[params]
17+
18+
compress/mode=0
19+
compress/lossy_quality=0.7
20+
compress/hdr_compression=1
21+
compress/bptc_ldr=0
22+
compress/normal_map=0
23+
compress/channel_pack=0
24+
mipmaps/generate=false
25+
mipmaps/limit=-1
26+
roughness/mode=0
27+
roughness/src_normal=""
28+
process/fix_alpha_border=true
29+
process/premult_alpha=false
30+
process/normal_map_invert_y=false
31+
process/hdr_as_srgb=false
32+
process/hdr_clamp_exposure=false
33+
process/size_limit=0
34+
detect_3d/compress_to=1

materials/grass.material

516 Bytes
Binary file not shown.

plugin.cfg

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[plugin]
2+
3+
name="SimpleGrassTextured"
4+
description="Create simple grass textured"
5+
author="IcterusGames"
6+
version="1.0.1"
7+
script="plugin.gd"

0 commit comments

Comments
 (0)