The Skung Cave commit
This commit is contained in:
@ -76,13 +76,19 @@ class OpenGL: Renderer
|
||||
}
|
||||
}
|
||||
|
||||
var wireframe: Bool
|
||||
{
|
||||
get { state.polygonMode == .line }
|
||||
set(mode) { state.polygonMode = mode ? .line : .fill }
|
||||
}
|
||||
|
||||
func setVsync(mode: VSyncMode) throws
|
||||
{
|
||||
guard SDL_GL_SetSwapInterval(mode.sdlInterval) == 0
|
||||
else { throw RendererError.sdlError(message: "SDL_GL_SetSwapInterval: \(String(cString: SDL_GetError()))") }
|
||||
}
|
||||
|
||||
func createMesh(mesh: Mesh) throws -> RenderMesh
|
||||
func createMesh<V: Vertex>(mesh: Mesh<V>) throws -> RenderMesh<V>
|
||||
{
|
||||
var buffers = [GLuint](repeating: 0, count: 2)
|
||||
buffers.withUnsafeMutableBufferPointer
|
||||
@ -94,35 +100,36 @@ class OpenGL: Renderer
|
||||
state.elementArrayBuffer = buffers[1]
|
||||
|
||||
glBufferData(GLenum(GL_ARRAY_BUFFER),
|
||||
MemoryLayout<Mesh.Vertex>.stride * mesh.vertices.count,
|
||||
MemoryLayout<V>.stride * mesh.vertices.count,
|
||||
mesh.vertices, GLenum(GL_STATIC_DRAW))
|
||||
glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER),
|
||||
MemoryLayout<Mesh.Index>.stride * mesh.indices.count,
|
||||
MemoryLayout<V>.stride * mesh.indices.count,
|
||||
mesh.indices, GLenum(GL_STATIC_DRAW))
|
||||
|
||||
state.elementArrayBuffer = OpenGLState.defaultBuffer
|
||||
state.arrayBuffer = OpenGLState.defaultBuffer
|
||||
|
||||
var subMeshes = [Mesh.SubMesh]()
|
||||
var subMeshes = [Mesh<V>.SubMesh]()
|
||||
if mesh.subMeshes.isEmpty
|
||||
{
|
||||
subMeshes.append(Mesh.SubMesh(start: 0, length: mesh.indices.count))
|
||||
subMeshes.append(Mesh<V>.SubMesh(start: 0, length: mesh.indices.count))
|
||||
}
|
||||
else
|
||||
{
|
||||
for subMesh in mesh.subMeshes
|
||||
{
|
||||
if ["Collision", "Collision3D"].contains(subMesh.key) { continue }
|
||||
subMeshes.append(Mesh.SubMesh(
|
||||
subMeshes.append(Mesh<V>.SubMesh(
|
||||
start: subMesh.value.start,
|
||||
length: subMesh.value.length))
|
||||
length: subMesh.value.length,
|
||||
material: subMesh.value.material))
|
||||
}
|
||||
}
|
||||
|
||||
return RenderMesh(
|
||||
vbo: Int(buffers[0]),
|
||||
ibo: Int(buffers[1]),
|
||||
subMeshes: subMeshes)
|
||||
subMeshes: subMeshes,
|
||||
materials: mesh.materials)
|
||||
}
|
||||
|
||||
func createTexture(data: UnsafeRawPointer, width: Int, height: Int) throws -> RenderTexture2D
|
||||
@ -172,7 +179,7 @@ class OpenGL: Renderer
|
||||
}
|
||||
|
||||
|
||||
func deleteMesh(_ mesh: RenderMesh)
|
||||
func deleteMesh<V: Vertex>(_ mesh: RenderMesh<V>)
|
||||
{
|
||||
var buffers = [GLuint](repeating: 0, count: 2)
|
||||
buffers[0] = GLuint(mesh.iboHnd)
|
||||
@ -208,42 +215,64 @@ class OpenGL: Renderer
|
||||
}
|
||||
|
||||
|
||||
private func draw(subMesh: Mesh.SubMesh)
|
||||
private func draw<V: Vertex>(subMesh: Mesh<V>.SubMesh)
|
||||
{
|
||||
glDrawElements(
|
||||
GLenum(GL_TRIANGLES),
|
||||
GLsizei(subMesh.length),
|
||||
GLenum(GL_UNSIGNED_SHORT),
|
||||
.init(bitPattern: MemoryLayout<Mesh.Index>.stride * subMesh.start));
|
||||
.init(bitPattern: MemoryLayout<Mesh<V>.Index>.stride * subMesh.start));
|
||||
}
|
||||
|
||||
private func draw(mesh: RenderMesh)
|
||||
private func bindMesh<V: Vertex>(mesh: RenderMesh<V>)
|
||||
{
|
||||
state.enableClient([ .vertex, .normal, .textureCoord ])
|
||||
state.enableClient([ .vertex, .colour, .normal, .textureCoord ])
|
||||
|
||||
state.arrayBuffer = UInt32(mesh.vboHnd)
|
||||
state.elementArrayBuffer = UInt32(mesh.iboHnd)
|
||||
|
||||
let stride = GLsizei(MemoryLayout<Mesh.Vertex>.stride)
|
||||
glVertexPointer(3, GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \Mesh.Vertex.position)!))
|
||||
glNormalPointer(GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \Mesh.Vertex.normal)!))
|
||||
glTexCoordPointer(2, GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \Mesh.Vertex.texCoord)!))
|
||||
|
||||
for subMesh in mesh.subMeshes
|
||||
let stride = GLsizei(MemoryLayout<V>.stride)
|
||||
if V.self == VertexPositionNormalTexcoord.self
|
||||
{
|
||||
draw(subMesh: subMesh)
|
||||
glVertexPointer(3, GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalTexcoord.position)!))
|
||||
glNormalPointer(GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalTexcoord.normal)!))
|
||||
glTexCoordPointer(2, GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalTexcoord.texCoord)!))
|
||||
}
|
||||
else if V.self == VertexPositionNormalColourTexcoord.self
|
||||
{
|
||||
glVertexPointer(3, GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalColourTexcoord.position)!))
|
||||
glColorPointer(4, GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalColourTexcoord.colour)!))
|
||||
glNormalPointer(GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalColourTexcoord.normal)!))
|
||||
glTexCoordPointer(2, GLenum(GL_FLOAT), stride,
|
||||
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalColourTexcoord.texCoord)!))
|
||||
}
|
||||
}
|
||||
|
||||
private func unbindMesh()
|
||||
{
|
||||
state.elementArrayBuffer = OpenGLState.defaultBuffer
|
||||
state.arrayBuffer = OpenGLState.defaultBuffer
|
||||
|
||||
state.disableClient([ .vertex, .normal, .textureCoord ])
|
||||
}
|
||||
|
||||
func draw(mesh: RenderMesh, model: Mat4f, environment env: Environment)
|
||||
private func draw<V: Vertex>(mesh: RenderMesh<V>)
|
||||
{
|
||||
bindMesh(mesh: mesh)
|
||||
for subMesh in mesh.subMeshes
|
||||
{
|
||||
draw(subMesh: subMesh)
|
||||
}
|
||||
unbindMesh()
|
||||
}
|
||||
|
||||
func draw<V: Vertex>(mesh: RenderMesh<V>, model: Mat4f, environment env: Environment)
|
||||
{
|
||||
if (mesh.subMeshes.isEmpty) { return }
|
||||
|
||||
@ -255,7 +284,7 @@ class OpenGL: Renderer
|
||||
glPopMatrix()
|
||||
}
|
||||
|
||||
func draw(mesh: RenderMesh, environment env: Environment)
|
||||
func draw<V: Vertex>(mesh: RenderMesh<V>, environment env: Environment)
|
||||
{
|
||||
if (mesh.subMeshes.isEmpty) { return }
|
||||
|
||||
@ -263,6 +292,14 @@ class OpenGL: Renderer
|
||||
draw(mesh: mesh)
|
||||
}
|
||||
|
||||
func draw<V: Vertex>(mesh: RenderMesh<V>, subMesh: Mesh<V>.SubMesh, environment env: Environment)
|
||||
{
|
||||
applyEnvironment(env)
|
||||
bindMesh(mesh: mesh)
|
||||
draw(subMesh: subMesh)
|
||||
unbindMesh()
|
||||
}
|
||||
|
||||
private func loadMatrix(_ matrix: Mat4f)
|
||||
{
|
||||
withUnsafePointer(to: matrix.columns)
|
||||
|
@ -793,4 +793,26 @@ struct OpenGLState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum PolygonMode { case point, line, fill }
|
||||
private var _polygonMode = PolygonMode.fill
|
||||
|
||||
var polygonMode: PolygonMode
|
||||
{
|
||||
get { _polygonMode }
|
||||
set(newMode)
|
||||
{
|
||||
if newMode != _polygonMode
|
||||
{
|
||||
let modeEnum = switch newMode
|
||||
{
|
||||
case .point: GL_POINT
|
||||
case .line: GL_LINE
|
||||
case .fill: GL_FILL
|
||||
}
|
||||
glPolygonMode(GLenum(GL_FRONT_AND_BACK), GLenum(modeEnum));
|
||||
_polygonMode = newMode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,15 +11,16 @@ public protocol Renderer
|
||||
func resize(width: Int32, height: Int32)
|
||||
|
||||
var clearColour: Colour { get set }
|
||||
var wireframe: Bool { get set }
|
||||
|
||||
func setVsync(mode: VSyncMode) throws
|
||||
|
||||
func createMesh(mesh: Mesh) throws -> RenderMesh
|
||||
func createMesh<V: Vertex>(mesh: Mesh<V>) throws -> RenderMesh<V>
|
||||
func createTexture(data: UnsafeRawPointer, width: Int, height: Int) throws -> RenderTexture2D
|
||||
func createTexture(data: UnsafeRawPointer, width: Int, height: Int,
|
||||
filter: FilterMode, mipMode: MipMode) throws -> RenderTexture2D
|
||||
|
||||
func deleteMesh(_ mesh: RenderMesh)
|
||||
func deleteMesh<V: Vertex>(_ mesh: RenderMesh<V>)
|
||||
func deleteTexture(_ texture: RenderTexture2D)
|
||||
|
||||
func setProjection(matrix: Mat4f)
|
||||
@ -27,8 +28,9 @@ public protocol Renderer
|
||||
|
||||
func setMaterial(_ mat: Material)
|
||||
|
||||
func draw(mesh: RenderMesh, model: Mat4f, environment: Environment)
|
||||
func draw(mesh: RenderMesh, environment: Environment)
|
||||
func draw<V: Vertex>(mesh: RenderMesh<V>, model: Mat4f, environment: Environment)
|
||||
func draw<V: Vertex>(mesh: RenderMesh<V>, environment: Environment)
|
||||
func draw<V: Vertex>(mesh: RenderMesh<V>, subMesh: Mesh<V>.SubMesh, environment: Environment)
|
||||
|
||||
func drawGizmos(lines: [Line])
|
||||
}
|
||||
@ -76,9 +78,9 @@ public protocol RendererResource
|
||||
var isValid: Bool { get }
|
||||
}
|
||||
|
||||
public struct RenderMesh: RendererResource
|
||||
public struct RenderMesh<V: Vertex>: RendererResource
|
||||
{
|
||||
public typealias T = Mesh
|
||||
public typealias T = Mesh<V>
|
||||
|
||||
public static var empty: RenderMesh { .init() }
|
||||
|
||||
@ -86,7 +88,8 @@ public struct RenderMesh: RendererResource
|
||||
|
||||
private let _valid: Bool;
|
||||
let vboHnd: Int, iboHnd: Int
|
||||
let subMeshes: [Mesh.SubMesh]
|
||||
public let subMeshes: [Mesh<V>.SubMesh]
|
||||
public let materials: [Material] // HACK !!!!
|
||||
|
||||
private init()
|
||||
{
|
||||
@ -94,14 +97,16 @@ public struct RenderMesh: RendererResource
|
||||
self.vboHnd = 0
|
||||
self.iboHnd = 0
|
||||
self.subMeshes = []
|
||||
self.materials = []
|
||||
}
|
||||
|
||||
init(vbo: Int, ibo: Int, subMeshes: [Mesh.SubMesh])
|
||||
init(vbo: Int, ibo: Int, subMeshes: [Mesh<V>.SubMesh], materials: [Material] = .init())
|
||||
{
|
||||
self._valid = true
|
||||
self.vboHnd = vbo
|
||||
self.iboHnd = ibo
|
||||
self.subMeshes = subMeshes
|
||||
self.materials = materials
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user