Grundlagenfrage: Polygonen Fabre zuweisen
-
Hallo miteinander,
nachdem ich google mehrfach angeworfen und auch diese Forumssuche bemüht habe gibt es trotzdem noch eine Frage.
Ich programmiere Direct3D mit DirectX10 mit Visual Studio 2010.
Ich habe einige Tutorials durchgearbeitet und mir dann das Tutorial 6 von Microsoft genommen, die ganze Lichtsache raus geschmissen, drehen mit der Maus angefangen zu implementieren und stehe jetzt vor dem Problem, dass ich Linien wunderbar Farben zuweisen kann. Diese wirken sich dann auf das aus Ihnen gebildete Polygon aus. Heißt: Es gibt Farbverläufe auf dem Polygon zwischen den Farben der Linien.
Ich würde jetzt aber gern den Polygonen Farben zuweisen. Und zwar jedem einzeln. Irgendwo gibt es da noch ein Denkproblem bei mir.Hier der Code dazu:
cpp-Datei:
#include <windows.h> #include <d3d10.h> #include <d3dx10.h> #include "resource.h" struct SimpleVertex { D3DXVECTOR3 Pos; D3DXCOLOR Color; // Color }; HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL; ID3D10Device* g_pd3dDevice = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D10RenderTargetView* g_pRenderTargetView = NULL; ID3D10Texture2D* g_pDepthStencil = NULL; ID3D10DepthStencilView* g_pDepthStencilView = NULL; ID3D10Effect* g_pEffect = NULL; ID3D10EffectTechnique* g_pTechniqueRender = NULL; ID3D10EffectTechnique* g_pTechniqueRenderLight = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10Buffer* g_pVertexBuffer = NULL; ID3D10Buffer* g_pIndexBuffer = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; ID3D10EffectVectorVariable* g_pOutputColorVariable = NULL; D3DXMATRIX g_World; D3DXMATRIX g_World1; D3DXMATRIX g_View; D3DXMATRIX g_Projection; int width,height,mousedown; signed int xPosLetzte,yPosLetzte; float xDrehung,yDrehung; HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void Render(); int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) { UNREFERENCED_PARAMETER( hPrevInstance ); UNREFERENCED_PARAMETER( lpCmdLine ); width=800; height=600; mousedown=0; if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; if( FAILED( InitDevice() ) ) { CleanupDevice(); return 0; } // Main message loop MSG msg = {0}; while( WM_QUIT != msg.message ) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if(msg.message==WM_LBUTTONDOWN && mousedown==0){ xPosLetzte = LOWORD(msg.lParam); yPosLetzte = HIWORD(msg.lParam); mousedown=1; } if (msg.message==WM_MOUSEMOVE &&((msg.wParam & MK_LBUTTON) != 0) && mousedown==1){ //linke Maustaste gedrückt //Neues Delta addieren int x=LOWORD(msg.lParam); int y=HIWORD(msg.lParam); xDrehung+=2*3.141*(xPosLetzte-LOWORD(msg.lParam))/width; yDrehung+=2*3.141*(yPosLetzte-HIWORD(msg.lParam))/height; //Aktuelle Position speichern xPosLetzte = LOWORD(msg.lParam); yPosLetzte = HIWORD(msg.lParam); } if(msg.message==WM_LBUTTONUP && mousedown==1){ mousedown=0; } TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } CleanupDevice(); return ( int )msg.wParam; } HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ) { // Register class WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Create window g_hInst = hInstance; RECT rc = { 0, 0, width, height }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Zeichnen", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE, }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ); if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // Create a render target view ID3D10Texture2D* pBuffer; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), ( LPVOID* )&pBuffer ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBuffer, NULL, &g_pRenderTargetView ); pBuffer->Release(); if( FAILED( hr ) ) return hr; // Create depth stencil texture D3D10_TEXTURE2D_DESC descDepth; descDepth.Width = width; descDepth.Height = height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D32_FLOAT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D10_USAGE_DEFAULT; descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = g_pd3dDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil ); if( FAILED( hr ) ) return hr; // Create the depth stencil view D3D10_DEPTH_STENCIL_VIEW_DESC descDSV; descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView ); if( FAILED( hr ) ) return hr; g_pd3dDevice->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView ); // Setup the viewport D3D10_VIEWPORT vp; vp.Width = width; vp.Height = height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pd3dDevice->RSSetViewports( 1, &vp ); // Create the effect DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Set the D3D10_SHADER_DEBUG flag to embed debug information in the shaders. // Setting this flag improves the shader debugging experience, but still allows // the shaders to be optimized and to run exactly the way they will run in // the release configuration of this program. dwShaderFlags |= D3D10_SHADER_DEBUG; #endif hr = D3DX10CreateEffectFromFile( L"Tutorial06.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ); if( FAILED( hr ) ) { MessageBox( NULL, L"The FX file cannot be located. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK ); return hr; } // Obtain the techniques g_pTechniqueRender = g_pEffect->GetTechniqueByName( "Render" ); //g_pTechniqueRenderLight = g_pEffect->GetTechniqueByName( "RenderLight" ); // Obtain the variables g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); // g_pLightDirVariable = g_pEffect->GetVariableByName( "vLightDir" )->AsVector(); //g_pLightColorVariable = g_pEffect->GetVariableByName( "vLightColor" )->AsVector(); g_pOutputColorVariable = g_pEffect->GetVariableByName( "vOutputColor" )->AsVector(); // Define the input layout D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, // { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0}, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Create the input layout D3D10_PASS_DESC PassDesc; g_pTechniqueRender->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ); if( FAILED( hr ) ) return hr; // Set the input layout g_pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Create vertex buffer SimpleVertex vertices[] = { { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXCOLOR (0.0f, 0.0f, 0.0f, 1.0f) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXCOLOR (0.0f, 1.0f, 0.0f, 1.0f) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXCOLOR (0.0f, 0.0f, 1.0f, 1.0f) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f) }, }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 24; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Set vertex buffer UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pd3dDevice->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset ); // Create index buffer // Create vertex buffer DWORD indices[] = { 3,1,0, 2,1,3, }; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( DWORD ) * 36; bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Set index buffer g_pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); // Set primitive topology g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Initialize the world matrices D3DXMatrixIdentity( &g_World ); // Initialize the view matrix D3DXVECTOR3 Eye( 0.0f, 4.0f, -10.0f ); D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f ); D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up ); // Initialize the projection matrix D3DXMatrixPerspectiveFovLH( &g_Projection, ( float )D3DX_PI * 0.25f, width / ( FLOAT )height, 0.1f, 100.0f ); return TRUE; } void CleanupDevice() { if( g_pd3dDevice ) g_pd3dDevice->ClearState(); if( g_pVertexBuffer ) g_pVertexBuffer->Release(); if( g_pIndexBuffer ) g_pIndexBuffer->Release(); if( g_pVertexLayout ) g_pVertexLayout->Release(); if( g_pEffect ) g_pEffect->Release(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); if( g_pDepthStencil ) g_pDepthStencil->Release(); if( g_pDepthStencilView ) g_pDepthStencilView->Release(); if( g_pSwapChain ) g_pSwapChain->Release(); if( g_pd3dDevice ) g_pd3dDevice->Release(); } LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; HDC hdc; switch( message ) { case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } void Render() { // Rotate cube around the origin D3DXMatrixRotationX( &g_World, yDrehung ); D3DXMatrixRotationY( &g_World1, xDrehung ); g_World=g_World+g_World1; // // Clear the back buffer // float ClearColor[4] = { 0.74f, 0.74f, 0.74f, 1.0f }; // red, green, blue, alpha g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); // // Clear the depth buffer to 1.0 (max depth) // g_pd3dDevice->ClearDepthStencilView( g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 ); // // Update matrix variables // g_pWorldVariable->SetMatrix( ( float* )&g_World ); g_pViewVariable->SetMatrix( ( float* )&g_View ); g_pProjectionVariable->SetMatrix( ( float* )&g_Projection ); ); D3D10_TECHNIQUE_DESC techDesc; g_pTechniqueRender->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ) { g_pTechniqueRender->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->DrawIndexed( 36, 0, 0 ); } g_pSwapChain->Present( 0, 0 ); }
.fx-Effektdatei:
matrix World; matrix View; matrix Projection; struct VS_INPUT { float4 Pos : POSITION; float4 Color : COLOR; }; struct PS_INPUT { float4 Pos : SV_POSITION; float4 Color : COLOR0; }; PS_INPUT VS( VS_INPUT input ) { PS_INPUT output = (PS_INPUT)0; output.Pos = mul( input.Pos, World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Color = input.Color; return output; } float4 PS( PS_INPUT input) : SV_Target { return input.Color; } technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Schon ein Tipp, wonach ich suchen soll, wäre genial.
Vielen Dank schonmal.
Gustav
-
du kannst den vertices der polygone deine wunschfarbe zuweisen.
-
rapso schrieb:
du kannst den vertices der polygone deine wunschfarbe zuweisen.
Gut - das ist klar. Aber wenn 2 benachbarte Polygone verschiedene Farben haben sollen muss ich die Linie, die zwischen ihnen ist, zweimal zeichnen, oder? Das ist, denke ich, schlecht für die Performance. Oder habe ich einen Denkfehler?
-
Jop, einfach deinen Vertices ne Farbe geben. Und ja, dann musst du die Vertices and Kanten, wo verschiedenen Farben zusammentreffen, duplizieren. Alternativ könntest du auch einen Buffer machen, in dem für jedes Dreieck die Farbe drin steht und dann im Geometry Shader über die Primitive ID die jeweilige Farbe an den PixelShader übergeben. Das wäre evtl. ein ganz kleines bisschen Effizienter, was bei dir aber im Moment wohl sowieso keine große Rolle spielt.
Btw: Ich würd an deiner Stelle zumindest in Zukunft nurmehr D3D11 verwenden. D3D10 hat gegenüber D3D11 nur Nachteile und keinen einzigen Vorteil, daher ist es imo sinnlos, heute noch D3D10 zu verwenden.
-
gustav schrieb:
rapso schrieb:
du kannst den vertices der polygone deine wunschfarbe zuweisen.
Gut - das ist klar. Aber wenn 2 benachbarte Polygone verschiedene Farben haben sollen muss ich die Linie, die zwischen ihnen ist, zweimal zeichnen, oder? Das ist, denke ich, schlecht für die Performance. Oder habe ich einen Denkfehler?
Polygone haben keine linien dazwischen, jedes zeichnet seine eigenen pixel und ueberlappt nicht mit dem nachbarn.
aber ja, wenn zwei benachbarte polygone unterschiedliche farben haben, koennen sie nicht den selben vertex benutzen. Das ist keine wirkliche frage der performance, sondern eine loesung fuer ein problem.
wenn du zwei+ loesungen hast fuer dein problem, kannst du anfangen performance zu vergleichenallerdings solltest du erstmal echt nicht drueber nachdenken, solange du kein performance problem hast. normalerweise ist das zeichnen der pixel das, was am meisten zeit beansprucht.
-
rapso schrieb:
Polygone haben keine linien dazwischen, jedes zeichnet seine eigenen pixel und ueberlappt nicht mit dem nachbarn.
aber ja, wenn zwei benachbarte polygone unterschiedliche farben haben, koennen sie nicht den selben vertex benutzen. Das ist keine wirkliche frage der performance, sondern eine loesung fuer ein problem.
wenn du zwei+ loesungen hast fuer dein problem, kannst du anfangen performance zu vergleichenallerdings solltest du erstmal echt nicht drueber nachdenken, solange du kein performance problem hast. normalerweise ist das zeichnen der pixel das, was am meisten zeit beansprucht.
ok - Danke. Dann werd ich das erstmal so versuchen, wenn alle anderen Probleme beseitigt sind.