Войти
ПрограммированиеФорумГрафика

Directx 11: Не рисует текстуры в модель

#0
14:10, 13 мар 2023

Всем привет. Сделал pbr текстуры и сделал тайл плитку. Я не знаю какой код вам присылать, так что покажу картинку, а вы напишите код чего предоставить. Координаты и позиция света передается в шейдеры, посмотрел через renderdoc.

Эта модель как будто прозрачная.

тайл | Directx 11: Не рисует текстуры в модель
#1
14:35, 13 мар 2023

За основу брал opengl шейдер https://www.programmersought.com/article/91679709226/

#2
14:36, 13 мар 2023

Тут в шейдере дело как я понял, но в чём может быть проблема? Выложу шейдеры сюда.

struct VS_INPUT {
  float3 pos: POSITION;
  float2 tex: TEXCOORD;
  float3 norm: NORMAL;
};

struct PS_INPUT {
  float4 pos: SV_POSITION;
  float2 tex: TEXCOORD;
  float3 norm: NORMAL;
  float3 WorldPos: POSITION0;
};

cbuffer MVP : register(b0)
{
  matrix mvp;
}

PS_INPUT main(VS_INPUT p)
{
  PS_INPUT o;
  o.norm = p.norm;
  o.tex = p.tex;


  float4 ps = float4(p.pos, 1.0);

  float4 resultPos = mul(ps, mvp);
  o.pos = resultPos;

  o.WorldPos = p.pos;
  return o;
}
struct PS_INPUT {
  float4 pos: SV_POSITION;
  float2 tex: TEXCOORD;
  float3 norm: NORMAL;
  float3 WorldPos: POSITION0;
};

static const int sizeLight = 1;

struct LIGHT
{
  float3 pos;
  float power;
};

cbuffer Light: register(b1)
{
  LIGHT light[sizeLight];
}

cbuffer CamPos : register(b2)
{
  float4 cam_pos;
}

static const float PI = 3.14159265359;

#define MEDIUMP_FLT_MAX    65504.0
#define MEDIUMP_FLT_MIN    0.00006103515625
#define saturateMediump(x) min(x, MEDIUMP_FLT_MAX)
// ----------------------------------------------------------------------------
float DistributionGGX(float3 N, float3 H, float roughness)
{
  //        float a = roughness*roughness;
  //        float a2 = a*a;
  //        float NdotH = max(dot(N, H), 0.0);
  //        float NdotH2 = NdotH*NdotH;
  //
  //        float nom   = a2;
  //        float denom = (NdotH2 * (a2 - 1.0) + 1.0);
  //        denom = PI * denom * denom;
  //
  //        return saturateMediump(nom / denom);

  // better ndf with spot light shape
  float3 NxH = cross(N, H);
  float oneMinusNoHSquared = dot(NxH, NxH);
  float NoH = max(dot(N, H), 0.0);
  float a = NoH * roughness;
  float k = roughness / (oneMinusNoHSquared + a * a);
  float d = k * k * (1.0 / PI);
  //  return saturateMediump(d,MEDIUMP_FLT_MAX);
  return min(d, MEDIUMP_FLT_MAX);
}
// ----------------------------------------------------------------------------
float GeometrySchlickGGX(float NdotV, float roughness)
{
  float r = (roughness + 1.0);
  float k = (r * r) / 8.0;

  float nom = NdotV;
  float denom = NdotV * (1.0 - k) + k;
  //  return saturateMediump(nom / denom,MEDIUMP_FLT_MAX);
  return min(nom / denom, MEDIUMP_FLT_MAX);
}
// ----------------------------------------------------------------------------
float GeometrySmith(float3 N, float3 V, float3 L, float roughness)
{
  float NdotV = max(dot(N, V), 0.0);
  float NdotL = max(dot(N, L), 0.0);
  float ggx2 = GeometrySchlickGGX(NdotV, roughness);
  float ggx1 = GeometrySchlickGGX(NdotL, roughness);
  //  saturateMediump(ggx1 * ggx2,MEDIUMP_FLT_MAX);
  return min(ggx1 * ggx2, MEDIUMP_FLT_MAX);
}
// ----------------------------------------------------------------------------
float3 fresnelSchlick(float cosTheta, float3 F0)
{
  return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}
