Модератор: Mikle
Option Explicit
Public Type ST3D_ColorRGB
R As Byte
G As Byte
B As Byte
End Type
Private Type ST3D_BitmapHeader
lngSize As Long
intReserved1 As Integer
intReserved2 As Integer
lngOffset As Long
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Public Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Dim StandartBitmapHeader As ST3D_BitmapHeader
Public Sub InitTexCraftModule()
With StandartBitmapHeader
.lngSize = 49152 + 54
.lngOffset = 54
.biBitCount = 24
.biWidth = 128
.biHeight = 128
.biSize = 40
.biPlanes = 1
.biSizeImage = 49152
.biCompression = 0
.biXPelsPerMeter = 50
.biYPelsPerMeter = 50
End With 'StandartBitmapHeader
End Sub
Public Function CreateTextureFromRGBArray(TexArr() As ST3D_ColorRGB) As Direct3DTexture8
Dim BMPheader(Len(StandartBitmapHeader) + 1) As Byte
CopyMemory BMPheader(2), StandartBitmapHeader, Len(StandartBitmapHeader)
BMPheader(0) = 66: BMPheader(1) = 77
Dim lm(49152 + 54) As Byte
CopyMemory lm(0), BMPheader(0), 54
CopyMemory lm(54), TexArr(0, 0), 49152
Set CreateTextureFromRGBArray = D3DX.CreateTextureFromFileInMemoryEx(Device, lm(0), UBound(lm), 128, 128, D3DX_DEFAULT, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, &H0, ByVal 0, ByVal 0)
End Function
Dim lmstr(127, 127) As ST3D_ColorRGB
Dim i As Integer
For i = 0 To 127
lmstr(i, 59).G = 255
Next i
Dim a As Direct3DTexture8
Set a = CreateTextureFromRGBArray(lmstr())
Mikle писал(а):Еще вариант:
Direct3DDevice8.CreateTexture - создаешь пустую текстуру.
Direct3DTexture8.GetSurfaceLevel - берешь нулевой сурфейс.
D3DX8.LoadSurfaceFromMemory - загружаешь данные в сурфейс из массива.
D3DX8.FilterTexture - создаешь мип-уровни с соответствующим фильтром.
Сурфейс в конце уничтожаешь.
Плюсы - не заморачиваешься с заголовками, работаешь прямо в формате текстуры.
Минусы - не загрузишь сжатые данные, типа .jpg, но из памяти оно надо?
Public Function CreateTextureFromFile(d3dDev As IDirect3DDevice9, fName As String) As IDirect3DTexture9
Dim Res As Long
Dim tSI As GdiplusStartupInput
Dim GDIP As Long
Dim Bmp As Long
Dim lData As BitmapData
Dim gdiR As RECTL
Dim x As Long, y As Long
Dim RECT As D3DLOCKED_RECT
tSI.GdiplusVersion = 1
Res = GdiplusStartup(GDIP, tSI)
If Res = 0 Then
Res = GdipCreateBitmapFromFile(StrPtr(fName), Bmp)
If Res = 0 Then
GdipGetImageWidth Bmp, x
GdipGetImageHeight Bmp, y
gdiR.Left = 0
gdiR.Right = x
gdiR.Top = 0
gdiR.Bottom = y
Res = GdipBitmapLockBits(Bmp, gdiR, ImageLockModeRead, PixelFormat32bppARGB, lData)
If Res = 0 Then
d3dDev.CreateTexture x, y, 0, D3DUSAGE_NONE Or D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, CreateTextureFromFile
If Not CreateTextureFromFile Is Nothing Then
CreateTextureFromFile.LockRect 0, RECT, ByVal 0, 0
MemCpy ByVal RECT.pBits, ByVal lData.Scan0, x * y * 4
CreateTextureFromFile.UnlockRect 0
End If
GdipBitmapUnlockBits Bmp, lData
End If
GdipDisposeImage Bmp
End If
GdiplusShutdown GDIP
End If
End Function
Public Function CreateTextureFromArrayRGBA(ArrayRGBA() As Long) As IDirect3DTexture9
Dim RECT As D3DLOCKED_RECT
Dim X As Long, Y As Long
X = UBound(ArrayRGBA, 2) + 1
Y = UBound(ArrayRGBA, 1) + 1
d3dev.CreateTexture X, Y, 0, D3DUSAGE_NONE Or D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, CreateTextureFromArrayRGBA
If Not CreateTextureFromArrayRGBA Is Nothing Then
CreateTextureFromArrayRGBA.LockRect 0, RECT, ByVal 0, 0
memcpy ByVal RECT.pBits, ArrayRGBA(0, 0), X * Y * 4
CreateTextureFromArrayRGBA.UnlockRect 0
End If
End Function
Old_Maple писал(а):Можешь здесь показать рабочий код?
If GdipBitmapLockBits(hImage, tRC, ImageLockModeRead Or ImageLockModeWrite Or ImageLockModeUserInputBuf, PixelFormat32bppARGB, tBmpData) <> 0 Then
cRet.UnlockRect 0
MsgBox "Unable to get image bits", vbCritical
GoTo CleanUp
End If
m_cVtxBuf.Lock 0, Len(m_tCorners(0)) * (UBound(m_tCorners) + 1), pVtxData, 0
memcpy ByVal pVtxData, m_tCorners(0), Len(m_tCorners(0)) * (UBound(m_tCorners) + 1)
m_cVtxBuf.Unlock
Old_Maple писал(а):The trick, спасибо за ссылку.
Как я понял ты имел ввиду вот этот кусок кода:
- Код: Выделить всё
If GdipBitmapLockBits(hImage, tRC, ImageLockModeRead Or ImageLockModeWrite Or ImageLockModeUserInputBuf, PixelFormat32bppARGB, tBmpData) <> 0 Then
cRet.UnlockRect 0
MsgBox "Unable to get image bits", vbCritical
GoTo CleanUp
End If
Но дальше, как я понимаю, уйти от memcpy() невозможно (событие Form_MouseMove())?
- Код: Выделить всё
m_cVtxBuf.Lock 0, Len(m_tCorners(0)) * (UBound(m_tCorners) + 1), pVtxData, 0
memcpy ByVal pVtxData, m_tCorners(0), Len(m_tCorners(0)) * (UBound(m_tCorners) + 1)
m_cVtxBuf.Unlock
Или такая возможность все же существует?
The trick писал(а):Ну так этот memcpy используется не для текстуры, а для вертексного буфера.
Old_Maple писал(а):У меня еще есть вопросы. А есть ли возможность передавать не всю текстуру, а лишь ее измененную часть? Например, небольшой фрагмент, в серединной части или хотя бы один пиксел?
Чтобы это можно было делать в цикле между рендерами.
Old_Maple писал(а):А есть ли возможность передавать не всю текстуру, а лишь ее измененную часть? Например, небольшой фрагмент
The trick писал(а):Ну локай нужный регион и пиши туда данные, но думаю это не очень эффективно постоянно локать. Какая конечная цель?
Mikle писал(а):А рендер в текстуру точно не подойдёт?
Mikle писал(а):Рендер в текстуру никакого отношения к шейдерам не имеет.
Я предлагаю текстуру, которую по ходу работы программы предполагается частично менять, создавать с флагом D3DUSAGE_RENDERTARGET. Это позволит рендерить в эту текстуру любое изображение так же, как ты рендеришь в бэкбуфер.
Old_Maple писал(а):Я и не знал, что такое возможно.
Mikle писал(а):Посмотри в примерах моего старого порта для DX9, там есть это:
https://disk.yandex.ru/d/2L5Yh8Yo39dfnY
Old_Maple писал(а):Ну а цель в конечном итоге достаточно проста, но весьма небыстро реализуема. Полная генерация мешей и текстур на предсказуемом генераторе псевдослучайных чисел. Полная программная генерация и тех и других. Ну а для того, чтобы не формировать текстуры в памяти заново иногда бывает полезным вносить лишь небольшие изменения в ранее сгенерированные текстуры, чтобы они несколько отличались от предшествующих.
The trick писал(а):Ну вообще можно локать в таких случаях, но лучше переписать всю логику на шейдерах как мне кажется. Просто гонять туда-сюда данные из видеопамяти в системную память довольно-таки медленная операция. Если эти манипуляции нужно делать каждый кадр, то лучше сделать так чтобы они все выполнялись в шейдере.
//Запуск процедуры вычисления на ядрах CDU
int d = SizeOfSqr / 2;
float v = 1.0f;
do{
DmSqrCDU <<<blocks, threads>>> (dev_Ns, SizeOfSqr, d, v, dev_RndSeed);
d /= 2;
v *= Spectre;
}while (d);
/*===========================================================================/
/ CORE of Diamond-Square Method (CUDA - implementation) /
/===========================================================================*/
__global__ void DmSqrCDU(float *dev_Ns, const int SizeOfSqr, int d ,const float v, unsigned char *dev_RndSeed){
int x = blockIdx.x * BLOCK_SIZE + threadIdx.x;
int y = blockIdx.y * BLOCK_SIZE + threadIdx.y;
int s = SizeOfSqr - 1;
int dd = d + d;
int xdd = (x + dd) & s;
int ydd = ((y + dd) & s);
if ( !(xdd % dd) && !(ydd % dd)){
int xd = (x + d) & s;
int yd = ((y + d) & s) * SizeOfSqr;
int ys = y * SizeOfSqr;
int ydds = ydd * SizeOfSqr;
dev_Ns[ys + xd] =
(dev_Ns[ys + x] +
dev_Ns[ys + xdd]) * 0.5f +
v * (Rnd2DCU(0, ys, xd, dev_RndSeed) - 0.5f);
dev_Ns[yd + x] =
(dev_Ns[ys + x] +
dev_Ns[ydds + x]) * 0.5f +
v * (Rnd2DCU(1, yd, x, dev_RndSeed) - 0.5f);
dev_Ns[yd + xd] =
(dev_Ns[ys + x] +
dev_Ns[ydds + x] +
dev_Ns[ys + xdd] +
dev_Ns[ydds + xdd]) * 0.25f +
v * (Rnd2DCU(2, yd, xd, dev_RndSeed) - 0.5f);
}
Old_Maple писал(а):вот пример программы генерации карты высот (Diamond-Square), который я написал на NVIDIA CUDA. Работает в разы быстрее! Но, справедливости ради следует заметить, что работает это только на картах NVidia.
Mikle писал(а):Если писать не на CUDA, а на шейдерах, будет работать везде. Но вот не всякий алгоритм хорошо ложится на шейдер. Элементарная нормализация массива к заданному диапазону становится на шейдерах проблемой.
Mikle писал(а):Не очень понятно зачем тебе при такой задаче дописывание каких-то фрагментов в текстуру - просто формируешь картинку до конца, а потом готовую заливаешь в текстуру. Или у тебя предполагаются анимированные текстуры?
Old_Maple писал(а):Видел как-то у тебя, Mikle программу по генерации текстур. Правда описания к ней я так и не нашел.
Old_Maple писал(а):Разумеется, здесь на первый план выходят - изменение вершин сеток (например, волны на поверхности океана), и изменение текстур, либо целиком (движение туч с изменяемыми облаками, либо фрагментарно (грозы и молнии). И это далеко не всё.
Mikle писал(а):Тут небольшое описание начала и сама программа с примерами: https://gamedev.ru/community/toolcorner ... s/TFScript
Mikle писал(а):Перечисленное можно сделать без перезаписи текстур.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10