mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 05:10:57 +00:00
technicolour icecream hellscape terrain
This commit is contained in:
@ -24,7 +24,7 @@ class Game: GameDelegate {
|
|||||||
var camera = Camera(fov: 60, size: .one, range: 0.06...900)
|
var camera = Camera(fov: 60, size: .one, range: 0.06...900)
|
||||||
var player = Player()
|
var player = Player()
|
||||||
var projection: matrix_float4x4 = .identity
|
var projection: matrix_float4x4 = .identity
|
||||||
var world = World()
|
var world = World(generator: StandardWorldGenerator())
|
||||||
var cubeMesh: RendererMesh?
|
var cubeMesh: RendererMesh?
|
||||||
var renderChunks = [SIMD3<Int>: RendererMesh]()
|
var renderChunks = [SIMD3<Int>: RendererMesh]()
|
||||||
var chunkMeshGeneration: ChunkMeshGeneration!
|
var chunkMeshGeneration: ChunkMeshGeneration!
|
||||||
@ -42,7 +42,7 @@ class Game: GameDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func resetPlayer() {
|
private func resetPlayer() {
|
||||||
self.player.position = .init(repeating: 0.5) + .up * Float(Chunk.size)
|
self.player.position = .init(repeating: 0.5) + .up * Float(Chunk.size) * 1.6
|
||||||
self.player.velocity = .zero
|
self.player.velocity = .zero
|
||||||
self.player.rotation = .init(.pi, 0)
|
self.player.rotation = .init(.pi, 0)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
struct StandardWorldGenerator: WorldGenerator {
|
struct StandardWorldGenerator: WorldGenerator {
|
||||||
var noise: ImprovedPerlin<Float>!, noise2: SimplexNoise<Float>!
|
private var heightNoise: LayeredNoiseAlt<SimplexNoise<Float>>!
|
||||||
|
private var terrainNoise: LayeredNoise<SimplexNoise<Float>>!
|
||||||
|
private var colorNoise: LayeredNoise<ImprovedPerlin<Float>>!
|
||||||
|
|
||||||
public mutating func reset(seed: UInt64) {
|
public mutating func reset(seed: UInt64) {
|
||||||
var random: any RandomProvider
|
var random: any RandomProvider
|
||||||
@ -10,29 +12,33 @@ struct StandardWorldGenerator: WorldGenerator {
|
|||||||
random = PCG32Random(seed: initialState)
|
random = PCG32Random(seed: initialState)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
self.noise = ImprovedPerlin<Float>(random: &random)
|
self.heightNoise = .init(random: &random, octaves: 200, frequency: 0.0002, amplitude: 2)
|
||||||
self.noise2 = SimplexNoise<Float>(random: &random)
|
self.terrainNoise = .init(random: &random, octaves: 10, frequency: 0.01, amplitude: 0.337)
|
||||||
|
self.colorNoise = .init(random: &random, octaves: 150, frequency: 0.00366, amplitude: 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeChunk(id chunkID: SIMD3<Int>) -> Chunk {
|
public func makeChunk(id chunkID: SIMD3<Int>) -> Chunk {
|
||||||
let chunkOrigin = chunkID &<< Chunk.shift
|
let chunkOrigin = chunkID &<< Chunk.shift
|
||||||
var chunk = Chunk(position: chunkOrigin)
|
var chunk = Chunk(position: chunkOrigin)
|
||||||
chunk.fill(allBy: { position in
|
for z in 0..<Chunk.size {
|
||||||
let fpos = SIMD3<Float>(chunkOrigin &+ position)
|
for x in 0..<Chunk.size {
|
||||||
let threshold: Float = 0.6
|
let height = self.heightNoise.get(SIMD2<Float>(chunkOrigin.xz &+ SIMD2<Int>(x, z)))
|
||||||
let value = fpos.y / 16.0
|
for y in 0..<Chunk.size {
|
||||||
+ self.noise.get(fpos * 0.05) * 1.1
|
let ipos = SIMD3(x, y, z)
|
||||||
+ self.noise.get(fpos * 0.10) * 0.5
|
let fpos = SIMD3<Float>(chunkOrigin &+ ipos)
|
||||||
+ self.noise.get(fpos * 0.30) * 0.23
|
let height = fpos.y / 64.0 + height
|
||||||
return if value < threshold {
|
let value = height + self.terrainNoise.get(fpos)
|
||||||
|
let block: BlockType = if value < 0 {
|
||||||
.solid(.init(
|
.solid(.init(
|
||||||
hue: Float(180 + self.noise2.get(fpos * 0.05) * 180),
|
hue: Float(180 + self.colorNoise.get(fpos) * 180),
|
||||||
saturation: Float(0.5 + self.noise2.get(SIMD4(fpos * 0.05, 4)) * 0.5),
|
saturation: 0.7, value: 0.9).linear)
|
||||||
value: Float(0.5 + self.noise2.get(SIMD4(fpos * 0.05, 9)) * 0.5).lerp(0.5, 1)).linear)
|
|
||||||
} else {
|
} else {
|
||||||
.air
|
.air
|
||||||
}
|
}
|
||||||
})
|
chunk.setBlock(internal: ipos, type: block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return chunk
|
return chunk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
protocol WorldGenerator {
|
public protocol WorldGenerator {
|
||||||
mutating func reset(seed: UInt64)
|
mutating func reset(seed: UInt64)
|
||||||
func makeChunk(id: SIMD3<Int>) -> Chunk
|
func makeChunk(id: SIMD3<Int>) -> Chunk
|
||||||
}
|
}
|
||||||
|
@ -58,3 +58,51 @@ public extension LayeredNoise where Generator: CoherentNoise4D {
|
|||||||
$0 + $1 } * self._amplitudeAdjusted
|
$0 + $1 } * self._amplitudeAdjusted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: - Experimental
|
||||||
|
|
||||||
|
public struct LayeredNoiseAlt<Generator: CoherentNoise> {
|
||||||
|
public typealias Scalar = Generator.Scalar
|
||||||
|
|
||||||
|
public let octaves: Int
|
||||||
|
public let frequency: Scalar
|
||||||
|
public let amplitude: Scalar
|
||||||
|
|
||||||
|
private let _generator: Generator
|
||||||
|
private let _amplitudeAdjusted: Scalar
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension LayeredNoiseAlt where Generator: CoherentNoiseRandomInit {
|
||||||
|
init<Random: RandomProvider>(random: inout Random, octaves: Int, frequency: Scalar, amplitude: Scalar = 1) {
|
||||||
|
self.octaves = octaves
|
||||||
|
self.frequency = frequency
|
||||||
|
self.amplitude = amplitude
|
||||||
|
self._generator = Generator(random: &random)
|
||||||
|
self._amplitudeAdjusted = amplitude / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension LayeredNoiseAlt where Generator: CoherentNoise3D & CoherentNoise2D {
|
||||||
|
func get(_ point: SIMD2<Scalar>) -> Scalar {
|
||||||
|
let layerOffset: Int = 1
|
||||||
|
return (1..<self.octaves).map { term in
|
||||||
|
let mul = Scalar(1 + term)
|
||||||
|
let point3D = SIMD3(point * frequency * mul, Scalar(term * layerOffset))
|
||||||
|
return self._generator.get(point3D) / mul
|
||||||
|
}.reduce(self._generator.get(point * frequency)) {
|
||||||
|
$0 + $1 } * self._amplitudeAdjusted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension LayeredNoiseAlt where Generator: CoherentNoise4D & CoherentNoise3D {
|
||||||
|
func get(_ point: SIMD3<Scalar>) -> Scalar {
|
||||||
|
let layerOffset: Int = 1
|
||||||
|
return (1..<self.octaves).map { term in
|
||||||
|
let mul = Scalar(1 + term)
|
||||||
|
let point4D = SIMD4(point * frequency * mul, Scalar(term * layerOffset))
|
||||||
|
return self._generator.get(point4D) / mul
|
||||||
|
}.reduce(self._generator.get(point * frequency)) {
|
||||||
|
$0 + $1 } * self._amplitudeAdjusted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,22 +3,6 @@ import Foundation
|
|||||||
public struct SimplexNoise<Scalar: BinaryFloatingPoint & SIMDScalar>: CoherentNoise2D, CoherentNoise3D, CoherentNoise4D, CoherentNoiseRandomInit, CoherentNoiseTableInit {
|
public struct SimplexNoise<Scalar: BinaryFloatingPoint & SIMDScalar>: CoherentNoise2D, CoherentNoise3D, CoherentNoise4D, CoherentNoiseRandomInit, CoherentNoiseTableInit {
|
||||||
private let p: [Int16], pMod12: [Int16]
|
private let p: [Int16], pMod12: [Int16]
|
||||||
|
|
||||||
private let grad3: [SIMD3<Scalar>] = [
|
|
||||||
.init(1, 1, 0), .init(-1, 1, 0), .init(1, -1, 0), .init(-1, -1, 0),
|
|
||||||
.init(1, 0, 1), .init(-1, 0, 1), .init(1, 0, -1), .init(-1, 0, -1),
|
|
||||||
.init(0, 1, 1), .init( 0, -1, 1), .init(0, 1, -1), .init( 0, -1, -1)
|
|
||||||
]
|
|
||||||
private let grad4: [SIMD4<Scalar>] = [
|
|
||||||
.init( 0, 1, 1, 1), .init( 0, 1, 1, -1), .init( 0, 1, -1, 1), .init( 0, 1, -1, -1),
|
|
||||||
.init( 0, -1, 1, 1), .init( 0, -1, 1, -1), .init( 0, -1, -1, 1), .init( 0, -1, -1, -1),
|
|
||||||
.init( 1, 0, 1, 1), .init( 1, 0, 1, -1), .init( 1, 0, -1, 1), .init( 1, 0, -1, -1),
|
|
||||||
.init(-1, 0, 1, 1), .init(-1, 0, 1, -1), .init(-1, 0, -1, 1), .init(-1, 0, -1, -1),
|
|
||||||
.init( 1, 1, 0, 1), .init( 1, 1, 0, -1), .init( 1, -1, 0, 1), .init( 1, -1, 0, -1),
|
|
||||||
.init(-1, 1, 0, 1), .init(-1, 1, 0, -1), .init(-1, -1, 0, 1), .init(-1, -1, 0, -1),
|
|
||||||
.init( 1, 1, 1, 0), .init( 1, 1, -1, 0), .init( 1, -1, 1, 0), .init( 1, -1, -1, 0),
|
|
||||||
.init(-1, 1, 1, 0), .init(-1, 1, -1, 0), .init(-1, -1, 1, 0), .init(-1, -1, -1, 0)
|
|
||||||
]
|
|
||||||
|
|
||||||
public init(permutation: [Int16]) {
|
public init(permutation: [Int16]) {
|
||||||
assert(permutation.count == 0x100)
|
assert(permutation.count == 0x100)
|
||||||
self.p = permutation
|
self.p = permutation
|
||||||
@ -58,7 +42,7 @@ public struct SimplexNoise<Scalar: BinaryFloatingPoint & SIMDScalar>: CoherentNo
|
|||||||
return 0
|
return 0
|
||||||
} else {
|
} else {
|
||||||
t *= t
|
t *= t
|
||||||
return t * t * self.grad3[gradID].xy.dot(corner)
|
return t * t * SIMD2<Scalar>(grad3[gradID].xy).dot(corner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let noise0 = cornerContribution(corner0, gradIndex0)
|
let noise0 = cornerContribution(corner0, gradIndex0)
|
||||||
@ -125,7 +109,7 @@ public struct SimplexNoise<Scalar: BinaryFloatingPoint & SIMDScalar>: CoherentNo
|
|||||||
return 0
|
return 0
|
||||||
} else {
|
} else {
|
||||||
t *= t
|
t *= t
|
||||||
return t * t * self.grad3[gradID].dot(corner)
|
return t * t * SIMD3<Scalar>(grad3[gradID]).dot(corner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let noise0 = cornerContribution(corner0, gradCorner0)
|
let noise0 = cornerContribution(corner0, gradCorner0)
|
||||||
@ -197,7 +181,7 @@ public struct SimplexNoise<Scalar: BinaryFloatingPoint & SIMDScalar>: CoherentNo
|
|||||||
return 0
|
return 0
|
||||||
} else {
|
} else {
|
||||||
t *= t
|
t *= t
|
||||||
return t * t * self.grad4[gradID].dot(corner)
|
return t * t * SIMD4<Scalar>(grad4[gradID]).dot(corner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let noise0 = cornerContribution(corner0, gradIndex0)
|
let noise0 = cornerContribution(corner0, gradIndex0)
|
||||||
@ -212,3 +196,20 @@ public struct SimplexNoise<Scalar: BinaryFloatingPoint & SIMDScalar>: CoherentNo
|
|||||||
@inline(__always) fileprivate func perm(_ idx: Int) -> Int { Int(self.p[idx & 0xFF]) }
|
@inline(__always) fileprivate func perm(_ idx: Int) -> Int { Int(self.p[idx & 0xFF]) }
|
||||||
@inline(__always) fileprivate func permMod12(_ idx: Int) -> Int { Int(self.pMod12[idx & 0xFF]) }
|
@inline(__always) fileprivate func permMod12(_ idx: Int) -> Int { Int(self.pMod12[idx & 0xFF]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate let grad3: [SIMD3<Int16>] = [
|
||||||
|
.init(1, 1, 0), .init(-1, 1, 0), .init(1, -1, 0), .init(-1, -1, 0),
|
||||||
|
.init(1, 0, 1), .init(-1, 0, 1), .init(1, 0, -1), .init(-1, 0, -1),
|
||||||
|
.init(0, 1, 1), .init( 0, -1, 1), .init(0, 1, -1), .init( 0, -1, -1)
|
||||||
|
]
|
||||||
|
|
||||||
|
fileprivate let grad4: [SIMD4<Int16>] = [
|
||||||
|
.init( 0, 1, 1, 1), .init( 0, 1, 1, -1), .init( 0, 1, -1, 1), .init( 0, 1, -1, -1),
|
||||||
|
.init( 0, -1, 1, 1), .init( 0, -1, 1, -1), .init( 0, -1, -1, 1), .init( 0, -1, -1, -1),
|
||||||
|
.init( 1, 0, 1, 1), .init( 1, 0, 1, -1), .init( 1, 0, -1, 1), .init( 1, 0, -1, -1),
|
||||||
|
.init(-1, 0, 1, 1), .init(-1, 0, 1, -1), .init(-1, 0, -1, 1), .init(-1, 0, -1, -1),
|
||||||
|
.init( 1, 1, 0, 1), .init( 1, 1, 0, -1), .init( 1, -1, 0, 1), .init( 1, -1, 0, -1),
|
||||||
|
.init(-1, 1, 0, 1), .init(-1, 1, 0, -1), .init(-1, -1, 0, 1), .init(-1, -1, 0, -1),
|
||||||
|
.init( 1, 1, 1, 0), .init( 1, 1, -1, 0), .init( 1, -1, 1, 0), .init( 1, -1, -1, 0),
|
||||||
|
.init(-1, 1, 1, 0), .init(-1, 1, -1, 0), .init(-1, -1, 1, 0), .init(-1, -1, -1, 0)
|
||||||
|
]
|
||||||
|
@ -12,10 +12,10 @@ public class World {
|
|||||||
private var _generator: any WorldGenerator
|
private var _generator: any WorldGenerator
|
||||||
private var _chunkGeneration: ChunkGeneration
|
private var _chunkGeneration: ChunkGeneration
|
||||||
|
|
||||||
public init() {
|
public init(generator: any WorldGenerator) {
|
||||||
self._chunks = [:]
|
self._chunks = [:]
|
||||||
self._chunkDamage = []
|
self._chunkDamage = []
|
||||||
self._generator = TerrorTowerGenerator()
|
self._generator = generator
|
||||||
self._chunkGeneration = ChunkGeneration(queue: .global(qos: .userInitiated))
|
self._chunkGeneration = ChunkGeneration(queue: .global(qos: .userInitiated))
|
||||||
self._chunkGeneration.world = self
|
self._chunkGeneration.world = self
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user