// ----------------------------------------------------------------------------
float3 fresnelSchlickRoughness(float cosTheta, float3 F0, float roughness)
{
  float a = 1.0 - roughness;
  
  return F0 + (max(float3(a, a, a), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}

float3 EnvDFGLazarov(float3 specularColor, float gloss, float ndotv) {
  //# [ Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II" ]
  //# Adaptation to fit our G term.
  float4 p0 = float4(0.5745, 1.548, -0.02397, 1.301);
  float4 p1 = float4(0.5753, -0.2511, -0.02066, 0.4755);
  float4 t = gloss * p0 + p1;
  float bias = clamp(t.x * min(t.y, exp2(-7.672 * ndotv)) + t.z, 0.0, 1.0);
  float delta = clamp(t.w, 0.0, 1.0);
  float scale = delta - bias;
  bias *= clamp(50.0 * specularColor.y, 0.0, 1.0);
  return specularColor * scale + bias;
}

Texture2D albedoMap: register(t0);
Texture2D heightMap: register(t1);
Texture2D metallicMap: register(t2);
Texture2D aoMap: register(t3);
Texture2D normalMap: register(t4);
Texture2D roughnessMap: register(t5);

SamplerState colorSampler_: register(s0);


float4 main(PS_INPUT p) : SV_TARGET
{
  float3 albedo = pow(albedoMap.Sample(colorSampler_, p.tex).rgb, float3(2.2, 2.2, 2.2));
  float metallic = metallicMap.Sample(colorSampler_, p.tex).r;
  float roughness = roughnessMap.Sample(colorSampler_, p.tex).r;
  //float ao = aoMap.Sample(colorSampler_, p.tex).r;
  float ao = 1.0;
  float3 camPos = float3(cam_pos.r, cam_pos.g, cam_pos.b);
  //        vec3 N = getNormalFromMap();
  float3 N = normalize(p.norm);
  float3 V = normalize(camPos - p.WorldPos);
  float3 R = reflect(-V, N);

  // calculate reflectance at normal incidence; if dia-electric (like plastic) use F0
  // of 0.04 and if it's a metal, use the albedo color as F0 (metallic workflow)
  float3 F0 = float3(0.04, 0.04, 0.04);
  F0 = lerp(F0, albedo, metallic);

  // reflectance equation
  float3 Lo = float3(0.0, 0.0, 0.0);
  int i = 0;
  // point light
  //for (int i = 0; i < sizeLight; ++i) {
    // calculate per-light radiance
    float3 L = normalize(light[i].pos - p.WorldPos);
    float3 H = normalize(V + L);
    float distance = length(light[i].pos - p.WorldPos);
    float attenuation = 1.0 / (distance * distance);
    float3 radiance = light[i].pos * attenuation;

    // Cook-Torrance BRDF
    float NDF = DistributionGGX(N, H, roughness);
    float G = GeometrySmith(N, V, L, roughness);
    float3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);

    float3 nominator = NDF * G * F;
    float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0);
    float3 specular = nominator / max(denominator, 0.001); // prevent divide by zero for NdotV=0.0 or NdotL=0.0

    // kS is equal to Fresnel
    float3 kS = F;
    // for energy conservation, the diffuse and specular light can't
    // be above 1.0 (unless the surface emits light); to preserve this
    // relationship the diffuse component (kD) should equal 1.0 - kS.
    float pw = 1.0;
    float3 kD = float3(pw, pw, pw) - kS;
    // multiply kD by the inverse metalness such that only non-metals
    // have diffuse lighting, or a linear blend if partly metal (pure metals
    // have no diffuse light).
    kD *= 1.0 - metallic;

    // scale light by NdotL
    float NdotL = max(dot(N, L), 0.0);

    // add to outgoing radiance Lo
    Lo += (kD * albedo / PI + specular) * radiance * NdotL;  // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
  //}


  // ambient lighting (note that the next IBL tutorial will replace
  // this ambient lighting with environment lighting).
  float apw = 0.1;
  float3 ambient = float3(apw, apw, apw);
  float3 ambientColor = ambient * albedo * ao;

  float3 color = ambientColor + Lo;

  // HDR tonemapping

  float3 cv = float3(1.0, 1.0, 1.0);
  color = color / (color + cv);
  // gamma correct
  float cz = 1.0 / 2.2;

  color = pow(color, float3(cz, cz, cz));

  return float4(color, 1.0);
}
#3
16:05, 13 мар 2023

v7
Большой шейдер
Толстый ч бы даже сказал бы

#4
20:39, 13 мар 2023

innuendo
Я попробовал сделать по простому и отправить так.

