Как я могу скопировать части изображения из буфера в текстуру для рендеринга?

Я искал простое решение, но ничего не нашел. В настоящее время я загружаю текстуру из файла и визуализирую ее в буфер, используя С++ 2012 Express DirectX9. Но я хочу иметь возможность копировать части буфера и использовать скопированную часть в качестве текстуры вместо загруженной текстуры.

Я хочу иметь возможность копировать/выбирать, как это делал бы редактор карт.

РЕДАКТИРОВАТЬ: Проблема решает :) Это были просто глупые ошибки.


person Community    schedule 28.12.2012    source источник
comment
Я думаю, вам следует изучить рендеринг в текстуру, а затем использовать часть этой текстуры для использования при более позднем рендеринге - если я правильно понимаю, чего вы хотите достичь   -  person marcinj    schedule 29.12.2012
comment
@marcin_j Хм, не могли бы вы пояснить? Я обновил свой код, чтобы показать, что я пытаюсь сделать.   -  person User    schedule 29.12.2012
comment
Можете ли вы описать, как вы визуализируете изображение? Вы визуализируете каждый тайл как четырехугольник с примененной текстурой? Используете ли вы фиксированный конвейер или пользовательские шейдеры?   -  person miloszmaki    schedule 29.12.2012
comment
@miloszmaki Я обновил свой код. Что я делаю, так это создаю вектор области в ячейках 32x32 для каждого окна, а затем оттуда я могу вычислить, в какой ячейке находится мышь, чтобы рисовать. Я также хочу использовать это, чтобы выбрать ячейку 32x32 из окна поддона...   -  person User    schedule 29.12.2012


Ответы (1)


Вы можете использовать функцию StretchRect (см. документацию).

Вы должны скопировать подмножество исходного буфера во весь целевой буфер (который в вашем случае является буфером новой текстуры). Что-то вроде этого:

LPDIRECT3DTEXTURE9 pTexSrc,     // source texture
                   pTexDst;     // new texture (a subset of the source texture)

// create the textures
// ...

LPDIRECT3DSURFACE9 pSrc, pDst;

pTexSrc->GetSurfaceLevel(0, &pSrc);
pTexDst->GetSurfaceLevel(0, &pDst);

RECT rect;   // (x0, y0, x1, y1) - coordinates of the subset to copy
rect.left = x0;
rect.right = x1;
rect.top = y0;
rect.bottom = y1;

pd3dDevice->StretchRect(pSrc, &rect, pDst, NULL, D3DTEXF_NONE);
// the last parameter could be also D3DTEXF_POINT or D3DTEXF_LINEAR

pSrc->Release();
pDst->Release(); // remember to release the surfaces when done !!!

РЕДАКТИРОВАТЬ:

Хорошо, я только что просмотрел тона вашего кода и думаю, что лучшим решением было бы использовать координаты uv вместо копирования подмножеств текстуры палитры. Вы должны вычислить соответствующие uv-координаты для данного тайла в game_class:: game_gui_add_current_graphic и использовать их в структуре CUSTOMVERTEX:

float width; // the width of the palette texture
float height; // the height of the palette texture
float tex_x, tex_y; // the coordinates of the upper left corner
                    // of the palette texture's subset to use for
                    // the current tile texturing
float tex_w, tex_h; // the width and height of the above mentioned subset

float u0, u1, v0, v1;
u0 = tex_x / width;
v0 = tex_y / height;
u1 = u0 + tex_w / width;
v1 = v0 + tex_h / height;

// create the vertices using the CUSTOMVERTEX struct
CUSTOMVERTEX vertices[] = {
{ 0.0f, 32.0f, 1.0f, u0, v1, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 0.0f, 1.0f, u0, v0, D3DCOLOR_XRGB(255, 0, 0), },
{ 32.0f, 32.0f, 1.0f, u1, v1, D3DCOLOR_XRGB(0, 0, 255), },    
{ 32.0f, 0.0f, 1.0f, u1, v0, D3DCOLOR_XRGB(0, 255, 0), } };

