#include #include "app.h" #include "util.h" #include "StaticMesh.h" struct SceneUniformBuffer { DKMatrix4 projectionMatrix; DKMatrix4 modelMatrix; DKMatrix4 viewMatrix; }; class DKGLDemo : public SampleApp { DKObject window; DKObject renderThread; DKAtomicNumber32 runningRenderThread; DKObject sampleMesh; DKObject sceneUniformBuffer; SceneUniformBuffer* sceneBufferData = nullptr; public: void LoadResource() { DKString vertexShaderPath = resourcePool.ResourceFilePath("shaders/ObjMeshShader/objmesh.vert.spv"); DKString fragMentShaderPath = resourcePool.ResourceFilePath("shaders/ObjMeshShader/objmesh.frag.spv"); DKString texturePath = resourcePool.ResourceFilePath("meshes/VikingRoom/viking_room.png"); sampleMesh->LoadShaderFromFile(resourcePool, vertexShaderPath, DKShaderStage::Vertex); sampleMesh->LoadShaderFromFile(resourcePool, fragMentShaderPath, DKShaderStage::Fragment); sampleMesh->LoadTextureFromFile(resourcePool, texturePath); } void LoadRenderResource(DKObject queue) { DKLog("Loading Static Meshes"); DKString path = resourcePool.ResourceFilePath("meshes/VikingRoom/viking_room.obj"); sampleMesh->LoadMeshResourceFromFile(queue->Device(), resourcePool, path); sampleMesh->LoadRenderResourceShader(queue->Device(), DKShaderStage::Vertex); sampleMesh->LoadRenderResourceShader(queue->Device(), DKShaderStage::Fragment); sampleMesh->LoadRenderResourceTexture(queue); } void SetupPipeline(DKRenderPipelineDescriptor& pipelineDesc) { sampleMesh->SetupPipelineDecriptor(pipelineDesc); } void SetupMaterial(DKObject device) { sampleMesh->SetupMaterial(device); } void SetupSceneUniformBuffer(DKObject device) { // should Go to Scene Uniform Buffer sceneUniformBuffer = device->CreateBuffer(sizeof(SceneUniformBuffer) , DKGpuBuffer::StorageModeShared, DKCpuCacheModeReadWrite); sceneBufferData = reinterpret_cast(sceneUniformBuffer->Contents()); sceneBufferData->projectionMatrix = DKMatrix4::identity; sceneBufferData->modelMatrix = DKMatrix4::identity; sceneBufferData->viewMatrix = DKMatrix4::identity; sceneUniformBuffer->Flush(); //DKAffineTransform3 trans; //trans.Multiply(DKLinearTransform3().Scale(0.5).Rotate(DKVector3(0,1,0), DKGL_PI * 0.5)); //ubo.modelMatrix.Multiply(trans.Matrix4()); //memcpy(uboBuffer->Contents(), &ubo, sizeof(ubo)); sampleMesh->SetupExternalUniformBuffer(sceneUniformBuffer, sizeof(SceneUniformBuffer), 0); } void EncodeScene(DKObject encoder) { sampleMesh->EncodeRenderCommand(encoder); } void RenderThread(void) { DKObject device = DKGraphicsDevice::SharedInstance(); DKObject queue = device->CreateCommandQueue(DKCommandQueue::Graphics); LoadRenderResource(queue); DKObject swapChain = queue->CreateSwapChain(window); DKRenderPipelineDescriptor pipelineDescriptor; // setup color-attachment render-targets pipelineDescriptor.colorAttachments.Resize(1); pipelineDescriptor.colorAttachments.Value(0).pixelFormat = swapChain->ColorPixelFormat(); pipelineDescriptor.colorAttachments.Value(0).blendState.enabled = false; pipelineDescriptor.colorAttachments.Value(0).blendState.sourceRGBBlendFactor = DKBlendFactor::SourceAlpha; pipelineDescriptor.colorAttachments.Value(0).blendState.destinationRGBBlendFactor = DKBlendFactor::OneMinusSourceAlpha; // setup depth-stencil pipelineDescriptor.depthStencilAttachmentPixelFormat = DKPixelFormat::D32Float; pipelineDescriptor.depthStencilDescriptor.depthWriteEnabled = true; pipelineDescriptor.depthStencilDescriptor.depthCompareFunction = DKCompareFunctionLessEqual; // setup topology and rasterization pipelineDescriptor.primitiveTopology = DKPrimitiveType::Triangle; pipelineDescriptor.frontFace = DKFrontFace::CCW; pipelineDescriptor.triangleFillMode = DKTriangleFillMode::Fill; pipelineDescriptor.depthClipMode = DKDepthClipMode::Clip; pipelineDescriptor.cullMode = DKCullMode::Back; pipelineDescriptor.rasterizationEnabled = true; SetupPipeline(pipelineDescriptor); DKPipelineReflection reflection; DKObject pipelineState = device->CreateRenderPipeline(pipelineDescriptor, &reflection); if (pipelineState) { PrintPipelineReflection(&reflection, DKLogCategory::Verbose); } SetupMaterial(device); SetupSceneUniformBuffer(device); DKObject depthBuffer = nullptr; DKCamera camera; DKVector3 cameraPosition = { 0, 5, 10 }; DKVector3 cameraTartget = { 0, 0, 0 }; DKAffineTransform3 tm(DKLinearTransform3().Scale(5).Rotate(DKVector3(-1, 0, 0), DKGL_PI * 0.5)); DKTimer timer; timer.Reset(); DKLog("Render thread begin"); while (!runningRenderThread.CompareAndSet(0, 0)) { DKRenderPassDescriptor rpd = swapChain->CurrentRenderPassDescriptor(); double t = timer.Elapsed(); double waveT = (cos(t) + 1.0) * 0.5; rpd.colorAttachments.Value(0).clearColor = DKColor(waveT, 0.0, 0.0, 0.0); int width = rpd.colorAttachments.Value(0).renderTarget->Width(); int height = rpd.colorAttachments.Value(0).renderTarget->Height(); if (depthBuffer) { if (depthBuffer->Width() != width || depthBuffer->Height() != height) depthBuffer = nullptr; } if (depthBuffer == nullptr) { // create depth buffer DKTextureDescriptor texDesc = {}; texDesc.textureType = DKTexture::Type2D; texDesc.pixelFormat = DKPixelFormat::D32Float; texDesc.width = width; texDesc.height = height; texDesc.depth = 1; texDesc.mipmapLevels = 1; texDesc.sampleCount = 1; texDesc.arrayLength = 1; texDesc.usage = DKTexture::UsageRenderTarget; depthBuffer = device->CreateTexture(texDesc); } rpd.depthStencilAttachment.renderTarget = depthBuffer; rpd.depthStencilAttachment.loadAction = DKRenderPassAttachmentDescriptor::LoadActionClear; rpd.depthStencilAttachment.storeAction = DKRenderPassAttachmentDescriptor::StoreActionDontCare; DKObject buffer = queue->CreateCommandBuffer(); DKObject encoder = buffer->CreateRenderCommandEncoder(rpd); if (encoder) { if (sceneUniformBuffer) { camera.SetView(cameraPosition, cameraTartget - cameraPosition, DKVector3(0, 1, 0)); camera.SetPerspective(DKGL_DEGREE_TO_RADIAN(90), float(width) / float(height), 1, 1000); sceneBufferData->projectionMatrix = camera.ProjectionMatrix(); sceneBufferData->viewMatrix = camera.ViewMatrix(); DKQuaternion quat(DKVector3(0, 1, 0), t); DKAffineTransform3 trans = tm * DKAffineTransform3(quat); sceneBufferData->modelMatrix = trans.Matrix4(); sceneUniformBuffer->Flush(); sampleMesh->SetupExternalUniformBuffer(sceneUniformBuffer, sizeof(SceneUniformBuffer), 0); } encoder->SetRenderPipelineState(pipelineState); EncodeScene(encoder); buffer->Commit(); swapChain->Present(); } else { } DKThread::Sleep(0.01); } DKLog("RenderThread terminating..."); } void OnInitialize(void) override { SampleApp::OnInitialize(); DKLogD("%s", DKGL_FUNCTION_NAME); // create window window = DKWindow::Create("DefaultWindow"); window->SetOrigin({ 0, 0 }); window->Resize({ 320, 240 }); window->Activate(); window->AddEventHandler(this, DKFunction([this](const DKWindow::WindowEvent& e) { if (e.type == DKWindow::WindowEvent::WindowClosed) DKApplication::Instance()->Terminate(0); }), NULL, NULL); sampleMesh = DKObject::New(); LoadResource(); runningRenderThread = 1; renderThread = DKThread::Create(DKFunction(this, &DKGLDemo::RenderThread)->Invocation()); } void OnTerminate(void) override { DKLogD("%s", DKGL_FUNCTION_NAME); runningRenderThread = 0; renderThread->WaitTerminate(); renderThread = NULL; window = NULL; SampleApp::OnTerminate(); } }; #ifdef _WIN32 int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) #else int main(int argc, const char* argv[]) #endif { DKGLDemo app; DKPropertySet::SystemConfig().SetValue("AppDelegate", "AppDelegate"); DKPropertySet::SystemConfig().SetValue("GraphicsAPI", "Vulkan"); return app.Run(); }