游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2990|回复: 5

DirectXGraphics访问贴图内存

[复制链接]

42

主题

140

帖子

203

积分

中级会员

Rank: 3Rank: 3

积分
203
发表于 2003-10-18 19:05:00 | 显示全部楼层 |阅读模式
DirectXGraphics访问贴图内存

Jack Hoxley译:zh1110


1.介绍
2. 贴图到贴图的拷贝
3. 快速访问贴图内存
4. 快速访问背景缓冲及前缓冲
5.内存中的操作

1. 介绍

也许你想将一些小的贴图组合成一张大的贴图,也许你想通过数学方法创建贴图(如羽化),也许你想将一张世界地图通过一定接口到贴图上。。。这些方法是我们将介绍的.

2. 贴图到贴图的拷贝

很典型的应用是一些小图形的平铺(草坪,石头,水)。

Direct3D 只允许在surfaces (Direct3DSurface8)间拷贝 , not textures (Direct3DTexture8) - 所以首先要转化成一个surface. 本质上我们并不是转化或拷贝他们到 surfaces, 我们是造了一个输入点, 相当于C/C++ 中的指针(如果你了解它)surface的改变会反映到textures 上,这样我们渲染就有了修改的目标. 下面是全部代码:

'## 声明DECLARATIONS ##
'//Our renderable textures 我们渲染的贴图
Dim TexSource As Direct3DTexture8
Dim TexDest As Direct3DTexture8
Dim TexComb As Direct3DTexture8
'//The surfaces that will point to them.它们的指针
Dim SurfSource As Direct3DSurface8
Dim SurfDest As Direct3DSurface8
Dim SurfComb As Direct3DSurface8
'## 初始INITIALISATION ##
'//Create Our TEXTURE objects创建我们的TEXTURE对象
Set TexSource = D3DX.CreateTextureFromFileEx(D3DDevice, App.Path & "\texsource.bmp", _
                                                                        128, 128, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, _
                                                                        D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, _
                                                                        ByVal 0)
Set TexDest = D3DX.CreateTextureFromFileEx(D3DDevice, App.Path & "\texdest.bmp", _
                                                                        128, 128, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, _
                                                                        D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, _
                                                                        ByVal 0)
Set TexComb = D3DX.CreateTexture(D3DDevice, 128, 128, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED)
'## 渲染循环RENDER LOOP ##
'//渲染时创建一个texture指针
    Set SurfSource = TexSource.GetSurfaceLevel(0)
    Set SurfDest = TexDest.GetSurfaceLevel(0)
    Set SurfComb = TexComb.GetSurfaceLevel(0)
'我们拷贝1/2的SurfSource面及1/2的 SurfDest面到SurfComb
    rctSource.Top = 0: rctSource.Left = 0: rctSource.Right = 64: rctSource.bottom = 128
    ptDest.X = 0: ptDest.Y = 0
    D3DDevice.CopyRects SurfSource, rctSource, 1, SurfComb, ptDest
   
    rctSource.Top = 0: rctSource.Left = 64: rctSource.Right = 128: rctSource.bottom = 128
    ptDest.X = 64: ptDest.Y = 0
    D3DDevice.CopyRects SurfDest, rctSource, 1, SurfComb, ptDest






我使用CreateTextureFromFileEx( ) - 这样可以指定特别的贴图类型。我们还可指定 D3D的Mip Mapping ,我们用主贴图所以我们输入0。

最后用 CopyRects( ) 函数.特别要说明的是rectangles区域不能超过贴图边缘,否则 D3D会拒绝,它也不同于coordinates的尺寸 0.0 to 1.0 scale...


--------------------------------------------------------------------------------

3. 快速访问贴图内存

它可以产生一些特殊效果(Alpha Blending, Colour Blending, Particle Effects, Lighting etc...),一些复杂程序也用到,此外你还可以自定义你的图片格式...

Dim pData As D3DLOCKED_RECT, pxArr() As Byte
    TexDMA.LockRect 0, pData, ByVal 0, 0
        '我们现在可以访问 stuff 利用 pData
        ReDim pxArr(pData.Pitch * 128) As Byte '所有 bytes类型就足够了,其他如integers or longs浪费
        DXCopyMemory pxArr(0), pData.pBits, pData.Pitch * 128 '  surface高度为128
         DXCopyMemory ByVal pData.pBits, pxArr(0), pData.Pitch * 128 'pxArr() 包含了 texture's 每一点的数据
    TexDMA.UnlockRect 0






vb本身不支持指针所以我们用 DXCopyMemory( ) (它包含了API 函数CopyMemory )....

4. 快速访问背景缓冲及前景缓冲

这其实是前面所讲的延伸.

Dim FrontBuffer As Direct3DSurface8
Dim BackBuffer As Direct3DSurface8

D3DDevice.GetFrontBuffer FrontBuffer
Set BackBuffer = D3DDevice.GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO)

'you can now lock as per normal:
FrontBuffer.LockRect pData, rct, 0
BackBuffer.LockRect pData, rct, 0
'etc...







--------------------------------------------------------------------------------

5.内存中的操作

什么是象数格式? 8 bit, 16 bit, 24 bit and 32 bit 是基本的格式, 它告诉你每点存储多少 bits 内存。如标志"D3DFMT_X8R8G8B8" and "D3DFMT_R5G6B5" (在 CreateTextureFromFileEx( ) 函数中)。8 bits = 1 byte.

TexDMA2.LockRect 0, pData, ByVal 0, 0
    '我们现在可以访问 stuff用 pData
    ReDim pxArr(pData.Pitch * 128) As Byte
    If Not (DXCopyMemory(pxArr(0), ByVal pData.pBits, pData.Pitch * 128) = D3D_OK) Then
        '发生错误时的语句
    End If
        ' XRGB 格式...
    For x = 0 To (pData.Pitch * 128) - 1 Step 4
        'unused = pxArr(x + 3)
        bRed = pxArr(x + 2)
        bGreen = pxArr(x + 1)
        bBlue = pxArr(x + 0)
            bRed = 0
            bGreen = 0
            bBlue = 255
        pxArr(x + 2) = bRed
        pxArr(x + 1) = bGreen
        pxArr(x + 0) = bBlue
    Next x
    If Not (DXCopyMemory(ByVal pData.pBits, pxArr(0), pData.Pitch * 128) = D3D_OK) Then
        '拷贝发生错误时的语句
    End If
TexDMA2.UnlockRect 0






original array 存储数据,排序为BGRXBGRXBGRXBGRXBGRX 所以我们在主循环用 "Step 4" ,我们同时要正确使用X/Ycoordinates .

 

16位格式的排序:[RRRRRGGG] [GGGBBBBB] (where [] signifies a byte)

16位下提取颜色的过程如下:

1. Take the two bytes, combine them into one straight 16 bit line
2. Mask out the green and blue channels, shift right 11 bits = Red
3. Mask out the red and blue channels, shift right 5 bits = Green
4. Mask out the red and green channels = Blue
- Manipulate colours here -
5. Shift the Red left by 11 bits, shift the green across by 5 bits
6. Combine the Red, Green and Blue values into a 16 bit long
7. Mask out the lowest 8 bits, shift right 8 bits = second byte
8. Mask out the highest 8 bits = first byte.


Step 1: 组合


bFirst = pxArr(x)
bSecond = pxArr(x + 1)
lRes = (bSecond * 2 ^ 8) Or bFirst






OR 操作真值表:

A  B  A Or B  
0  0  0  
1  0  1  
0  1  1  
1  1  1  

1111111100000000 = bSecond shifted left 8 bits
0000000011111111 = bFirst
---------------------
1111111111111111 = lRes

Step 2: 提取红色部分
And操作真值表

A  B  A And B  
0  0  0  
1  0  0  
0  1  0  
1  1  1  

1011011101100111 = 16 bit chain
1111100000000000 = Red mask, 63488
---------------------
1011000000000000 = output, red shifted left by 11 bits
0000000000010110 = Red correctly shifted right by 11 bits.

bRed = (lRes And 63488) / 2 ^ 11
bRed = (255 / 31) * bRed 'to convert to the familiar 0-255 range.





Step 3: 提取绿色部分

bGreen = (lRes And 2016) / 2 ^ 5
bGreen = (255 / 63) * bGreen 'to convert it to 0-255 range






Again, we convert it to the 0-255 range.

Step 4: 提取蓝色部分

bBlue = lRes And 31
bBlue = (255 / 31) * bBlue 'convert it to 0-255 range





Step 5 & 6: 再次处理

'//Convert RED
    bRed = Int((31 / 255) * bRed) 'convert it back to the 0-31 scale
    lRed = bRed * 2 ^ 11
   
'//Convert GREEN
    bGreen = Int((63 / 255) * bGreen) 'convert it back to the 0-63 scale
    lGreen = bGreen * 2 ^ 5
   
'//Convert BLUE
    bBlue = Int((31 / 255) * bBlue) 'convert back to the 0-31 scale
    lBlue = bBlue
   
'//Assemble Complete Long
    lRes = lRed Or lGreen Or lBlue





 

'bSecond is the highest 8 bits
bSecond = (lRes And 65280) / 2 ^ 8
'bfirst is the lowest 8 bits
bFirst = lRes And 255
pxArr(x) = bFirst
pxArr(x + 1) = bSecond







sf_2003101819516.rar

91.14 KB, 下载次数:

42

主题

140

帖子

203

积分

中级会员

Rank: 3Rank: 3

积分
203
 楼主| 发表于 2003-10-18 19:05:00 | 显示全部楼层

Re: DirectXGraphics访问贴图内存

这是本人据此技术做的模糊特效

sf_2003101819547.rar

45.17 KB, 下载次数:

45

主题

222

帖子

229

积分

中级会员

Rank: 3Rank: 3

积分
229
发表于 2003-11-10 17:53:00 | 显示全部楼层

Re:DirectXGraphics访问贴图内存

你那例子为什么这么慢.3fps

42

主题

140

帖子

203

积分

中级会员

Rank: 3Rank: 3

积分
203
 楼主| 发表于 2003-11-11 09:16:00 | 显示全部楼层

Re:DirectXGraphics访问贴图内存

vb是慢的,可以用最快ps,vs

6

主题

103

帖子

103

积分

注册会员

Rank: 2

积分
103
发表于 2006-9-10 23:48:00 | 显示全部楼层

Re:DirectXGraphics访问贴图内存


什么都下不了

0

主题

62

帖子

62

积分

注册会员

Rank: 2

积分
62
发表于 2007-4-4 19:44:00 | 显示全部楼层

Re:DirectXGraphics访问贴图内存

很有用的东西,支持
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-4-12 15:56

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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