2015-12-11 6 views
0

Наше программное обеспечение в настоящее время использует конвейер с фиксированной функциональностью в Direct3D9, чтобы предложить нашим пользователям легко просматриваемый сценарий для передачи света и объектов в простую сцену. Мы допускаем направленное, точечное и точечное освещение. Я пытаюсь перенести нас на Direct3D11, но я хочу, чтобы он был как можно ближе к конвейеру с фиксированной функцией Direct3D9 как базовый. Мы можем добавить такие вещи, как пиксельное освещение позже. Я новичок в кодировании шейдеров, и хотя я много лет занимаюсь C++, я чувствую себя вне своего элемента. Мне интересно, есть ли поддерживающий DX11 шейдер, который отлично эмулирует освещение, предлагаемое конвейером с фиксированной функцией DX9. Я видел пример эмуляции старого света в FixedFuncEMUFX11, и я буду пытаться использовать его в качестве базы, но я просто знаю, что я не делаю этого так эффективно, как это было возможно, и математика для правильного освещения эмуляция вне меня. Есть ли какой-либо открытый источник, который эмулирует конвейер фиксированной функции или будет содержать направленные, точечные и точечные реализации для DirectX11/10? Я думаю, что все, что мне нужно, это файлы .fx или .hlsl. Даже если он достигнет 8 источников света, все будет хорошо.Эмуляция Direct3D9 конвейера с фиксированной функцией в Direct3D11

В настоящее время я использую DirectXTK в качестве руководства для правильного программирования DirectX11, но если есть лучший стандарт для кодирования, мне бы хотелось увидеть пример стандартной методологии программирования движка рендеринга DirectX11. Спасибо за любой совет, который вы можете дать.

ответ

2

Для базового рендеринга с Direct3D 11, встроенные шейдеры DirectX Tool Kit основаны на XNA Game Studio 4, который обеспечивает хороший набор основных функций, включая направленное освещение и освещение на пикселях. Они предназначены для работы со всем оборудованием Direct3D Feature Level, поэтому они не реализуют такие вещи, как прожекторы, которые легко выполняются с использованием более современного оборудования.

Образец FixedFuncEMU11 является Direct3D 11 порт наследия DirectX SDK в FixedFuncEMU Direct3D 10 образца. Шейдеры полезны для понимания различных конвейеров с фиксированной функцией Direct3D 9, но не охватывают «стандартные» вещи, такие как реализация стандартных моделей освещения в HLSL. Также обратите внимание, что в этом примере используется Effects system for Direct3D 11, у которого есть own issues. Тем не менее, это полезно для просмотра:

  • с фиксированной функцией трансформации Трубопроводные
  • фиксированной функции трубопровода Освещение
  • AlphaTest
  • пользователя клип Planes
  • Pixel Противотуманные
  • Гуро и плоская тень режимов
  • Проецируемые текстурные поиски (texldp)
  • Multi-Texturing
  • D3DFILL_POINT FillMode
  • экрана пространство UI рендеринга

Вы можете попробовать некоторые из старых Direct3D 9 времен введений HLSL шейдеров программирования. Хотя на 100% не совместимы с Direct3D 11, они довольно близки, и сам HLSL в основном тот же. Например, я нашел this article.

Есть также несколько отличных книг Direct3D 11, которые покрывают шейдеры HLSL, поскольку в Direct3D нет конвейера с фиксированной функцией. См. Book Recommendations для некоторых деталей и заметок, поскольку некоторые из этих книг были написаны до того, как был открыт SDK DirectX в отставке.В частности, вы должны посмотреть на 3D-рендеринг в реальном времени с DirectX и HLSL от Varcholik, так как он сильно ориентирован на авторинг HLSL.

+0

спасибо. Я проверю эту книгу. С тех пор я также открыл Ogre3D, который призван предложить эмуляцию Fixed Function Pipeline. В худшем случае я должен иметь возможность скопировать код прожектора. Они строят шейдеры динамически на основе сцены, что является интересным подходом. – cowtung

0

Для всех, кто оказался здесь, ища эмуляцию Fixed Function Pipeline в hlsl, это в значительной степени то, что я искал: http://www.3dgep.com/texturing-lighting-directx-11/ Шейдер там не очень оптимизирован, но написан для ясности и хорошего введение для новичков в hlsl. Существует очень мало лишних трещин для просеивания, чтобы точно увидеть, что происходит, и минимальный минимум, чтобы ваша сцена работала. Прожектор не является точной репликацией прожектора FFP DX9, но его легко модифицировать, чтобы стать таковым.

#define MAX_LIGHTS 8 

// Light types. 
#define DIRECTIONAL_LIGHT 0 
#define POINT_LIGHT 1 
#define SPOT_LIGHT 2 

Texture2D Texture : register(t0); 
sampler Sampler : register(s0); 

struct _Material 
{ 
    float4 Emissive;  // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    float4 Ambient;  // 16 bytes 
    //------------------------------------(16 byte boundary) 
    float4 Diffuse;  // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    float4 Specular;  // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    float SpecularPower; // 4 bytes 
    bool UseTexture;  // 4 bytes 
    float2 Padding;  // 8 bytes 
    //----------------------------------- (16 byte boundary) 
}; // Total:    // 80 bytes (5 * 16) 

cbuffer MaterialProperties : register(b0) 
{ 
    _Material Material; 
}; 

struct Light 
{ 
    float4  Position;    // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    float4  Direction;    // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    float4  Color;     // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    float  SpotAngle;    // 4 bytes 
    float  ConstantAttenuation; // 4 bytes 
    float  LinearAttenuation;  // 4 bytes 
    float  QuadraticAttenuation; // 4 bytes 
    //----------------------------------- (16 byte boundary) 
    int   LightType;    // 4 bytes 
    bool  Enabled;    // 4 bytes 
    int2  Padding;    // 8 bytes 
    //----------------------------------- (16 byte boundary) 
}; // Total:       // 80 bytes (5 * 16 byte boundary) 

