Применение текстур к индексированным примитивам. С++ DX9

У меня есть базовая программа, которая рисует куб из 48 тетраэдров. Точнее, он использует 27 вершин и индексный буфер для рисования этих тетраэдров. Я хотел бы применить текстуру ко всем тетраэдрам, но все учебники, которые я нашел о текстурах, не отображают с использованием индексов, и каждая вершина в моей программе используется в 16 других тетраэдрах, поэтому я даже не могу понять, как ориентироваться текстуры. Сама программа слишком длинная и слишком запутанная, чтобы я мог ее опубликовать, но если бы кто-нибудь мог сказать мне, можно ли помещать текстуры в индексированные примитивы или нет, а также дать мне ссылку на учебник, я был бы признателен.

РЕДАКТИРОВАТЬ: Код ici:

void setVertices(FLOAT cubeYOffset, FLOAT cubeXOffset, FLOAT cubeZOffset, int tetraRender[]){
CUSTOMVERTEX vertices[] = { 
    { cubeXOffset+1.0f, cubeYOffset+0.0f, cubeZOffset-1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, },//Center top = 0
    { cubeXOffset+0.0f, cubeYOffset+0.0f, cubeZOffset-1.0f, -0.5f, 0.5f, 0.0f, -1.0f, 1.0f, },
    { cubeXOffset+0.0f, cubeYOffset+0.0f, cubeZOffset+0.0f, -0.5f, 0.5f, 0.5f, -1.0f, 1.0f, },
    { cubeXOffset+1.0f, cubeYOffset+0.0f, cubeZOffset+0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f, },
    { cubeXOffset+2.0f, cubeYOffset+0.0f, cubeZOffset+0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, },
    { cubeXOffset+2.0f, cubeYOffset+0.0f, cubeZOffset-1.0f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, },
    { cubeXOffset+2.0f, cubeYOffset+0.0f, cubeZOffset-2.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, },
    { cubeXOffset+1.0f, cubeYOffset+0.0f, cubeZOffset-2.0f, 0.0f, 0.5f, -0.5f, 0.0f, 1.0f, },
    { cubeXOffset+0.0f, cubeYOffset+0.0f, cubeZOffset-2.0f, -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, },

    { cubeXOffset+1.0f, cubeYOffset-1.0f, cubeZOffset-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, },//Center middle = 9
    { cubeXOffset+0.0f, cubeYOffset-1.0f, cubeZOffset-1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, },
    { cubeXOffset+0.0f, cubeYOffset-1.0f, cubeZOffset+0.0f, -0.5f, 0.0f, 0.5f, -1.0f, 0.0f, },
    { cubeXOffset+1.0f, cubeYOffset-1.0f, cubeZOffset+0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, },
    { cubeXOffset+2.0f, cubeYOffset-1.0f, cubeZOffset+0.0f, 0.5f, 0.0f, 0.5f, 1.0f, 0.0f, },
    { cubeXOffset+2.0f, cubeYOffset-1.0f, cubeZOffset-1.0f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, },
    { cubeXOffset+2.0f, cubeYOffset-1.0f, cubeZOffset-2.0f, 0.5f, 0.0f, -0.5f, 1.0f, 0.0f, },
    { cubeXOffset+1.0f, cubeYOffset-1.0f, cubeZOffset-2.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, },
    { cubeXOffset+0.0f, cubeYOffset-1.0f, cubeZOffset-2.0f, -0.5f, 0.0f, -0.5f, -1.0f, 0.0f, },

    { cubeXOffset+1.0f, cubeYOffset-2.0f, cubeZOffset-1.0f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, },//Center bottom = 18
    { cubeXOffset+0.0f, cubeYOffset-2.0f, cubeZOffset-1.0f, -0.5f, -0.5f, 0.0f, -1.0f, -1.0f, },
    { cubeXOffset+0.0f, cubeYOffset-2.0f, cubeZOffset+0.0f, -0.5f, -0.5f, 0.5f, -1.0f, -1.0f, },
    { cubeXOffset+1.0f, cubeYOffset-2.0f, cubeZOffset+0.0f, 0.0f, -0.5f, 0.5f, 0.0f, -1.0f, },
    { cubeXOffset+2.0f, cubeYOffset-2.0f, cubeZOffset+0.0f, 0.5f, -0.5f, 0.5f, 1.0f, -1.0f, },
    { cubeXOffset+2.0f, cubeYOffset-2.0f, cubeZOffset-1.0f, 0.5f, -0.5f, 0.0f, 1.0f, -1.0f, },
    { cubeXOffset+2.0f, cubeYOffset-2.0f, cubeZOffset-2.0f, 0.5f, -0.5f, -0.5f, 1.0f, -1.0f, },
    { cubeXOffset+1.0f, cubeYOffset-2.0f, cubeZOffset-2.0f, 0.0f, -0.5f, -0.5f, 0.0f, -1.0f, },
    { cubeXOffset+0.0f, cubeYOffset-2.0f, cubeZOffset-2.0f, -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, },//26(actually 27th)
};
d3ddev->CreateVertexBuffer(27*sizeof(CUSTOMVERTEX),
                           0,
                           CUSTOMFVF,
                           D3DPOOL_MANAGED,
                           &v_buffer,
                           NULL);

VOID* pVoid;
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();

short tetra[48][12] = {
    //tetra 1
    0, 1, 2,
    0, 1, 11,
    0, 2, 11,
    1, 2, 11,

    //tetro 2
    0, 2, 3,
    0, 2, 11,
    0 , 3, 11,
    2, 3, 11,

    //tetro 3
    0, 3, 4,
    0, 3, 13,
    0, 4, 13,
    3, 4, 13,

    //tetro 4
    0, 4, 5,
    0, 4, 13,
    0, 5, 13,
    4, 5, 13,

    //tetro 5
    0, 5, 6,
    0, 5, 15,
    0, 6, 15,
    5, 6, 15,

    //tetro 6
    0, 6, 7,
    0, 6, 15,
    0, 7, 15,
    6, 7, 15,

    //tetro 7
    0, 7, 8,
    0, 7, 17,
    0, 8, 17,
    7, 8, 17,

    //tetro 8
    0, 8, 1,
    0, 8, 17,
    0, 1, 17,
    8, 1, 17,

    //tetro 9
    0, 1, 11,
    0, 1, 10,
    0, 10, 11,
    1, 10, 11,

    //tetro 10
    0, 3, 11,
    0, 3, 12,
    0, 11, 12,
    3, 11, 12,

    //tetro 11
    0, 3, 13,
    0, 3, 12,
    0, 12, 13,
    3, 12, 13,

    //tetro 12
    0, 5, 13,
    0, 5, 14,
    0, 13, 14,
    5, 13, 14,

    //tetro 13
    0, 5, 15,
    0, 5, 14,
    0, 14, 15,
    5, 14, 15,

    //tetro 14
    0, 7, 15,
    0, 7, 16,
    0, 15, 16,
    7, 15, 16,

    //tetro 15
    0, 7, 17,
    0, 7, 16,
    0, 16, 17,
    7, 16, 17,

    //tetro 16
    0, 1, 17,
    0, 1, 10,
    0, 17, 10,
    1, 17, 10,

    //tetro 17
    0, 10, 11,
    0, 9, 10,
    0, 9, 11,
    9, 10, 11,

    //tetro 18
    0, 11, 12,
    0, 9, 11,
    0, 9, 12,
    9, 11, 12,

    //tetro 19
    0, 12, 13,
    0, 9, 12,
    0, 9, 13,
    9, 12, 13,

    //tetro 20
    0, 13, 14,
    0, 9, 13,
    0, 9, 14,
    9, 13, 14,

    //tetro 21
    0, 14, 15,
    0, 9, 14,
    0, 9, 15,
    9, 14, 15,

    //tetro 22
    0, 15, 16,
    0, 9, 15,
    0, 9, 16,
    9, 15, 16,

    //tetro 23
    0, 16, 17,
    0, 9, 16,
    0, 9, 17,
    9, 16, 17,

    //tetro 24
    0, 17, 10,
    0, 9, 17,
    0, 9, 10,
    9, 17, 10,

    //tetro 17
    9, 10, 11,
    9, 18, 10,
    9, 18, 11,
    18, 10, 11,

    //tetro 18
    9, 11, 12,
    9, 18, 11,
    9, 18, 12,
    18, 11, 12,

    //tetro 19
    9, 12, 13,
    9, 18, 12,
    9, 18, 13,
    18, 12, 13,

    //tetro 20
    9, 13, 14,
    9, 18, 13,
    9, 18, 14,
    18, 13, 14,

    //tetro 21
    9, 14, 15,
    9, 18, 14,
    9, 18, 15,
    18, 14, 15,

    //tetro 22
    9, 15, 16,
    9, 18, 15,
    9, 18, 16,
    18, 15, 16,

    //tetro 23
    9, 16, 17,
    9, 18, 16,
    9, 18, 17,
    18, 16, 17,

    //tetro 24
    9, 17, 10,
    9, 18, 17,
    9, 18, 10,
    18, 17, 10,

    //tetro 9
    18, 19, 11,
    18, 19, 10,
    18, 10, 11,
    19, 10, 11,

    //tetro 10
    18, 21, 11,
    18, 21, 12,
    18, 11, 12,
    21, 11, 12,

    //tetro 11
    18, 21, 13,
    18, 21, 12,
    18, 12, 13,
    21, 12, 13,

    //tetro 12
    18, 23, 13,
    18, 23, 14,
    18, 13, 14,
    23, 13, 14,

    //tetro 13
    18, 23, 15,
    18, 23, 14,
    18, 14, 15,
    23, 14, 15,

    //tetro 14
    18, 25, 15,
    18, 25, 16,
    18, 15, 16,
    25, 15, 16,

    //tetro 15
    18, 25, 17,
    18, 25, 16,
    18, 16, 17,
    25, 16, 17,

    //tetro 16
    18, 19, 17,
    18, 19, 10,
    18, 17, 10,
    19, 17, 10,

    //tetro 19
    18, 19, 20,
    18, 19, 11,
    18, 20, 11,
    19, 20, 11,

    //tetro 20
    18, 20, 21,
    18, 20, 11,
    18 , 21, 11,
    20, 21, 11,

    //tetro 21
    18, 21, 22,
    18, 21, 13,
    18, 22, 13,
    21, 22, 13,

    //tetro 22
    18, 22, 23,
    18, 22, 13,
    18, 23, 13,
    22, 23, 13,

    //tetro 23
    18, 23, 24,
    18, 23, 15,
    18, 24, 15,
    23, 24, 15,

    //tetro 24
    18, 24, 25,
    18, 24, 15,
    18, 25, 15,
    24, 25, 15,

    //tetro 25
    18, 25, 26,
    18, 25, 17,
    18, 26, 17,
    25, 26, 17,

    //tetro 26
    18, 26, 19,
    18, 26, 17,
    18, 19, 17,
    26, 19, 17,
};
short indices [576];
int i = 0;
int i2 = 0;
ind = 0;
int ic;
for(i; i < 48; i++){
    if (tetraRender[i] == 1){
        for(i2; i2 < 12; i2++){     
            if((ind == 0)&&(i2 == 0)){ 
                ic = 0;
            }else{
                ic = ind*12+i2;
            }
            indices[ic] = tetra[i][i2]; 
        }
        i2 = 0;
        ind++;
    }
}

if (ind > 0) {
d3ddev->CreateIndexBuffer(12*ind*sizeof(short),
                            0,
                            D3DFMT_INDEX16,
                            D3DPOOL_MANAGED,
                            &i_buffer,
                            NULL);
i_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, indices, 12*ind*2);
i_buffer->Unlock();
}
    }

