#include #include #include "Bild.h" #include "DLLRegister.h" #include "DXBuffer.h" #include "Fenster.h" #include "Globals.h" #include "GraphicsApi.h" #include "Kam3D.h" #include "Model3DList.h" #include "Shader.h" #include "Textur.h" #include "TexturList.h" #include "TexturModel.h" #include "UIPixelShader.h" #include "UIVertexShader.h" #include "Welt3D.h" using namespace Framework; struct TexturEffect { bool enabled; float percentage; }; DirectX11::DirectX11() : GraphicsApi(DIRECTX11), d3d11Device(0), d3d11Context(0), d3d11SpawChain(0), uiTextur(0), vertexShader(0), pixelShader(0), sampleState(0), rtview(0), dsView(0), depthStencilBuffer(0), depthStencilState(0), depthDisabledStencilState(0), blendStateAlphaBlend(0), vp(0), texturModel(0), texturRegister(new TexturList()), texturRS(0), meshRS(0), defaultTextur(0), diffuseLights(0), pointLights(0) {} DirectX11::~DirectX11() { if (diffuseLights) diffuseLights->release(); if (pointLights) pointLights->release(); if (defaultTextur) defaultTextur->release(); if (texturRS) texturRS->Release(); if (meshRS) meshRS->Release(); if (texturModel) texturModel->release(); texturRegister->release(); if (blendStateAlphaBlend) { blendStateAlphaBlend->Release(); blendStateAlphaBlend = NULL; } if (uiTextur) { uiTextur->release(); uiTextur = NULL; } if (sampleState) { sampleState->Release(); sampleState = NULL; } if (pixelShader) { pixelShader->release(); pixelShader = NULL; } if (vertexShader) { vertexShader->release(); vertexShader = NULL; } if (depthDisabledStencilState) { depthDisabledStencilState->Release(); depthDisabledStencilState = NULL; } delete vp; vp = 0; if (dsView) { dsView->Release(); dsView = NULL; } if (depthStencilState) { depthStencilState->Release(); depthStencilState = NULL; } if (depthStencilBuffer) { depthStencilBuffer->Release(); depthStencilBuffer = NULL; } if (rtview) { rtview->Release(); rtview = NULL; } if (d3d11SpawChain) { d3d11SpawChain->Release(); d3d11SpawChain = NULL; } if (d3d11Device) { d3d11Device->Release(); d3d11Device = NULL; } if (d3d11Context) { d3d11Context->Release(); d3d11Context = NULL; getDLLRegister()->releaseDLL("d3d11.dll"); } } typedef HRESULT(__stdcall* D3D11CreateDeviceAndSwapChainFunction)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, const D3D_FEATURE_LEVEL*, UINT, UINT, const DXGI_SWAP_CHAIN_DESC*, IDXGISwapChain**, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**); void DirectX11::initialize( WFenster* fenster, Vec2 backBufferSize, bool fullScreen) { if (d3d11Device) return GraphicsApi::initialize(fenster, backBufferSize, fullScreen); GraphicsApi::initialize(fenster, backBufferSize, fullScreen); //-------------------------------------------------------------------- // Create Device HINSTANCE dll = getDLLRegister()->ladeDLL("d3d11.dll", "d3d11.dll"); if (!dll) { WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht gefunden werden."), MB_ICONERROR); return; } D3D11CreateDeviceAndSwapChainFunction createDeviceAndSwapChain = (D3D11CreateDeviceAndSwapChainFunction)GetProcAddress( dll, "D3D11CreateDeviceAndSwapChain"); if (!createDeviceAndSwapChain) { getDLLRegister()->releaseDLL("d3d11.dll"); WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("Der Einstiegspunkt D3D11CreateDeviceAndSwapChain fon " "DirectX 11 konnte nicht gefunden werden."), MB_ICONERROR); return; } // create a struct to hold information about the swap chain DXGI_SWAP_CHAIN_DESC scd; // clear out the struct for use ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); scd.Windowed = !fullScreen; scd.BufferCount = 2; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.SampleDesc.Count = 1; // multisampling setting scd.SampleDesc.Quality = 0; // vendor-specific flag scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; scd.OutputWindow = fenster ? fenster->getFensterHandle() : 0; scd.BufferDesc.Width = this->backBufferSize.x; scd.BufferDesc.Height = this->backBufferSize.y; // windowed/full-screen mode D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; D3D_FEATURE_LEVEL support = D3D_FEATURE_LEVEL_11_0; // create a device, device context and swap chain using the information in // the scd struct UINT flag = 0; #ifdef _DEBUG if (debugDX) flag |= D3D11_CREATE_DEVICE_DEBUG; #endif HRESULT result = createDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flag, &featureLevel, 1, D3D11_SDK_VERSION, &scd, &d3d11SpawChain, &d3d11Device, &support, &d3d11Context); if (result != S_OK) { getDLLRegister()->releaseDLL("d3d11.dll"); std::cout << "ERROR: D3D11CreateDeviceAndSwapChain returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } ID3D11Texture2D* backBufferPtr; // Get the pointer to the back buffer. result = d3d11SpawChain->GetBuffer( 0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr); if (result != S_OK) { std::cout << "ERROR: d3d11SpawChain->GetBuffer returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } vp = new D3D11_VIEWPORT(); memset(vp, 0, sizeof(D3D11_VIEWPORT)); vp->Width = (float)this->backBufferSize.x; vp->Height = (float)this->backBufferSize.y; vp->MinDepth = 0.0f; vp->MaxDepth = 1.0f; d3d11Context->RSSetViewports(1, vp); // Create the render target view with the back buffer pointer. result = d3d11Device->CreateRenderTargetView(backBufferPtr, NULL, &rtview); if (result != S_OK) { std::cout << "ERROR: d3d11Device->CreateRenderTargetView returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } // Release pointer to the back buffer as we no longer need it. backBufferPtr->Release(); // Initialize the description of the depth buffer. D3D11_TEXTURE2D_DESC depthBufferDesc; ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); // Set up the description of the depth buffer. depthBufferDesc.Width = this->backBufferSize.x; depthBufferDesc.Height = this->backBufferSize.y; depthBufferDesc.MipLevels = 1; depthBufferDesc.ArraySize = 1; depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthBufferDesc.SampleDesc.Count = 1; depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; // Create the texture for the depth buffer using the filled out description. result = d3d11Device->CreateTexture2D( &depthBufferDesc, NULL, &depthStencilBuffer); if (result != S_OK) { std::cout << "ERROR: d3d11Device->CreateTexture2D returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } // Initialize the description of the stencil state. D3D11_DEPTH_STENCIL_DESC depthStencilDesc; ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); // Set up the description of the stencil state. depthStencilDesc.DepthEnable = true; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; depthStencilDesc.StencilEnable = true; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; // Stencil operations if pixel is front-facing. depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Stencil operations if pixel is back-facing. depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Create the depth stencil state. result = d3d11Device->CreateDepthStencilState( &depthStencilDesc, &depthStencilState); if (result != S_OK) { std::cout << "ERROR: d3d11Device->CreateDepthStencilState returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } d3d11Context->OMSetDepthStencilState(depthStencilState, 1); // Initialize the depth stencil view. D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); // Set up the depth stencil view description. depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; // Create the depth stencil view. result = d3d11Device->CreateDepthStencilView( depthStencilBuffer, &depthStencilViewDesc, &dsView); if (result != S_OK) { std::cout << "ERROR: d3d11Device->CreateDepthStencilView returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } d3d11Context->OMSetRenderTargets(1, &rtview, dsView); D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; // Clear the second depth stencil state before setting the parameters. ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc)); // Now create a second depth stencil state which turns off the Z buffer for // 2D rendering. The only difference is that DepthEnable is set to false, // all other parameters are the same as the other depth stencil state. depthDisabledStencilDesc.DepthEnable = false; depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthDisabledStencilDesc.StencilEnable = true; depthDisabledStencilDesc.StencilReadMask = 0xFF; depthDisabledStencilDesc.StencilWriteMask = 0xFF; depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Create the state using the device. result = d3d11Device->CreateDepthStencilState( &depthDisabledStencilDesc, &depthDisabledStencilState); if (result != S_OK) { std::cout << "ERROR: d3d11Device->CreateDepthStencilState returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } //------------------------------------------------- // Shaders vertexShader = initializeVertexShader( (unsigned char*)UIVertexShader, sizeof(UIVertexShader)); pixelShader = initializePixelShader( (unsigned char*)UIPixelShader, sizeof(UIPixelShader)); // Create a texture sampler state description. D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 1; samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; samplerDesc.BorderColor[0] = 0; samplerDesc.BorderColor[1] = 0; samplerDesc.BorderColor[2] = 0; samplerDesc.BorderColor[3] = 0; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; // Create the texture sampler state. result = d3d11Device->CreateSamplerState(&samplerDesc, &sampleState); if (result != S_OK) { std::cout << "ERROR: d3d11Device->CreateSamplerState returned " << result << "\n"; WMessageBox(fenster->getFensterHandle(), new Text("Fehler"), new Text("DirectX 11 konnte nicht initialisiert werden."), MB_ICONERROR); return; } //--------------------------------------------------------------- // Framework Backbuffer Texture Bild* renderB = new Bild(1); renderB->setAlpha3D(1); renderB->neuBild(this->backBufferSize.x, this->backBufferSize.y, 0); uiTextur = createOrGetTextur("_f_Render_Bild", renderB); ((DX11Textur*)uiTextur)->setUseMips(0); texturModel = new TexturModel(this); texturModel->setSize(this->backBufferSize); texturModel->setTextur(dynamic_cast(uiTextur->getThis())); D3D11_BLEND_DESC blendState; ZeroMemory(&blendState, sizeof(D3D11_BLEND_DESC)); blendState.AlphaToCoverageEnable = false; blendState.IndependentBlendEnable = false; blendState.RenderTarget[0].BlendEnable = true; blendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; blendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO; blendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; blendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; d3d11Device->CreateBlendState(&blendState, &blendStateAlphaBlend); d3d11Context->OMSetBlendState(blendStateAlphaBlend, 0, 0xFFFFFFFF); // Setup Render Objekt vertexShader->benutzeShader(); d3d11Context->PSSetSamplers(0, 1, &sampleState); pixelShader->benutzeShader(); D3D11_RASTERIZER_DESC rasterDesc; ZeroMemory(&rasterDesc, sizeof(rasterDesc)); rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; d3d11Device->CreateRasterizerState(&rasterDesc, &texturRS); ZeroMemory(&rasterDesc, sizeof(rasterDesc)); rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_WIREFRAME; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; d3d11Device->CreateRasterizerState(&rasterDesc, &meshRS); d3d11Context->RSSetState(texturRS); Bild* b = new Bild(); b->neuBild(10, 10, 0xFFFFFFFF); defaultTextur = createOrGetTextur("_default_textur", b); diffuseLights = new DX11StructuredBuffer( sizeof(DiffuseLight), d3d11Device, d3d11Context); pointLights = new DX11StructuredBuffer( sizeof(PointLight), d3d11Device, d3d11Context); } void DirectX11::update() { modelList->removeAll(); if (texturModel) { texturModel->release(); texturModel = 0; } if (pointLights) pointLights = (DX11StructuredBuffer*)pointLights->release(); if (diffuseLights) diffuseLights = (DX11StructuredBuffer*)diffuseLights->release(); if (texturRS) { texturRS->Release(); texturRS = NULL; } if (meshRS) { meshRS->Release(); meshRS = NULL; } texturRegister->leeren(); if (defaultTextur) defaultTextur = (Textur*)defaultTextur->release(); if (blendStateAlphaBlend) { blendStateAlphaBlend->Release(); blendStateAlphaBlend = NULL; } if (uiTextur) { uiTextur->release(); uiTextur = NULL; } if (sampleState) { sampleState->Release(); sampleState = NULL; } if (pixelShader) { pixelShader->release(); pixelShader = NULL; } if (vertexShader) { vertexShader->release(); vertexShader = NULL; } if (depthDisabledStencilState) { depthDisabledStencilState->Release(); depthDisabledStencilState = NULL; } delete vp; vp = 0; if (dsView) { dsView->Release(); dsView = NULL; } if (depthStencilState) { depthStencilState->Release(); depthStencilState = NULL; } if (depthStencilBuffer) { depthStencilBuffer->Release(); depthStencilBuffer = NULL; } if (rtview) { rtview->Release(); rtview = NULL; } if (d3d11SpawChain) { d3d11SpawChain->Release(); d3d11SpawChain = NULL; } if (d3d11Device) { d3d11Device->Release(); d3d11Device = NULL; } if (d3d11Context) { d3d11Context->Release(); d3d11Context = NULL; } initialize(dynamic_cast(fenster->getThis()), backBufferSize, fullScreen); } void DirectX11::beginFrame(bool fill2D, bool fill3D, int fillColor) { if (fill2D) uiTextur->zBild()->setFarbe(fillColor); if (fill3D || true) { float color[4]; // Setup the color to clear the buffer. color[0] = ((fillColor >> 16) & 0xFF) / 255.f; // R color[1] = ((fillColor >> 8) & 0xFF) / 255.f; // G color[2] = (fillColor & 0xFF) / 255.f; // B color[3] = ((fillColor >> 24) & 0xFF) / 255.f; // A d3d11Context->ClearRenderTargetView(rtview, color); } // Bind the render target view and depth stencil buffer to the output render // pipeline. d3d11Context->OMSetRenderTargets(1, &rtview, dsView); // Clear the depth buffer. d3d11Context->ClearDepthStencilView( dsView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); // Set the depth stencil state. d3d11Context->OMSetDepthStencilState(depthStencilState, 1); } void DirectX11::renderObject(Model3D* zObj) { if (!zObj->zModelData()) return; int curId = zObj->zModelData()->getId(); zObj->zModelData()->updateGPUMemory(); Mat4 trans = Mat4::identity(); int anz = zObj->errechneMatrizen(trans, matrixBuffer); if (vertexShader) vertexShader->füllConstBuffer( (char*)matrixBuffer, 0, sizeof(Mat4) * anz); float matirialBuffer[3]; // light factors (phong model) matirialBuffer[0] = zObj->getAmbientFactor(); matirialBuffer[1] = zObj->getDiffusFactor(); matirialBuffer[2] = zObj->getSpecularFactor(); if (pixelShader) pixelShader->füllConstBuffer( (char*)matirialBuffer, 1, sizeof(float) * 3); unsigned int offset = 0; unsigned int es = (unsigned)zObj->zModelData()->zDXVertexBuffer()->getElementLength(); ID3D11Buffer* vBuffer = ((DX11Buffer*)zObj->zModelData()->zDXVertexBuffer())->zBuffer(); d3d11Context->IASetVertexBuffers(0, 1, &vBuffer, &es, &offset); Model3DTextur* zTextur = zObj->zTextur(); int ind = 0; int current = 0; if (zObj->zEffectTextur()) { ID3D11ShaderResourceView* v[1]; DX11Textur* zEffectTextur = (DX11Textur*)zObj->zEffectTextur(); if (zEffectTextur && zEffectTextur->brauchtUpdate()) zEffectTextur->updateTextur(); v[0] = *zEffectTextur; d3d11Context->PSSetShaderResources(3, 1, v); TexturEffect e = {1, zObj->getEffectPercentage()}; if (pixelShader) pixelShader->füllConstBuffer((char*)&e, 3, sizeof(TexturEffect)); } else { TexturEffect e = {0, 0.f}; if (pixelShader) pixelShader->füllConstBuffer((char*)&e, 3, sizeof(TexturEffect)); } DXGI_FORMAT f = DXGI_FORMAT_R32_UINT; if (zObj->zModelData()->zDXIndexBuffer()->getElementLength() == 2) f = DXGI_FORMAT_R16_UINT; if (zObj->zModelData()->zDXIndexBuffer()->getElementLength() == 1) f = DXGI_FORMAT_R8_UINT; d3d11Context->IASetIndexBuffer( ((DX11Buffer*)zObj->zModelData()->zDXIndexBuffer())->zBuffer(), f, 0); d3d11Context->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); zObj->beforeRender(this, vertexShader, pixelShader); for (auto i = zObj->zModelData()->getPolygons(); i; ++i) { if (zObj->needRenderPolygon(ind)) { Textur* t = zTextur->zPolygonTextur(ind); if (t && t->brauchtUpdate()) t->updateTextur(); if (t) { ID3D11ShaderResourceView* v[3]; v[0] = *(DX11Textur*)t; v[1] = *diffuseLights; v[2] = *pointLights; d3d11Context->PSSetShaderResources(0, 3, v); d3d11Context->DrawIndexed(i->indexAnz, current, 0); } else { d3d11Context->RSSetState(meshRS); ID3D11ShaderResourceView* v[3]; v[0] = *(DX11Textur*)defaultTextur; v[1] = *diffuseLights; v[2] = *pointLights; d3d11Context->PSSetShaderResources(0, 3, v); d3d11Context->DrawIndexed(i->indexAnz, current, 0); d3d11Context->RSSetState(texturRS); } } ind++; current += i->indexAnz; } zObj->afterRender(this, pixelShader, vertexShader); } // Überprüft, ob eine Kugel in dem Sichtbaren Raum der Welt liegt und gezeichnet // werden muss // pos: Der Mittelpunkt der Kugel // radius: Der Radius der Kugel // dist: Einen Zeiger auf einen float, in dem das quadrat des Abstands zur // Kammeraposition gespeichert wird, falls diese Funktion true zurückgiebt und // der Zeiger nicht 0 ist bool DirectX11::isInFrustrum( const Vec3& pos, float radius, float* dist) const { for (int i = 0; i < 6; i++) { if (frustrum[i] * pos + radius < 0) return 0; } if (dist) *dist = kamPos.abstand(pos); return 1; } bool DirectX11::isInFrustrum( const Vec3& pos, Vec3 radius, float* dist) const { for (int i = 0; i < 6; i++) { float r = abs(frustrum[i].normal() * radius); if (frustrum[i] * pos + r < 0) return 0; } if (dist) *dist = kamPos.abstand(pos); return 1; } void DirectX11::renderKamera(Kam3D* zKamera) { d3d11Context->RSSetViewports(1, (D3D11_VIEWPORT*)zKamera->zViewPort()); Mat4 tmp = zKamera->getProjectionMatrix() * zKamera->getViewMatrix(); frustrum[0].x = tmp.elements[3][0] + tmp.elements[0][0]; frustrum[0].y = tmp.elements[3][1] + tmp.elements[0][1]; frustrum[0].z = tmp.elements[3][2] + tmp.elements[0][2]; frustrum[0].w = tmp.elements[3][3] + tmp.elements[0][3]; frustrum[1].x = tmp.elements[3][0] - tmp.elements[0][0]; frustrum[1].y = tmp.elements[3][1] - tmp.elements[0][1]; frustrum[1].z = tmp.elements[3][2] - tmp.elements[0][2]; frustrum[1].w = tmp.elements[3][3] - tmp.elements[0][3]; frustrum[2].x = tmp.elements[3][0] - tmp.elements[1][0]; frustrum[2].y = tmp.elements[3][1] - tmp.elements[1][1]; frustrum[2].z = tmp.elements[3][2] - tmp.elements[1][2]; frustrum[2].w = tmp.elements[3][3] - tmp.elements[1][3]; frustrum[3].x = tmp.elements[3][0] + tmp.elements[1][0]; frustrum[3].y = tmp.elements[3][1] + tmp.elements[1][1]; frustrum[3].z = tmp.elements[3][2] + tmp.elements[1][2]; frustrum[3].w = tmp.elements[3][3] + tmp.elements[1][3]; frustrum[4].x = tmp.elements[2][0]; frustrum[4].y = tmp.elements[2][1]; frustrum[4].z = tmp.elements[2][2]; frustrum[4].w = tmp.elements[2][3]; frustrum[5].x = tmp.elements[3][0] - tmp.elements[2][0]; frustrum[5].y = tmp.elements[3][1] - tmp.elements[2][1]; frustrum[5].z = tmp.elements[3][2] - tmp.elements[2][2]; frustrum[5].w = tmp.elements[3][3] - tmp.elements[2][3]; for (int i = 0; i < 6; i++) frustrum[i].normalize(); viewAndProj[0] = zKamera->getViewMatrix(); viewAndProj[1] = zKamera->getProjectionMatrix(); kamPos = zKamera->getWorldPosition(); if (vertexShader) vertexShader->füllConstBuffer( (char*)viewAndProj, 1, sizeof(Mat4) * 2); if (pixelShader) pixelShader->füllConstBuffer((char*)&kamPos, 0, sizeof(float) * 3); Welt3D* w = zKamera->zWelt(); w->lock(); int lc[] = {w->getDiffuseLightCount(), w->getPointLightCount()}; pixelShader->füllConstBuffer((char*)lc, 2, sizeof(int) * 2); w->copyLight(diffuseLights, pointLights); int maxDist = 0; int minDist = 0x7FFFFFFF; Array alphaModels; w->render([this, &minDist, &maxDist, &alphaModels, &lc](Model3D* obj) { float dist; if (isInFrustrum(obj->getPos(), obj->getRadius(), &dist)) { if ((int)dist > maxDist) maxDist = (int)dist; if ((int)dist < minDist) minDist = (int)dist; if (obj->hatAlpha()) alphaModels.add(obj); else { pixelShader->füllConstBuffer((char*)lc, 2, sizeof(int) * 2); renderObject(obj); } } }); maxDist++; if (alphaModels.getEintragAnzahl()) { int size = maxDist - minDist; int* index = new int[size]; memset(index, 0, size * 4); Model3D** sorted = new Model3D*[size * alphaModels.getEintragAnzahl()]; for (auto obj : alphaModels) { float dist; dist = kamPos.abstand(obj->getPos()); if (isInFrustrum(obj->getPos(), obj->getRadius(), &dist)) { int pos = (int)dist - minDist; sorted[pos * alphaModels.getEintragAnzahl() + index[pos]++] = obj; } } for (int i = 0; i < size; i++) { for (int j = 0; j < index[i]; j++) { renderObject(sorted[i * alphaModels.getEintragAnzahl() + j]); } } delete[] index; delete[] sorted; } w->unlock(); } void DirectX11::renderKamera(Kam3D* zKamera, Textur* zTarget) { ID3D11RenderTargetView* texturRtView; DX11Textur* d11Textur = dynamic_cast(zTarget); if (!d11Textur) throw "incompatible textur object was passed to renderKamera of " "DirectX11 GPU API"; d11Textur->setRenderTarget(1); if (d11Textur->brauchtUpdate()) d11Textur->updateTextur(); D3D11_TEXTURE2D_DESC depthBufferDesc; ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); // Set up the description of the depth buffer. depthBufferDesc.Width = zTarget->zBild()->getBreite(); depthBufferDesc.Height = zTarget->zBild()->getHeight(); depthBufferDesc.MipLevels = 1; depthBufferDesc.ArraySize = 1; depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthBufferDesc.SampleDesc.Count = 1; depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; ID3D11Texture2D* txtDepthStencilBuffer; // Create the texture for the depth buffer using the filled out description. HRESULT result = d3d11Device->CreateTexture2D( &depthBufferDesc, NULL, &txtDepthStencilBuffer); if (result != S_OK) throw "could not create depth Stencil buffer"; // Initialize the depth stencil view. D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); // Set up the depth stencil view description. depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; ID3D11DepthStencilView* txtDsView; // Create the depth stencil view. result = d3d11Device->CreateDepthStencilView( txtDepthStencilBuffer, &depthStencilViewDesc, &txtDsView); if (result != S_OK) throw "could not create depth stencil view"; D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc; renderTargetViewDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; renderTargetViewDesc.Texture2D.MipSlice = 0; result = d3d11Device->CreateRenderTargetView( (ID3D11Texture2D*)*d11Textur, &renderTargetViewDesc, &texturRtView); if (result != S_OK) throw "could not create render target view for given texture"; d3d11Context->OMSetRenderTargets(1, &texturRtView, txtDsView); float color[4] = {0, 0, 0, 0}; d3d11Context->ClearRenderTargetView(texturRtView, color); d3d11Context->ClearDepthStencilView( txtDsView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); renderKamera(zKamera); result = d3d11SpawChain->Present(0, 0); if (result != S_OK) throw "could not present the rendered content"; d3d11Context->OMSetRenderTargets(1, &rtview, dsView); texturRtView->Release(); txtDsView->Release(); txtDepthStencilBuffer->Release(); } void DirectX11::presentFrame() { // Set the depth stencil state. d3d11Context->OMSetDepthStencilState(depthDisabledStencilState, 1); uiTextur->updateTextur(); d3d11Context->RSSetViewports(1, vp); float screenAspect = (float)backBufferSize.x / (float)backBufferSize.y; Mat4 view = view.translation(Vec3(0.f, 0.f, backBufferSize.y * 1.2075f)); viewAndProj[0] = view; viewAndProj[1] = view.projektion((float)PI / 4.0f, screenAspect, 0.1f, 10000.f); kamPos = Vec3(0.f, 0.f, backBufferSize.y * 1.2075f); if (vertexShader) vertexShader->füllConstBuffer( (char*)viewAndProj, 1, sizeof(Mat4) * 2); if (pixelShader) pixelShader->füllConstBuffer((char*)&kamPos, 0, sizeof(float) * 3); if (fenster && !IsIconic(fenster->getFensterHandle())) renderObject(texturModel); HRESULT result = d3d11SpawChain->Present(0, 0); if (!SUCCEEDED(result)) { HRESULT res = d3d11Device->GetDeviceRemovedReason(); update(); WMessageBox(fenster ? fenster->getFensterHandle() : 0, new Text("Fehler"), new Text("Es ist ein Fehler beim rendern aufgetreten."), MB_ICONERROR); } } Bild* DirectX11::zUIRenderBild() const { return uiTextur->zBild(); } Textur* DirectX11::createOrGetTextur(const char* name, Bild* b) { if (!d3d11Device) { if (b) b->release(); return 0; } if (texturRegister->hatTextur(name)) { Textur* ret = texturRegister->getTextur(name); if (b) ret->setBildZ(b); return ret; } Textur* ret = new DX11Textur(d3d11Device, d3d11Context); if (b) ret->setBildZ(b); texturRegister->addTextur(dynamic_cast(ret->getThis()), name); return ret; } typedef HRESULT(__stdcall* CreateDXGIFactory2Function)(UINT, REFIID, void**); typedef HRESULT(__stdcall* D3D11CreateDeviceFunction)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**); bool DirectX11::isAvailable() { HINSTANCE dxgiDLL = getDLLRegister()->ladeDLL("dxgi.dll", "dxgi.dll"); if (!dxgiDLL) return 0; HINSTANCE d3d11DLL = getDLLRegister()->ladeDLL("d3d11.dll", "d3d11.dll"); if (!d3d11DLL) { getDLLRegister()->releaseDLL("dxgi.dll"); return 0; } CreateDXGIFactory2Function createFactory = (CreateDXGIFactory2Function)GetProcAddress( dxgiDLL, "CreateDXGIFactory2"); if (!createFactory) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d11.dll"); return 0; } D3D11CreateDeviceFunction createDevice = (D3D11CreateDeviceFunction)GetProcAddress( d3d11DLL, "D3D11CreateDevice"); if (!createDevice) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d11.dll"); return 0; } IDXGIFactory4* factory; UINT createFactoryFlags = 0; #if defined(_DEBUG) createFactoryFlags = DXGI_CREATE_FACTORY_DEBUG; #endif HRESULT res = createFactory( createFactoryFlags, __uuidof(IDXGIFactory4), (void**)&factory); if (FAILED(res)) { getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d11.dll"); return 0; } int index = 0; UINT flag = 0; #ifdef _DEBUG flag |= D3D11_CREATE_DEVICE_DEBUG; #endif do { IDXGIAdapter1* current; res = factory->EnumAdapters1(index++, ¤t); if (res == S_OK) { DXGI_ADAPTER_DESC1 dxgiAdapterDesc1; current->GetDesc1(&dxgiAdapterDesc1); ID3D11Device* device = 0; ID3D11DeviceContext* context = 0; D3D_FEATURE_LEVEL level = D3D_FEATURE_LEVEL_11_0; if ((dxgiAdapterDesc1.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0 && SUCCEEDED(createDevice(current, D3D_DRIVER_TYPE_UNKNOWN, 0, flag, &level, 1, D3D11_SDK_VERSION, &device, 0, &context))) { context->Release(); device->Release(); current->Release(); factory->Release(); getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d11.dll"); return 1; } current->Release(); } } while (res != DXGI_ERROR_NOT_FOUND); factory->Release(); getDLLRegister()->releaseDLL("dxgi.dll"); getDLLRegister()->releaseDLL("d3d11.dll"); return 0; } DXBuffer* DirectX11::createIndexBuffer() { return new DX11Buffer( sizeof(int), d3d11Device, d3d11Context, D3D11_BIND_INDEX_BUFFER); } DXBuffer* DirectX11::createVertexBuffer() { return new DX11Buffer( sizeof(Vertex3D), d3d11Device, d3d11Context, D3D11_BIND_VERTEX_BUFFER); } DX11VertexShader* DirectX11::initializeVertexShader( unsigned char* byteCode, int size) { DX11VertexShader* vertexShader = new DX11VertexShader(d3d11Device, d3d11Context); vertexShader->setCompiledByteArray(byteCode, size); D3D11_INPUT_ELEMENT_DESC polygonLayout[5]; // Create the vertex input layout description. // This setup needs to match the VertexType stucture in the ModelClass and // in the shader. polygonLayout[0].SemanticName = "POSITION"; polygonLayout[0].SemanticIndex = 0; polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; polygonLayout[0].InputSlot = 0; polygonLayout[0].AlignedByteOffset = 0; polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[0].InstanceDataStepRate = 0; polygonLayout[1].SemanticName = "TEXCOORD"; polygonLayout[1].SemanticIndex = 0; polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; polygonLayout[1].InputSlot = 0; polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[1].InstanceDataStepRate = 0; polygonLayout[2].SemanticName = "NORMAL"; polygonLayout[2].SemanticIndex = 0; polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; polygonLayout[2].InputSlot = 0; polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[2].InstanceDataStepRate = 0; polygonLayout[3].SemanticName = "KNOCHEN_ID"; polygonLayout[3].SemanticIndex = 0; polygonLayout[3].Format = DXGI_FORMAT_R32_UINT; polygonLayout[3].InputSlot = 0; polygonLayout[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[3].InstanceDataStepRate = 0; polygonLayout[4].SemanticName = "VERTEX_ID"; polygonLayout[4].SemanticIndex = 0; polygonLayout[4].Format = DXGI_FORMAT_R32_UINT; polygonLayout[4].InputSlot = 0; polygonLayout[4].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[4].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[4].InstanceDataStepRate = 0; vertexShader->erstelleInputLayout(polygonLayout, 5); vertexShader->erstelleConstBuffer(sizeof(Mat4) * MAX_KNOCHEN_ANZ, vertexShader ->getFirstUninitializedBufferIndex()); // matrizen für skelett // annimationen vertexShader->erstelleConstBuffer(sizeof(Mat4) * 2, vertexShader ->getFirstUninitializedBufferIndex()); // View and Projection Matrix return vertexShader; } DX11PixelShader* DirectX11::initializePixelShader( unsigned char* byteCode, int size) { DX11PixelShader* pixelShader = new DX11PixelShader(d3d11Device, d3d11Context); pixelShader->setCompiledByteArray((unsigned char*)byteCode, size); pixelShader->erstelleConstBuffer(sizeof(float) * 3, pixelShader->getFirstUninitializedBufferIndex()); // Kamera Position pixelShader->erstelleConstBuffer(sizeof(float) * 3, pixelShader->getFirstUninitializedBufferIndex()); // materialkonstanten // nach phong model pixelShader->erstelleConstBuffer( sizeof(int) * 2, pixelShader->getFirstUninitializedBufferIndex()); pixelShader->erstelleConstBuffer( sizeof(TexturEffect), pixelShader->getFirstUninitializedBufferIndex()); // TODO: Remove Following Test Code int lc[] = {0, 0}; pixelShader->füllConstBuffer((char*)lc, 2, sizeof(int) * 2); TexturEffect e = {0, 0.f}; pixelShader->füllConstBuffer((char*)&e, 3, sizeof(TexturEffect)); return pixelShader; } DLLEXPORT ID3D11DeviceContext* DirectX11::zContext() { return d3d11Context; } DXBuffer* DirectX11::createStructuredBuffer(int eSize) { return new DX11StructuredBuffer(eSize, d3d11Device, d3d11Context); }