Применение текстур к индексированным примитивам.C ++ DX9 - PullRequest
1 голос
/ 01 мая 2011

У меня есть базовая программа, которая рисует куб из 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-освещение, хотя у меня нет ни малейшего почему.

Ответы [ 2 ]

1 голос
/ 01 мая 2011

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

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

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

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();
    }
}

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

1 голос
/ 01 мая 2011

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

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

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

...