1+ /* Copyright (c) 2025, Sascha Willems
2+ *
3+ * SPDX-License-Identifier: MIT
4+ *
5+ */
6+
7+ struct VSInput
8+ {
9+ float3 Pos;
10+ float3 Color;
11+ float3 Normal;
12+ };
13+
14+ struct VSOutput
15+ {
16+ float4 Pos : SV_POSITION;
17+ float ClipDistance : SV_ClipDistance0;
18+ float3 Normal;
19+ float3 Color;
20+ float3 EyePos;
21+ float3 LightVec;
22+ };
23+
24+ struct UBO
25+ {
26+ float4x4 projection;
27+ float4x4 view;
28+ float4x4 model;
29+ float4 lightPos;
30+ };
31+ ConstantBuffer < UBO> ubo;
32+
33+ [shader(" vertex" )]
34+ VSOutput vertexMain(VSInput input)
35+ {
36+ VSOutput output;
37+ output .Normal = input .Normal ;
38+ output .Color = input .Color ;
39+ output .Pos = mul(ubo .projection , mul(ubo .view , mul(ubo .model , float4(input .Pos , 1 . 0 ))));
40+ output .EyePos = mul(ubo .view , mul(ubo .model , float4(input .Pos , 1 . 0 ))).xyz ;
41+ output .LightVec = normalize(ubo .lightPos .xyz - output .EyePos );
42+ // Clip against reflection plane
43+ float4 clipPlane = float4(0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 );
44+ output .ClipDistance = dot(float4(input .Pos , 1 . 0 ), clipPlane);
45+ return output;
46+ }
47+
48+
49+ [shader(" fragment" )]
50+ float4 fragmentMain(VSOutput input)
51+ {
52+ float3 Eye = normalize(- input .EyePos );
53+ float3 Reflected = normalize(reflect(- input .LightVec , input .Normal ));
54+ float4 IAmbient = float4(0 . 1 , 0 . 1 , 0 . 1 , 1 . 0 );
55+ float4 IDiffuse = max(dot(input .Normal , input .LightVec ), 0 . 0 ).xxxx ;
56+ float specular = 0 . 75 ;
57+ float4 ISpecular = float4(0 . 0 , 0 . 0 , 0 . 0 , 0 . 0 );
58+ if (dot(input .EyePos , input .Normal ) < 0 . 0 )
59+ {
60+ ISpecular = float4(0 . 5 , 0 . 5 , 0 . 5 , 1 . 0 ) * pow(max(dot(Reflected, Eye), 0 . 0 ), 16 . 0 ) * specular;
61+ }
62+ return float4((IAmbient + IDiffuse) * float4(input .Color , 1 . 0 ) + ISpecular);
63+ }
0 commit comments