pretty much works now
This commit is contained in:
@@ -10,5 +10,6 @@ target_sources(RayTracer
|
|||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_subdirectory(metal/)
|
add_subdirectory(metal/)
|
||||||
endif()
|
endif()
|
||||||
|
add_subdirectory(cpu/)
|
||||||
add_subdirectory(scene/)
|
add_subdirectory(scene/)
|
||||||
add_subdirectory(util/)
|
add_subdirectory(util/)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ target_sources(RayTracer
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
CPURenderer.h
|
CPURenderer.h
|
||||||
CPURenderer.cpp
|
CPURenderer.cpp
|
||||||
CPURenderer.h
|
CPUScene.h
|
||||||
CPURenderer.cpp)
|
CPUScene.cpp)
|
||||||
+19
-2
@@ -1,21 +1,31 @@
|
|||||||
#include "CPURenderer.h"
|
#include "CPURenderer.h"
|
||||||
#include "scene/Renderer.h"
|
#include "scene/Renderer.h"
|
||||||
|
#include "CPUScene.h"
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_impl_glfw.h>
|
#include <imgui_impl_glfw.h>
|
||||||
#include <imgui_impl_opengl3.h>
|
#include <imgui_impl_opengl3.h>
|
||||||
|
|
||||||
#define GLSL(...) "#version 400\n" #__VA_ARGS__
|
#define GLSL(...) "#version 400\n" #__VA_ARGS__
|
||||||
|
|
||||||
|
static void glfw_error_callback(int error, const char* description)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
|
||||||
|
}
|
||||||
CPURenderer::CPURenderer()
|
CPURenderer::CPURenderer()
|
||||||
{
|
{
|
||||||
|
width = 1920;
|
||||||
|
height = 1080;
|
||||||
glewExperimental = true;
|
glewExperimental = true;
|
||||||
|
glfwSetErrorCallback(glfw_error_callback);
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // We don't want the old OpenGL
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // We don't want the old OpenGL
|
||||||
window = glfwCreateWindow(width, height, "RayTracer", nullptr, nullptr);
|
float xscale = 1, yscale = 1;
|
||||||
glfwSwapInterval(1);
|
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale);
|
||||||
|
window = glfwCreateWindow(width / xscale, height / yscale, "RayTracer", nullptr, nullptr);
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
@@ -28,6 +38,8 @@ CPURenderer::CPURenderer()
|
|||||||
ImGui_ImplOpenGL3_Init();
|
ImGui_ImplOpenGL3_Init();
|
||||||
|
|
||||||
glewInit();
|
glewInit();
|
||||||
|
|
||||||
|
scene = new CPUScene();
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
@@ -91,6 +103,11 @@ CPURenderer::CPURenderer()
|
|||||||
glClearColor(0, 0, 0, 0);
|
glClearColor(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPURenderer::~CPURenderer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 rand01(glm::uvec3 x)
|
glm::vec3 rand01(glm::uvec3 x)
|
||||||
{ // pseudo-random number generator
|
{ // pseudo-random number generator
|
||||||
for (int i = 3; i-- > 0;)
|
for (int i = 3; i-- > 0;)
|
||||||
|
|||||||
+25
-28
@@ -1,12 +1,11 @@
|
|||||||
#include "scene/Renderer.h"
|
#include "scene/Renderer.h"
|
||||||
|
#include "cpu/CPURenderer.h"
|
||||||
#include "util/ModelLoader.h"
|
#include "util/ModelLoader.h"
|
||||||
#include "metal/MetalRenderer.h"
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::unique_ptr<Renderer> renderer = std::make_unique<MetalRenderer>();
|
std::unique_ptr<Renderer> renderer = std::make_unique<CPURenderer>();
|
||||||
|
|
||||||
renderer->addDirectionalLight(DirectionalLight{
|
renderer->addDirectionalLight(DirectionalLight{
|
||||||
.direction = glm::normalize(glm::vec3(-0.4f, -0.3f, -0.2f)),
|
.direction = glm::normalize(glm::vec3(-0.4f, -0.3f, -0.2f)),
|
||||||
.color = glm::vec3(1, 1, 1),
|
.color = glm::vec3(1, 1, 1),
|
||||||
@@ -15,13 +14,12 @@ int main()
|
|||||||
renderer->addModels(ModelLoader::loadModel("../../res/models/cube.fbx"),
|
renderer->addModels(ModelLoader::loadModel("../../res/models/cube.fbx"),
|
||||||
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
|
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
|
||||||
renderer->addModels(ModelLoader::loadModel("../../res/models/cube.fbx"),
|
renderer->generate();
|
||||||
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
|
||||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
|
|
||||||
renderer->generate();
|
|
||||||
Camera camera = Camera{
|
Camera camera = Camera{
|
||||||
.position = glm::vec3(5, 1, 2),
|
.position = glm::vec3(5, 1, 2),
|
||||||
.target = glm::vec3(0, 0, 0),
|
.target = glm::vec3(0, 0, 0),
|
||||||
|
.f = 0,
|
||||||
|
.A = 0,
|
||||||
.S_O = 6,
|
.S_O = 6,
|
||||||
};
|
};
|
||||||
RenderParameter render = RenderParameter{
|
RenderParameter render = RenderParameter{
|
||||||
@@ -33,27 +31,26 @@ int main()
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
renderer->beginFrame();
|
renderer->beginFrame();
|
||||||
ImGui::Text("Camera Parameters");
|
ImGui::Text("Camera Parameters");
|
||||||
ImGui::InputFloat3("Position", &camera.position.x);
|
ImGui::InputFloat3("Position", &camera.position.x);
|
||||||
ImGui::InputFloat3("Target", &camera.target.x);
|
ImGui::InputFloat3("Target", &camera.target.x);
|
||||||
ImGui::InputFloat("Focal Length", &camera.f);
|
ImGui::InputFloat("Focal Length", &camera.f);
|
||||||
ImGui::InputFloat("Aperture", &camera.A);
|
ImGui::InputFloat("Aperture", &camera.A);
|
||||||
ImGui::InputFloat("S_O", &camera.S_O);
|
ImGui::InputFloat("S_O", &camera.S_O);
|
||||||
ImGui::Text("Render Parameters");
|
ImGui::Text("Render Parameters");
|
||||||
ImGui::InputInt2("Dimensions", (int*)&render.width);
|
ImGui::InputInt2("Dimensions", (int*)&render.width);
|
||||||
ImGui::InputInt("Samples", (int*)&render.numSamples);
|
ImGui::InputInt("Samples", (int*)&render.numSamples);
|
||||||
if (ImGui::Button("Render"))
|
if (ImGui::Button("Render"))
|
||||||
{
|
{
|
||||||
std::cout << "Test" << std::endl;
|
renderer->startRender(camera, render);
|
||||||
renderer->startRender(camera, render);
|
}
|
||||||
|
ImGui::Text("Render Stats");
|
||||||
|
ImGui::Text("Last Sample Time: %.3f ms", renderer->getLastSampleTime());
|
||||||
|
ImGui::Text("Average Sample Time: %.3f ms", renderer->getAverageSampleTime());
|
||||||
|
ImGui::PlotLines("Sample Times", renderer->getSampleTimes().data(), renderer->getSampleTimes().size(), 0, 0, FLT_MAX, FLT_MAX,
|
||||||
|
ImVec2(0, 40));
|
||||||
|
renderer->update();
|
||||||
}
|
}
|
||||||
ImGui::Text("Render Stats");
|
|
||||||
ImGui::Text("Last Sample Time: %.3f ms", renderer->getLastSampleTime());
|
|
||||||
ImGui::Text("Average Sample Time: %.3f ms", renderer->getAverageSampleTime());
|
|
||||||
ImGui::PlotLines("Sample Times", renderer->getSampleTimes().data(), renderer->getSampleTimes().size(), 0, 0, FLT_MAX, FLT_MAX,
|
|
||||||
ImVec2(0, 40));
|
|
||||||
renderer->update();
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-13
@@ -68,7 +68,7 @@ struct BRDF
|
|||||||
float3 albedo = float3(1, 1, 1);
|
float3 albedo = float3(1, 1, 1);
|
||||||
float alpha = 1;
|
float alpha = 1;
|
||||||
float3 specularColor = float3(1, 1, 1);
|
float3 specularColor = float3(1, 1, 1);
|
||||||
float shininess = 0.04;
|
float shininess = 0.004;
|
||||||
float3 emissive = float3(0, 0, 0);
|
float3 emissive = float3(0, 0, 0);
|
||||||
MaterialType materialType;
|
MaterialType materialType;
|
||||||
float3 evaluate(HitInfo hit, float3 viewDir, float3 lightDir, float3 lightColor)
|
float3 evaluate(HitInfo hit, float3 viewDir, float3 lightDir, float3 lightColor)
|
||||||
@@ -76,7 +76,7 @@ struct BRDF
|
|||||||
float3 normal = hit.normal;
|
float3 normal = hit.normal;
|
||||||
float diffuse = max(dot(normal, lightDir), 0.0f);
|
float diffuse = max(dot(normal, lightDir), 0.0f);
|
||||||
float3 h = normalize(lightDir + viewDir);
|
float3 h = normalize(lightDir + viewDir);
|
||||||
float specular = pow(min(max(dot(normal, h), 0.0f), 1.0f), shininess);
|
float specular = pow(clamp(dot(normal, h), 0.0f, 1.0f), shininess);
|
||||||
|
|
||||||
return (albedo * diffuse * lightColor) + float3(0.03, 0.03, 0.03);
|
return (albedo * diffuse * lightColor) + float3(0.03, 0.03, 0.03);
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ inline T interpolateVertexAttribute(constant T *attributes,
|
|||||||
|
|
||||||
// Compute the sum of the vertex attributes weighted by the barycentric coordinates.
|
// Compute the sum of the vertex attributes weighted by the barycentric coordinates.
|
||||||
// The barycentric coordinates sum to one.
|
// The barycentric coordinates sum to one.
|
||||||
return (1.0f - uv.x - uv.y) * T0 + uv.x * T1 + uv.y * T2;
|
return (1.0f - uv.x - uv.y) * T2 + uv.x * T0 + uv.y * T1;
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel void computeKernel(
|
kernel void computeKernel(
|
||||||
@@ -129,10 +129,11 @@ kernel void computeKernel(
|
|||||||
constant packed_float2* texCoords [[buffer(2)]],
|
constant packed_float2* texCoords [[buffer(2)]],
|
||||||
constant packed_float3* normals [[buffer(3)]],
|
constant packed_float3* normals [[buffer(3)]],
|
||||||
constant ModelReference* modelRefs [[buffer(4)]],
|
constant ModelReference* modelRefs [[buffer(4)]],
|
||||||
constant DirectionalLight* directionalLights [[buffer(5)]],
|
constant BRDF* materials [[buffer(5)]],
|
||||||
constant PointLight* pointLights [[buffer(6)]],
|
constant DirectionalLight* directionalLights [[buffer(6)]],
|
||||||
constant MTLAccelerationStructureInstanceDescriptor* instances [[buffer(7)]],
|
constant PointLight* pointLights [[buffer(7)]],
|
||||||
instance_acceleration_structure accelerationStructure [[buffer(8)]],
|
constant MTLAccelerationStructureInstanceDescriptor* instances [[buffer(8)]],
|
||||||
|
instance_acceleration_structure accelerationStructure [[buffer(9)]],
|
||||||
texture2d<float, access::read_write> accumulator [[texture(0)]],
|
texture2d<float, access::read_write> accumulator [[texture(0)]],
|
||||||
texture2d<float, access::read_write> image [[texture(1)]]
|
texture2d<float, access::read_write> image [[texture(1)]]
|
||||||
)
|
)
|
||||||
@@ -201,11 +202,11 @@ kernel void computeKernel(
|
|||||||
const auto indices = indexBuffer[ref.indicesOffset + intersection.primitive_id];
|
const auto indices = indexBuffer[ref.indicesOffset + intersection.primitive_id];
|
||||||
info.position = interpolateVertexAttribute(positions, ref.positionOffset, indices.x, indices.y, indices.z, intersection.triangle_barycentric_coord);
|
info.position = interpolateVertexAttribute(positions, ref.positionOffset, indices.x, indices.y, indices.z, intersection.triangle_barycentric_coord);
|
||||||
info.texCoords = interpolateVertexAttribute(texCoords, ref.positionOffset, indices.x, indices.y, indices.z, intersection.triangle_barycentric_coord);
|
info.texCoords = interpolateVertexAttribute(texCoords, ref.positionOffset, indices.x, indices.y, indices.z, intersection.triangle_barycentric_coord);
|
||||||
info.normal = interpolateVertexAttribute(normals, ref.positionOffset, indices.x, indices.y, indices.z, intersection.triangle_barycentric_coord);
|
info.normal = normalize(interpolateVertexAttribute(normals, ref.positionOffset, indices.x, indices.y, indices.z, intersection.triangle_barycentric_coord));
|
||||||
info.normalLight = dot(info.normal, cam.direction) < 0 ? info.normal : -info.normal;
|
info.normalLight = dot(info.normal, cam.direction) < 0 ? info.normal : -info.normal;
|
||||||
|
|
||||||
BRDF brdf;
|
BRDF brdf;
|
||||||
brdf.albedo = float3(0, 1, 0);
|
brdf.albedo = float3(0, 1, 0);
|
||||||
|
|
||||||
float p = max(max(brdf.albedo.x, brdf.albedo.y), brdf.albedo.z);
|
float p = max(max(brdf.albedo.x, brdf.albedo.y), brdf.albedo.z);
|
||||||
if (payload.depth > 5)
|
if (payload.depth > 5)
|
||||||
@@ -229,9 +230,9 @@ kernel void computeKernel(
|
|||||||
shadowRay.max_distance = INFINITY;
|
shadowRay.max_distance = INFINITY;
|
||||||
i.accept_any_intersection(true);
|
i.accept_any_intersection(true);
|
||||||
intersection = i.intersect(shadowRay, accelerationStructure, 0xff);
|
intersection = i.intersect(shadowRay, accelerationStructure, 0xff);
|
||||||
if(intersection.type != intersection_type::none)
|
if(intersection.type == intersection_type::none)
|
||||||
{
|
{
|
||||||
payload.accumulatedRadiance += brdf.evaluate(info, -cam.direction, shadowRay.direction, directionalLights[l].color);
|
payload.accumulatedRadiance += brdf.evaluate(info, -cam.direction, normalize(shadowRay.direction), directionalLights[l].color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (uint l = 0; l < sample.numPointLights; ++l)
|
for (uint l = 0; l < sample.numPointLights; ++l)
|
||||||
@@ -243,7 +244,7 @@ kernel void computeKernel(
|
|||||||
shadowRay.max_distance = 1;
|
shadowRay.max_distance = 1;
|
||||||
i.accept_any_intersection(true);
|
i.accept_any_intersection(true);
|
||||||
intersection = i.intersect(shadowRay, accelerationStructure, 0xff);
|
intersection = i.intersect(shadowRay, accelerationStructure, 0xff);
|
||||||
if (intersection.type != intersection_type::none)
|
if (intersection.type == intersection_type::none)
|
||||||
{
|
{
|
||||||
float d = length(lightDir);
|
float d = length(lightDir);
|
||||||
float illuminance = max(1 - d / pointLights[l].attenuation, 0.0f);
|
float illuminance = max(1 - d / pointLights[l].attenuation, 0.0f);
|
||||||
@@ -267,7 +268,11 @@ kernel void computeKernel(
|
|||||||
payload.depth++;
|
payload.depth++;
|
||||||
}
|
}
|
||||||
float resolver = float(sample.samplesPerPixel) / float(sample.pass+1);
|
float resolver = float(sample.samplesPerPixel) / float(sample.pass+1);
|
||||||
float4 previous = accumulator.read(threadId);
|
float4 previous = float4(0);
|
||||||
|
if(sample.pass != 0)
|
||||||
|
{
|
||||||
|
previous = accumulator.read(threadId);
|
||||||
|
}
|
||||||
float4 result = previous + float4(payload.accumulatedRadiance / float(sample.samplesPerPixel), 0);
|
float4 result = previous + float4(payload.accumulatedRadiance / float(sample.samplesPerPixel), 0);
|
||||||
accumulator.write(result, threadId);
|
accumulator.write(result, threadId);
|
||||||
image.write(pow(max(result * resolver, 0), float4(0.45f)), threadId);
|
image.write(pow(max(result * resolver, 0), float4(0.45f)), threadId);
|
||||||
|
|||||||
+110
-84
@@ -14,11 +14,10 @@ id<CAMetalDrawable> drawable;
|
|||||||
id<MTLDevice> device;
|
id<MTLDevice> device;
|
||||||
id<MTLLibrary> library;
|
id<MTLLibrary> library;
|
||||||
id<MTLCommandQueue> queue;
|
id<MTLCommandQueue> queue;
|
||||||
id<MTLCommandQueue> renderQueue;
|
|
||||||
id<MTLFunction> function;
|
id<MTLFunction> function;
|
||||||
id<MTLComputePipelineState> computePipeline;
|
id<MTLComputePipelineState> computePipeline;
|
||||||
id<MTLTexture> accumulator;
|
id<MTLTexture> accumulator = nullptr;
|
||||||
id<MTLTexture> resultTexture;
|
id<MTLTexture> resultTexture = nullptr;
|
||||||
|
|
||||||
MTLRenderPassDescriptor* renderPass;
|
MTLRenderPassDescriptor* renderPass;
|
||||||
id<MTLRenderCommandEncoder> renderEncoder;
|
id<MTLRenderCommandEncoder> renderEncoder;
|
||||||
@@ -34,54 +33,56 @@ MetalRenderer::MetalRenderer()
|
|||||||
width = 1920;
|
width = 1920;
|
||||||
height = 1080;
|
height = 1080;
|
||||||
device = MTLCreateSystemDefaultDevice();
|
device = MTLCreateSystemDefaultDevice();
|
||||||
|
|
||||||
library = [device newDefaultLibrary];
|
library = [device newDefaultLibrary];
|
||||||
|
|
||||||
queue = [device newCommandQueue];
|
queue = [device newCommandQueue];
|
||||||
renderQueue = [device newCommandQueue];
|
|
||||||
|
|
||||||
scene = new MetalScene(device, queue);
|
scene = new MetalScene(device, queue);
|
||||||
|
|
||||||
function = [library newFunctionWithName:@"computeKernel"];
|
function = [library newFunctionWithName:@"computeKernel"];
|
||||||
|
|
||||||
NSError* error;
|
NSError* error;
|
||||||
computePipeline = [device newComputePipelineStateWithFunction:function error:&error];
|
computePipeline = [device newComputePipelineStateWithFunction:function error:&error];
|
||||||
|
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||||
glfwSetErrorCallback(glfw_error_callback);
|
glfwSetErrorCallback(glfw_error_callback);
|
||||||
glfwInit();
|
glfwInit();
|
||||||
float xscale = 1, yscale = 1;
|
float xscale = 1, yscale = 1;
|
||||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale);
|
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale);
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
handle = glfwCreateWindow(width / xscale, height / yscale, "RayTracer", nullptr, nullptr);
|
handle = glfwCreateWindow(width / xscale, height / yscale, "RayTracer", nullptr, nullptr);
|
||||||
|
|
||||||
|
ImGui_ImplGlfw_InitForOpenGL(handle, true);
|
||||||
ImGui_ImplGlfw_InitForOpenGL(handle, false);
|
|
||||||
ImGui_ImplMetal_Init(device);
|
ImGui_ImplMetal_Init(device);
|
||||||
|
|
||||||
NSWindow* cocoaWindow = glfwGetCocoaWindow(handle);
|
NSWindow* cocoaWindow = glfwGetCocoaWindow(handle);
|
||||||
metalLayer = [CAMetalLayer layer];
|
metalLayer = [CAMetalLayer layer];
|
||||||
metalLayer.device = device;
|
metalLayer.device = device;
|
||||||
metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
[[cocoaWindow contentView] setLayer:metalLayer];
|
[[cocoaWindow contentView] setLayer:metalLayer];
|
||||||
[[cocoaWindow contentView] setWantsLayer:true];
|
[[cocoaWindow contentView] setWantsLayer:true];
|
||||||
renderPass = [[MTLRenderPassDescriptor alloc] init];
|
renderPass = [[MTLRenderPassDescriptor alloc] init];
|
||||||
|
|
||||||
MTLRenderPipelineDescriptor *renderDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
MTLRenderPipelineDescriptor *renderDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||||
|
|
||||||
renderDescriptor.vertexFunction = [library newFunctionWithName:@"copyVertex"];
|
renderDescriptor.vertexFunction = [library newFunctionWithName:@"copyVertex"];
|
||||||
renderDescriptor.fragmentFunction = [library newFunctionWithName:@"copyFragment"];
|
renderDescriptor.fragmentFunction = [library newFunctionWithName:@"copyFragment"];
|
||||||
|
|
||||||
renderDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
renderDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
|
|
||||||
pipelineState = [device newRenderPipelineStateWithDescriptor:renderDescriptor error:&error];
|
pipelineState = [device newRenderPipelineStateWithDescriptor:renderDescriptor error:&error];
|
||||||
|
|
||||||
|
[renderDescriptor release];
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalRenderer::~MetalRenderer() {}
|
MetalRenderer::~MetalRenderer() {
|
||||||
|
[renderPass release];
|
||||||
|
}
|
||||||
|
|
||||||
void MetalRenderer::addPointLight(PointLight point) { scene->addPointLight(point); }
|
void MetalRenderer::addPointLight(PointLight point) { scene->addPointLight(point); }
|
||||||
void MetalRenderer::addDirectionalLight(DirectionalLight dir) { scene->addDirectionalLight(dir); }
|
void MetalRenderer::addDirectionalLight(DirectionalLight dir) { scene->addDirectionalLight(dir); }
|
||||||
@@ -91,14 +92,16 @@ void MetalRenderer::generate() { scene->generate(); }
|
|||||||
|
|
||||||
void MetalRenderer::beginFrame()
|
void MetalRenderer::beginFrame()
|
||||||
{
|
{
|
||||||
glfwPollEvents();
|
@autoreleasepool {
|
||||||
|
|
||||||
|
glfwPollEvents();
|
||||||
int w, h;
|
int w, h;
|
||||||
glfwGetFramebufferSize(handle, &w, &h);
|
glfwGetFramebufferSize(handle, &w, &h);
|
||||||
framebufferWidth = width;
|
framebufferWidth = width;
|
||||||
framebufferHeight = height;
|
framebufferHeight = height;
|
||||||
metalLayer.drawableSize = CGSizeMake(framebufferWidth, framebufferHeight);
|
metalLayer.drawableSize = CGSizeMake(framebufferWidth, framebufferHeight);
|
||||||
drawable = [metalLayer nextDrawable];
|
drawable = [metalLayer nextDrawable];
|
||||||
renderCmd = [renderQueue commandBuffer];
|
renderCmd = [queue commandBuffer];
|
||||||
renderPass.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 0);
|
renderPass.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 0);
|
||||||
renderPass.colorAttachments[0].texture = drawable.texture;
|
renderPass.colorAttachments[0].texture = drawable.texture;
|
||||||
renderPass.colorAttachments[0].loadAction = MTLLoadActionClear;
|
renderPass.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
@@ -113,18 +116,25 @@ drawable = [metalLayer nextDrawable];
|
|||||||
|
|
||||||
// Draw a quad which fills the screen.
|
// Draw a quad which fills the screen.
|
||||||
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||||
|
|
||||||
|
[renderEncoder retain];
|
||||||
|
[renderCmd retain];
|
||||||
|
[drawable retain];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::update()
|
void MetalRenderer::update()
|
||||||
{
|
{
|
||||||
|
@autoreleasepool {
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), renderCmd, renderEncoder);
|
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), renderCmd, renderEncoder);
|
||||||
[renderEncoder endEncoding];
|
[renderEncoder endEncoding];
|
||||||
|
[renderEncoder release];
|
||||||
[renderCmd presentDrawable:drawable];
|
[renderCmd presentDrawable:drawable];
|
||||||
[renderCmd commit];
|
[renderCmd commit];
|
||||||
[renderCmd release];
|
[renderCmd release];
|
||||||
[renderEncoder release];
|
[drawable release];
|
||||||
[drawable release];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::render(Camera camera, RenderParameter parameter)
|
void MetalRenderer::render(Camera camera, RenderParameter parameter)
|
||||||
@@ -140,6 +150,11 @@ void MetalRenderer::render(Camera camera, RenderParameter parameter)
|
|||||||
.height = parameter.height,
|
.height = parameter.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(accumulator != nullptr)
|
||||||
|
{
|
||||||
|
[accumulator release];
|
||||||
|
[resultTexture release];
|
||||||
|
}
|
||||||
MTLTextureDescriptor* texDescriptor = [[MTLTextureDescriptor alloc] init];
|
MTLTextureDescriptor* texDescriptor = [[MTLTextureDescriptor alloc] init];
|
||||||
[texDescriptor setWidth:parameter.width];
|
[texDescriptor setWidth:parameter.width];
|
||||||
[texDescriptor setHeight:parameter.height];
|
[texDescriptor setHeight:parameter.height];
|
||||||
@@ -147,58 +162,69 @@ void MetalRenderer::render(Camera camera, RenderParameter parameter)
|
|||||||
[texDescriptor setUsage:MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead];
|
[texDescriptor setUsage:MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead];
|
||||||
accumulator = [device newTextureWithDescriptor:texDescriptor];
|
accumulator = [device newTextureWithDescriptor:texDescriptor];
|
||||||
resultTexture = [device newTextureWithDescriptor:texDescriptor];
|
resultTexture = [device newTextureWithDescriptor:texDescriptor];
|
||||||
|
[texDescriptor release];
|
||||||
for (uint i = 0; i < parameter.numSamples; ++i)
|
for (uint i = 0; i < parameter.numSamples; ++i)
|
||||||
{
|
{
|
||||||
id<MTLCommandBuffer> cmdBuffer = [queue commandBuffer];
|
if(!running)
|
||||||
id<MTLComputeCommandEncoder> encoder = [cmdBuffer computeCommandEncoder];
|
return;
|
||||||
// cmdBuffer->addCompletedHandler([this](MTL::CommandBuffer* cmdBuffer)
|
@autoreleasepool{
|
||||||
// { std::memcpy(image.data(), resultTexture->buffer(), image.size() * sizeof(glm::vec3)); });
|
id<MTLCommandBuffer> cmdBuffer = [queue commandBuffer];
|
||||||
|
id<MTLComputeCommandEncoder> encoder = [cmdBuffer computeCommandEncoder];
|
||||||
|
// cmdBuffer->addCompletedHandler([this](MTL::CommandBuffer* cmdBuffer)
|
||||||
|
// { std::memcpy(image.data(), resultTexture->buffer(), image.size() * sizeof(glm::vec3)); });
|
||||||
|
|
||||||
SampleParams sample = {
|
SampleParams sample = {
|
||||||
.pass = i,
|
.pass = i,
|
||||||
.samplesPerPixel = parameter.numSamples,
|
.samplesPerPixel = parameter.numSamples,
|
||||||
.numDirectionalLights = scene->getNumDirLights(),
|
.numDirectionalLights = scene->getNumDirLights(),
|
||||||
.numPointLights = scene->getNumPointLights(),
|
.numPointLights = scene->getNumPointLights(),
|
||||||
};
|
};
|
||||||
[encoder setComputePipelineState:computePipeline];
|
[encoder setComputePipelineState:computePipeline];
|
||||||
[encoder setBuffer:scene->indicesBuffer offset:0 atIndex:0];
|
[encoder setBuffer:scene->indicesBuffer offset:0 atIndex:0];
|
||||||
[encoder setBuffer:scene->positionBuffer offset:0 atIndex:1];
|
[encoder setBuffer:scene->positionBuffer offset:0 atIndex:1];
|
||||||
[encoder setBuffer:scene->texCoordsBuffer offset:0 atIndex:2];
|
[encoder setBuffer:scene->texCoordsBuffer offset:0 atIndex:2];
|
||||||
[encoder setBuffer:scene->normalBuffer offset:0 atIndex:3];
|
[encoder setBuffer:scene->normalBuffer offset:0 atIndex:3];
|
||||||
[encoder setBuffer:scene->modelRefsBuffer offset:0 atIndex:4];
|
[encoder setBuffer:scene->modelRefsBuffer offset:0 atIndex:4];
|
||||||
[encoder setBuffer:scene->directionalLightBuffer offset:0 atIndex:5];
|
[encoder setBuffer:scene->directionalLightBuffer offset:0 atIndex:6];
|
||||||
[encoder setBuffer:scene->pointLightBuffer offset:0 atIndex:6];
|
[encoder setBuffer:scene->pointLightBuffer offset:0 atIndex:7];
|
||||||
[encoder setBuffer:scene->instanceBuffer offset:0 atIndex:7];
|
[encoder setBuffer:scene->instanceBuffer offset:0 atIndex:8];
|
||||||
[encoder setAccelerationStructure:scene->accelerationStructure atBufferIndex:8];
|
[encoder setAccelerationStructure:scene->accelerationStructure atBufferIndex:9];
|
||||||
[encoder setTexture:accumulator atIndex:0];
|
[encoder setTexture:accumulator atIndex:0];
|
||||||
[encoder setTexture:resultTexture atIndex:1];
|
[encoder setTexture:resultTexture atIndex:1];
|
||||||
[encoder setBytes:&gpuCam length:sizeof(GPUCamera) atIndex:9];
|
[encoder setBytes:&gpuCam length:sizeof(GPUCamera) atIndex:10];
|
||||||
[encoder setBytes:&sample length:sizeof(SampleParams) atIndex:10];
|
[encoder setBytes:&sample length:sizeof(SampleParams) atIndex:11];
|
||||||
[encoder useResource:scene->instanceBuffer usage:MTLResourceUsageRead];
|
[encoder useResource:scene->instanceBuffer usage:MTLResourceUsageRead];
|
||||||
[encoder useResource:scene->positionBuffer usage:MTLResourceUsageRead];
|
[encoder useResource:scene->positionBuffer usage:MTLResourceUsageRead];
|
||||||
[encoder useResource:scene->texCoordsBuffer usage:MTLResourceUsageRead];
|
[encoder useResource:scene->texCoordsBuffer usage:MTLResourceUsageRead];
|
||||||
[encoder useResource:scene->normalBuffer usage:MTLResourceUsageRead];
|
[encoder useResource:scene->normalBuffer usage:MTLResourceUsageRead];
|
||||||
[encoder useResource:scene->modelRefsBuffer usage:MTLResourceUsageRead];
|
[encoder useResource:scene->modelRefsBuffer usage:MTLResourceUsageRead];
|
||||||
if (scene->getNumDirLights() > 0)
|
if (scene->getNumDirLights() > 0)
|
||||||
{
|
{
|
||||||
[encoder useResource:scene->directionalLightBuffer usage:MTLResourceUsageRead];
|
[encoder useResource:scene->directionalLightBuffer usage:MTLResourceUsageRead];
|
||||||
}
|
}
|
||||||
if (scene->getNumPointLights() > 0)
|
if (scene->getNumPointLights() > 0)
|
||||||
{
|
{
|
||||||
[encoder useResource:scene->pointLightBuffer usage:MTLResourceUsageRead];
|
[encoder useResource:scene->pointLightBuffer usage:MTLResourceUsageRead];
|
||||||
|
}
|
||||||
|
[encoder useResource:scene->instanceBuffer usage:MTLResourceUsageRead];
|
||||||
|
[encoder useResource:scene->accelerationStructure usage:MTLResourceUsageRead];
|
||||||
|
[encoder useResource:accumulator usage:MTLResourceUsageWrite];
|
||||||
|
[encoder useResource:resultTexture usage:MTLResourceUsageWrite];
|
||||||
|
NSUInteger width = (NSUInteger)parameter.width;
|
||||||
|
NSUInteger height = (NSUInteger)parameter.height;
|
||||||
|
MTLSize threadsPerThreadgroup = MTLSizeMake(8, 8, 1);
|
||||||
|
MTLSize threadgroups = MTLSizeMake((width + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width,
|
||||||
|
(height + threadsPerThreadgroup.height - 1) / threadsPerThreadgroup.height, 1);
|
||||||
|
[encoder dispatchThreadgroups:threadgroups threadsPerThreadgroup:threadsPerThreadgroup];
|
||||||
|
[encoder endEncoding];
|
||||||
|
[cmdBuffer commit];
|
||||||
|
[cmdBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull cmd) {
|
||||||
|
sampleTimes.push_back((cmd.GPUEndTime - cmd.GPUStartTime) * 1000.f);
|
||||||
|
if(sampleTimes.size() > 200)
|
||||||
|
{
|
||||||
|
sampleTimes.erase(sampleTimes.begin());
|
||||||
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
[encoder useResource:scene->instanceBuffer usage:MTLResourceUsageRead];
|
|
||||||
[encoder useResource:scene->accelerationStructure usage:MTLResourceUsageRead];
|
|
||||||
[encoder useResource:accumulator usage:MTLResourceUsageWrite];
|
|
||||||
[encoder useResource:resultTexture usage:MTLResourceUsageWrite];
|
|
||||||
NSUInteger width = (NSUInteger)parameter.width;
|
|
||||||
NSUInteger height = (NSUInteger)parameter.height;
|
|
||||||
MTLSize threadsPerThreadgroup = MTLSizeMake(8, 8, 1);
|
|
||||||
MTLSize threadgroups = MTLSizeMake((width + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width,
|
|
||||||
(height + threadsPerThreadgroup.height - 1) / threadsPerThreadgroup.height, 1);
|
|
||||||
[encoder dispatchThreadgroups:threadgroups threadsPerThreadgroup:threadsPerThreadgroup];
|
|
||||||
[encoder endEncoding];
|
|
||||||
[cmdBuffer commit];
|
|
||||||
sampleTimes.push_back(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-16
@@ -6,24 +6,25 @@
|
|||||||
class MetalScene : public Scene
|
class MetalScene : public Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalScene(id<MTLDevice> device, id<MTLCommandQueue> queue);
|
MetalScene(id<MTLDevice> device, id<MTLCommandQueue> queue);
|
||||||
virtual ~MetalScene();
|
virtual ~MetalScene();
|
||||||
|
|
||||||
virtual void createRayTracingHierarchy() override;
|
virtual void createRayTracingHierarchy() override;
|
||||||
|
|
||||||
id<MTLAccelerationStructure> newAccelerationStructureWithDescriptor(MTLAccelerationStructureDescriptor* descriptor);
|
id<MTLAccelerationStructure> newAccelerationStructureWithDescriptor(MTLAccelerationStructureDescriptor* descriptor);
|
||||||
|
|
||||||
id<MTLDevice> device;
|
id<MTLDevice> device;
|
||||||
id<MTLCommandQueue> queue;
|
id<MTLCommandQueue> queue;
|
||||||
|
|
||||||
id<MTLBuffer> indicesBuffer;
|
id<MTLBuffer> indicesBuffer;
|
||||||
id<MTLBuffer> positionBuffer;
|
id<MTLBuffer> positionBuffer;
|
||||||
id<MTLBuffer> texCoordsBuffer;
|
id<MTLBuffer> texCoordsBuffer;
|
||||||
id<MTLBuffer> normalBuffer;
|
id<MTLBuffer> normalBuffer;
|
||||||
id<MTLBuffer> modelRefsBuffer;
|
id<MTLBuffer> modelRefsBuffer;
|
||||||
id<MTLBuffer> directionalLightBuffer;
|
id<MTLBuffer> materialsBuffer;
|
||||||
id<MTLBuffer> pointLightBuffer;
|
id<MTLBuffer> directionalLightBuffer;
|
||||||
id<MTLBuffer> instanceBuffer;
|
id<MTLBuffer> pointLightBuffer;
|
||||||
|
id<MTLBuffer> instanceBuffer;
|
||||||
|
|
||||||
id<MTLAccelerationStructure> accelerationStructure;
|
id<MTLAccelerationStructure> accelerationStructure;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user