游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3070|回复: 8

还是渲染到纹理问题

[复制链接]

23

主题

64

帖子

64

积分

注册会员

Rank: 2

积分
64
发表于 2010-10-6 22:52:00 | 显示全部楼层 |阅读模式
为什么我的渲染对象只渲染了一遍就不再渲染了,谁能给我找找问题出在哪里!(只要在机子上跑一下就可以发现问题,但我就是不知道问题出在哪里)代码如下:
#include <d3d9.h>
#include <d3dx9.h>

#define  SAFE_RELEASE(o) {if(o){o->Release();o = NULL;}}

struct LINEVERTEX
{
        D3DXVECTOR3 pos;
        D3DCOLOR color;
};

#define D3DFVF_LINEVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE )

struct RECTVERTEX
{
        D3DXVECTOR3 Pos;
        D3DCOLOR Color;
        D3DXVECTOR2 Tex;
};

#define  D3DFVF_RECTVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

//全局变量
LPDIRECT3D9             g_pD3d = NULL;
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL;
D3DCAPS9                g_Caps = {(D3DDEVTYPE)0};
LPDIRECT3DVERTEXBUFFER9 g_pLineVB = NULL;
LPDIRECT3DINDEXBUFFER9  g_pLineIB = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pRectVB = NULL;
LPDIRECT3DTEXTURE9      g_pRenderTexture = NULL;
LPDIRECT3DSURFACE9      g_pRenderSurface = NULL;

HRESULT InitD3d(HWND hWnd)
{
        if(NULL == (g_pD3d = Direct3DCreate9(D3D_SDK_VERSION)))
                return E_FAIL;

        D3DDISPLAYMODE d3ddm;
        if(FAILED(g_pD3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
                return E_FAIL;

        RECT rect;
        GetClientRect(hWnd, &rect);

        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));
        d3dpp.Windowed = TRUE;
        d3dpp.BackBufferWidth = rect.right - rect.left;
        d3dpp.BackBufferHeight = rect.bottom - rect.top;
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat = d3ddm.Format;
        d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
        d3dpp.EnableAutoDepthStencil = TRUE;

        if(FAILED(g_pD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                g_Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                &d3dpp, &g_pd3dDevice)))
                return E_FAIL;

        g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
        g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

        return S_OK;
}

//创建定点缓冲区
HRESULT InitVB()
{
        if(FAILED(g_pd3dDevice->CreateVertexBuffer(4 * sizeof(RECTVERTEX), 0, D3DFVF_RECTVERTEX,
                D3DPOOL_DEFAULT, &g_pRectVB, NULL)))
                return E_FAIL;
        RECTVERTEX* rVtx;
        if(SUCCEEDED(g_pRectVB->Lock(0, 4 * sizeof(RECTVERTEX), (void**)&rVtx, 0)))
        {
                rVtx[0].Pos = D3DXVECTOR3(-10.0f, 7.5f, 0.0f);
                rVtx[1].Pos = D3DXVECTOR3(-10.0f, -7.5f, 0.0f);
                rVtx[2].Pos = D3DXVECTOR3(10.0f, 7.5f, 0.0f);
                rVtx[3].Pos = D3DXVECTOR3(10.0f, -7.5f, 0.0f);

                rVtx[0].Color = 0xffffffff;
                rVtx[1].Color = 0xffffffff;
                rVtx[2].Color = 0xffffffff;
                rVtx[3].Color = 0xffffffff;

                rVtx[0].Tex = D3DXVECTOR2(0, 0);
                rVtx[1].Tex = D3DXVECTOR2(0, 1);
                rVtx[2].Tex = D3DXVECTOR2(1, 0);
                rVtx[3].Tex = D3DXVECTOR2(1, 1);

                g_pRectVB->Unlock();
        }
        else
                return E_FAIL;

        if(FAILED(g_pd3dDevice->CreateVertexBuffer(12 * sizeof(LINEVERTEX),0, D3DFVF_LINEVERTEX,
                D3DPOOL_DEFAULT, &g_pLineVB, NULL)))
                return E_FAIL;

        LINEVERTEX* lVtx;
        if(FAILED(g_pLineVB->Lock(0, 12*sizeof(LINEVERTEX), (void**)&lVtx, 0)))
                return E_FAIL;
        float fDeltaY = 3.0f;
        for (int i = 0; i <= 2 * 5; i += 2)
        {
                lVtx.pos = D3DXVECTOR3(-10.0f, -7.5+i*fDeltaY/2, 0.0f);
                lVtx[i+1].pos = D3DXVECTOR3(10.0f, -7.5+i*fDeltaY/2, 0.0f);

                lVtx.color = 0xffffffff;
                lVtx[i+1].color = 0xffffffff;
        }
        g_pLineVB->Unlock();

        //创建渲染到纹理表面
        if(FAILED(g_pd3dDevice->CreateTexture(512, 512, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8,
                D3DPOOL_DEFAULT, &g_pRenderTexture, NULL)))
                return E_FAIL;

        //获得纹理的渲染表面
        if(FAILED(g_pRenderTexture->GetSurfaceLevel(0, &g_pRenderSurface)))
                return E_FAIL;

        return S_OK;
}

