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


  • Mod

    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.


  • Mod

    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 vergleichen 😉

    allerdings 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 vergleichen 😉

    allerdings 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.


Anmelden zum Antworten