Add project files

This commit is contained in:
ChaoticByte 2024-09-06 17:11:48 +02:00
commit b10fbca719
No known key found for this signature in database
14 changed files with 588 additions and 0 deletions

View file

@ -0,0 +1,122 @@
@tool
extends MeshInstance3D
# Copyright (c) 2024 Julian Müller (ChaoticByte)
# points of a leaf
const VERTS: Array[Vector3] = [
Vector3(-0.5, 0.0, -0.5), # 0: left base back
Vector3(0.5, 0.0, -0.5), # 1: right base back
Vector3(-0.5, 0.5, -0.5), # 2: left middle back
Vector3(0.5, 0.5, -0.5), # 3: right middle back
Vector3(-0.5, 0.0, 0.5), # 4: left base front
Vector3(0.5, 0.0, 0.5), # 5: right base front
Vector3(-0.5, 0.5, 0.5), # 6: left middle front
Vector3(0.5, 0.5, 0.5), # 7: right middle front
Vector3(0.0, 1.0, 0.0) # 8: tip
]
# triangles of a leaf
var TRIS: Array[PackedVector3Array] = [
([VERTS[2], VERTS[8], VERTS[6]]), # tip left
([VERTS[8], VERTS[3], VERTS[7]]), # tip right
([VERTS[6], VERTS[8], VERTS[7]]), # tip front
([VERTS[2], VERTS[3], VERTS[8]]), # tip back
([VERTS[0], VERTS[4], VERTS[5]]), # base abc
([VERTS[0], VERTS[5], VERTS[1]]), # base acd
([VERTS[6], VERTS[4], VERTS[0]]), # left abc
([VERTS[6], VERTS[0], VERTS[2]]), # left acd
([VERTS[3], VERTS[1], VERTS[5]]), # right abc
([VERTS[3], VERTS[5], VERTS[7]]), # right acd
([VERTS[7], VERTS[5], VERTS[4]]), # front abc
([VERTS[7], VERTS[4], VERTS[6]]), # front acd
([VERTS[2], VERTS[0], VERTS[1]]), # back abc
([VERTS[2], VERTS[1], VERTS[3]]), # back acd
]
@export_category("Procedural Grass")
@export var click_to_update: bool:
set(_val):
generate_grass()
@export var color_base: Color
@export var color_tip: Color
@export var leaf_width: float = 0.03
@export var leaf_height_min: float = 0.1
@export var leaf_height_max: float = 1.0
@export var leaf_height_add: float = 0.0
@export var leaf_height_mult: float = 0.75
@export var offset_mult: float = 0.15
@export var num_leafs: Vector2 = Vector2(40, 40)
@export var leafs_gap: float = 0.1
# I wanna use noise directly instead of an texture
# - If using FastNoiseLite: use a frequency around 0.1 and SimplexSmooth
@export var height_noise_abs: bool = true
@export var height_noise: Noise
# - If using FastNoiseLite: use a frequency around 0.2 and SimplexSmooth
@export var offset_noise: Noise
var st = SurfaceTool.new()
var shader = preload("res://procedural_grass/procedural_grass.gdshader")
var shader_mat = ShaderMaterial.new()
var rotation_rng = RandomNumberGenerator.new()
func generate_leaf(leaf_height: float, offset_xz: Vector2) -> void:
# create leaf
var rot = rotation_rng.randf_range(0.0, 2*PI)
var leaf_size = Vector3(leaf_width, leaf_height, leaf_width)
var leaf_offset = Vector3(offset_xz.x, 0.0, offset_xz.y)
for tri_ in TRIS:
var tri = PackedVector3Array()
var colors = PackedColorArray()
for v in tri_:
tri.append((
v.rotated(Vector3.UP, rot)
* leaf_size
) + leaf_offset
)
if v.y < 0:
colors.append(color_base)
else:
colors.append(color_tip)
st.add_triangle_fan(tri, PackedVector2Array(), colors)
func generate_grass() -> void:
assert(
height_noise != null and offset_noise != null,
"generate_grass was called, but height_noise or offset_noise is null"
)
var m = ArrayMesh.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
st.set_smooth_group(-1) # !
for x in range(-num_leafs.x/2, num_leafs.x/2):
for y in range(-num_leafs.y/2, num_leafs.y/2):
var h = height_noise.get_noise_2d(x, y) + leaf_height_add
if height_noise_abs:
h = abs(h)
if h > 0:
h = clamp(h, leaf_height_min, leaf_height_max)
var o = Vector2(
offset_noise.get_noise_2d(x, y),
offset_noise.get_noise_2d(x + num_leafs.x, y + num_leafs.y) # reuse
) * offset_mult
generate_leaf(
leaf_height_mult * h,
o + (Vector2(x, y) * leafs_gap)
)
st.generate_normals(false)
st.commit(m)
# set material
if shader_mat.shader == null:
shader_mat.shader = shader
m.surface_set_material(0, shader_mat)
# set mesh
self.set_mesh(m)

View file

@ -0,0 +1,54 @@
shader_type spatial;
render_mode cull_disabled;
// Copyright (c) 2024 Julian Mueller (ChaoticByte)
global uniform float wind_strength;
global uniform float wind_turbulence;
global uniform vec2 wind_direction;
global uniform sampler2D wind_noise;
global uniform float wind_noise_scale;
global uniform float wind_noise_strength;
const float TRANSLUCENCY = 0.15;
void vertex() {
// scale down grass where the camera is
vec3 camera_pos_relative = (CAMERA_POSITION_WORLD - (NODE_POSITION_WORLD + VERTEX));
VERTEX.y *= min(1.0, length(camera_pos_relative.xz));
// waving according to wind direction, strength, noise, etc.
ivec2 wind_noise_texsize = textureSize(wind_noise, 0);
// calculate a substitute for the uv
vec2 uv = (NODE_POSITION_WORLD.xz + VERTEX.xz)
/ vec2(wind_noise_texsize)
* -wind_direction
* wind_noise_scale
+ (TIME * 0.01 * wind_turbulence);
// get the noise at this position
float noise = (textureLod(wind_noise, uv, 0.0).g - 0.5) * wind_noise_strength;
VERTEX.xz += pow(VERTEX.y, 1.2) * (
(wind_strength * wind_direction)
+ (noise * wind_direction)
);
}
void fragment() {
ALBEDO = COLOR.rgb;
}
void light() {
// Adapted from https://godotshaders.com/shader/shoji-shader-translucency-sun-spot/
// The normal between the object/fragment and the light source
float nl = clamp(dot(NORMAL, LIGHT), -1.0, 1.0);
if (nl <= 0.0) {
// the normal is facing away from the light source
float light_through = clamp(-nl, 0.0, 1.0) * TRANSLUCENCY;
float attenuation = max(0.2, ATTENUATION); // softer shadows on this side
DIFFUSE_LIGHT += clamp(light_through, 0.0, 1.0) * LIGHT_COLOR/PI * attenuation;
}
else {
// The normal is facing toward the light source
// -> Diffuse (Lambert)
DIFFUSE_LIGHT += clamp(dot(NORMAL, LIGHT), 0.0, 1.0) * LIGHT_COLOR/PI * ATTENUATION;
}
}

View file

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://dq4xt6tl25c4v"]
[ext_resource type="Script" path="res://procedural_grass/procedural_grass.gd" id="2_e58by"]
[node name="ProceduralGrass" type="MeshInstance3D"]
script = ExtResource("2_e58by")
color_base = Color(0.415686, 0.431373, 0.133333, 1)
color_tip = Color(0.378045, 0.596905, 0.184511, 1)