The Skung Rockification of Ziggy Skungdust and the SIMD's

This commit is contained in:
2024-05-13 01:11:03 +10:00
parent b62cd056b5
commit 6c44476062
40 changed files with 2066 additions and 386 deletions

View File

@ -1,3 +1,6 @@
import Maths
public enum Fog
{
public enum Mode

View File

@ -1,19 +1,21 @@
public struct Material
{
public var id: String
public var diffuse: Colour, specular: Colour
public var diffuse: Colour, specular: Colour, emmision: Colour
public var specularExp: Float
public var texture: RenderTexture2D
public init(id: String = "",
diffuse: Colour = .white,
specular: Colour = .zero,
gloss: Float = 0,
specular: Colour = .black,
emmision: Colour = .black,
gloss: Float = 20,
texture: RenderTexture2D = .empty)
{
self.id = id
self.diffuse = diffuse
self.specular = specular
self.emmision = emmision
self.specularExp = gloss
self.texture = texture
}

View File

@ -1,9 +1,11 @@
//#set OPENGL3
import Foundation
import Maths
import SDL2
#if OPENGL3
import OpenGL
#if OPENGL3
import OpenGL.GL
#else
import OpenGL.GL3
#endif
@ -41,7 +43,7 @@ class OpenGL: Renderer
guard SDL_GL_MakeCurrent(sdlWindow, glCtx) == 0
else { throw RendererError.sdlError(message: "SDL_GL_MakeCurrent: \(String(cString: SDL_GetError()))") }
state.enable([.texture2D, .cullFace, .depthTest, .rescaleNormal, .colourMaterial])
state.enable([.texture2D, .cullFace, .depthTest, .rescaleNormal/*, .colourMaterial */])
if srgb { state.enable(.frameBufferSrgb) }
state.cullFace = .back
state.clearDepth = 1
@ -132,13 +134,12 @@ class OpenGL: Renderer
materials: mesh.materials)
}
func createTexture(data: UnsafeRawPointer, width: Int, height: Int) throws -> RenderTexture2D
func createTexture(image: Image) throws -> RenderTexture2D
{
try createTexture(data: data, width: width, height: height, filter: .linear, mipMode: .off)
try createTexture(image: image, filter: .linear, mipMode: .off)
}
func createTexture(data: UnsafeRawPointer, width: Int, height: Int,
filter: FilterMode, mipMode: MipMode) throws -> RenderTexture2D
func createTexture(image: Image, filter: FilterMode, mipMode: MipMode) throws -> RenderTexture2D
{
let min: Int32 = switch mipMode
{
@ -146,14 +147,19 @@ class OpenGL: Renderer
case .nearest: filter.glMip
case .linear: filter.glLinearMip
}
return RenderTexture2D(try loadTexture(data: data,
width: GLsizei(width), height: GLsizei(height),
minFilter: min, magFilter: filter.gl))
return try image.data.withUnsafeBytes
{ raw in
RenderTexture2D(try loadTexture(
data: raw.baseAddress!, format: image.format,
width: GLsizei(image.width), height: GLsizei(image.height),
mipLevels: image.mipLevels,
minFilter: min, magFilter: filter.gl))
}
}
private func loadTexture(
data: UnsafeRawPointer,
width: GLsizei, height: GLsizei,
data: UnsafeRawPointer, format: Image.Format,
width: GLsizei, height: GLsizei, mipLevels: Int,
minFilter: Int32 = GL_LINEAR, magFilter: Int32 = GL_LINEAR,
wrap: Int32 = GL_REPEAT) throws -> GLuint
{
@ -165,19 +171,49 @@ class OpenGL: Renderer
state.texture2DParameter(active: 0, param: .magFilter, int: magFilter)
state.texture2DParameter(active: 0, param: .wrapS, int: wrap)
state.texture2DParameter(active: 0, param: .wrapT, int: wrap)
let format: GLint = srgb ? GL_SRGB8 : GL_RGBA
glTexImage2D(GLenum(GL_TEXTURE_2D),
0, format, width, height, 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), data)
let upload = getTextureUploader(format: format)
var offset = 0
for i in 0...mipLevels
{
let levelWidth = width &>> i, levelHeight = height &>> i
let size = format.computeSize(width: UInt32(levelWidth), height: UInt32(levelHeight))
upload(GLint(i), levelWidth, levelHeight, data + offset, GLsizei(size))
offset += size
}
// Generate mipmaps if needed
if [GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST]
.contains(minFilter) { glGenerateMipmap(GLenum(GL_TEXTURE_2D)) }
.contains(minFilter) && mipLevels == 0 { glGenerateMipmap(GLenum(GL_TEXTURE_2D)) }
state.bindTexture2D(active: 0, texture: OpenGLState.defaultTexture)
return texId
}
private typealias UploadFunc = (GLint, GLsizei, GLsizei, UnsafeRawPointer, GLsizei) -> Void
private func getTextureUploader(format: Image.Format) -> UploadFunc
{
let target = GLenum(GL_TEXTURE_2D)
let border: GLint = 0
return switch format
{
case .argb8888: { (level, width, height, data, size) in
glTexImage2D(target, level, GLint(self.srgb ? GL_SRGB8 : GL_RGBA),
width, height, border, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), data)
}
case .s3tc_bc1: { (level, width, height, data, size) in
glCompressedTexImage2D(target, level, GLenum(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT),
width, height, border, size, data)
}
case .rgtc_bc5_3dc: { (level, width, height, data, size) in
glCompressedTexImage2D(target, level, GLenum(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT),
width, height, border, size, data)
}
default: fatalError()
}
}
func deleteMesh<V: Vertex>(_ mesh: RenderMesh<V>)
{
@ -210,7 +246,11 @@ class OpenGL: Renderer
func setMaterial(_ mat: Material)
{
glColor4f(mat.diffuse.r, mat.diffuse.g, mat.diffuse.b, mat.diffuse.a)
//glColor4f(mat.diffuse.r, mat.diffuse.g, mat.diffuse.b, mat.diffuse.a)
state.materialDiffuse = srgb ? mat.diffuse.linear : mat.diffuse
state.materialSpecular = srgb ? mat.specular.linear : mat.specular
state.materialEmmision = srgb ? mat.emmision.linear : mat.emmision
state.materialShininess = mat.specularExp
state.bindTexture2D(active: 0, texture: mat.texture.isValid ? mat.texture.id : 0)
}
@ -226,14 +266,13 @@ class OpenGL: Renderer
private func bindMesh<V: Vertex>(mesh: RenderMesh<V>)
{
state.enableClient([ .vertex, .colour, .normal, .textureCoord ])
state.arrayBuffer = UInt32(mesh.vboHnd)
state.elementArrayBuffer = UInt32(mesh.iboHnd)
let stride = GLsizei(MemoryLayout<V>.stride)
if V.self == VertexPositionNormalTexcoord.self
{
state.enableClient([ .vertex, .normal, .textureCoord ])
glVertexPointer(3, GLenum(GL_FLOAT), stride,
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalTexcoord.position)!))
glNormalPointer(GLenum(GL_FLOAT), stride,
@ -243,6 +282,7 @@ class OpenGL: Renderer
}
else if V.self == VertexPositionNormalColourTexcoord.self
{
state.enableClient([ .vertex, .colour, .normal, .textureCoord ])
glVertexPointer(3, GLenum(GL_FLOAT), stride,
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalColourTexcoord.position)!))
glColorPointer(4, GLenum(GL_FLOAT), stride,
@ -252,6 +292,16 @@ class OpenGL: Renderer
glTexCoordPointer(2, GLenum(GL_FLOAT), stride,
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VertexPositionNormalColourTexcoord.texCoord)!))
}
else if V.self == VMeshVertex.self
{
state.enableClient([ .vertex, .normal, .textureCoord ])
glVertexPointer(3, GLenum(GL_FLOAT), stride,
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VMeshVertex.position)!))
glTexCoordPointer(2, GLenum(GL_FLOAT), stride,
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VMeshVertex.texCoord)!))
glNormalPointer(GLenum(GL_BYTE), stride,
UnsafeRawPointer.init(bitPattern: MemoryLayout.offset(of: \VMeshVertex.normal)!))
}
}
private func unbindMesh()
@ -259,7 +309,7 @@ class OpenGL: Renderer
state.elementArrayBuffer = OpenGLState.defaultBuffer
state.arrayBuffer = OpenGLState.defaultBuffer
state.disableClient([ .vertex, .normal, .textureCoord ])
state.disableClient([ .vertex, .colour, .normal, .textureCoord ])
}
private func draw<V: Vertex>(mesh: RenderMesh<V>)
@ -302,7 +352,8 @@ class OpenGL: Renderer
private func loadMatrix(_ matrix: Mat4f)
{
withUnsafePointer(to: matrix.columns)
//withUnsafePointer(to: matrix.columns)
withUnsafePointer(to: matrix)
{
$0.withMemoryRebound(to: GLfloat.self, capacity: 16)
{ (values: UnsafePointer<GLfloat>) in
@ -313,7 +364,8 @@ class OpenGL: Renderer
private func mulMatrix(_ matrix: Mat4f)
{
withUnsafePointer(to: matrix.columns)
//withUnsafePointer(to: matrix.columns)
withUnsafePointer(to: matrix)
{
$0.withMemoryRebound(to: GLfloat.self, capacity: 16)
{ (values: UnsafePointer<GLfloat>) in
@ -360,6 +412,7 @@ class OpenGL: Renderer
}
state.lightModelAmbient = env.ambient
state.lightModelLocalViewer = true
let lightCaps: [OpenGLState.Capability] = [
.light0, .light1, .light2, .light3,

View File

@ -1,3 +1,4 @@
import Maths
import OpenGL
@ -308,23 +309,28 @@ struct OpenGLState
}
}
enum CullFace { case front, back, frontAndBack }
private var _cullFace: CullFace = .back
enum Face { case front, back, frontAndBack }
private var _cullFace: Face = .back
var cullFace: CullFace
fileprivate func glFace(_ face: Face) -> GLenum
{
let face = switch face
{
case .front: GL_FRONT
case .back: GL_BACK
case .frontAndBack: GL_FRONT_AND_BACK
}
return GLenum(face)
}
var cullFace: Face
{
get { _cullFace }
set(newMode)
{
if newMode != _cullFace
{
let modeEnum = switch newMode
{
case .front: GL_FRONT
case .back: GL_BACK
case .frontAndBack: GL_FRONT_AND_BACK
}
glCullFace(GLenum(modeEnum))
glCullFace(glFace(newMode))
_cullFace = newMode
}
}
@ -815,4 +821,97 @@ struct OpenGLState
}
}
}
private var _materialAmbient = Colour(r: 0.2, g: 0.2, b: 0.2)
private var _materialDiffuse = Colour(r: 0.8, g: 0.8, b: 0.8)
private var _materialSpecular = Colour.black
private var _materialEmmision = Colour.black
fileprivate func setMaterialColour(_ face: Face, _ pname: Int32, _ colour: Colour)
{
let face = glFace(.frontAndBack)
if _capabilities.contains(.colourMaterial)
{
glColorMaterial(face, GLenum(pname))
glColor4f(colour.r, colour.g, colour.b, colour.a)
}
else
{
withUnsafePointer(to: colour)
{
$0.withMemoryRebound(to: GLfloat.self, capacity: 4)
{
glMaterialfv(face, GLenum(pname), $0)
}
}
}
}
var materialAmbient: Colour
{
get { _materialAmbient }
set(newColour)
{
if newColour != _materialAmbient
{
setMaterialColour(.frontAndBack, GL_AMBIENT, newColour)
_materialAmbient = newColour
}
}
}
var materialDiffuse: Colour
{
get { _materialDiffuse }
set(newColour)
{
if newColour != _materialDiffuse
{
setMaterialColour(.frontAndBack, GL_DIFFUSE, newColour)
_materialDiffuse = newColour
}
}
}
var materialSpecular: Colour
{
get { _materialSpecular }
set(newColour)
{
if newColour != _materialSpecular
{
setMaterialColour(.frontAndBack, GL_SPECULAR, newColour)
_materialSpecular = newColour
}
}
}
var materialEmmision: Colour
{
get { _materialEmmision }
set(newColour)
{
if newColour != _materialEmmision
{
setMaterialColour(.frontAndBack, GL_EMISSION, newColour)
_materialEmmision = newColour
}
}
}
private var _materialShininess: Float = 0
var materialShininess: Float
{
get { _materialShininess }
set(newParam)
{
if newParam != _materialShininess
{
let face = glFace(.frontAndBack)
glMaterialf(face, GLenum(GL_SHININESS), newParam)
_materialShininess = newParam
}
}
}
}

View File

@ -1,4 +1,5 @@
import Foundation
import Maths
import OpenGL.GL
@ -16,9 +17,8 @@ public protocol Renderer
func setVsync(mode: VSyncMode) throws
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 createTexture(image: Image) throws -> RenderTexture2D
func createTexture(image: Image, filter: FilterMode, mipMode: MipMode) throws -> RenderTexture2D
func deleteMesh<V: Vertex>(_ mesh: RenderMesh<V>)
func deleteTexture(_ texture: RenderTexture2D)