Skip to content

Commit

Permalink
Finally RTX Pathtracer index indices, vertices and material data corr…
Browse files Browse the repository at this point in the history
…ect, both outputs shows correct albedo
  • Loading branch information
krupitskas committed Nov 24, 2024
1 parent 13dc79c commit 9557b57
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 89 deletions.
3 changes: 2 additions & 1 deletion Shaders/ForwardPassPS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,6 @@ float4 main(RS2PS input) : SV_Target

float3 f = C_ambient + C_diffuse * in_shadow + emissive.xyz; // + cubeMapSample.xyz + Specular

return float4(f.xyz, 1.0);
return float4(base_color.rgb, 1);
//return float4(f.xyz, 1.0);
}
128 changes: 72 additions & 56 deletions Shaders/HitRT.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@
// D3D12_RAYTRACING_SHADER_CONFIG pipeline subobjet.
struct HitInfo
{
float4 color_distance;
float4 encoded_normals; // Octahedron encoded

float3 hit_position;
uint material_id;

float2 uvs;

bool has_hit()
{
return material_id != -1;
}
};

// Attributes output by the raytracing when hitting a surface,
Expand All @@ -19,15 +29,35 @@ struct Attributes
float2 bary;
};

inline uint PackInstanceID(uint material_id, uint geometry_id)
// octahedron encoding of normals
float2 octWrap(float2 v)
{
return float2((1.0f - abs(v.y)) * (v.x >= 0.0f ? 1.0f : -1.0f), (1.0f - abs(v.x)) * (v.y >= 0.0f ? 1.0f : -1.0f));
}

float2 encodeNormalOctahedron(float3 n)
{
return ((geometry_id & 0x3FFF) << 10) | (material_id & 0x3FF);
float2 p = float2(n.x, n.y) * (1.0f / (abs(n.x) + abs(n.y) + abs(n.z)));
p = (n.z < 0.0f) ? octWrap(p) : p;
return p;
}

inline void UnpackInstanceID(uint instanceID, out uint material_id, out uint geometry_id)
float3 decodeNormalOctahedron(float2 p)
{
material_id = instanceID & 0x3FF;
geometry_id = (instanceID >> 10) & 0x3FFF;
float3 n = float3(p.x, p.y, 1.0f - abs(p.x) - abs(p.y));
float2 tmp = (n.z < 0.0f) ? octWrap(float2(n.x, n.y)) : float2(n.x, n.y);
n.x = tmp.x;
n.y = tmp.y;
return normalize(n);
}

float4 EncodeNormals(float3 geometryNormal, float3 shadingNormal) {
return float4(encodeNormalOctahedron(geometryNormal), encodeNormalOctahedron(shadingNormal));
}

void DecodeNormals(float4 encodedNormals, out float3 geometryNormal, out float3 shadingNormal) {
geometryNormal = decodeNormalOctahedron(encodedNormals.xy);
shadingNormal = decodeNormalOctahedron(encodedNormals.zw);
}

