power_play/src/kernel/kernel_material.rst
2025-08-11 22:44:18 -05:00

109 lines
3.3 KiB
ReStructuredText

ConstantBuffer<K_MaterialSig> sig : register(b0);
/* ========================== *
* Vertex shader
* ========================== */
Struct(VsInput)
{
Semantic(u32, SV_InstanceID);
Semantic(u32, SV_VertexID);
};
Struct(VSOutput)
{
nointerpolation Semantic(u32, tex_nurid);
nointerpolation Semantic(u32, grid_id);
Semantic(Vec2, uv);
Semantic(Vec4, tint_lin);
Semantic(Vec4, emittance_lin);
Semantic(Vec4, SV_Position);
};
K_ENTRY VSOutput vs(VsInput input)
{
static const Vec2 unit_quad_verts[4] = {
Vec2(-0.5f, -0.5f),
Vec2(0.5f, -0.5f),
Vec2(0.5f, 0.5f),
Vec2(-0.5f, 0.5f)
};
StructuredBuffer<K_MaterialInstance> instances = GpuResourceFromUrid(sig.instances_urid);
K_MaterialInstance instance = instances[input.SV_InstanceID];
Vec2 vert = unit_quad_verts[input.SV_VertexID];
Vec2 world_pos = mul(instance.xf, Vec3(vert, 1)).xy;
VSOutput output;
output.SV_Position = mul(sig.projection, Vec4(world_pos, 0, 1));
output.tex_nurid = instance.tex_nurid;
output.grid_id = instance.grid_id;
output.uv = instance.uv0 + ((vert + 0.5) * (instance.uv1 - instance.uv0));
output.tint_lin = LinearFromSrgbU32(instance.tint_srgb);
output.emittance_lin = LinearFromSrgbVec4(Vec4(instance.light_emittance_srgb, instance.is_light));
return output;
}
/* ========================== *
* Pixel shader
* ========================== */
Struct(PsInput)
{
VSOutput vs;
};
Struct(PSOutput)
{
Semantic(Vec4, SV_Target0); /* Albedo */
Semantic(Vec4, SV_Target1); /* Emittance */
};
K_ENTRY PSOutput ps(PsInput input)
{
PSOutput output;
Vec4 albedo = input.vs.tint_lin;
/* Texture */
if (input.vs.tex_nurid < 0xFFFFFFFF) {
Texture2D<Vec4> tex = GpuResourceFromNurid(input.vs.tex_nurid);
albedo *= tex.Sample(s_point_clamp, input.vs.uv);
}
/* Grid */
if (input.vs.grid_id < 0xFFFFFFFF) {
StructuredBuffer<K_MaterialGrid> grids = GpuResourceFromUrid(sig.grids_urid);
K_MaterialGrid grid = grids[input.vs.grid_id];
Vec2 grid_pos = input.vs.SV_Position.xy + grid.offset;
float half_thickness = grid.line_thickness / 2;
float spacing = grid.line_spacing;
u32 color_srgb = grid.bg0_srgb;
Vec2 v = abs(round(grid_pos / spacing) * spacing - grid_pos);
float dist = min(v.x, v.y);
if (grid_pos.y <= half_thickness && grid_pos.y >= -half_thickness) {
color_srgb = grid.x_srgb;
} else if (grid_pos.x <= half_thickness && grid_pos.x >= -half_thickness) {
color_srgb = grid.y_srgb;
} else if (dist < half_thickness) {
color_srgb = grid.line_srgb;
} else {
bool checker = 0;
u32 cell_x = (u32)(abs(grid_pos.x) / spacing) + (grid_pos.x < 0);
u32 cell_y = (u32)(abs(grid_pos.y) / spacing) + (grid_pos.y < 0);
if (cell_x % 2 == 0) {
checker = cell_y % 2 == 0;
} else {
checker = cell_y % 2 == 1;
}
if (checker) {
color_srgb = grid.bg1_srgb;
}
}
albedo = LinearFromSrgbU32(color_srgb);
}
Vec4 emittance = input.vs.emittance_lin * albedo.a;
output.SV_Target0 = albedo;
output.SV_Target1 = emittance;
return output;
}