游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4212|回复: 10

请问:纹理是否必须从图形文件载入?能不能在程序中生

[复制链接]

106

主题

743

帖子

745

积分

高级会员

Rank: 4

积分
745
QQ
发表于 2006-7-25 20:47:00 | 显示全部楼层 |阅读模式
请问:纹理是否必须从图形文件载入?能不能在程序中生成?

0

主题

1037

帖子

1037

积分

金牌会员

Rank: 6Rank: 6

积分
1037
发表于 2006-7-25 21:45:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

是可以的。以下一个简单例子,来自Introduction to 3D Game Programming with DirectX 9.0
bool Terrain::genTexture(D3DXVECTOR3* directionToLight)
{
        // Method fills the top surface of a texture procedurally.  Then
        // lights the top surface.  Finally, it fills the other mipmap
        // surfaces based on the top surface data using D3DXFilterTexture.

        HRESULT hr = 0;

        // texel for each quad cell
        int texWidth  = _numCellsPerRow;
        int texHeight = _numCellsPerCol;

        // create an empty texture
        hr = D3DXCreateTexture(
                _device,
                texWidth, texHeight,
                0, // create a complete mipmap chain
                0, // usage
                D3DFMT_X8R8G8B8,// 32 bit XRGB format
                D3DPOOL_MANAGED, &_tex);

        if(FAILED(hr))
                return false;

        D3DSURFACE_DESC textureDesc;
        _tex->GetLevelDesc(0 /*level*/, &textureDesc);

        // make sure we got the requested format because our code
        // that fills the texture is hard coded to a 32 bit pixel depth.
        if( textureDesc.Format != D3DFMT_X8R8G8B8 )
                return false;
               
        D3DLOCKED_RECT lockedRect;
        _tex->LockRect(0/*lock top surface*/, &lockedRect,
                0 /* lock entire tex*/, 0/*flags*/);         

        DWORD* imageData = (DWORD*)lockedRect.pBits;
        for(int i = 0; i < texHeight; i++)
        {
                for(int j = 0; j < texWidth; j++)
                {
                        D3DXCOLOR c;

                        // get height of upper left vertex of quad.
                        float height = (float)getHeightmapEntry(i, j) / _heightScale;

                        if( (height) < 42.5f )                  c = d3d::BEACH_SAND;
                        else if( (height) < 85.0f )         c = d3d:IGHT_YELLOW_GREEN;
                        else if( (height) < 127.5f ) c = d3d:UREGREEN;
                        else if( (height) < 170.0f ) c = d3d:ARK_YELLOW_GREEN;
                        else if( (height) < 212.5f ) c = d3d::DARKBROWN;
                        else                             c = d3d::WHITE;

                        // fill locked data, note we divide the pitch by four because the
                        // pitch is given in bytes and there are 4 bytes per DWORD.
                        imageData[i * lockedRect.Pitch / 4 + j] = (D3DCOLOR)c;
                }
        }

        _tex->UnlockRect(0);

        if(!lightTerrain(directionToLight))
        {
                ::MessageBox(0, "lightTerrain() - FAILED", 0, 0);
                return false;
        }
       
        hr = D3DXFilterTexture(
                _tex,
                0, // default palette
                0, // use top level as source level
                D3DX_DEFAULT); // default filter

        if(FAILED(hr))
        {
                ::MessageBox(0, "D3DXFilterTexture() - FAILED", 0, 0);
                return false;
        }

        return true;
}

0

主题

1037

帖子

1037

积分

金牌会员

Rank: 6Rank: 6

积分
1037
发表于 2006-7-25 21:46:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

一贴缩进就没了......

106

主题

743

帖子

745

积分

高级会员

Rank: 4

积分
745
QQ
 楼主| 发表于 2006-7-26 21:28:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

请看下面的代码,编译可以通过,但不能运行。调试运行到注释的地方显示:
First-chance exception in hwb.exe: 0xC0000005: Access Violation.

dxsbzz->CreateTexture(120,60,0,0,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&wldxzz,0);