Итак, это объявление вершин и индексов просто для того, чтобы дать вам представление. Это очень беспорядочно, так что извините, и если вы не видите, что он делает, так это объявляет спиралевидный набор вершин, за которым следует объявление всех индексов тетраэдров. затем он использует массив int в функции from для рисования только указанных тетраэдров.

И да, я использую 3D-освещение, хотя и не знаю, почему.


person HonestHeuristic    schedule 01.05.2011    source источник


Ответы (2)


Вы не должны больше использовать систему FVF. Используйте систему IDirect3DVertexDeclaration9, которая на самом деле гораздо более гибкая. Проблема с FVF заключается в том, что когда вы устанавливаете флаги вместе, порядок не может быть указан, тогда как система VERTEXELEMENT9[] способна указывать порядок элементов, а также то, какие из них содержатся внутри.

Простой ответ о том, как генерировать координаты текстуры, довольно прост: когда вы рассматриваете вершину, ее положение в 3D-пространстве и, таким образом, в конечном итоге ее координаты текстуры фиксированы, независимо от того, частью какого треугольника она на самом деле является. . Таким образом, если вы не собираетесь эмулировать какие-то очень острые края, в этом случае вам следует дублировать вершины, вполне приемлемо иметь одну текс-координат для каждой вершины без дополнительных усилий.