// Vertex data for usage in Hit shader
Expand Down Expand Up @@ -84,10 +114,9 @@ uint3 GetIndices(uint geometry_id, uint triangle_index)
{
PerInstanceData data = PerInstanceBuffer[geometry_id];

uint base_index = (triangle_index * 3);
int address = data.indices_before + base_index;
int address = data.indices_before + triangle_index * 3;

uint i0 = IndexBuffer[address];
uint i0 = IndexBuffer[address + 0];
uint i1 = IndexBuffer[address + 1];
uint i2 = IndexBuffer[address + 2];

Expand All @@ -101,64 +130,51 @@ VertexData GetVertexData(uint geometry_id, uint triangle_index, float3 barycentr

VertexData v = (VertexData)0;

VertexLayout input_vertex[3];

float3 triangle_vertices[3];

int address = PerInstanceBuffer[geometry_id].vertices_before;

// Interpolate the vertex attributes
//for (uint i = 0; i < 3; i++)
//{
// //int address = (indices[i] * 12) * 4;
// int addess = VertexBuffer[geometry_id].vertices_before;
//
// // Load and interpolate position and transform it to world space
// triangle_vertices[i] = mul(ObjectToWorld3x4(), float4(asfloat(VertexBuffer[geometry_id].Load3(address)), 1.0f)).xyz;
// v.position += triangle_vertices[i] * barycentrics[i];
// address += 12;
//
// // Load and interpolate normal
// v.normal += asfloat(VertexBuffer[geometry_id].Load3(address)) * barycentrics[i];
// address += 12;
//
// // Load and interpolate tangent
// address += 12;
//
// // Load bitangent direction
// address += 4;
//
// // Load and interpolate texture coordinates
// v.uv += asfloat(vertices[geometry_id].Load2(address)) * barycentrics[i];
//}

//// Transform normal from local to world space
//v.normal = normalize(mul(ObjectToWorld3x4(), float4(v.normal, 0.0f)).xyz);

//// Calculate geometry normal from triangle vertices positions
//float3 edge20 = triangle_vertices[2] - triangle_vertices[0];
//float3 edge21 = triangle_vertices[2] - triangle_vertices[1];
//float3 edge10 = triangle_vertices[1] - triangle_vertices[0];

//v.geometryNormal = normalize(cross(edge20, edge10));
for (uint i = 0; i < 3; i++)
{
input_vertex[i] = VertexBuffer[address + indices[i]];

// Load and interpolate position and transform it to world space
triangle_vertices[i] = mul(ObjectToWorld3x4(), float4(input_vertex[i].position.xyz, 1.0f)).xyz;

v.position += triangle_vertices[i] * barycentrics[i];

// Load and interpolate normal
v.shading_normal += input_vertex[i].normal * barycentrics[i];

// Load and interpolate texture coordinates
v.uv += input_vertex[i].texcoord_0 * barycentrics[i];
}

// Transform normal from local to world space
v.shading_normal = normalize(mul(ObjectToWorld3x4(), float4(v.shading_normal, 0.0f)).xyz);

// Calculate geometry normal from triangle vertices positions
float3 edge20 = triangle_vertices[2] - triangle_vertices[0];
float3 edge21 = triangle_vertices[2] - triangle_vertices[1];
float3 edge10 = triangle_vertices[1] - triangle_vertices[0];

v.geometry_normal = normalize(cross(edge20, edge10));

return v;
}

[shader("closesthit")]
void ClosestHit(inout HitInfo payload, Attributes attrib)
{
uint primitive_index = PrimitiveIndex();

float3 barycentrics = float3(1.f - attrib.bary.x - attrib.bary.y, attrib.bary.x, attrib.bary.y);

uint material_id;
uint geometry_id;
UnpackInstanceID(primitive_index, material_id, geometry_id);

VertexData vertex_data = GetVertexData(geometry_id, primitive_index, barycentrics);

const float3 A = float3(1, 0, 0);
const float3 B = float3(0, 1, 0);
const float3 C = float3(0, 0, 1);

float3 hit_color = A * barycentrics.x + B * barycentrics.y + C * barycentrics.z;
VertexData vertex = GetVertexData(InstanceIndex(), PrimitiveIndex(), barycentrics);

payload.color_distance = float4(hit_color, RayTCurrent());
payload.encoded_normals = EncodeNormals(vertex.geometry_normal, vertex.shading_normal);
payload.hit_position = vertex.position;
payload.material_id = PerInstanceBuffer[InstanceIndex()].material_id;
payload.uvs = vertex.uv;
}
14 changes: 12 additions & 2 deletions Shaders/MissRT.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@
// D3D12_RAYTRACING_SHADER_CONFIG pipeline subobjet.
struct HitInfo
{
float4 color_distance;
float4 encoded_normals; // Octahedron encoded

float3 hit_position;
uint material_id;

float2 uvs;

bool has_hit()
{
return material_id != -1;
}
};

// Attributes output by the raytracing when hitting a surface, here the barycentric coordinates
Expand All @@ -21,5 +31,5 @@ struct Attributes
[shader("miss")]
void Miss(inout HitInfo payload : SV_RayPayload)
{
payload.color_distance = float4(0.2f, 0.2f, 0.8f, -1.f);
payload.material_id = -1;
}
65 changes: 57 additions & 8 deletions Shaders/RayGenRT.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@

struct HitInfo
{
float4 color_distance;
float4 encoded_normals; // Octahedron encoded

bool has_hit;
float3 hit_position;
uint material_id;

float2 uvs;

bool has_hit()
{
return material_id != -1;
}
};

// Attributes output by the raytracing when hitting a surface,
Expand Down Expand Up @@ -81,6 +89,38 @@ uint4 Pcg4d(uint4 v)
return v;
}