D3DLOCKED_RECT lsxx;
        wldxzz->LockRect( 0,&lsxx,0,0);//调试到这里无法继续进行。
                byte *wlncdz=(byte *)lsxx.pBits;
        for(int i=0;i<7200;i=i+4)
        {
        wlncdz=222;
        }
        wldxzz->UnlockRect(0);

0

主题

1037

帖子

1037

积分

金牌会员

Rank: 6Rank: 6

积分
1037
发表于 2006-7-26 21:41:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

13

主题

60

帖子

60

积分

注册会员

Rank: 2

积分
60
发表于 2006-7-27 00:27:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

我写了一个用GDI动态映射纹理的一个小例子,
就是说用GDI再如图片,然后再图片上面画画,textout,lineto等等
然后再映到纹理

#include <d3d8.h>
#include <d3dx8.h>
#include <mmsystem.h>


#pragma comment(lib,"d3d8.lib")
#pragma comment(lib,"d3dx8.lib")
#pragma comment(lib,"winmm.lib")

LPDIRECT3D8             g_pD3D       = NULL; // 用来创建D3D设备
LPDIRECT3DDEVICE8       g_pd3dDevice = NULL; // D3D设备
LPDIRECT3DVERTEXBUFFER8 g_pVB        = NULL; // 顶点缓冲区
LPDIRECT3DTEXTURE8      g_pTexture   = NULL; // 纹理

HWND                  hWnd         = NULL;
HBITMAP                 texturebmp   = NULL;
// 自定义顶点结构
struct CUSTOMVERTEX
{
    D3DXVECTOR3 position;        // 顶点坐标
        D3DCOLOR    color;                // 顶点颜色
        FLOAT       tu, tv;                // 贴图坐标
};

// 我们自定义的FVF,定义了顶点的结构,
// D3DFVF_XYZ                : 表示顶点坐标
// D3DFVF_DIFFUSE        : 表示顶点的颜色
// D3DFVF_TX!                : 表示有图
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

// 初始化D3D
HRESULT InitD3D( HWND hWnd )
{
        // 创建D3D对象
        if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
                return E_FAIL;

        // 获取当前的显示模式
        D3DDISPLAYMODE d3ddm;
        if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
                return E_FAIL;

        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory( &d3dpp, sizeof(d3dpp) );
        d3dpp.Windowed = TRUE;                                                // 窗口模式
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;        // 设置交换模式
        d3dpp.BackBufferFormat = d3ddm.Format;                // 设置背景缓冲区格式为当前左面格式
        d3dpp.EnableAutoDepthStencil = TRUE;                // 打开深度缓冲zbuffer
        d3dpp.AutoDepthStencilFormat = D3DFMT_D16;        // 深度缓冲格式

        // 创建D3D设备
        // 第一个参数:使用默认的显卡适配器
        // 第二个参数:请求使用硬件抽象层(HAL)
        // 第三个参数:窗口句柄
        // 第四个参数:使用软件处理顶点
        // 第五个参数:创建的参数
        // 第六个参数:创建的D3D设备指针
        if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT,
                                                                          D3DDEVTYPE_HAL,
                                                                          hWnd,
                                                                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                                                          &d3dpp,
                                                                          &g_pd3dDevice ) ) )
        {
                return E_FAIL;
        }

        // 关闭culling,让我们能看到3角型的正反面
        g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

        // 打开ZBUFFER
        g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

        // Turn off D3D lighting
    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

        return S_OK;
}