Что касается рендеринга системы без сбоев, то пришло время использовать шейдер, в основном потому, что fixed-function мертв, и почти весь современный рендеринг использует шейдеры, и вы должны были изучить этот материал давным-давно, чтобы знать, как его использовать. К счастью, базовое текстурирование является базовым и не требует ничего особенно сложного.

D3DVERTEXELEMENT9 vertexDecl[] = {
    { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
    { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
    { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
    D3DDECL_END()
};
struct CustomVertex {
    float position[3];
    float normal[3];
    float texcoords[2];
};

IDirect3DVertexDeclaration9* vertexdecl;
d3ddev->CreateVertexDeclaration(vertexDecl, &vertexdecl);

А что касается шейдера, то тут подойдет что-то довольно простое.

// Stuff we send to the shader from C++
// This is not per-vertex. Anything we loaded into the 
// vertex data itself is input to the vertex shader.
// Direct3D 9.0c also supports hardware instancing, but I'll
// leave you to work that one out yourself.

// World * View * Projection matrix gives the result in Homogenous Clip 
// Co-ordinates, which is what Direct3D wants from us as output
uniform extern float4x4 WVPMatrix;
// WorldInverseTranspose transforms the normal into world space
// successfully, even with non-linear transformations as the World
uniform extern float4x4 WorldInverseTransposeMatrix;
// This is just a 2D texture that we can change at any time
uniform extern texture MyTexture;
// The sampler state determines how the texture is filtered.
sampler TexS = sampler_state
{
    Texture = <MyTexture>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};
// What we output from the vertex shader. This is basically the position
// of the vertex in HCC (the first two), and anything we want to pass into
// the pixel shader (the second two).
struct VS_OUTPUT {
    float4 position : POSITION0;
    float3 normal : NORMAL0;
    float2 texcoords : TEXCOORD0;
};
// What we're putting in to the vertex shader. This is basically
// our vertex structure from C++.
struct VS_INPUT {
    float3 position : POSITION0;
    float3 normal : NORMAL0;
    float2 texcoords : TEXCOORD0;
};
VS_OUTPUT VertexShader(VS_INPUT in) {
    VS_OUTPUT out = (VS_OUTPUT)0;
    // just pass texcoords on, we're not interested
    out.texcoords = in.texcoords;
    // get the resulting vertex position that we need
    out.position = mul(float4(in.position, 1.0f), WVPMatrix);
    // transform the normal into world space
    out.normal = mul(float4(in.normal, 0.0f), WorldInverseTransposeMatrix).xyz;
}
float4 PixelShader(float3 normal : NORMAL0, float2 texcoords : TEXCOORD0) {
    return tex2D(TexS, texcoords);
}
technique BasicShader 
{
    pass p0
    {            
        vertexShader = compile vs_3_0 VertexShader();
        pixelShader  = compile ps_3_0 PixelShader();
    }
}

Я не делал здесь никаких расчетов освещения, но передал нормаль в пиксельный шейдер.

person Puppy    schedule 01.05.2011
comment
Ладно 3 балла: 1) Я тебя ненавижу! это означает, что я должен переписать и переучить ВСЕ КОГДА-ЛИБО 2) Я ЛЮБЛЮ ТЕБЯ Теперь я могу узнать гораздо больше классных вещей! 3) У вас случайно не было ссылки на учебник по этому материалу, потому что ваш относительно короткий пост слишком продвинут для моих мозгов динозавра. - person HonestHeuristic; 01.05.2011
comment
@strigon33: Все в порядке - шейдеры бывают совершенно разными, и даже с моими довольно щедрыми комментариями нельзя ожидать, что вы сразу поймете суть. Лично я читал книгу (DirectX 9.0c: A Shader Approach Фрэнка Луны). - person Puppy; 01.05.2011
comment
Если я смогу найти его, я найду, но я только что нашел в сети действительно хороший бесплатный учебник, который охватывает DX-текстуры, оттенки аудиовхода, так что я не знаю, я посмотрю на него и посмотрю. Мне вдруг кажется, что я вообще ничего не знаю о DX - person HonestHeuristic; 01.05.2011
comment
@strigon33: Это потому, что вы мало что знаете о DirectX в том виде, в каком он существует сейчас, в отличие от того, как он существовал пять или десять лет назад. - person Puppy; 01.05.2011
comment
Я начал программировать с DX в прошлом году и учился из руководств, которые мог найти, а именно, DirectXTutorials.com, которые были превосходны, но я мог использовать только бесплатные. Я узнал об этом буквально только от вас. - person HonestHeuristic; 01.05.2011
comment
@strigon33: Вероятно, они бесплатны, потому что они старые. Я проверил этот сайт, и все, что я получил, было каким-то сайтом для поиска спама, ничего общего. - person Puppy; 01.05.2011
comment
ВАУ это древние! Мне нужно найти хорошие книги для чтения! - person HonestHeuristic; 02.05.2011