// octahedron encoding of normals
float2 octWrap(float2 v)
{
return float2((1.0f - abs(v.y)) * (v.x >= 0.0f ? 1.0f : -1.0f), (1.0f - abs(v.x)) * (v.y >= 0.0f ? 1.0f : -1.0f));
}

float2 encodeNormalOctahedron(float3 n)
{
float2 p = float2(n.x, n.y) * (1.0f / (abs(n.x) + abs(n.y) + abs(n.z)));
p = (n.z < 0.0f) ? octWrap(p) : p;
return p;
}

float3 decodeNormalOctahedron(float2 p)
{
float3 n = float3(p.x, p.y, 1.0f - abs(p.x) - abs(p.y));
float2 tmp = (n.z < 0.0f) ? octWrap(float2(n.x, n.y)) : float2(n.x, n.y);
n.x = tmp.x;
n.y = tmp.y;
return normalize(n);
}

float4 EncodeNormals(float3 geometryNormal, float3 shadingNormal) {
return float4(encodeNormalOctahedron(geometryNormal), encodeNormalOctahedron(shadingNormal));
}

void DecodeNormals(float4 encodedNormals, out float3 geometryNormal, out float3 shadingNormal) {
geometryNormal = decodeNormalOctahedron(encodedNormals.xy);
shadingNormal = decodeNormalOctahedron(encodedNormals.zw);
}

struct VertexLayout
{
float3 position;
Expand Down Expand Up @@ -128,7 +168,6 @@ void RayGen()
{
// Initialize the ray payload
HitInfo payload;
payload.color_distance = float4(0, 0, 0, 0);

// Get the location within the dispatched 2D grid of work items
// (often maps to pixels, so this could represent a pixel coordinate).
Expand Down Expand Up @@ -163,13 +202,23 @@ void RayGen()
payload
);

SurfaceShaderParameters mat = MaterialBuffer[0];
float2 uvs = float2(0.0f, 0.0f);

Texture2D albedo_texture = ResourceDescriptorHeap[mat.albedo_texture_index];
if(!payload.has_hit())
{
gOutput[pixel_xy] = float4(255, 0, 0, 1.f);
return;
}

float2 uvs = float2(0.0f, 0.0f);
float3 geometry_normal;
float3 shading_normal;
DecodeNormals(payload.encoded_normals, geometry_normal, shading_normal);

SurfaceShaderParameters mat = MaterialBuffer[payload.material_id];

Texture2D albedo_texture = ResourceDescriptorHeap[mat.albedo_texture_index];

float3 albedo_color = albedo_texture.SampleLevel(LinearSampler, uvs, 0.0f).rgb;
float3 albedo_color = albedo_texture.SampleLevel(LinearSampler, payload.uvs, 0.0f).rgb;

gOutput[pixel_xy] = float4(payload.color_distance.rgb * albedo_color.rgb, 1.f);
gOutput[pixel_xy] = float4(albedo_color, 1.f);
}
12 changes: 0 additions & 12 deletions Yasno/Graphics/RenderScene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,6 @@ namespace ysn
std::vector<D3D12_SAMPLER_DESC> sampler_descs;
};

// TODO: Move to some shared place between C++ and HLSL
inline uint32_t PackInstanceID(uint32_t material_id, uint32_t geometry_id)
{
return ((geometry_id & 0x3FFF) << 10) | (material_id & 0x3FF);
}

inline void UnpackInstanceID(uint32_t instance_id, uint32_t& material_id, uint32_t& geometry_id)
{
material_id = instance_id & 0x3FF;
geometry_id = (instance_id >> 10) & 0x3FFF;
}

// Per instance data for rendering, this can be split into smaller parts
YSN_SHADER_STRUCT RenderInstanceData
{
Expand Down
Loading

0 comments on commit 9557b57

Please sign in to comment.