2013-09-11 7 views
0

У меня есть Pixel ShaderКак передать текстуры в пиксельные шейдеры DirectX 9?

// fxc.exe tiles.fs /T ps_3_0 /Fotiles.fsc /Fctiles.fsl 

struct PSInput 
{ 
    float4 Pos : TEXCOORD0; 
    float3 Normal : TEXCOORD1; 
    float2 TexcoordUV : TEXCOORD2; 
    float2 TexcoordST : TEXCOORD3; 
}; 

sampler2D sampler0; //uniform 
sampler2D sampler1; //uniform 
sampler2D sampler2; //uniform 
sampler2D sampler3; //uniform 
sampler2D alphamap1;//uniform 
sampler2D alphamap2;//uniform 
sampler2D alphamap3;//uniform 
uniform int tex_count = 0; 

uniform float4 color_ambient = float4(0.75, 0.75, 0.75, 1.0); 
uniform float4 color_diffuse = float4(0.25, 0.25, 0.25, 1.0); 
uniform float4 color_specular = float4(1.0, 1.0, 1.0, 1.0); 
uniform float shininess = 77.0f; 
uniform float3 light_position = float3(12.0f, 32.0f, 560.0f); 

float4 main(PSInput In) : COLOR 
{ 
    float3 light_direction = normalize(light_position - (float3)In.Pos); 
    float3 normal = normalize(In.Normal); 
    float3 half_vector = normalize(light_direction + normalize((float3)In.Pos)); 
    float diffuse = max(0.0, dot(normal, light_direction)); 
    float specular = pow(max(0.0, dot(In.Normal, half_vector)), shininess); 
    float4 color = tex2D(sampler0, In.TexcoordUV); 

    if (tex_count > 0){ 
     float4 temp = tex2D(sampler1, In.TexcoordUV); 
     float4 amap = tex2D(alphamap1, In.TexcoordST); 
     color = lerp(color, temp, amap.a); 
    } 
    if (tex_count > 1){ 
     float4 temp = tex2D(sampler2, In.TexcoordUV); 
     float4 amap = tex2D(alphamap2, In.TexcoordST); 
     color = lerp(color, temp, amap.a); 
    } 
    if (tex_count > 2){ 
     float4 temp = tex2D(sampler3, In.TexcoordUV); 
     float4 amap = tex2D(alphamap3, In.TexcoordST); 
     color = lerp(color, temp, amap.a); 
    } 
    color = color * color_ambient + diffuse * color_diffuse + specular * color_specular; 

    return color; 
} 

Vertex Shader

// fxc.exe tiles.vs /T vs_3_0 /Fotiles.vsc /Fctiles.vsl 

struct VSInput 
{ 
    float3 Pos : POSITION; 
    float3 Normal : NORMAL; 
    float2 TexcoordUV : TEXCOORD0; 
    float2 TexcoordST : TEXCOORD1; 
}; 

struct PSInput 
{ 
    float4 Pos : POSITION; 
    float3 Normal : TEXCOORD0; 
    float2 TexcoordUV : TEXCOORD1; 
    float2 TexcoordST : TEXCOORD2; 
}; 

uniform matrix modelMatrix; 
uniform matrix projectionMatrix; 
uniform matrix lookAtMatrix; 

PSInput main(VSInput In) 
{ 
    PSInput Out = (PSInput) 0; 

    //projectionMatrix * lookAtMatrix * modelMatrix; 
    matrix MVP = mul(modelMatrix, lookAtMatrix); 
    MVP = mul(MVP, projectionMatrix); 

    Out.Normal = mul(In.Normal, (float3x3)modelMatrix); 
    Out.Pos = mul(float4(In.Pos, 1.0), MVP);  
    Out.TexcoordUV = In.TexcoordUV; 
    Out.TexcoordST = In.TexcoordST; 

    return Out; 
} 

же работает под OpenGL + GLSL кроме mix заменены lerp (я надеюсь, что его правильно). К примеру из http://www.two-kings.de/tutorials/dxgraphics/dxgraphics18.html я проходя текстуры с:

ps_pConstantTable.SetInt(m_pD3DDevice, texCountHandle, 0); 
for i := 0 to texCount - 1 do begin 
    tBlp := texture_buf[cx, cy][i]; 
    if tBlp = nil then 
     break; 

    m_pD3DDevice.SetTexture(i, tBlp.itex); 
    ps_pConstantTable.SetInt(m_pD3DDevice, texCountHandle, i); 

    if i > 0 then begin 
    // this time, use blending: 
    m_pD3DDevice.SetTexture(i + 3, AlphaMaps[cx, cy][i]); 
    end; 
end; 

так порядковые текстуры имеют индексы 0-3 и альфа-4-6 (макс texCount 4). Проблема: я вижу сетку (рельеф), но она сплошная черная. Мне нужно что-то другое, чтобы установить (без шейдеров он также был черным, пока я не назначил материалы и свет)? Могу ли я передавать такие текстуры? Могу ли я сделать это с sampler2D как uniform (как)?

Редактировать: пример с источниками, шейдерами, несколькими используемыми текстурами и альфа-картами, данными вершин с нормалями в filebeam http://fbe.am/nm4. Как можно меньше. Также содержит DXErr9ab.dll для регистрации ошибок.

+0

Пожалуйста, поставьте SSCCE –

+0

Я попробую, но сейчас это часть довольно большой программы. Должен ли я включать инициализацию DirectX, индекс заполнения (TRIANGLE_STRIP) и буферы вершин и т. Д.? – user2091150

+1

Маленький, насколько это возможно –

ответ

1

Чтобы использовать текстуры в пиксельном шейдер, вы можете следующие ниже шаги

Создания текстуры в вашем C файл/C++ с помощью D3DXCreateTextureFromFile или других функций.

if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, "FaceTexture.jpg", 
    &g_pTexture))) 
return E_FAIL; 

Объявите D3DXHANDLE и связать его с фактурой в файле шейдера. (Вы должны скомпилировать файл эффекта до этого шага, effects_ здесь является указателем на ID3DXEffect)

texture_handle = effects->GetParameterByName(0, "FaceTexture"); 

Установите текстуру в визуализации функции

effects_->SetTexture(texture_handle, g_pTexture); 

Объявите текстуру в файле шейдера

Текстура FaceTexture;

Объявить пробник в файле шейдера

// Face texture sampler 
sampler FaceTextureSampler = sampler_state 
{ 
    Texture = <FaceTexture>; 
    MipFilter = LINEAR; 
    MinFilter = LINEAR; 
    MagFilter = LINEAR; 
}; 

ли выборки в пиксельный функции шейдера

float4 BasicPS(OutputVS outputVS) : COLOR 
{ 
    float4 Output; 
    Output = FaceTexture.Sample(FaceTextureSampler, outputVS.texUV); 
    return Output; 
} 

Если у вас установлен DirectX SDK, я рекомендую вам взглянуть на образец " BasicHLSL ", который имеет очень основное представление шейдеров Vertex и пиксельных шейдеров (включая текстуру).

+0

Возможно ли работать с текстурами без эффектов? – user2091150

+0

для DirectX9, да, вы можете использовать конвейер с фиксированной функцией вместо шейдера, для DirectX10/11, нет, поскольку фиксированный конвейер был удален из directx10. – zdd

+0

, вы можете также программировать шейдеры с помощью HLSL без использования системы эффектов в DirectX10/11. DirectX SDK имеет образец об этом. вы можете взглянуть. – zdd