Rewrite lighting shader to use Light and Material objects
This commit is contained in:
parent
2ef3781935
commit
91c92c9675
3 changed files with 71 additions and 16 deletions
|
@ -42,6 +42,11 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
var uniformBufferIndex = 0
|
||||
var uniforms: UnsafeMutablePointer<Uniforms>
|
||||
|
||||
var lightsBuffer: MTLBuffer
|
||||
var lights: UnsafeMutablePointer<Light>
|
||||
var materialBuffer: MTLBuffer
|
||||
var material: UnsafeMutablePointer<Material>
|
||||
|
||||
var projectionMatrix: matrix_float4x4 = matrix_float4x4()
|
||||
var rotation: Float = 0
|
||||
|
||||
|
@ -103,7 +108,18 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
depthStateDesciptor.isDepthWriteEnabled = true
|
||||
self.depthState = device.makeDepthStencilState(descriptor:depthStateDesciptor)!
|
||||
|
||||
let lightsBufferLength = MemoryLayout<Light>.size * 4
|
||||
self.lightsBuffer = self.device.makeBuffer(length: lightsBufferLength, options: .storageModeShared)!
|
||||
self.lights = UnsafeMutableRawPointer(lightsBuffer.contents()).bindMemory(to: Light.self, capacity: 4)
|
||||
|
||||
let materialBufferLength = MemoryLayout<Material>.size
|
||||
self.materialBuffer = self.device.makeBuffer(length: materialBufferLength, options: .storageModeShared)!
|
||||
self.material = UnsafeMutableRawPointer(materialBuffer.contents()).bindMemory(to: Material.self, capacity: 1)
|
||||
|
||||
super.init()
|
||||
|
||||
populateLights()
|
||||
populateMaterials()
|
||||
}
|
||||
|
||||
class func buildRenderPipelineWithDevice(device: MTLDevice,
|
||||
|
@ -185,6 +201,22 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
return progress
|
||||
}
|
||||
|
||||
private func populateLights() {
|
||||
for i in 0..<4 {
|
||||
lights[i].enabled = false
|
||||
}
|
||||
|
||||
lights[0].enabled = true
|
||||
lights[0].position = simd_float4(x: 2, y: 10, z: 5, w: 1)
|
||||
lights[0].color = simd_float3(0.5, 0.5, 0)
|
||||
}
|
||||
|
||||
private func populateMaterials() {
|
||||
material[0].diffuseColor = simd_float3(0.8)
|
||||
material[0].specularColor = simd_float3(1)
|
||||
material[0].specularExponent = 10
|
||||
}
|
||||
|
||||
private func updateDynamicBufferState() {
|
||||
/// Update the state of our uniform buffers before rendering
|
||||
|
||||
|
@ -281,6 +313,9 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
renderEncoder.setVertexBuffer(terrain.faceNormalsBuffer, offset: 0, index: BufferIndex.faceNormals.rawValue)
|
||||
renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
|
||||
renderEncoder.setFragmentBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
|
||||
|
||||
renderEncoder.setFragmentBuffer(lightsBuffer, offset: 0, index: BufferIndex.lights.rawValue)
|
||||
renderEncoder.setFragmentBuffer(materialBuffer, offset: 0, index: BufferIndex.materials.rawValue)
|
||||
|
||||
for (index, element) in terrain.mesh.vertexDescriptor.layouts.enumerated() {
|
||||
guard let layout = element as? MDLVertexBufferLayout else {
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
#include <simd/simd.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, BufferIndex) {
|
||||
BufferIndexMeshPositions = 0,
|
||||
BufferIndexNormals = 1,
|
||||
BufferIndexMeshGenerics = 2,
|
||||
BufferIndexFaceNormals = 3,
|
||||
BufferIndexUniforms = 4,
|
||||
BufferIndexMeshPositions = 0,
|
||||
BufferIndexNormals = 1,
|
||||
BufferIndexMeshGenerics = 2,
|
||||
BufferIndexFaceNormals = 3,
|
||||
BufferIndexUniforms = 4,
|
||||
BufferIndexLights = 5,
|
||||
BufferIndexMaterials = 6,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, NormalBufferIndex) {
|
||||
|
|
|
@ -24,7 +24,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
float4 position [[position]];
|
||||
float4 eyeCoords;
|
||||
float3 eyeCoords;
|
||||
float3 normal;
|
||||
float2 texCoord;
|
||||
} ColorInOut;
|
||||
|
@ -42,7 +42,7 @@ vertex ColorInOut vertexShader(Vertex in [[stage_in]],
|
|||
float4 eyeCoords = uniforms.modelViewMatrix * vertexCoords;
|
||||
|
||||
out.position = uniforms.projectionMatrix * eyeCoords;
|
||||
out.eyeCoords = eyeCoords;
|
||||
out.eyeCoords = eyeCoords.xyz / eyeCoords.w;
|
||||
// TODO: Use the face normal.
|
||||
out.normal = normalize(in.normal);
|
||||
out.texCoord = in.texCoord;
|
||||
|
@ -51,23 +51,41 @@ vertex ColorInOut vertexShader(Vertex in [[stage_in]],
|
|||
}
|
||||
|
||||
fragment float4 fragmentShader(ColorInOut in [[stage_in]],
|
||||
constant Light *lights [[buffer(BufferIndexLights)]],
|
||||
constant Material *materials [[buffer(BufferIndexMaterials)]],
|
||||
constant Uniforms &uniforms [[buffer(BufferIndexUniforms)]])
|
||||
{
|
||||
// Compute the normal at this position.
|
||||
float3 normal = normalize(uniforms.normalMatrix * in.normal);
|
||||
float3 lightDirection = normalize(float3(-8, 8, 1) - in.eyeCoords.xyz);
|
||||
|
||||
// Compute the vector pointing to the light from this position.
|
||||
float3 lightDirection;
|
||||
constant Light &light = lights[0];
|
||||
if (light.position.w == 0.0) {
|
||||
lightDirection = normalize(light.position.xyz);
|
||||
} else {
|
||||
lightDirection = normalize(light.position.xyz / light.position.w - in.eyeCoords);
|
||||
}
|
||||
|
||||
// Compute the direction of the viewer from this position.
|
||||
float3 viewDirection = normalize(-in.eyeCoords.xyz);
|
||||
float3 reflection = -reflect(lightDirection, normal);
|
||||
|
||||
float4 out;
|
||||
float lightDotNormal = dot(normal, lightDirection);
|
||||
if (lightDotNormal <= 0.0) {
|
||||
float lightDirDotNormal = dot(lightDirection, normal);
|
||||
if (lightDirDotNormal <= 0.0) {
|
||||
// No color contribution to this pixel.
|
||||
out = float4();
|
||||
out = float4(0);
|
||||
} else {
|
||||
float3 color = 0.8 * lightDotNormal * float3(0.6);
|
||||
float reflectDotViewDirection = dot(reflection, viewDirection);
|
||||
if (reflectDotViewDirection > 0.0) {
|
||||
color += 0.4 * pow(reflectDotViewDirection, 10) * float3(0, 0, 1);
|
||||
constant Material &material = materials[0];
|
||||
|
||||
// Comput the direction of reflection given the light direction and the normal at this point. Negate it because the vector returned points from the light to this position and we want it from this position toward the light.
|
||||
float3 reflection = -reflect(lightDirection, normal);
|
||||
|
||||
float3 color = lightDirDotNormal * light.color * material.diffuseColor;
|
||||
float reflectDotViewDir = dot(reflection, viewDirection);
|
||||
if (reflectDotViewDir > 0.0) {
|
||||
float factor = pow(reflectDotViewDir, material.specularExponent);
|
||||
color += factor * material.specularColor * light.color;
|
||||
}
|
||||
out = float4(color, 1);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue