mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
demos/teapot: Add diffuse lighting.
This commit is contained in:
Notes:
Henri Verbeet
2025-07-14 18:53:47 +02:00
Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1611
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define M_PI 3.14159265
|
||||
|
||||
cbuffer teapot_cb : register(b0)
|
||||
{
|
||||
float4x4 mvp_matrix;
|
||||
float level;
|
||||
uint wireframe;
|
||||
};
|
||||
|
||||
struct control_point
|
||||
@@ -33,9 +36,19 @@ struct patch_constant_data
|
||||
float inside[2] : SV_InsideTessFactor;
|
||||
};
|
||||
|
||||
struct gs_in
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float3 pos : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
};
|
||||
|
||||
struct ps_in
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float3 pos : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
float2 barycentric : BARYCENTRIC;
|
||||
};
|
||||
|
||||
float4 vs_main(float4 position : POSITION, uint id : SV_InstanceID) : SV_POSITION
|
||||
@@ -92,30 +105,98 @@ float3 eval_cubic(float3 p0, float3 p1, float3 p2, float3 p3, float t)
|
||||
eval_quadratic(p1, p2, p3, t), t);
|
||||
}
|
||||
|
||||
struct ps_in eval_patch(float2 t, float4 p[16])
|
||||
struct gs_in eval_patch(float2 t, float4 p[16])
|
||||
{
|
||||
float3 position, q[4];
|
||||
struct ps_in o;
|
||||
float3 position, normal, q[4], u, v;
|
||||
struct gs_in o;
|
||||
|
||||
q[0] = eval_cubic( p[0].xyz, p[1].xyz, p[2].xyz, p[3].xyz, t.x);
|
||||
q[1] = eval_cubic( p[4].xyz, p[5].xyz, p[6].xyz, p[7].xyz, t.x);
|
||||
q[2] = eval_cubic( p[8].xyz, p[9].xyz, p[10].xyz, p[11].xyz, t.x);
|
||||
q[3] = eval_cubic(p[12].xyz, p[13].xyz, p[14].xyz, p[15].xyz, t.x);
|
||||
u = eval_quadratic(q[0], q[1], q[2], t.y) - eval_quadratic(q[1], q[2], q[3], t.y);
|
||||
|
||||
q[0] = eval_cubic(p[0].xyz, p[4].xyz, p[8].xyz, p[12].xyz, t.y);
|
||||
q[1] = eval_cubic(p[1].xyz, p[5].xyz, p[9].xyz, p[13].xyz, t.y);
|
||||
q[2] = eval_cubic(p[2].xyz, p[6].xyz, p[10].xyz, p[14].xyz, t.y);
|
||||
q[3] = eval_cubic(p[3].xyz, p[7].xyz, p[11].xyz, p[15].xyz, t.y);
|
||||
v = eval_quadratic(q[0], q[1], q[2], t.x) - eval_quadratic(q[1], q[2], q[3], t.x);
|
||||
|
||||
position = eval_cubic(q[0], q[1], q[2], q[3], t.x);
|
||||
o.position = mul(mvp_matrix, float4(position, 1.0));
|
||||
o.pos = position;
|
||||
|
||||
/* The patches for the bottom of the teapot and the top of its lid are
|
||||
* degenerate. Technically this isn't the right way to deal with that, but
|
||||
* it's easy and gets the right result for these patches. */
|
||||
if (length(v) == 0.0)
|
||||
normal = cross(p[4].xyz - p[0].xyz, p[7].xyz - p[3].xyz);
|
||||
else
|
||||
normal = cross(u, v);
|
||||
o.normal = normalize(normal);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
[domain("quad")]
|
||||
struct ps_in ds_main(struct patch_constant_data input,
|
||||
struct gs_in ds_main(struct patch_constant_data input,
|
||||
float2 tess_coord : SV_DomainLocation, const OutputPatch<control_point, 16> patch)
|
||||
{
|
||||
return eval_patch(tess_coord, patch);
|
||||
}
|
||||
|
||||
[maxvertexcount(3)]
|
||||
void gs_main(triangle struct gs_in i[3], inout TriangleStream<struct ps_in> stream)
|
||||
{
|
||||
struct ps_in v[3];
|
||||
float3 n;
|
||||
|
||||
v[0].position = i[0].position;
|
||||
v[0].pos = i[0].pos;
|
||||
v[0].normal = i[0].normal;
|
||||
v[0].barycentric = float2(1.0, 0.0);
|
||||
|
||||
v[1].position = i[1].position;
|
||||
v[1].pos = i[1].pos;
|
||||
v[1].normal = i[1].normal;
|
||||
v[1].barycentric = float2(0.0, 1.0);
|
||||
|
||||
v[2].position = i[2].position;
|
||||
v[2].pos = i[2].pos;
|
||||
v[2].normal = i[2].normal;
|
||||
v[2].barycentric = float2(0.0, 0.0);
|
||||
|
||||
stream.Append(v[0]);
|
||||
stream.Append(v[1]);
|
||||
stream.Append(v[2]);
|
||||
}
|
||||
|
||||
/* Lambertian diffuse. */
|
||||
float3 brdf_lambert(float3 diffuse)
|
||||
{
|
||||
return diffuse / M_PI;
|
||||
}
|
||||
|
||||
float4 ps_main(struct ps_in i) : SV_TARGET
|
||||
{
|
||||
return float4(1.0, 0.69, 0.0, 1.0);
|
||||
float3 light_dir = normalize(float3(5.0, 5.0, 10.0));
|
||||
float3 light_colour = float3(1.0, 0.95, 0.88);
|
||||
float3 light_irradiance = 5.0 * light_colour;
|
||||
float3 barycentric, diffuse_colour, radiance;
|
||||
float3 base_colour = float3(0.8, 0.8, 0.8);
|
||||
float3 ambient = 0.3 * light_colour;
|
||||
float cos_theta_i, wire;
|
||||
float metallic = 0.3;
|
||||
|
||||
diffuse_colour = base_colour * (1.0 - metallic);
|
||||
cos_theta_i = saturate(dot(normalize(i.normal), light_dir));
|
||||
/* Cook-Torrance. */
|
||||
radiance = brdf_lambert(diffuse_colour) * light_irradiance * cos_theta_i;
|
||||
radiance += ambient * base_colour;
|
||||
|
||||
barycentric = float3(i.barycentric, 1.0 - (i.barycentric.x + i.barycentric.y));
|
||||
barycentric /= fwidth(barycentric);
|
||||
wire = wireframe ? min(min(barycentric.x, barycentric.y), barycentric.z) : 1.0;
|
||||
|
||||
return float4(lerp(float3(1.00, 0.69, 0.0), saturate(radiance), saturate(wire)), 1.0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user