//提取内存~
char * HBtoMe(HBITMAP hBitmap,int *length) // 函数 从HBITMAP 中得到内存
{
        char* buffer;
        //设备描述表  
    HDC  hDC;  
    //当前分辨率下每象素所占字节数  
    int  iBits;  
    //位图中每象素所占字节数  
    WORD  wBitCount;  
    //定义调色板大小,  位图中像素字节大小  ,位图文件大小  ,  写入文件字节数   
    DWORD  dwPaletteSize=0,  dwBmBitsSize=0,  dwDIBSize=0,  dwWritten=0;   
    //位图属性结构   
    BITMAP  Bitmap;      
    //位图文件头结构  
    BITMAPFILEHEADER  bmfHdr;      
    //位图信息头结构   
    BITMAPINFOHEADER  bi;      
        //指向位图信息头结构      
    LPBITMAPINFOHEADER  lpbi;      
    //定义文件,分配内存句柄,调色板句柄   
    HANDLE  hDib,  hPal,hOldPal=NULL;   
            
    //计算位图文件每个像素所占字节数   
    hDC  =  CreateDC("DISPLAY",  NULL,  NULL,  NULL);  
    iBits  =  GetDeviceCaps(hDC,  BITSPIXEL)  *  GetDeviceCaps(hDC,  PLANES);   
    DeleteDC(hDC);   
    if  (iBits  <=  1)                    wBitCount  =  1;   
    else  if  (iBits  <=  4)              wBitCount  =  4;   
    else  if  (iBits  <=  8)              wBitCount  =  8;   
        else                                                                  wBitCount  =  24;   
            
    GetObject(hBitmap,  sizeof(Bitmap),  (LPSTR)&Bitmap);  
    bi.biSize                    =  sizeof(BITMAPINFOHEADER);  
    bi.biWidth                   =  Bitmap.bmWidth;  
    bi.biHeight                  =  Bitmap.bmHeight;  
        bi.biPlanes                  =  1;  
    bi.biBitCount                =  wBitCount;  
    bi.biCompression             =  BI_RGB;  
    bi.biSizeImage               =  0;  
    bi.biXPelsPerMeter           =  0;  
    bi.biYPelsPerMeter           =  0;  
    bi.biClrImportant            =  0;  
    bi.biClrUsed                 =  0;  
            
    dwBmBitsSize  =  ((Bitmap.bmWidth  *  wBitCount  +  31)  /  32)  *  4  *  Bitmap.bmHeight;  
            
           //为位图内容分配内存   
    hDib  =  GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));   
    lpbi  =  (LPBITMAPINFOHEADER)GlobalLock(hDib);   
    *lpbi  =  bi;   

    //  处理调色板      
    hPal  =  GetStockObject(DEFAULT_PALETTE);   
    if  (hPal)   
    {   
         hDC  =  ::GetDC(NULL);   
         hOldPal  =  ::SelectPalette(hDC,  (HPALETTE)hPal,  FALSE);   
         RealizePalette(hDC);   
    }  

           //  获取该调色板下新的像素值   
    GetDIBits(hDC,  hBitmap,  0,  (UINT)  Bitmap.bmHeight,  (LPSTR)lpbi  +  sizeof(BITMAPINFOHEADER)   
              +dwPaletteSize, (BITMAPINFO  *)lpbi,  DIB_RGB_COLORS);   
            
    //恢复调色板      
    if  (hOldPal)   
    {   
        ::SelectPalette(hDC,  (HPALETTE)hOldPal,  TRUE);   
        RealizePalette(hDC);   
        ::ReleaseDC(NULL,  hDC);   
    }   
        //  设置位图文件头   
    bmfHdr.bfType  =  0x4D42;  //  "BM"   
        dwDIBSize  =  sizeof(BITMAPFILEHEADER)  +  sizeof(BITMAPINFOHEADER)  +  dwPaletteSize  +  dwBmBitsSize;      
        bmfHdr.bfSize  =  dwDIBSize;   
    bmfHdr.bfReserved1  =  0;   
    bmfHdr.bfReserved2  =  0;   
    bmfHdr.bfOffBits  =  (DWORD)sizeof(BITMAPFILEHEADER)  +  (DWORD)sizeof(BITMAPINFOHEADER)  +  dwPaletteSize;

        //strncpy(buffer,(char*)&bmfHdr,sizeof(bmfHdr));  //内存copy
        *length = dwDIBSize;
        buffer = new char[dwDIBSize];
        memcpy(buffer,(char*)lpbi,dwDIBSize);
        memcpy(buffer,(char*)lpbi,sizeof(bmfHdr));
        GlobalUnlock(hDib);   
    GlobalFree(hDib);  
        return buffer;
}

