Revision control

Copy as Markdown

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
Model {
id: grassChunkModel
pickable: false
property alias windDir: material.windDir
property alias windstrength: material.windstrength
property alias baseColor: material.baseColor
Component.onCompleted: {
generate()
}
function generate() {
grassChunkMesh.generateMesh()
}
function show() {
opacity = 1.0
}
function hide() {
opacity = 0.
}
visible: opacity > 0.1
opacity: 1.0
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
materials: [
CustomMaterial {
id: material
cullMode: Material.NoCulling
vertexShader: "media/shaders/grass.vert"
fragmentShader: "media/shaders/grass.frag"
property real time: 0
property color baseColor: "white"
FrameAnimation {
id: frameAnimation
running: true
onTriggered: {
material.time += 0.1 * frameTime
}
}
property real windstrength: 1.0
property vector2d windDir: Qt.vector2d(0.5, 0.5);
property TextureInput grass_base : TextureInput {
texture: Texture {
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/grass_bc.jpg"
}
}
property TextureInput turbulence : TextureInput {
texture: CommonResources.turbulenceTexture
}
property TextureInput perlin : TextureInput {
texture: Texture {
generateMipmaps: true
mipFilter: Texture.Linear
source: "media/textures/perlin.jpg"
}
}
}
]
geometry: ProceduralMesh {
id: grassChunkMesh
function generateMesh() {
let verts = []
let uvs = []
let indices = []
let colrs = []
const xOffset = 10.
const zOffset = 10.
const countX = 100.
const countZ = 100.
const segments = 9.
const height = 150.
const thickness = 5.
const thicknessHalf = thickness * 0.5
const segmentHeight = height / segments
let pos = Qt.vector3d(0, 0, 0)
let index = 0
const countXHalf = countX / 2;
const countZHalf = countZ / 2;
for (let xx = -countXHalf; xx < countXHalf; ++xx) {
for (let zz = -countZHalf; zz < countZHalf; ++zz) {
pos.x = xx * xOffset
pos.z = zz * zOffset
const xxNorm = xx / countX + 0.5
const zzNorm = zz / countZ + 0.5
for (let ss = 0; ss <= segments; ++ss) {
const uvY = ss / segments
const posLX = pos.x - thicknessHalf
const posLY = segmentHeight * ss + pos.y
const posLZ = pos.z
verts.push(Qt.vector3d(posLX, posLY, posLZ))
uvs.push(Qt.vector2d(0, uvY))
colrs.push(Qt.vector4d(pos.x, pos.z, xxNorm, zzNorm))
const posRX = pos.x + thicknessHalf
const posRY = segmentHeight * ss + pos.y
const posRZ = pos.z
verts.push(Qt.vector3d(posRX, posRY, posRZ))
uvs.push(Qt.vector2d(1.0, uvY))
colrs.push(Qt.vector4d(pos.x, pos.z, xxNorm, zzNorm))
if (ss < segments) {
indices.push(index, index + 1, index + 2)
indices.push(index + 2, index + 1, index + 3)
}
index += 2
}
}
}
positions = verts
uv0s = uvs
colors = colrs
indexes = indices
}
}
}