//创建索引缓存
HRESULT InitIB()
{
        WORD indices[] =
        {
                0, 1, 2, 3, 4, 5, 6,7 ,8 ,9, 10, 11, 0, 10, 1, 11
        };

        if(FAILED(g_pd3dDevice->CreateIndexBuffer(16*sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT,
                &g_pLineIB, NULL)))
                return E_FAIL;

        VOID* pIndices;
        if(FAILED(g_pLineIB->Lock(0, 16 * sizeof(WORD), (void**)&pIndices, 0)))
                return E_FAIL;
        memcpy(pIndices, indices, 16 * sizeof(WORD));
        g_pLineIB->Unlock();

        return S_OK;
}

HRESULT InitGeometry()
{
        if(FAILED(InitVB()))
                return E_FAIL;
        if(FAILED(InitIB()))
                return E_FAIL;
}

void Cleanup()
{
        SAFE_RELEASE(g_pLineVB);
        SAFE_RELEASE(g_pLineIB);
        SAFE_RELEASE(g_pRectVB);
        SAFE_RELEASE(g_pRenderTexture);
        SAFE_RELEASE(g_pd3dDevice);
        SAFE_RELEASE(g_pD3d);
}

void SetupCamera()
{
        D3DXMATRIXA16 matWorld;
        D3DXMatrixIdentity(&matWorld);
        g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);

        D3DXMATRIXA16 matView;
        D3DXVECTOR3 vEye(0.0f, 0.0f, -20.0f);
        D3DXVECTOR3 vLookAt(0.0f, 0.0f, 0.0f);
        D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);
        D3DXMatrixLookAtLH(&matView, &vEye, &vLookAt, &vUp);
        g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);

        D3DXMATRIXA16 matProj;
        D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 800.0f / 600.0f, 1.0f, 100.0f);
        g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}

void Render()
{
        LPDIRECT3DSURFACE9 pBackBuffer;
        g_pd3dDevice->GetRenderTarget(0, &pBackBuffer);

        g_pd3dDevice->SetRenderTarget(0, g_pRenderSurface);

        g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0xff, 0xff, 0), 1.0f, 0);

        if(SUCCEEDED(g_pd3dDevice->BeginScene()))
        {
                SetupCamera();

                D3DXMATRIXA16 matProj;
                D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI / 4, 1.0f, 1.0f, 100.0f);

                g_pd3dDevice->SetStreamSource(0, g_pLineVB, 0, sizeof(LINEVERTEX));
                g_pd3dDevice->SetFVF(D3DFVF_LINEVERTEX);
                g_pd3dDevice->SetIndices(g_pLineIB);
                g_pd3dDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 12, 0, 8);

                g_pd3dDevice->EndScene();
        }

        g_pd3dDevice->SetRenderTarget(0, pBackBuffer);

        g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0xff, 0xff), 1.0f, 0);
        if (SUCCEEDED(g_pd3dDevice->BeginScene()))
        {
                SetupCamera();

                D3DXMATRIXA16 matWorld;
                D3DXMatrixRotationAxis( & matWorld ,  & D3DXVECTOR3( 1  ,  1  , 0 ) ,
                        sinf(D3DX_PI  *   2.0f   *  (timeGetTime()  %   5000 )  /   5000.0f ));
                g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);

                g_pd3dDevice->SetTexture(0, g_pRenderTexture);
                g_pd3dDevice -> SetTextureStageState( 0 , D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
                g_pd3dDevice -> SetTextureStageState( 0 , D3DTSS_TEXCOORDINDEX,  0 );

                g_pd3dDevice -> SetSamplerState( 0  , D3DSAMP_ADDRESSU , D3DTADDRESS_MIRROR);
                g_pd3dDevice -> SetSamplerState( 0  , D3DSAMP_ADDRESSV , D3DTADDRESS_MIRROR);
                g_pd3dDevice -> SetRenderState(D3DRS_LIGHTING , FALSE);

                g_pd3dDevice->SetStreamSource(0, g_pRectVB, 0, sizeof(RECTVERTEX));
                g_pd3dDevice->SetFVF(D3DFVF_RECTVERTEX);
                g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
               
                g_pd3dDevice->EndScene();
        }

        g_pd3dDevice-&gtresent(NULL, NULL, NULL, NULL);
}

//  消息处理
LRESULT WINAPI MsgProc(HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam)
{
        switch (message)
        {
        case  WM_DESTROY:
                Cleanup();
                PostQuitMessage( 0 );
                break ;
        }
        return  :efWindowProc(hWnd, message , wParam , lParam);
}

