11shader_type spatial;
22render_mode skip_vertex_transform;
3- render_mode unshaded;
3+ // render_mode unshaded;
44
55// World space
66// Not allowed to pass matrices through instance uniforms, so have to unpack into vectors.
@@ -10,17 +10,114 @@ instance uniform vec4 modelview_basis_y;
1010instance uniform vec4 modelview_basis_z;
1111instance uniform vec4 modelview_basis_w;
1212
13- uniform vec4 albedo: source_color;
13+ uniform vec4 albedo : source_color;
14+ uniform float grid_size;
15+
16+ varying vec3 uvw;
17+
18+ // Maps from an arbitrary edge index to the indices of the vertices in a tetrahedron [a,b,c,d].
19+ const int TETRAHEDRON_EDGE_TO_VERTEX_MAP[] = {
20+ 0 , 1 ,
21+ 0 , 2 ,
22+ 0 , 3 ,
23+ 1 , 2 ,
24+ 1 , 3 ,
25+ 2 , 3
26+ };
27+ // Nonsense abstract lookup table for different cases of vertices above and below the cross-section plane. Derived by
28+ // sketching out 3D tetrahedra and hoping it also worked for 4D (it does).
29+ // 16 cases for number of vertices above and below the cross-section plane, each case leads to at most two triangles for 6 vertices.
30+ // Each triangle in the cross-section is made up of vertices that are interpolated along the edges of the tetrahedron,
31+ // falling where the edge intersetcs the cross-section plane. So this table is 16x6, 16 cases, 6 possible verts,
32+ // each value maps to an edge in the TETRAHEDRON_EDGE_TO_VERTEX_MAP. -1 indicates the vertex is unused for that case.
33+ // General pattern: one vertex above and three below is one triangle on the edges between the one vertex above and the rest,
34+ // one vertex below and three above is same but the winding order is flipped, two above and two below is two triangles in some awful pattern.
35+ // Flipping the bit pattern (i.e. flipping the tetrahedron) reverses the winding order of both triangles.
36+ const int CROSS_SECTION_LOOKUP[] = {
37+ - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // 0000
38+ 0 , 1 , 2 , - 1 , - 1 , - 1 , // 0001
39+ 0 , 4 , 3 , - 1 , - 1 , - 1 , // 0010
40+ 2 , 4 , 1 , 3 , 1 , 4 , // 0011
41+ 1 , 3 , 5 , - 1 , - 1 , - 1 , // 0100
42+ 0 , 3 , 2 , 5 , 2 , 3 , // 0101
43+ 1 , 0 , 5 , 4 , 5 , 0 , // 0110
44+ 2 , 4 , 5 , - 1 , - 1 , - 1 , // 0111
45+ 2 , 5 , 4 , - 1 , - 1 , - 1 , // 1000
46+ 1 , 5 , 0 , 4 , 0 , 5 , // 1001
47+ 0 , 2 , 3 , 3 , 2 , 5 , // 1010
48+ 1 , 5 , 3 , - 1 , - 1 , - 1 , // 1011
49+ 2 , 1 , 4 , 4 , 1 , 3 , // 1100
50+ 0 , 3 , 4 , - 1 , - 1 , - 1 , // 1101
51+ 0 , 2 , 1 , - 1 , - 1 , - 1 , // 1110
52+ - 1 , - 1 , - 1 , - 1 , - 1 , - 1 // 1111
53+ };
54+
55+ int get_face_lookup_index(float w1, float w2, float w3, float w4, int vertex_id) {
56+ // Bitwise ops limit compatibility so summing instead.
57+ int negative1 = w1 < 0.0 ? 1 : 0 ;
58+ int negative2 = w2 < 0.0 ? 2 : 0 ;
59+ int negative3 = w3 < 0.0 ? 4 : 0 ;
60+ int negative4 = w4 < 0.0 ? 8 : 0 ;
61+ int lookup_index = negative1 + negative2 + negative3 + negative4;
62+
63+ // First index in the group of three that the indicated vertex belongs to.
64+ return (lookup_index * 6 ) + vertex_id - (vertex_id % 3 );
65+ }
66+
67+ vec3 slice_edge(vec4 v1, vec4 v2) {
68+ float mix_weight = v1.w / (v1.w - v2.w);
69+ return mix (v1, v2, mix_weight).xyz;
70+ }
1471
1572void vertex() {
16- mat4 modelview_basis = mat4 (modelview_basis_x, modelview_basis_y, modelview_basis_z, modelview_basis_w);
17- // Make an arbitrary triangle from the cell so there's something on the screen.
18- vec4 position = (VERTEX.x == 1.0 ? CUSTOM0 : (VERTEX.y == 1.0 ? CUSTOM1 : CUSTOM2));
19- position = (modelview_basis * position) + modelview_origin;
20- POSITION = PROJECTION_MATRIX * vec4 (position.xyz, 1.0 );
21- // TODO actual cross-sectioning
73+ mat4 modelview_basis = mat4 (modelview_basis_x, modelview_basis_y, modelview_basis_z, modelview_basis_w);
74+
75+ vec4 verts[] = { CUSTOM0, CUSTOM1, CUSTOM2, CUSTOM3 };
76+ verts[0 ] = (modelview_basis * verts[0 ]) + modelview_origin;
77+ verts[1 ] = (modelview_basis * verts[1 ]) + modelview_origin;
78+ verts[2 ] = (modelview_basis * verts[2 ]) + modelview_origin;
79+ verts[3 ] = (modelview_basis * verts[3 ]) + modelview_origin;
80+
81+ vec3 uvws[] = { vec3 (UV, COLOR.a), vec3 (UV2, VERTEX.y), NORMAL, COLOR.rgb };
82+
83+ int vertex_id = int (VERTEX.x);
84+ int face = get_face_lookup_index(verts[0 ].w, verts[1 ].w, verts[2 ].w, verts[3 ].w, vertex_id);
85+ if (CROSS_SECTION_LOOKUP[face] == - 1 ) {
86+ // This vertex is unused, cull
87+ POSITION = vec4 (0.0 , 0.0 , CLIP_SPACE_FAR, 1.0 );
88+ } else {
89+ int position_edge = CROSS_SECTION_LOOKUP[face + (vertex_id % 3 )];
90+ int edge_vert1 = TETRAHEDRON_EDGE_TO_VERTEX_MAP[position_edge * 2 ];
91+ int edge_vert2 = TETRAHEDRON_EDGE_TO_VERTEX_MAP[(position_edge * 2 ) + 1 ];
92+ vec4 position1 = verts[edge_vert1];
93+ vec4 position2 = verts[edge_vert2];
94+ float mix_weight = position1.w / (position1.w - position2.w);
95+ vec4 position = mix (position1, position2, mix_weight);
96+ // Vertex is view space and used for lighting, position is clip space and used for rasterizing.
97+ VERTEX = position.xyz;
98+ POSITION = PROJECTION_MATRIX * vec4 (position.xyz, 1.0 );
99+
100+ uvw = mix (uvws[edge_vert1], uvws[edge_vert2], mix_weight);
101+
102+ // Compute flat normals.
103+ int face_v1_edge = CROSS_SECTION_LOOKUP[face];
104+ int face_v2_edge = CROSS_SECTION_LOOKUP[face + 1 ];
105+ int face_v3_edge = CROSS_SECTION_LOOKUP[face + 2 ];
106+ vec3 face_v1 = slice_edge(verts[TETRAHEDRON_EDGE_TO_VERTEX_MAP[face_v1_edge * 2 ]], verts[TETRAHEDRON_EDGE_TO_VERTEX_MAP[face_v1_edge * 2 + 1 ]]);
107+ vec3 face_v2 = slice_edge(verts[TETRAHEDRON_EDGE_TO_VERTEX_MAP[face_v2_edge * 2 ]], verts[TETRAHEDRON_EDGE_TO_VERTEX_MAP[face_v2_edge * 2 + 1 ]]);
108+ vec3 face_v3 = slice_edge(verts[TETRAHEDRON_EDGE_TO_VERTEX_MAP[face_v3_edge * 2 ]], verts[TETRAHEDRON_EDGE_TO_VERTEX_MAP[face_v3_edge * 2 + 1 ]]);
109+ vec3 normal = normalize (cross (face_v2 - face_v1, face_v3 - face_v1));
110+ vec3 tangent = normalize (face_v2 - face_v1);
111+ vec3 binormal = normalize (cross (normal, tangent));
112+ NORMAL = normal;
113+ TANGENT = tangent;
114+ BINORMAL = binormal;
115+ }
22116}
23117
24118void fragment() {
25- ALBEDO = albedo.rgb;
119+ vec3 uvw_scaled = uvw * 10.0 ;
120+ int cell = (int (uvw_scaled.x) + int (uvw_scaled.y) + int (uvw_scaled.z)) % 2 ;
121+ ALBEDO = cell == 0 ? vec3 (0.0 ) : albedo.rgb;
122+ NORMAL = normalize (NORMAL);
26123}
0 commit comments