cbuffer LightProperties : register(b1) 
{ 
    float4 EyePosition;     // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    float4 GlobalAmbient;    // 16 bytes 
    //----------------------------------- (16 byte boundary) 
    Light Lights[MAX_LIGHTS];   // 80 * 8 = 640 bytes 
}; // Total:       // 672 bytes (42 * 16 byte boundary) 

float4 DoDiffuse(Light light, float3 L, float3 N) 
{ 
    float NdotL = max(0, dot(N, L)); 
    return light.Color * NdotL; 
} 

float4 DoSpecular(Light light, float3 V, float3 L, float3 N) 
{ 
    // Phong lighting. 
    float3 R = normalize(reflect(-L, N)); 
    float RdotV = max(0, dot(R, V)); 

    // Blinn-Phong lighting 
    float3 H = normalize(L + V); 
    float NdotH = max(0, dot(N, H)); 

    return light.Color * pow(RdotV, Material.SpecularPower); 
} 

float DoAttenuation(Light light, float d) 
{ 
    return 1.0f/(light.ConstantAttenuation + light.LinearAttenuation * d + light.QuadraticAttenuation * d * d); 
} 

struct LightingResult 
{ 
    float4 Diffuse; 
    float4 Specular; 
}; 

LightingResult DoPointLight(Light light, float3 V, float4 P, float3 N) 
{ 
    LightingResult result; 

    float3 L = (light.Position - P).xyz; 
    float distance = length(L); 
    L = L/distance; 

    float attenuation = DoAttenuation(light, distance); 

    result.Diffuse = DoDiffuse(light, L, N) * attenuation; 
    result.Specular = DoSpecular(light, V, L, N) * attenuation; 

    return result; 
} 

LightingResult DoDirectionalLight(Light light, float3 V, float4 P, float3 N) 
{ 
    LightingResult result; 

    float3 L = -light.Direction.xyz; 

    result.Diffuse = DoDiffuse(light, L, N); 
    result.Specular = DoSpecular(light, V, L, N); 

    return result; 
} 

float DoSpotCone(Light light, float3 L) 
{ 
    float spotMinAngle = cos(light.SpotAngle); 
    float spotMaxAngle = (spotMinAngle + 1.0f)/2.0f; 
    float cosAngle = dot(light.Direction.xyz, L); 
    return smoothstep(spotMinAngle, spotMaxAngle, cosAngle); 
} 

LightingResult DoSpotLight(Light light, float3 V, float4 P, float3 N) 
{ 
    LightingResult result; 

    float3 L = (light.Position - P).xyz; 
    float distance = length(L); 
    L = L/distance; 

    float attenuation = DoAttenuation(light, distance); 
    float spotIntensity = DoSpotCone(light, -L); 

    result.Diffuse = DoDiffuse(light, L, N) * attenuation * spotIntensity; 
    result.Specular = DoSpecular(light, V, L, N) * attenuation * spotIntensity; 

    return result; 
} 

LightingResult ComputeLighting(float4 P, float3 N) 
{ 
    float3 V = normalize(EyePosition - P).xyz; 

    LightingResult totalResult = { {0, 0, 0, 0}, {0, 0, 0, 0} }; 

    [unroll] 
    for(int i = 0; i < MAX_LIGHTS; ++i) 
    { 
     LightingResult result = { {0, 0, 0, 0}, {0, 0, 0, 0} }; 

     if (!Lights[i].Enabled) continue; 

     switch(Lights[i].LightType) 
     { 
     case DIRECTIONAL_LIGHT: 
      { 
       result = DoDirectionalLight(Lights[i], V, P, N); 
      } 
      break; 
     case POINT_LIGHT: 
      { 
       result = DoPointLight(Lights[i], V, P, N); 
      } 
      break; 
     case SPOT_LIGHT: 
      { 
       result = DoSpotLight(Lights[i], V, P, N); 
      } 
      break; 
     } 
     totalResult.Diffuse += result.Diffuse; 
     totalResult.Specular += result.Specular; 
    } 

    totalResult.Diffuse = saturate(totalResult.Diffuse); 
    totalResult.Specular = saturate(totalResult.Specular); 

    return totalResult; 
} 

struct PixelShaderInput 
{ 
    float4 PositionWS : TEXCOORD1; 
    float3 NormalWS  : TEXCOORD2; 
    float2 TexCoord  : TEXCOORD0; 
}; 

float4 TexturedLitPixelShader(PixelShaderInput IN) : SV_TARGET 
{ 
    LightingResult lit = ComputeLighting(IN.PositionWS, normalize(IN.NormalWS)); 

    float4 emissive = Material.Emissive; 
    float4 ambient = Material.Ambient * GlobalAmbient; 
    float4 diffuse = Material.Diffuse * lit.Diffuse; 
    float4 specular = Material.Specular * lit.Specular; 

    float4 texColor = { 1, 1, 1, 1 }; 

    if (Material.UseTexture) 
    { 
     texColor = Texture.Sample(Sampler, IN.TexCoord); 
    } 

    float4 finalColor = (emissive + ambient + diffuse + specular) * texColor; 

    return finalColor; 
} 
+0

Хотя эта ссылка может ответить на вопрос, лучше включить основные части ответа здесь и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - [Из обзора] (/ review/low-quality-posts/11979472) – Alessiox

+0

Спасибо. Я добавил соответствующий код. Я новичок в размещении, любые отзывы приветствуются. – cowtung