mirror of
				https://github.com/GayPizzaSpecifications/voxelotl-engine.git
				synced 2025-11-04 10:59:39 +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,19 +441,22 @@ 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,
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user