//  Windows 入口
int  WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN  int  nShowCmd )
{
        WNDCLASS wndClass;
        memset( & wndClass ,  0  ,  sizeof (wndClass));
        wndClass.hInstance  =  hInstance;
        wndClass.lpszClassName  =   L" 渲染到纹理 " ;
        wndClass.lpfnWndProc  =  MsgProc;
        RegisterClass( & wndClass);

        //  创建窗口
        HWND hWnd  =  CreateWindow( L" 渲染到纹理 "  ,  L" 渲染到纹理! "  
                ,  WS_OVERLAPPEDWINDOW  ,  0  ,  0  ,  800  , 600  ,0
                ,  0  , wndClass.hInstance ,  0 );
        //  显示窗口
        ShowWindow(hWnd , SW_SHOWDEFAULT);
        UpdateWindow(hWnd);

        //  初始化 D3D 设备
        if (SUCCEEDED(InitD3d(hWnd)))
        {
                if(FAILED(InitGeometry()))
                        return E_FAIL;
                //  消息处理循环
                MSG msg;
                memset( & msg ,  0  ,  sizeof (msg));
                while (msg.message  !=  WM_QUIT)
                {
                        if (PeekMessage( & msg ,  0  ,  0  ,  0  , PM_REMOVE))
                        {
                                TranslateMessage( & msg);
                                DispatchMessage( & msg);
                        }
                        else
                        {
                                Render();
                        }
                }
        }
        //  清空场景
        Cleanup();

        UnregisterClass( L" 渲染到纹理 "  , wndClass.hInstance);

        return   0 ;
}

1

主题

15

帖子

33

积分

注册会员

Rank: 2

积分
33
发表于 2010-10-7 22:15:00 | 显示全部楼层

Re:还是渲染到纹理问题

void Render()怎么 有 2个 g_pd3dDevice->EndScene();?

23

主题

64

帖子

64

积分

注册会员

Rank: 2

积分
64
 楼主| 发表于 2010-10-8 09:22:00 | 显示全部楼层

Re:还是渲染到纹理问题

两个begain,就应该有两个end吧

1

主题

24

帖子

31

积分

注册会员

Rank: 2

积分
31
发表于 2010-10-8 10:48:00 | 显示全部楼层

Re:还是渲染到纹理问题

你在渲染到纹理的地方少了一句                
g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
另外你把画线的颜色调整一下,不要用白色的线画吧.

23

主题

64

帖子

64

积分

注册会员

Rank: 2

积分
64
 楼主| 发表于 2010-10-8 11:25:00 | 显示全部楼层

Re: Re:还是渲染到纹理问题

yfplane: Re:还是渲染到纹理问题

你在渲染到纹理的地方少了一句                
g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
另外...

我按你的方式修改了一下,还是不行!

23

主题

64

帖子

64

积分

注册会员

Rank: 2

积分
64
 楼主| 发表于 2010-10-8 11:26:00 | 显示全部楼层

Re:还是渲染到纹理问题

为什么只有第一次可以画出来,然后就不可以了呢。。。

72

主题

447

帖子

454

积分

中级会员

Rank: 3Rank: 3

积分
454
QQ
发表于 2010-10-8 13:50:00 | 显示全部楼层

Re:还是渲染到纹理问题

http://www.dingge.com/forum/viewthread.php?tid=21260

10

主题

55

帖子

55

积分

注册会员

Rank: 2

积分
55
发表于 2010-10-9 12:26:00 | 显示全部楼层

Re:还是渲染到纹理问题

我调试了一下你的程序总的说来有以下几个问题
1.InitGeometry()不是所有路径都有返回值。
   需要在最后加上一个return S_OK;
2.g_pRenderSurface没有做Release处理,会出现内存泄露
3.Render()中的局部变量pBackBuffer需要做释放处理。可参考SDK中的GetRenderTarget()注解:
    Calling this method will increase the internal reference count on the IDirect3DSurface9 interface. Failure to call IUnknown::Release when finished using the IDirect3DSurface9 interface results in a memory leak.
4.解决你最终的问题。
     一开始运行你的程序的时候DEBUG会给出一个WARNING:
     Direct3D9: (WARN) :Can not render to a render target that is also used as a texture. A render target was detected as bound, but couldn't detect if texture was actually used in rendering.
     这是因为你在第一次调用Render()的时候做了g_pd3dDevice->SetTexture(0, g_pRenderTexture);这时候g_pRenderTexture指向的纹理已经与设备的第0层纹理关联。当你第二次调用Render()的时候,由于D3D不能确定g_pRenderTexture指向的纹理(即设备的第0层纹理)是否正在被使用,所以无法绘制到g_pRenderTexture指向的纹理上。要解决你的问题,只需要在使用完g_pRenderTexture指向的纹理之后使设备的第0层纹理不再关联它就行。即g_pd3dDevice->SetTexture( 0, NULL );

OK, 问题都解决了!

23

主题

64

帖子

64

积分

注册会员

Rank: 2

积分
64
 楼主| 发表于 2010-10-9 14:47:00 | 显示全部楼层

Re:还是渲染到纹理问题

谢谢楼上!问题终于解决了,真的是万分的感激、、、
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-6 15:07

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表