mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 21:21:34 +00:00
move some shared binds to a setup stage
This commit is contained in:
@ -84,17 +84,18 @@ class Game: GameDelegate {
|
|||||||
self.world.update()
|
self.world.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static let material = Material(
|
||||||
|
ambient: Color(rgba8888: 0x4F4F4F00).linear,
|
||||||
|
diffuse: Color(rgba8888: 0xDFDFDF00).linear,
|
||||||
|
specular: Color(rgba8888: 0x2F2F2F00).linear,
|
||||||
|
gloss: 75)
|
||||||
|
|
||||||
func draw(_ renderer: Renderer, _ time: GameTime) {
|
func draw(_ renderer: Renderer, _ time: GameTime) {
|
||||||
let totalTime = Float(time.total.asFloat)
|
let totalTime = Float(time.total.asFloat)
|
||||||
|
|
||||||
let env = Environment(
|
let env = Environment(
|
||||||
cullFace: .back,
|
cullFace: .back,
|
||||||
lightDirection: .init(0.75, -1, 0.5))
|
lightDirection: .init(0.75, -1, 0.5))
|
||||||
let material = Material(
|
|
||||||
ambient: Color(rgba8888: 0x4F4F4F00).linear,
|
|
||||||
diffuse: Color(rgba8888: 0xDFDFDF00).linear,
|
|
||||||
specular: Color(rgba8888: 0x2F2F2F00).linear,
|
|
||||||
gloss: 75)
|
|
||||||
|
|
||||||
// Update chunk meshes if needed
|
// Update chunk meshes if needed
|
||||||
self.world.handleRenderDamagedChunks { id, chunk in
|
self.world.handleRenderDamagedChunks { id, chunk in
|
||||||
@ -109,7 +110,7 @@ class Game: GameDelegate {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let drawPos = SIMD3<Float>(id &<< Chunk.shift)
|
let drawPos = SIMD3<Float>(id &<< Chunk.shift)
|
||||||
self.modelBatch.draw(.init(mesh: chunk!, material: material), position: drawPos)
|
self.modelBatch.draw(.init(mesh: chunk!, material: Self.material), position: drawPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let position = player.rayhitPos {
|
if let position = player.rayhitPos {
|
||||||
@ -117,7 +118,7 @@ class Game: GameDelegate {
|
|||||||
.init(angle: totalTime * 3.0, axis: .Y) *
|
.init(angle: totalTime * 3.0, axis: .Y) *
|
||||||
.init(angle: totalTime * 1.5, axis: .X) *
|
.init(angle: totalTime * 1.5, axis: .X) *
|
||||||
.init(angle: totalTime * 0.7, axis: .Z)
|
.init(angle: totalTime * 0.7, axis: .Z)
|
||||||
self.modelBatch.draw(.init(mesh: self.cubeMesh!, material: material),
|
self.modelBatch.draw(.init(mesh: self.cubeMesh!, material: Self.material),
|
||||||
position: position, scale: 0.0725 * 0.5, rotation: rotation,
|
position: position, scale: 0.0725 * 0.5, rotation: rotation,
|
||||||
color: .init(r: 0.5, g: 0.5, b: 1))
|
color: .init(r: 0.5, g: 0.5, b: 1))
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//TODO: Sort, Blend
|
||||||
public struct Environment {
|
public struct Environment {
|
||||||
public var cullFace: Face
|
public var cullFace: Face
|
||||||
public var lightDirection: SIMD3<Float>
|
public var lightDirection: SIMD3<Float>
|
||||||
|
@ -13,33 +13,17 @@ public struct ModelBatch {
|
|||||||
self._instances = Array()
|
self._instances = Array()
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Sort, Blend
|
|
||||||
public mutating func begin(camera: Camera, environment: Environment) {
|
public mutating func begin(camera: Camera, environment: Environment) {
|
||||||
self._active = true
|
self._active = true
|
||||||
self._cam = camera
|
self._cam = camera
|
||||||
self._env = environment
|
self._env = environment
|
||||||
self._prev = nil
|
self._prev = nil
|
||||||
|
self._renderer.setupBatch(material: Game.material, environment: environment, camera: camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
private mutating func flush() {
|
private mutating func flush() {
|
||||||
assert(self._instances.count > 0)
|
assert(self._instances.count > 0)
|
||||||
if self._instances.count == 1 {
|
self._renderer.submitBatch(mesh: self._prev.mesh, instances: self._instances)
|
||||||
let instance = self._instances.first!
|
|
||||||
self._renderer.draw(
|
|
||||||
model: instance.world,
|
|
||||||
color: instance.color,
|
|
||||||
mesh: self._prev.mesh,
|
|
||||||
material: self._prev.material,
|
|
||||||
environment: self._env,
|
|
||||||
camera: self._cam)
|
|
||||||
} else {
|
|
||||||
self._renderer.batch(
|
|
||||||
instances: self._instances,
|
|
||||||
mesh: self._prev.mesh,
|
|
||||||
material: self._prev.material,
|
|
||||||
environment: self._env,
|
|
||||||
camera: self._cam)
|
|
||||||
}
|
|
||||||
self._instances.removeAll(keepingCapacity: true)
|
self._instances.removeAll(keepingCapacity: true)
|
||||||
self._prev = nil
|
self._prev = nil
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public class Renderer {
|
|||||||
private let _defaultStorageMode: MTLResourceOptions
|
private let _defaultStorageMode: MTLResourceOptions
|
||||||
|
|
||||||
private var depthTextures: [MTLTexture]
|
private var depthTextures: [MTLTexture]
|
||||||
private var _instances: [MTLBuffer?]
|
//private var _instances: [MTLBuffer?]
|
||||||
|
|
||||||
private var _encoder: MTLRenderCommandEncoder! = nil
|
private var _encoder: MTLRenderCommandEncoder! = nil
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ public class Renderer {
|
|||||||
return depthStencilTexture
|
return depthStencilTexture
|
||||||
}
|
}
|
||||||
|
|
||||||
self._instances = [MTLBuffer?](repeating: nil, count: numFramesInFlight)
|
//self._instances = [MTLBuffer?](repeating: nil, count: numFramesInFlight)
|
||||||
|
|
||||||
let stencilDepthDescription = MTLDepthStencilDescriptor()
|
let stencilDepthDescription = MTLDepthStencilDescriptor()
|
||||||
stencilDepthDescription.depthCompareFunction = .less // OpenGL default
|
stencilDepthDescription.depthCompareFunction = .less // OpenGL default
|
||||||
@ -377,8 +377,12 @@ public class Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw(model: matrix_float4x4, color: Color<Float>, mesh: RendererMesh, material: Material, environment: Environment, camera: Camera) {
|
func createModelBatch() -> ModelBatch {
|
||||||
assert(self._encoder != nil, "draw can't be called outside of a frame being rendered")
|
return ModelBatch(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal func setupBatch(material: Material, environment: Environment, camera: Camera) {
|
||||||
|
assert(self._encoder != nil, "startBatch can't be called outside of a frame being rendered")
|
||||||
|
|
||||||
var vertUniforms = VertexShaderUniforms(projView: camera.viewProjection)
|
var vertUniforms = VertexShaderUniforms(projView: camera.viewProjection)
|
||||||
var fragUniforms = FragmentShaderUniforms(
|
var fragUniforms = FragmentShaderUniforms(
|
||||||
@ -388,50 +392,24 @@ public class Renderer {
|
|||||||
diffuseColor: SIMD4(material.diffuse),
|
diffuseColor: SIMD4(material.diffuse),
|
||||||
specularColor: SIMD4(material.specular),
|
specularColor: SIMD4(material.specular),
|
||||||
specularIntensity: material.gloss)
|
specularIntensity: material.gloss)
|
||||||
var instance = VertexShaderInstance(
|
|
||||||
model: model,
|
|
||||||
normalModel: model.inverse.transpose,
|
|
||||||
color: SIMD4(color))
|
|
||||||
|
|
||||||
self._encoder.setCullMode(.init(environment.cullFace))
|
self._encoder.setCullMode(.init(environment.cullFace))
|
||||||
|
|
||||||
self._encoder.setVertexBuffer(mesh._vertBuf, offset: 0, index: VertexShaderInputIdx.vertices.rawValue)
|
|
||||||
// Ideal as long as our uniforms total 4 KB or less
|
// Ideal as long as our uniforms total 4 KB or less
|
||||||
self._encoder.setVertexBytes(&instance,
|
|
||||||
length: MemoryLayout<VertexShaderInstance>.stride,
|
|
||||||
index: VertexShaderInputIdx.instance.rawValue)
|
|
||||||
self._encoder.setVertexBytes(&vertUniforms,
|
self._encoder.setVertexBytes(&vertUniforms,
|
||||||
length: MemoryLayout<VertexShaderUniforms>.stride,
|
length: MemoryLayout<VertexShaderUniforms>.stride,
|
||||||
index: VertexShaderInputIdx.uniforms.rawValue)
|
index: VertexShaderInputIdx.uniforms.rawValue)
|
||||||
self._encoder.setFragmentBytes(&fragUniforms,
|
self._encoder.setFragmentBytes(&fragUniforms,
|
||||||
length: MemoryLayout<FragmentShaderUniforms>.stride,
|
length: MemoryLayout<FragmentShaderUniforms>.stride,
|
||||||
index: FragmentShaderInputIdx.uniforms.rawValue)
|
index: FragmentShaderInputIdx.uniforms.rawValue)
|
||||||
|
|
||||||
self._encoder.drawIndexedPrimitives(
|
|
||||||
type: .triangle,
|
|
||||||
indexCount: mesh.numIndices,
|
|
||||||
indexType: .uint16,
|
|
||||||
indexBuffer: mesh._idxBuf,
|
|
||||||
indexBufferOffset: 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createModelBatch() -> ModelBatch {
|
internal func submitBatch(mesh: RendererMesh, instances: [ModelBatch.Instance]) {
|
||||||
return ModelBatch(self)
|
assert(self._encoder != nil, "submitBatch can't be called outside of a frame being rendered")
|
||||||
}
|
|
||||||
|
|
||||||
func batch(instances: [ModelBatch.Instance], mesh: RendererMesh, material: Material, environment: Environment, camera: Camera) {
|
|
||||||
assert(self._encoder != nil, "batch can't be called outside of a frame being rendered")
|
|
||||||
|
|
||||||
var vertUniforms = VertexShaderUniforms(projView: camera.viewProjection)
|
|
||||||
var fragUniforms = FragmentShaderUniforms(
|
|
||||||
cameraPosition: camera.position,
|
|
||||||
directionalLight: normalize(environment.lightDirection),
|
|
||||||
ambientColor: SIMD4(material.ambient),
|
|
||||||
diffuseColor: SIMD4(material.diffuse),
|
|
||||||
specularColor: SIMD4(material.specular),
|
|
||||||
specularIntensity: material.gloss)
|
|
||||||
|
|
||||||
let numInstances = instances.count
|
let numInstances = instances.count
|
||||||
|
assert(numInstances > 0, "submitBatch called with zero instances")
|
||||||
|
|
||||||
|
/*
|
||||||
let instancesBytes = numInstances * MemoryLayout<VertexShaderInstance>.stride
|
let instancesBytes = numInstances * MemoryLayout<VertexShaderInstance>.stride
|
||||||
|
|
||||||
// (Re)create instance buffer if needed
|
// (Re)create instance buffer if needed
|
||||||
@ -463,27 +441,30 @@ public class Renderer {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
self._encoder.setCullMode(.init(environment.cullFace))
|
|
||||||
|
|
||||||
self._encoder.setVertexBuffer(mesh._vertBuf, offset: 0, index: VertexShaderInputIdx.vertices.rawValue)
|
|
||||||
self._encoder.setVertexBuffer(instanceBuffer,
|
self._encoder.setVertexBuffer(instanceBuffer,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
index: VertexShaderInputIdx.instance.rawValue)
|
index: VertexShaderInputIdx.instance.rawValue)
|
||||||
|
*/
|
||||||
|
let instanceData = instances.map { instance in
|
||||||
|
VertexShaderInstance(
|
||||||
|
model: instance.world,
|
||||||
|
normalModel: instance.world.inverse.transpose,
|
||||||
|
color: SIMD4(instance.color))
|
||||||
|
}
|
||||||
|
|
||||||
|
self._encoder.setVertexBuffer(mesh._vertBuf, offset: 0, index: VertexShaderInputIdx.vertices.rawValue)
|
||||||
// Ideal as long as our uniforms total 4 KB or less
|
// Ideal as long as our uniforms total 4 KB or less
|
||||||
self._encoder.setVertexBytes(&vertUniforms,
|
self._encoder.setVertexBytes(instanceData,
|
||||||
length: MemoryLayout<VertexShaderUniforms>.stride,
|
length: numInstances * MemoryLayout<VertexShaderInstance>.stride,
|
||||||
index: VertexShaderInputIdx.uniforms.rawValue)
|
index: VertexShaderInputIdx.instance.rawValue)
|
||||||
self._encoder.setFragmentBytes(&fragUniforms,
|
|
||||||
length: MemoryLayout<FragmentShaderUniforms>.stride,
|
|
||||||
index: FragmentShaderInputIdx.uniforms.rawValue)
|
|
||||||
|
|
||||||
self._encoder.drawIndexedPrimitives(
|
self._encoder.drawIndexedPrimitives(
|
||||||
type: .triangle,
|
type: .triangle,
|
||||||
indexCount: mesh.numIndices,
|
indexCount: mesh.numIndices,
|
||||||
indexType: .uint16,
|
indexType: .uint16,
|
||||||
indexBuffer: mesh._idxBuf,
|
indexBuffer: mesh._idxBuf,
|
||||||
indexBufferOffset: 0,
|
indexBufferOffset: 0,
|
||||||
instanceCount: numInstances)
|
instanceCount: numInstances)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user