// 填充顶点缓区
HRESULT InitGeometry()
{
        HDC hdc,MemDC;
        HBITMAP bmp;
        bmp = (HBITMAP)LoadImage( 0,"3dgame.bmp", IMAGE_BITMAP,256,256,LR_LOADFROMFILE);
        MemDC = CreateCompatibleDC(hdc);
        SelectObject(MemDC,bmp);
        TextOut(MemDC,10,10,"Hello World",11);
        char* bmpArr;
        int length;
        bmpArr = HBtoMe(bmp,&length);
        DeleteObject(bmp);
        DeleteObject(MemDC);
        //add by ajohn 创建GDI对象 bitmap 然后利用该对象映射纹理
/*        HDC hdc,MemDC;
        hdc = GetDC(hWnd);
        MemDC = CreateCompatibleDC(hdc);
        HANDLE hfile = CreateFile("3dgame.bmp",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);//创建文件句柄
        HBITMAP bmp = NULL;
        int width,height;
        DWORD length = GetFileSize(hfile,NULL); //打开文件
        char* bmpArr = new char[length+1];
        char *bmpArr1;
        DWORD read;
        ReadFile(hfile,bmpArr,length,&read,NULL);//读取二进制文件到内存~~~
        if(read !=length) //如果读取不成功
                return E_FAIL;
       
        BITMAPFILEHEADER        bmfHeader; //位图文件头信息
        DWORD bmfHeaderLen = sizeof(bmfHeader);
        strncpy((LPSTR)&bmfHeader, (LPSTR)bmpArr, bmfHeaderLen);//填充头信息            -------1
        if (bmfHeader.bfType == (*(WORD*)"BM") )//BM代表位图必须为BM
        {
                char* lpDIB = bmpArr + bmfHeaderLen; //内存指针的+运算
                BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)lpDIB;//读内存 强制装换  -------2
                width = bmiHeader.biWidth;
                height = bmiHeader.biHeight;
                BITMAPINFO &bmInfo = *(LPBITMAPINFO)lpDIB;               //这两块内存嵌套? -------3

                LPVOID lpDIBBits = bmpArr + ((BITMAPFILEHEADER *)bmpArr)->bfOffBits;
                bmp = CreateDIBitmap(MemDC,&bmiHeader,CBM_INIT,lpDIBBits,&bmInfo,DIB_RGB_COLORS);
                SelectObject(MemDC,bmp);
                TextOut(MemDC,10,10,"Hello World",11);
                bmpArr1 = new char[length+1];
               
                HBtoMe(bmp,bmpArr1);
        }
       

       
        // 从一个文件创建我们的纹理
        /*该函数是d3dx8tex.h中定义,参数为,1 设备,2 地址 3,字节 4,纹理
          D3DXCreateTextureFromFileInMemory(
        LPDIRECT3DDEVICE8         pDevice,
        LPCVOID                   pSrcData,
        UINT                      SrcDataSize,
        LPDIRECT3DTEXTURE8*       ppTexture);*/
        if( FAILED( D3DXCreateTextureFromFileInMemory(g_pd3dDevice,bmpArr,length,&g_pTexture)))
                return E_FAIL;

        delete bmpArr;
        //if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "3dgame.bmp",
        //                                                                           &g_pTexture ) ) )
        //        return E_FAIL;
        // 创建顶点缓冲区
        if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX),
                                                                                                  0, D3DFVF_CUSTOMVERTEX,
                                                                                                  D3DPOOL_DEFAULT, &g_pVB ) ) )
        {
                return E_FAIL;
        }
        // 填充顶点缓冲区
        CUSTOMVERTEX* pVertices;
        if( FAILED( g_pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ) ) )
                return E_FAIL;

        // 这是一个上下各50个点的圆筒,每个顶点都有其颜色和贴图坐标
        for( DWORD i=0; i<50; i++ )
        {
                FLOAT theta = (2*D3DX_PI*i)/(50-1);
                pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );
                pVertices[2*i+0].color    = 0xffffffff;
                pVertices[2*i+0].tu       = ((FLOAT)50-i)/(50-1);
                pVertices[2*i+0].tv       = 1.0f;

                pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );
                pVertices[2*i+1].color    = 0xff808080;
                pVertices[2*i+1].tu       = ((FLOAT)50-i)/(50-1);
                pVertices[2*i+1].tv       = 0.0f;
        }
        g_pVB->Unlock();
        DeleteObject(MemDC);
        DeleteObject(bmp);
        return S_OK;
}