float4 main(PS_INPUT p) : SV_TARGET
{
  return albedoMap.Sample(colorSampler_, p.tex);

И всё-равно такое, только цвет сменился на белый. Возможно что-то в текстуре не так.

#5
21:39, 13 мар 2023

Теперь вот так показывает. Текстура вроде полностью считывается.

tile_r | Directx 11: Не рисует текстуры в модель
#6
23:54, 13 мар 2023

Немного поработал с кодом, но всё равно. Вот как сейчас выглядит. Хотя текстура не так выглядит. Нижняя часть левая правильно, а остальное нет.

Изображение

Вот код инициализации текстуры.

void Downloader::LoadTextureFile(ObjectData* obj, std::string& filepath)
{
  FILE* fp = nullptr;
  const char* filename = filepath.c_str();
  fopen_s(&fp, filepath.c_str(), "r+b");
  if (fp == nullptr)
    exit(0);

  int i;
  int total;
  uint32_t width;
  uint32_t height;

  fread(&i, 1, sizeof(int), fp);
  fread(&total, 1, sizeof(int), fp);
  fread(&width, 1, sizeof(int), fp);
  fread(&height, 1, sizeof(int), fp);

  if (i != 1) {
    i = BytesOperation::bites_swap_little_big_engian_uint(i);
    total = BytesOperation::bites_swap_little_big_engian_uint(total);
    width = BytesOperation::bites_swap_little_big_engian_uint(width);
    height = BytesOperation::bites_swap_little_big_engian_uint(height);
  }

  if (i != 1) {
    exit(0);
  }

  switch (total) {
  case N_PBR_HEADER:
    obj->texture_data = new uint8_t * [N_PBR_HEADER];
    break;
  default:
    obj->texture_data = new uint8_t * [total];
    break;
  }

  obj->texture_width = width;
  obj->texture_height = height;
  obj->total = total;

  uint64_t sizeBuffer = (uint64_t) width * (uint64_t) height * (uint64_t)4;

  for (int i = 0; i < total; i++) {
    obj->texture_data[i] = new uint8_t[sizeBuffer];
    int ret = fread(obj->texture_data[i], 1, sizeBuffer, fp);
    int a = 0;
  }

  fclose(fp);

  obj->countTextures = total;
}

void Downloader::GenerateBuffers(ObjectData* obj)
{
  D3D11_BUFFER_DESC bufferDesc;
  ZeroMemory(&bufferDesc, sizeof(D3D11_BUFFER_DESC));

  bufferDesc.Usage = D3D11_USAGE_DEFAULT;
  bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  bufferDesc.ByteWidth = sizeof(float) * obj->f_size * 24;

  D3D11_SUBRESOURCE_DATA resourceData;
  ZeroMemory(&resourceData, sizeof(D3D11_SUBRESOURCE_DATA));

  resourceData.pSysMem = obj->vao_data;
  resourceData.SysMemPitch = 0;

  Graphics* gr = Graphics::GetInstance();

  obj->v_buffer = nullptr;

  HRESULT res = gr->d3d11Device->CreateBuffer(&bufferDesc, &resourceData, &obj->v_buffer);

  int a = 0;

  obj->colorMap = new ID3D11Texture2D * [obj->total]();

  D3D11_TEXTURE2D_DESC tx2d;
  ZeroMemory(&tx2d, sizeof(tx2d));
  tx2d.Height = obj->texture_height;
  tx2d.Width = obj->texture_width;
  tx2d.MipLevels = 1;
  tx2d.ArraySize = 1;
  tx2d.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  tx2d.Usage = D3D11_USAGE_DEFAULT;
  tx2d.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
  tx2d.SampleDesc.Count = 1;

  obj->textureView = new ID3D11ShaderResourceView * [obj->total]();

  for (int i = 0; i < obj->countTextures; i++) {
    obj->colorMap[i] = nullptr;

    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
    srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    srvDesc.Texture2D.MipLevels = 1;

    D3D11_SUBRESOURCE_DATA dt;
    ZeroMemory(&dt, sizeof(dt));
    dt.pSysMem = obj->texture_data[i];
    dt.SysMemPitch = obj->texture_width * 4;
    dt.SysMemSlicePitch = 0;

    ID3D11Texture2D* buffer = nullptr;
    HRESULT result = gr->d3d11Device->CreateTexture2D(&tx2d, &dt, &buffer);

    if (buffer) {
      obj->textureView[i] = nullptr;
      result = gr->d3d11Device->CreateShaderResourceView(buffer, &srvDesc, &obj->textureView[i]);
      //buffer->Release();
    }
  }
}

Капец, непонятно почему искажена текстура.

#7
4:26, 14 мар 2023

Это просто трагедия
Как жить дальше я не знаю

#8
0:17, 15 мар 2023

Я делал модель в blender и сохранял её в obj формате. Потом в substance painter открывал как directx graphical api и разрисовывал и сохранял в 1024x1024. Потом перегонял в свой формат текстур и оттуда загружал. Текстура искаженная. Я думаю это отличие в том, что в blender opengl, а не directx и он не так координаты сохраняет текстур.

Перешел в linux, сделал подобную модель в blender, в substance painter открыл как opengl и сохранил в 1024x1024. Перевел в формат текстур и открыл и всё нормально отображается, а в windows нет.

#9
0:53, 15 мар 2023

Зачем амбиент колор считать с альбедо?

#10
1:33, 15 мар 2023

innuendo
Я не разбираюсь в таких расчетах и просто взял шейдер для opengl копипаст. Кстати, я справился и теперь текстура правильно рисуется.

ПрограммированиеФорумГрафика