Я ни в коем случае не эксперт DirectX, но исходя из своего опыта, я предполагаю, что он использует подход, очень похожий на OpenGL.

Если вы хотите текстурировать объект, вам нужны текстурные координаты для каждой вершины, в дополнение к атрибуту положения и, возможно, другим (нормаль, касательный вектор, ...). Поскольку вы используете индексный буфер для адресации данных вершин, я предполагаю, что у вас есть последние в буфере вершин. Таким образом, добавляя координаты текстуры к каждой вершине, вы можете наложить текстуру на свои тетраэдры. Обратите внимание, однако, что вы не можете иметь разные координаты текстуры для каждой вершины, если ваш индексный буфер говорит: «Я хочу треугольник с индексами 0, 1 и 2», вы всегда будете получать данные о положении и текстурных координатах с индексами 0, 1. , 2.

Что вы можете сделать, так это изменить координаты текстуры для каждого тетраэдра в целом, сначала применив к ним матрицу преобразования. Это преобразование отличается от преобразования, которое вы применяете к своим атрибутам положения.

person onitake    schedule 01.05.2011
comment
Похоже, все, что вам нужно, уже есть: { cubeXOffset+1.0f, cubeYOffset+0.0f, cubeZOffset-1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, } — первые три атрибута позиции (cubeXOffset, ...), затем нормаль (0.0f, 0.5f, 0.0f) и, наконец, координаты текстуры (0.0f, 1.0f). Чтобы нарисовать текстуру, все, что вам нужно сделать, это активировать атрибуты texcoord, назначить текстуру первому текстурному блоку и включить текстурирование. К сожалению, я не могу помочь вам с этим, так как я не знаком со спецификой DX... Вы пробовали уроки NeHe по текстурированию? - person onitake; 01.05.2011
comment
но когда я это делаю, он падает! У меня есть текстура и структура текстуры (что угодно), а затем я говорю ей использовать эту текстуру в функции рендеринга, и она не - person HonestHeuristic; 01.05.2011