Direct3D 11 - transparente sprites - problem



  • ich habe einen renderer für 2d-sprites für ein gui-system mit directx 11 geschrieben. ich bin jetzt quasi fertig und es funktioniert alles über batching, grundlegendes gui-system, ..., aber eine sache bereitet mir probleme:
    Wenn ich ein sprite welches teilweise transparent is zeichne, werden die dahinterliegenden sprites nicht gezeichnet.

    code zu posten ist jetzt etwas schwierig, aber hier ist die initialization methode des renderers. ich hab einfach mal die ganze funktion gepostet; ist warscheinlich ja nur irgendwie eine einstellung denke ich.

    void graphics::Dx11_rendertarget::initialize(
    				HWND hwnd, core::vector2d<unsigned int> vp_size,
    				bool fullscreen, bool vsync, bool alpha_blending)
    	{   // initialize render-target for a specific window
    	HRESULT result;
    
    	Hwnd = hwnd;
    	MyVsync = vsync;
    	MyViewport_size = vp_size;
    
    	// create graphics interface factory
    	IDXGIFactory* factory;
    	result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not create graphics interface factory");
    
    	// use the factory to create an adapter for the primary graphics interface (video card)
    	IDXGIAdapter* adapter;
    	result = factory->EnumAdapters(0, &adapter);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not enumerate primary graphics interface");
    
    	// enumerate the primary adapter output (monitor)
    	IDXGIOutput* adapter_output;
    	result = adapter->EnumOutputs(0, &adapter_output);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not enumerate primary adapter output");
    
    	// get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM 
    	// display format for the adapter output (monitor)
    	unsigned int num_modes;
    	result = adapter_output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 
    								DXGI_ENUM_MODES_INTERLACED, &num_modes, NULL);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not get display mode list");
    
    	// create a list to hold all the possible display modes for this 
    	// monitor/video card combination
    	DXGI_MODE_DESC* display_mode_list = new DXGI_MODE_DESC[num_modes];
    	if (!display_mode_list)
    		throw std::runtime_error("new operator failed");
    
    	// now fill the display mode list structures
    	result = adapter_output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 
    								DXGI_ENUM_MODES_INTERLACED, &num_modes, display_mode_list);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not get display mode list");
    
    	// now go through all the display modes and find the one that matches 
    	// the screen width and height. when a match is found store the numerator 
    	// and denominator of the refresh rate for that monitor.
    	unsigned int numerator=0, denominator=0;
    	for (unsigned int i=0; i<num_modes; ++i){
    		if (display_mode_list[i].Width == vp_size.x){
    			if (display_mode_list[i].Height == vp_size.y){
    				numerator = display_mode_list[i].RefreshRate.Numerator;
    				denominator = display_mode_list[i].RefreshRate.Denominator;
    			}
    		}
    	}
    
    	// get the adapter (video card) description
    	DXGI_ADAPTER_DESC adapter_desc;
    	result = adapter->GetDesc(&adapter_desc);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not get videocard description");
    
    	// store videocard information
    	MyVideocard_memory = (size_t)(adapter_desc.DedicatedVideoMemory / 1024 / 1024);
    	MyVideocard_desc = adapter_desc.Description;
    
    	delete [] display_mode_list;
    	display_mode_list = nullptr;
    
    	adapter_output->Release();
    	adapter_output = nullptr;
    	adapter->Release();
    	adapter = nullptr;
    	factory->Release();
    	factory = nullptr;
    
    	///////////
    
    	// initialize the swap chain description
    	DXGI_SWAP_CHAIN_DESC swapchain_desc;
        ZeroMemory(&swapchain_desc, sizeof(swapchain_desc));
        swapchain_desc.BufferCount = 1;
        swapchain_desc.BufferDesc.Width = vp_size.x;
        swapchain_desc.BufferDesc.Height = vp_size.y;
        swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    
    	// set the refresh rate of the back buffer
    	if (vsync){
    	    swapchain_desc.BufferDesc.RefreshRate.Numerator = numerator;
    		swapchain_desc.BufferDesc.RefreshRate.Denominator = denominator;
    	}else{
    	    swapchain_desc.BufferDesc.RefreshRate.Numerator = 0;
    		swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
    	}
    
        swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapchain_desc.OutputWindow = hwnd;
    
        swapchain_desc.SampleDesc.Count = 1;    // turn multisampling off
        swapchain_desc.SampleDesc.Quality = 0;
    
    	swapchain_desc.Windowed = !fullscreen;
    	swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    	swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    	swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    	swapchain_desc.Flags = 0;
    
    	// set the feature level to DirectX 11
    	D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0;
    
    	// create the swap chain, Direct3D device, and Direct3D device context
    	result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, 
    					&feature_level, 1, D3D11_SDK_VERSION, &swapchain_desc, 
    					&MySwapchain, &MyDev, NULL, &MyDevcon);
    	if (FAILED(result))
    		throw std::runtime_error("could not create device and swapchain");
    
    	// get the pointer to the back buffer
    	ID3D11Texture2D* backbuffer_ptr;
    	result = MySwapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backbuffer_ptr);
    	if (FAILED(result))
    		throw std::runtime_error("could not get the backbuffer from the swapchain");
    
    	// create the render target view with the back buffer pointer
    	result = MyDev->CreateRenderTargetView(backbuffer_ptr, NULL, &MyRtv);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not create the render target view");
    
    	backbuffer_ptr->Release();
    	backbuffer_ptr = nullptr;
    
    	////////
    
    	// description of the depth buffer
    	D3D11_TEXTURE2D_DESC depthbuffer_desc;
    	ZeroMemory(&depthbuffer_desc, sizeof(depthbuffer_desc));
    
    	depthbuffer_desc.Width = vp_size.x;
    	depthbuffer_desc.Height = vp_size.y;
    	depthbuffer_desc.MipLevels = 1;
    	depthbuffer_desc.ArraySize = 1;
    	depthbuffer_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    	depthbuffer_desc.SampleDesc.Count = 1;
    	depthbuffer_desc.SampleDesc.Quality = 0;
    	depthbuffer_desc.Usage = D3D11_USAGE_DEFAULT;
    	depthbuffer_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    	depthbuffer_desc.CPUAccessFlags = 0;
    	depthbuffer_desc.MiscFlags = 0;
    
    	// create the texture for the depth buffer using the filled out description
    	result = MyDev->CreateTexture2D(&depthbuffer_desc, NULL, &MyDepthstencil_buffer);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not create the depth buffer");
    
    	// description of the stencil state
    	D3D11_DEPTH_STENCIL_DESC depthstencil_desc;
    	ZeroMemory(&depthstencil_desc, sizeof(depthstencil_desc));
    
    	depthstencil_desc.DepthEnable = false;
    	depthstencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    	depthstencil_desc.DepthFunc = D3D11_COMPARISON_LESS;
    
    	depthstencil_desc.StencilEnable = true;
    	depthstencil_desc.StencilReadMask = 0xFF;
    	depthstencil_desc.StencilWriteMask = 0xFF;
    
    	depthstencil_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    	depthstencil_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    	depthstencil_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    	depthstencil_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    
    	depthstencil_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    	depthstencil_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    	depthstencil_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    	depthstencil_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    
    	// create and set the depth stencil state
    	result = MyDev->CreateDepthStencilState(&depthstencil_desc, &MyDepthstencil_state);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not create the depth stencil state");
    
    	MyDevcon->OMSetDepthStencilState(MyDepthstencil_state, 1);
    
    	// depth stencil view description
    	D3D11_DEPTH_STENCIL_VIEW_DESC depthstencil_view_desc;
    	ZeroMemory(&depthstencil_view_desc, sizeof(depthstencil_view_desc));
    
    	depthstencil_view_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    	depthstencil_view_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    	depthstencil_view_desc.Texture2D.MipSlice = 0;
    
    	// create the depth stencil view
    	result = MyDev->CreateDepthStencilView(MyDepthstencil_buffer, 
    						&depthstencil_view_desc, &MyDepthstencil_view);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not create the depth stencil view");
    
    	// bind the render target view and depth stencil buffer to the output render pipeline
    	MyDevcon->OMSetRenderTargets(1, &MyRtv, MyDepthstencil_view);
    
    	/////////
    
    	// setup the raster description which will determine how and what polygons will be drawn
    	D3D11_RASTERIZER_DESC raster_desc;
    	raster_desc.AntialiasedLineEnable = false;
    	raster_desc.CullMode = D3D11_CULL_BACK;
    	raster_desc.DepthBias = 0;
    	raster_desc.DepthBiasClamp = 0.0f;
    	raster_desc.DepthClipEnable = true;
    	raster_desc.FillMode = D3D11_FILL_SOLID;
    	raster_desc.FrontCounterClockwise = false;
    	raster_desc.MultisampleEnable = false;
    	raster_desc.ScissorEnable = false;
    	raster_desc.SlopeScaledDepthBias = 0.0f;
    
    	// create and set the rasterizer state
    	result = MyDev->CreateRasterizerState(&raster_desc, &MyRasterizer_state);
    	if (FAILED(result)) 
    		throw std::runtime_error("could not the rasterizer state");
    
    	MyDevcon->RSSetState(MyRasterizer_state);
    
    	/////////
    
    	// setup the viewport for rendering
    	D3D11_VIEWPORT viewport;
        viewport.Width  = (FLOAT)vp_size.x;
        viewport.Height = (FLOAT)vp_size.y;
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 1.0f;
        viewport.TopLeftX = 0.0f;
        viewport.TopLeftY = 0.0f;
    
    	// create the viewport
        MyDevcon->RSSetViewports(1, &viewport);
    
    	///////////
    
    	// initialize the world matrix to the idobject matrix
    	D3DXMatrixIdentity(&MyWorld_mat);
    
    	// create an orthographic projection matrix for 2D rendering
    	D3DXMatrixOrthoLH(&MyOrtho_mat, (FLOAT)vp_size.x, (FLOAT)vp_size.y, 
    					  0.1f/*screen_near*/, 1000.0f/*screen_depth*/);
    
    	//////////
    
    	// create a blend state description
    	D3D11_BLEND_DESC blendstate_desc;
    	ZeroMemory(&blendstate_desc, sizeof(D3D11_BLEND_DESC));
    
    	blendstate_desc.RenderTarget[0].BlendEnable = (BOOL)alpha_blending;
        //blendstate_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
        blendstate_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
        blendstate_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
        blendstate_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
        blendstate_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
        blendstate_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
        blendstate_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
        blendstate_desc.RenderTarget[0].RenderTargetWriteMask = 0x0f;
    
    	// create the blend state
    	result = MyDev->CreateBlendState(&blendstate_desc, &MyBlendstate);
    	if (FAILED(result))
    		throw std::runtime_error("could not create alpha-enable-blend-state");
    	}
    


  • Ich will ein png mit teilweiser transparenz rendern. leider funktioniert das mal so garnicht und irgendwas stimmt anscheinend nicht mit dem D3D11_BLEND_DESC oder der art wie ich das bild lade (letzteres wäre komisch und unwarscheinlich).
    Hat irgendeiner eine ahnung was ich falsch mache oder ein funktionierendes beispiel aus eigenen projekten?



  • Ich hab mir den Code jetzt nicht genau angesehen, aber ich würde mal vermuten, dass du eben einfach die Sprites die "weiter hinten liegen" nicht zuerst zeichnest, was du aber musst, wenn du willst, dass die Sprites "weiter vorne" oben drübergeblendet werden...



  • das ist klar, das ist nicht das problem das problem ist speziell dass ich bitmap fonts zeichnen. dafür hab ich eine textur die bis auf die buchstaben (schwarz) komplett durchsichtig ist. wenn ich das ganze jetzt zeichne werden die pixel die durchsichtig sind anscheinend mit schwarz und weiß ergänzt 😕
    Ich hab erst falsch gedacht und angenommen es würde einfach der überlappende teil der darunterliegenden sprite nicht gezeichnet werden, aber das war nen denkfehler.. geht nur um den blend-state glaube ich, weil ich da die transparenz nicht richtig ans laufen bekomme



  • Ok, offenbar versteh ich nicht, was genau das Problem ist. Kannst du vielleicht einen Screenshot davon posten?



  • Bitmap font: PNG
    http://s7.directupload.net/file/d/3416/7ksigp7g_png.htm
    Einfach mal nur als Sprite gerendert:
    http://s1.directupload.net/file/d/3416/3tnb7jci_jpg.htm

    anstatt transparenz sieht man halt nur weiß oder interessanterweise auch schwarz.


Anmelden zum Antworten