// 释放D3D
VOID Cleanup()
{
        // 释放纹理
        if( g_pTexture != NULL )
                g_pTexture->Release();

        // 释放地点缓冲区
    if( g_pVB != NULL )
        g_pVB->Release();

        // 释放D3D设备
    if( g_pd3dDevice != NULL)
        g_pd3dDevice->Release();

        // 释放D3D
    if( g_pD3D != NULL)
        g_pD3D->Release();
}

// 设置世界矩阵和摄象机
VOID SetupMatrices()
{
    // 让世界矩阵绕Y轴旋转
    D3DXMATRIX matWorld;
    D3DXMatrixIdentity( &matWorld );
    D3DXMatrixRotationY( &matWorld, timeGetTime()/1000.f );
    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

        // 设置摄象机的位置
    D3DXMATRIX matView;
    D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 1.5f,-5.0f ),
                                  &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
                                  &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

        // 设置摄象机的放射参数
    D3DXMATRIX matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

// 渲染
VOID Render()
{
    if( NULL == g_pd3dDevice )
        return;

    // 清除背景为兰色
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
   
    // 开始绘制场景
    g_pd3dDevice->BeginScene();
   
    // --渲染图形--

    // 设置摄象机位置
    SetupMatrices();

        // 指定贴图
        g_pd3dDevice->SetTexture( 0, g_pTexture );
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1 );
    g_pd3dDevice->SetStreamSource( 0, g_pVB, sizeof(CUSTOMVERTEX) );
    g_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
    g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50-2 );
    g_pd3dDevice->EndScene();
    g_pd3dDevice-&gtresent( NULL, NULL, NULL, NULL );
}
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:        // 退出消息
            PostQuitMessage( 0 );
            return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      "D3D Tutorial", NULL };
    RegisterClassEx( &wc );
    hWnd = CreateWindow( "D3D Tutorial", "GDI映射纹理",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              GetDesktopWindow(), NULL, wc.hInstance, NULL );
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
                if( SUCCEEDED( InitGeometry() ) )
                {
                        ShowWindow( hWnd, SW_SHOWDEFAULT );
                        UpdateWindow( hWnd );
            MSG msg;
            ZeroMemory( &msg, sizeof(msg) );
            while( msg.message!=WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();
            }
                }
    }
    Cleanup();
    UnregisterClass( "D3D Tutorial", wc.hInstance );
    return 0;
}

13

主题

60

帖子

60

积分

注册会员

Rank: 2

积分
60
发表于 2006-7-27 00:28:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

D3DXCreateTextureFromFileInMemory
注意这个函数

13

主题

978

帖子

978

积分

高级会员

Rank: 4

积分
978
发表于 2006-7-27 10:18:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

答案是:可以
这就是著名的Procedure Texture

106

主题

743

帖子

745

积分

高级会员

Rank: 4

积分
745
QQ
 楼主| 发表于 2006-7-27 22:02:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

6楼的程序可以通过编译,但是不能运行,我用的是VC++6.0中文版编译的,不知道有没有问题。

7楼说的D3DXCreateTextureFromFileInMemory这个函数是怎么用的?

我用了6楼的想法,先加载一幅图片,然后在里面绘图,结果显示的图形里面并没有纹理图。
问题:是否用了dcl_texcoord0 v2     mov oT0.xy,v2这两条指令后,纹理图就能显示出来了?
还有没有后续工作要做才能显示出来?

121

主题

2029

帖子

2034

积分

金牌会员

Rank: 6Rank: 6

积分
2034
QQ
发表于 2006-7-28 09:20:00 | 显示全部楼层

Re:请问:纹理是否必须从图形文件载入?能不能在程序中

gdi是一个疯狂的想法。。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-25 01:22

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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