Пример: Ваша палитра состоит из 3 строк и 4 столбцов с 12 возможными текстурами ячеек. Каждая текстура имеет размер 32 x 32. Итак, tex_w = tex_h = 32;, width = 4 * tex_w; и height = 3 * tex_h;. Предположим, вы хотите вычислить координаты uv для плитки, которая должна быть текстурирована с изображением во второй строке и третьем столбце палитры. Затем tex_x = (3-1)*tex_w; и tex_y = (2-1)*tex_h;. Наконец, вы вычисляете UV, как в приведенном выше коде (в этом примере вы получите {u0,v0,u1,v1} = {(3-1)/4, (2-1)/3, 3/4, 2/3} = {0,5, 0,33, 0,75, 0,66}).

person miloszmaki    schedule 28.12.2012
comment
Кажется, происходит сбой при вызове GetSurfaceLevel - person User; 29.12.2012
comment
Сначала нужно создать текстуры. Используйте D3DXCreateTextureFromFile для вашей первой текстуры и D3DXCreateTexture для целевой текстуры. - person miloszmaki; 29.12.2012
comment
Да, я понял это только сейчас. Однако как я могу скопировать текстуру в другую текстуру? - person User; 29.12.2012
comment
StretchRect как раз это и делает. Он копирует подмножество исходной текстуры в конечную текстуру. Вам просто нужно указать координаты подмножества в rect. - person miloszmaki; 29.12.2012
comment
Да, но мне нужно скопировать его в новую текстуру, чтобы я мог сохранить его в векторе, чтобы затем я мог пройти через вектор, чтобы отобразить каждое местоположение x, y. - person User; 29.12.2012
comment
Кажется, что текстура просто черная. - person User; 29.12.2012
comment
Вам нужно указать D3DUSAGE_RENDERTARGET при создании целевой текстуры. StretchRect не поддерживает копирование текстуры в текстуру, если целевая текстура не является целевой текстурой рендеринга. Кроме того, если вам не нужны мип-карты, передайте 1 вместо 0 в качестве третьего параметра функции CreateTexture. - person miloszmaki; 29.12.2012
comment
Хорошо, я немного понимаю. Я обновил свой пост именно тем, что я делаю. Спасибо за помощь! - person User; 29.12.2012
comment
Не забудьте освободить поверхности, как только растяжение будет сделано! Кстати, нельзя ли просто использовать UV-координаты для доступа к нужной текстуре из палитры (текстурный атлас) вместо того, чтобы делать множество избыточных копий подмножеств текстуры? - person miloszmaki; 29.12.2012
comment
Все еще не работает, он все еще черный! Любые другие мысли? Редактировать: я не знаю, как это сделать, но если бы это было проще, то конечно... - person User; 29.12.2012
comment
Я думаю, вы должны текстурировать каждый тайл со всей текстурой палитры и просто устанавливать соответствующие координаты uv, чтобы тайл был текстурирован подмножеством текстуры. Я отредактировал ответ, проверьте его. - person miloszmaki; 30.12.2012
comment
Аааа, я вижу, что ты говоришь. Хм, а почему другой способ не работает? - person User; 30.12.2012
comment
Не знаю, тоже должно работать. Возможно у вас какие-то баги с копированием и рендерингом текстур. - person miloszmaki; 30.12.2012
comment
как бы я визуализировал с вышеуказанным редактированием? Я видимо просто не до конца понимаю :( - person User; 30.12.2012
comment
Вы должны визуализировать каждую плитку как четыре вершины CUSTOMVERTEX точно так же, как вы делали это в своем коде, но с соответствующими координатами uv. Вам нужно применить только одну текстуру для каждой плитки, которая представляет собой текстуру всей палитры. Координаты uv заставят плитки текстурироваться с правильным подмножеством палитры. Не забудьте указать D3DFVF_TEX1 в вашем D3DFVF_CUSTOMVERTEX. - person miloszmaki; 30.12.2012
comment
Хм, на самом деле это не работает, рука показывается как целое изображение (не 32x32). Сейчас я загружаю большое изображение в палитру. - person User; 30.12.2012
comment
У меня работает miloszmaki, но он работает только с верхней ячейкой 32x32 :/ - person User; 31.12.2012
comment
Я понял это, но теперь кажется, что я теряю детали текстуры Оо. Спасибо, хотя вы помогли достаточно! - person User; 31.12.2012