1+ /* Copyright (c) 2025, Sascha Willems
2+ *
3+ * SPDX-License-Identifier: MIT
4+ *
5+ */
6+
7+ struct VSInput
8+ {
9+ float3 Pos;
10+ float3 Normal;
11+ };
12+
13+ struct VSOutput
14+ {
15+ float4 Pos : SV_POSITION;
16+ float3 WorldPos;
17+ float3 Normal;
18+ float LodBias;
19+ float3 ViewVec;
20+ float3 LightVec;
21+ };
22+
23+ struct UBO
24+ {
25+ float4x4 projection;
26+ float4x4 model;
27+ float4x4 invModel;
28+ float lodBias;
29+ };
30+ ConstantBuffer < UBO> ubo;
31+
32+ SamplerCube samplerColor;
33+
34+ [shader(" vertex" )]
35+ VSOutput vertexMain(VSInput input)
36+ {
37+ VSOutput output;
38+ output .Pos = mul(ubo .projection , mul(ubo .model , float4(input .Pos .xyz , 1 . 0 )));
39+
40+ output .WorldPos = mul(ubo .model , float4(input .Pos , 1 . 0 )).xyz ;
41+ output .Normal = mul((float3x3 )ubo .model , input .Normal );
42+ output .LodBias = ubo .lodBias ;
43+
44+ float3 lightPos = float3(0 . 0 f , - 5 . 0 f , 5 . 0 f );
45+ output .LightVec = lightPos .xyz - output .WorldPos .xyz ;
46+ output .ViewVec = - output .WorldPos ;
47+ return output;
48+ }
49+
50+ [shader(" fragment" )]
51+ float4 fragmentMain(VSOutput input) : SV_TARGET
52+ {
53+ float3 cI = normalize (input .ViewVec );
54+ float3 cR = reflect (cI, normalize(input .Normal ));
55+
56+ cR = mul(ubo .invModel , float4(cR, 0 . 0 )).xyz ;
57+ // Convert cubemap coordinates into Vulkan coordinate space
58+ cR .z *= - 1 . 0 ;
59+
60+ float4 color = samplerColor .SampleLevel (cR, input .LodBias );
61+
62+ float3 N = normalize(input .Normal );
63+ float3 L = normalize(input .LightVec );
64+ float3 V = normalize(input .ViewVec );
65+ float3 R = reflect(- L, N);
66+ float3 ambient = float3(0 . 5 , 0 . 5 , 0 . 5 ) * color .rgb ;
67+ float3 diffuse = max(dot(N, L), 0 . 0 ) * float3(1 . 0 , 1 . 0 , 1 . 0 );
68+ float3 specular = pow(max(dot(R, V), 0 . 0 ), 16 . 0 ) * float3(0 . 5 , 0 . 5 , 0 . 5 );
69+ return float4(ambient + diffuse * color .rgb + specular, 1 . 0 );
70+ }
0 commit comments