Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/gl_tests/ClipDistanceTest.cpp
1693 views
1
//
2
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
5
//
6
// ClipDistanceTest.cpp: Test cases for GL_APPLE_clip_distance/GL_EXT_clip_cull_distance extension.
7
//
8
9
#include "test_utils/ANGLETest.h"
10
#include "test_utils/gl_raii.h"
11
#include "util/EGLWindow.h"
12
#include "util/test_utils.h"
13
14
using namespace angle;
15
16
class ClipDistanceTest : public ANGLETest
17
{
18
protected:
19
ClipDistanceTest()
20
{
21
setWindowWidth(16);
22
setWindowHeight(16);
23
setConfigRedBits(8);
24
setConfigGreenBits(8);
25
setConfigBlueBits(8);
26
setConfigAlphaBits(8);
27
setConfigDepthBits(24);
28
}
29
};
30
31
// Query max clip distances and enable, disable states of clip distances
32
TEST_P(ClipDistanceTest, StateQuery)
33
{
34
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
35
36
GLint maxClipDistances = 0;
37
glGetIntegerv(GL_MAX_CLIP_DISTANCES_APPLE, &maxClipDistances);
38
39
EXPECT_GL_NO_ERROR();
40
EXPECT_GE(maxClipDistances, 8);
41
42
GLboolean enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);
43
EXPECT_GL_NO_ERROR();
44
EXPECT_EQ(enabled, GL_FALSE);
45
46
glEnable(GL_CLIP_DISTANCE1_APPLE);
47
EXPECT_GL_NO_ERROR();
48
glEnable(GL_CLIP_DISTANCE7_APPLE);
49
EXPECT_GL_NO_ERROR();
50
enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);
51
EXPECT_EQ(enabled, GL_TRUE);
52
53
glDisable(GL_CLIP_DISTANCE1_APPLE);
54
EXPECT_GL_NO_ERROR();
55
enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);
56
EXPECT_EQ(enabled, GL_FALSE);
57
58
EXPECT_EQ(glIsEnabled(GL_CLIP_DISTANCE7_APPLE), GL_TRUE);
59
}
60
61
// Write to one gl_ClipDistance element
62
TEST_P(ClipDistanceTest, OneClipDistance)
63
{
64
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
65
66
constexpr char kVS[] = R"(
67
#extension GL_APPLE_clip_distance : require
68
69
uniform vec4 u_plane;
70
71
attribute vec2 a_position;
72
73
void main()
74
{
75
gl_Position = vec4(a_position, 0.0, 1.0);
76
77
gl_ClipDistance[0] = dot(gl_Position, u_plane);
78
})";
79
80
ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());
81
glLinkProgram(programRed);
82
glUseProgram(programRed);
83
ASSERT_GL_NO_ERROR();
84
85
glEnable(GL_CLIP_DISTANCE0_APPLE);
86
87
// Clear to blue
88
glClearColor(0, 0, 1, 1);
89
glClear(GL_COLOR_BUFFER_BIT);
90
91
// Draw full screen quad with color red
92
glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 0, 0, 0.5);
93
EXPECT_GL_NO_ERROR();
94
drawQuad(programRed, "a_position", 0);
95
EXPECT_GL_NO_ERROR();
96
97
// All pixels on the left of the plane x = -0.5 must be blue
98
for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
99
{
100
for (int y = 0; y < getWindowHeight(); ++y)
101
{
102
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
103
}
104
}
105
106
// All pixels on the right of the plane x = -0.5 must be red
107
for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth(); ++x)
108
{
109
for (int y = 0; y < getWindowHeight(); ++y)
110
{
111
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
112
}
113
}
114
115
// Clear to green
116
glClearColor(0, 1, 0, 1);
117
glClear(GL_COLOR_BUFFER_BIT);
118
119
// Draw full screen quad with color red
120
glUniform4f(glGetUniformLocation(programRed, "u_plane"), -1, 0, 0, -0.5);
121
EXPECT_GL_NO_ERROR();
122
drawQuad(programRed, "a_position", 0);
123
EXPECT_GL_NO_ERROR();
124
125
// All pixels on the left of the plane x = -0.5 must be red
126
for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
127
{
128
for (int y = 0; y < getWindowHeight(); ++y)
129
{
130
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
131
}
132
}
133
134
// All pixels on the right of the plane x = -0.5 must be green
135
for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth(); ++x)
136
{
137
for (int y = 0; y < getWindowHeight(); ++y)
138
{
139
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
140
}
141
}
142
143
// Disable GL_CLIP_DISTANCE
144
glDisable(GL_CLIP_DISTANCE0_APPLE);
145
drawQuad(programRed, "a_position", 0);
146
147
// All pixels must be red
148
for (int x = 0; x < getWindowWidth(); ++x)
149
{
150
for (int y = 0; y < getWindowHeight(); ++y)
151
{
152
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
153
}
154
}
155
}
156
157
// Write to 3 clip distances
158
TEST_P(ClipDistanceTest, ThreeClipDistances)
159
{
160
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
161
162
constexpr char kVS[] = R"(
163
#extension GL_APPLE_clip_distance : require
164
165
uniform vec4 u_plane[3];
166
167
attribute vec2 a_position;
168
169
void main()
170
{
171
gl_Position = vec4(a_position, 0.0, 1.0);
172
173
gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);
174
gl_ClipDistance[3] = dot(gl_Position, u_plane[1]);
175
gl_ClipDistance[7] = dot(gl_Position, u_plane[2]);
176
})";
177
178
ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());
179
glLinkProgram(programRed);
180
glUseProgram(programRed);
181
ASSERT_GL_NO_ERROR();
182
183
// Enable 3 clip distances
184
glEnable(GL_CLIP_DISTANCE0_APPLE);
185
glEnable(GL_CLIP_DISTANCE3_APPLE);
186
glEnable(GL_CLIP_DISTANCE7_APPLE);
187
ASSERT_GL_NO_ERROR();
188
189
// Clear to blue
190
glClearColor(0, 0, 1, 1);
191
glClear(GL_COLOR_BUFFER_BIT);
192
193
// Draw full screen quad with color red
194
// x = -0.5
195
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);
196
// x = 0.5
197
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);
198
// x + y = 1
199
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);
200
EXPECT_GL_NO_ERROR();
201
drawQuad(programRed, "a_position", 0);
202
EXPECT_GL_NO_ERROR();
203
204
// All pixels on the left of the plane x = -0.5 must be blue
205
for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
206
{
207
for (int y = 0; y < getWindowHeight(); ++y)
208
{
209
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
210
}
211
}
212
213
// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
214
// triangle
215
for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)
216
{
217
for (int y = 0; y < getWindowHeight(); ++y)
218
{
219
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
220
}
221
}
222
223
for (int y = 0; y < getWindowHeight(); ++y)
224
{
225
for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
226
{
227
if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)
228
{
229
// bottom left triangle clipped by x=0.5 plane
230
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
231
}
232
else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)
233
{
234
// upper right triangle plus right of x=0.5 plane
235
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
236
}
237
}
238
}
239
240
// Clear to green
241
glClearColor(0, 1, 0, 1);
242
glClear(GL_COLOR_BUFFER_BIT);
243
244
// Disable gl_ClipDistance[3]
245
glDisable(GL_CLIP_DISTANCE3_APPLE);
246
247
// Draw full screen quad with color red
248
EXPECT_GL_NO_ERROR();
249
drawQuad(programRed, "a_position", 0);
250
EXPECT_GL_NO_ERROR();
251
252
// All pixels on the left of the plane x = -0.5 must be green
253
for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
254
{
255
for (int y = 0; y < getWindowHeight(); ++y)
256
{
257
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
258
}
259
}
260
261
// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
262
// triangle
263
for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)
264
{
265
for (int y = 0; y < getWindowHeight(); ++y)
266
{
267
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
268
}
269
}
270
271
for (int y = 0; y < getWindowHeight(); ++y)
272
{
273
for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
274
{
275
if (x < getWindowWidth() * 3 / 2 - y - 1)
276
{
277
// bottom left triangle
278
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
279
}
280
else if (x > getWindowWidth() * 3 / 2 - y + 1)
281
{
282
// upper right triangle
283
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
284
}
285
}
286
}
287
}
288
289
// Redeclare gl_ClipDistance in shader with explicit size, also use it in a global function
290
// outside main()
291
TEST_P(ClipDistanceTest, ThreeClipDistancesRedeclared)
292
{
293
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
294
295
constexpr char kVS[] = R"(
296
#extension GL_APPLE_clip_distance : require
297
298
varying highp float gl_ClipDistance[3];
299
300
void computeClipDistances(in vec4 position, in vec4 plane[3])
301
{
302
gl_ClipDistance[0] = dot(position, plane[0]);
303
gl_ClipDistance[1] = dot(position, plane[1]);
304
gl_ClipDistance[2] = dot(position, plane[2]);
305
}
306
307
uniform vec4 u_plane[3];
308
309
attribute vec2 a_position;
310
311
void main()
312
{
313
gl_Position = vec4(a_position, 0.0, 1.0);
314
315
computeClipDistances(gl_Position, u_plane);
316
})";
317
318
ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());
319
glLinkProgram(programRed);
320
glUseProgram(programRed);
321
ASSERT_GL_NO_ERROR();
322
323
// Enable 3 clip distances
324
glEnable(GL_CLIP_DISTANCE0_APPLE);
325
glEnable(GL_CLIP_DISTANCE1_APPLE);
326
glEnable(GL_CLIP_DISTANCE2_APPLE);
327
ASSERT_GL_NO_ERROR();
328
329
// Clear to blue
330
glClearColor(0, 0, 1, 1);
331
glClear(GL_COLOR_BUFFER_BIT);
332
333
// Draw full screen quad with color red
334
// x = -0.5
335
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);
336
// x = 0.5
337
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);
338
// x + y = 1
339
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);
340
EXPECT_GL_NO_ERROR();
341
drawQuad(programRed, "a_position", 0);
342
EXPECT_GL_NO_ERROR();
343
344
// All pixels on the left of the plane x = -0.5 must be blue
345
for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
346
{
347
for (int y = 0; y < getWindowHeight(); ++y)
348
{
349
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
350
}
351
}
352
353
// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
354
// triangle
355
for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)
356
{
357
for (int y = 0; y < getWindowHeight(); ++y)
358
{
359
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
360
}
361
}
362
363
for (int y = 0; y < getWindowHeight(); ++y)
364
{
365
for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
366
{
367
if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)
368
{
369
// bottom left triangle clipped by x=0.5 plane
370
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
371
}
372
else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)
373
{
374
// upper right triangle plus right of x=0.5 plane
375
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
376
}
377
}
378
}
379
}
380
381
class ClipCullDistanceTest : public ClipDistanceTest
382
{};
383
384
// Query max clip distances and enable, disable states of clip distances
385
TEST_P(ClipCullDistanceTest, StateQuery)
386
{
387
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
388
389
GLint maxClipDistances = 0;
390
glGetIntegerv(GL_MAX_CLIP_DISTANCES_EXT, &maxClipDistances);
391
392
EXPECT_GL_NO_ERROR();
393
EXPECT_GE(maxClipDistances, 8);
394
395
GLint maxCullDistances = 0;
396
glGetIntegerv(GL_MAX_CULL_DISTANCES_EXT, &maxCullDistances);
397
398
EXPECT_GL_NO_ERROR();
399
EXPECT_GE(maxCullDistances, 8);
400
401
GLint maxCombinedClipAndCullDistances = 0;
402
glGetIntegerv(GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT, &maxCombinedClipAndCullDistances);
403
404
EXPECT_GL_NO_ERROR();
405
EXPECT_GE(maxCombinedClipAndCullDistances, 8);
406
407
GLboolean enabled = glIsEnabled(GL_CLIP_DISTANCE1_EXT);
408
EXPECT_GL_NO_ERROR();
409
EXPECT_EQ(enabled, GL_FALSE);
410
411
glEnable(GL_CLIP_DISTANCE1_EXT);
412
EXPECT_GL_NO_ERROR();
413
glEnable(GL_CLIP_DISTANCE7_EXT);
414
EXPECT_GL_NO_ERROR();
415
enabled = glIsEnabled(GL_CLIP_DISTANCE1_EXT);
416
EXPECT_EQ(enabled, GL_TRUE);
417
418
glDisable(GL_CLIP_DISTANCE1_EXT);
419
EXPECT_GL_NO_ERROR();
420
enabled = glIsEnabled(GL_CLIP_DISTANCE1_EXT);
421
EXPECT_EQ(enabled, GL_FALSE);
422
423
EXPECT_EQ(glIsEnabled(GL_CLIP_DISTANCE7_EXT), GL_TRUE);
424
}
425
426
// Check that the validation for EXT_clip_cull_distance extension is correct
427
// If gl_ClipDistance or gl_CullDistance is redeclared in some shader stages, the array size of the
428
// redeclared variables should match
429
TEST_P(ClipCullDistanceTest, SizeCheck)
430
{
431
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
432
433
// Validate array size match of redeclared ClipDistance built-in
434
constexpr char kVSErrorClipDistance[] = R"(#version 300 es
435
#extension GL_EXT_clip_cull_distance : require
436
437
out highp float gl_ClipDistance[1];
438
439
uniform vec4 u_plane;
440
441
in vec2 a_position;
442
443
void main()
444
{
445
gl_Position = vec4(a_position, 0.0, 1.0);
446
447
gl_ClipDistance[0] = dot(gl_Position, u_plane);
448
449
gl_CullDistance[0] = dot(gl_Position, u_plane);
450
gl_CullDistance[1] = dot(gl_Position, u_plane);
451
})";
452
453
constexpr char kFSErrorClipDistance[] = R"(#version 300 es
454
#extension GL_EXT_clip_cull_distance : require
455
in highp float gl_ClipDistance[2];
456
precision highp float;
457
out vec4 my_FragColor;
458
void main()
459
{
460
my_FragColor = vec4(gl_ClipDistance[0], gl_ClipDistance[1], gl_CullDistance[0], 1.0f);
461
})";
462
463
GLProgram programClipDistance;
464
programClipDistance.makeRaster(kVSErrorClipDistance, kFSErrorClipDistance);
465
EXPECT_GL_FALSE(programClipDistance.valid());
466
467
// Validate array size match of redeclared CullDistance built-in
468
constexpr char kVSErrorCullDistance[] = R"(#version 300 es
469
#extension GL_EXT_clip_cull_distance : require
470
471
out highp float gl_CullDistance[1];
472
473
uniform vec4 u_plane;
474
475
in vec2 a_position;
476
477
void main()
478
{
479
gl_Position = vec4(a_position, 0.0, 1.0);
480
481
gl_CullDistance[0] = dot(gl_Position, u_plane);
482
483
gl_ClipDistance[0] = dot(gl_Position, u_plane);
484
gl_ClipDistance[1] = dot(gl_Position, u_plane);
485
})";
486
487
constexpr char kFSErrorCullDistance[] = R"(#version 300 es
488
#extension GL_EXT_clip_cull_distance : require
489
in highp float gl_CullDistance[2];
490
precision highp float;
491
out vec4 my_FragColor;
492
void main()
493
{
494
my_FragColor = vec4(gl_CullDistance[0], gl_CullDistance[1], gl_ClipDistance[0], 1.0f);
495
})";
496
497
GLProgram programCullDistance;
498
programCullDistance.makeRaster(kVSErrorCullDistance, kFSErrorCullDistance);
499
EXPECT_GL_FALSE(programCullDistance.valid());
500
}
501
502
// Write to one gl_ClipDistance element
503
TEST_P(ClipCullDistanceTest, OneClipDistance)
504
{
505
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
506
507
constexpr char kVS[] = R"(#version 300 es
508
#extension GL_EXT_clip_cull_distance : require
509
510
uniform vec4 u_plane;
511
512
in vec2 a_position;
513
514
void main()
515
{
516
gl_Position = vec4(a_position, 0.0, 1.0);
517
518
gl_ClipDistance[0] = dot(gl_Position, u_plane);
519
})";
520
521
ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());
522
glLinkProgram(programRed);
523
glUseProgram(programRed);
524
ASSERT_GL_NO_ERROR();
525
526
glEnable(GL_CLIP_DISTANCE0_EXT);
527
528
// Clear to blue
529
glClearColor(0, 0, 1, 1);
530
glClear(GL_COLOR_BUFFER_BIT);
531
532
// Draw full screen quad with color red
533
glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 0, 0, 0.5);
534
EXPECT_GL_NO_ERROR();
535
drawQuad(programRed, "a_position", 0);
536
EXPECT_GL_NO_ERROR();
537
538
// All pixels on the left of the plane x = -0.5 must be blue
539
GLuint x = 0;
540
GLuint y = 0;
541
GLuint width = getWindowWidth() / 4 - 1;
542
GLuint height = getWindowHeight();
543
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::blue);
544
545
// All pixels on the right of the plane x = -0.5 must be red
546
x = getWindowWidth() / 4 + 2;
547
y = 0;
548
width = getWindowWidth() - x;
549
height = getWindowHeight();
550
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);
551
552
// Clear to green
553
glClearColor(0, 1, 0, 1);
554
glClear(GL_COLOR_BUFFER_BIT);
555
556
// Draw full screen quad with color red
557
glUniform4f(glGetUniformLocation(programRed, "u_plane"), -1, 0, 0, -0.5);
558
EXPECT_GL_NO_ERROR();
559
drawQuad(programRed, "a_position", 0);
560
EXPECT_GL_NO_ERROR();
561
562
// All pixels on the left of the plane x = -0.5 must be red
563
x = 0;
564
y = 0;
565
width = getWindowWidth() / 4 - 1;
566
height = getWindowHeight();
567
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);
568
569
// All pixels on the right of the plane x = -0.5 must be green
570
x = getWindowWidth() / 4 + 2;
571
y = 0;
572
width = getWindowWidth() - x;
573
height = getWindowHeight();
574
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::green);
575
576
// Disable GL_CLIP_DISTANCE
577
glDisable(GL_CLIP_DISTANCE0_EXT);
578
drawQuad(programRed, "a_position", 0);
579
580
// All pixels must be red
581
x = 0;
582
y = 0;
583
width = getWindowWidth();
584
height = getWindowHeight();
585
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);
586
}
587
588
// Write to 3 clip distances
589
TEST_P(ClipCullDistanceTest, ThreeClipDistances)
590
{
591
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
592
593
constexpr char kVS[] = R"(#version 300 es
594
#extension GL_EXT_clip_cull_distance : require
595
596
uniform vec4 u_plane[3];
597
598
in vec2 a_position;
599
600
void main()
601
{
602
gl_Position = vec4(a_position, 0.0, 1.0);
603
604
gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);
605
gl_ClipDistance[3] = dot(gl_Position, u_plane[1]);
606
gl_ClipDistance[7] = dot(gl_Position, u_plane[2]);
607
})";
608
609
ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());
610
glLinkProgram(programRed);
611
glUseProgram(programRed);
612
ASSERT_GL_NO_ERROR();
613
614
// Enable 3 clip distances
615
glEnable(GL_CLIP_DISTANCE0_EXT);
616
glEnable(GL_CLIP_DISTANCE3_EXT);
617
glEnable(GL_CLIP_DISTANCE7_EXT);
618
ASSERT_GL_NO_ERROR();
619
620
// Clear to blue
621
glClearColor(0, 0, 1, 1);
622
glClear(GL_COLOR_BUFFER_BIT);
623
624
// Draw full screen quad with color red
625
// x = -0.5
626
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);
627
// x = 0.5
628
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);
629
// x + y = 1
630
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);
631
EXPECT_GL_NO_ERROR();
632
drawQuad(programRed, "a_position", 0);
633
EXPECT_GL_NO_ERROR();
634
635
// All pixels on the left of the plane x = -0.5 must be blue
636
GLuint x = 0;
637
GLuint y = 0;
638
GLuint width = getWindowWidth() / 4 - 1;
639
GLuint height = getWindowHeight();
640
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::blue);
641
642
// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
643
// triangle
644
x = getWindowWidth() / 4 + 2;
645
y = 0;
646
width = getWindowWidth() / 2 - x;
647
height = getWindowHeight();
648
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);
649
650
std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
651
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
652
actualColors.data());
653
for (int y = 0; y < getWindowHeight(); ++y)
654
{
655
for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
656
{
657
const int currentPosition = y * getWindowHeight() + x;
658
659
if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)
660
{
661
// bottom left triangle clipped by x=0.5 plane
662
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
663
}
664
else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)
665
{
666
// upper right triangle plus right of x=0.5 plane
667
EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);
668
}
669
}
670
}
671
672
// Clear to green
673
glClearColor(0, 1, 0, 1);
674
glClear(GL_COLOR_BUFFER_BIT);
675
676
// Disable gl_ClipDistance[3]
677
glDisable(GL_CLIP_DISTANCE3_EXT);
678
679
// Draw full screen quad with color red
680
EXPECT_GL_NO_ERROR();
681
drawQuad(programRed, "a_position", 0);
682
EXPECT_GL_NO_ERROR();
683
684
// All pixels on the left of the plane x = -0.5 must be green
685
for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
686
{
687
for (int y = 0; y < getWindowHeight(); ++y)
688
{
689
EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
690
}
691
}
692
693
// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
694
// triangle
695
x = getWindowWidth() / 4 + 2;
696
y = 0;
697
width = getWindowWidth() / 2 - x;
698
height = getWindowHeight();
699
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);
700
701
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
702
actualColors.data());
703
for (int y = 0; y < getWindowHeight(); ++y)
704
{
705
for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
706
{
707
const int currentPosition = y * getWindowHeight() + x;
708
709
if (x < getWindowWidth() * 3 / 2 - y - 1)
710
{
711
// bottom left triangle
712
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
713
}
714
else if (x > getWindowWidth() * 3 / 2 - y + 1)
715
{
716
// upper right triangle
717
EXPECT_EQ(GLColor::green, actualColors[currentPosition]);
718
}
719
}
720
}
721
}
722
723
// Redeclare gl_ClipDistance in shader with explicit size, also use it in a global function
724
// outside main()
725
TEST_P(ClipCullDistanceTest, ThreeClipDistancesRedeclared)
726
{
727
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
728
729
constexpr char kVS[] = R"(#version 300 es
730
#extension GL_EXT_clip_cull_distance : require
731
732
out highp float gl_ClipDistance[3];
733
734
void computeClipDistances(in vec4 position, in vec4 plane[3])
735
{
736
gl_ClipDistance[0] = dot(position, plane[0]);
737
gl_ClipDistance[1] = dot(position, plane[1]);
738
gl_ClipDistance[2] = dot(position, plane[2]);
739
}
740
741
uniform vec4 u_plane[3];
742
743
in vec2 a_position;
744
745
void main()
746
{
747
gl_Position = vec4(a_position, 0.0, 1.0);
748
749
computeClipDistances(gl_Position, u_plane);
750
})";
751
752
ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());
753
glLinkProgram(programRed);
754
glUseProgram(programRed);
755
ASSERT_GL_NO_ERROR();
756
757
// Enable 3 clip distances
758
glEnable(GL_CLIP_DISTANCE0_EXT);
759
glEnable(GL_CLIP_DISTANCE1_EXT);
760
glEnable(GL_CLIP_DISTANCE2_EXT);
761
ASSERT_GL_NO_ERROR();
762
763
// Clear to blue
764
glClearColor(0, 0, 1, 1);
765
glClear(GL_COLOR_BUFFER_BIT);
766
767
// Draw full screen quad with color red
768
// x = -0.5
769
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);
770
// x = 0.5
771
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);
772
// x + y = 1
773
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);
774
EXPECT_GL_NO_ERROR();
775
drawQuad(programRed, "a_position", 0);
776
EXPECT_GL_NO_ERROR();
777
778
// All pixels on the left of the plane x = -0.5 must be blue
779
GLuint x = 0;
780
GLuint y = 0;
781
GLuint width = getWindowWidth() / 4 - 1;
782
GLuint height = getWindowHeight();
783
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::blue);
784
785
// All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
786
// triangle
787
x = getWindowWidth() / 4 + 2;
788
y = 0;
789
width = getWindowWidth() / 2 - x;
790
height = getWindowHeight();
791
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);
792
793
std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
794
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
795
actualColors.data());
796
for (int y = 0; y < getWindowHeight(); ++y)
797
{
798
for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
799
{
800
const int currentPosition = y * getWindowHeight() + x;
801
802
if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)
803
{
804
// bottom left triangle clipped by x=0.5 plane
805
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
806
}
807
else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)
808
{
809
// upper right triangle plus right of x=0.5 plane
810
EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);
811
}
812
}
813
}
814
}
815
816
// Write to one gl_CullDistance element
817
TEST_P(ClipCullDistanceTest, OneCullDistance)
818
{
819
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
820
821
constexpr char kVS[] = R"(#version 300 es
822
#extension GL_EXT_clip_cull_distance : require
823
824
uniform vec4 u_plane;
825
826
in vec2 a_position;
827
828
void main()
829
{
830
gl_Position = vec4(a_position, 0.0, 1.0);
831
832
gl_CullDistance[0] = dot(gl_Position, u_plane);
833
})";
834
835
ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());
836
glLinkProgram(programRed);
837
glUseProgram(programRed);
838
ASSERT_GL_NO_ERROR();
839
840
// Clear to blue
841
glClearColor(0, 0, 1, 1);
842
glClear(GL_COLOR_BUFFER_BIT);
843
844
// Draw full screen quad with color red
845
glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 0, 0, 0.5);
846
EXPECT_GL_NO_ERROR();
847
drawQuad(programRed, "a_position", 0);
848
EXPECT_GL_NO_ERROR();
849
850
// All pixels must be red
851
GLuint x = 0;
852
GLuint y = 0;
853
GLuint width = getWindowWidth();
854
GLuint height = getWindowHeight();
855
EXPECT_PIXEL_RECT_EQ(x, y, width, height, GLColor::red);
856
857
// Clear to green
858
glClearColor(0, 1, 0, 1);
859
glClear(GL_COLOR_BUFFER_BIT);
860
861
// Draw full screen quad with color red
862
glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 1, 0, 0);
863
EXPECT_GL_NO_ERROR();
864
drawQuad(programRed, "a_position", 0);
865
EXPECT_GL_NO_ERROR();
866
867
// All pixels on the plane y >= -x must be red
868
std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
869
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
870
actualColors.data());
871
for (int x = 0; x < getWindowWidth(); ++x)
872
{
873
for (int y = 0; y < getWindowHeight(); ++y)
874
{
875
const int currentPosition = y * getWindowHeight() + x;
876
877
if ((x + y) >= 0)
878
{
879
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
880
}
881
else
882
{
883
EXPECT_EQ(GLColor::green, actualColors[currentPosition]);
884
}
885
}
886
}
887
}
888
889
// Write to 4 clip distances
890
TEST_P(ClipCullDistanceTest, FourClipDistances)
891
{
892
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
893
894
constexpr char kVS[] = R"(#version 300 es
895
#extension GL_EXT_clip_cull_distance : require
896
897
in vec2 a_position;
898
uniform vec4 u_plane[4];
899
900
void main()
901
{
902
gl_Position = vec4(a_position, 0.0, 1.0);
903
904
gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);
905
gl_ClipDistance[1] = dot(gl_Position, u_plane[1]);
906
gl_ClipDistance[2] = dot(gl_Position, u_plane[2]);
907
gl_ClipDistance[3] = dot(gl_Position, u_plane[3]);
908
})";
909
910
ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());
911
glUseProgram(programRed);
912
ASSERT_GL_NO_ERROR();
913
914
// Enable 3 clip distances
915
glEnable(GL_CLIP_DISTANCE0_EXT);
916
glEnable(GL_CLIP_DISTANCE2_EXT);
917
glEnable(GL_CLIP_DISTANCE3_EXT);
918
ASSERT_GL_NO_ERROR();
919
920
// Disable 1 clip distances
921
glDisable(GL_CLIP_DISTANCE1_EXT);
922
ASSERT_GL_NO_ERROR();
923
924
// Clear to blue
925
glClearColor(0, 0, 1, 1);
926
glClear(GL_COLOR_BUFFER_BIT);
927
928
constexpr unsigned int kNumVertices = 12;
929
const std::array<Vector3, kNumVertices> quadVertices = {
930
{Vector3(-1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f),
931
Vector3(1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, -1.0f, 0.0f),
932
Vector3(1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, -1.0f, 0.0f),
933
Vector3(-1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, 1.0f, 0.0f)}};
934
935
GLBuffer vertexBuffer;
936
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
937
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),
938
GL_STATIC_DRAW);
939
ASSERT_GL_NO_ERROR();
940
941
GLint positionLocation = glGetAttribLocation(programRed, "a_position");
942
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
943
ASSERT_GL_NO_ERROR();
944
945
glEnableVertexAttribArray(positionLocation);
946
ASSERT_GL_NO_ERROR();
947
948
// Draw full screen quad and small size triangle with color red
949
// y <= 1.0f
950
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);
951
// y >= 0.5f
952
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);
953
// y >= 3x-0.5f
954
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);
955
// y >= -3x-0.5f
956
glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);
957
EXPECT_GL_NO_ERROR();
958
959
glDrawArrays(GL_TRIANGLES, 0, kNumVertices);
960
EXPECT_GL_NO_ERROR();
961
962
const int windowWidth = getWindowWidth();
963
const int windowHeight = getWindowHeight();
964
auto checkLeftPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {
965
return (3 * (x - (windowWidth / 2 - 1)) - (windowHeight / 4 + 1) + y);
966
};
967
auto checkRightPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {
968
return (-3 * (x - (windowWidth / 2)) - (windowHeight / 4 + 1) + y);
969
};
970
971
// Only pixels in the triangle must be red
972
std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
973
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
974
actualColors.data());
975
for (int x = 0; x < getWindowWidth(); ++x)
976
{
977
for (int y = 0; y < getWindowHeight(); ++y)
978
{
979
// The drawing method of Swiftshader and Native graphic card is different. So the
980
// compare function doesn't check the value on the line.
981
const int currentPosition = y * getWindowHeight() + x;
982
983
if (checkLeftPlaneFunc(x, y) > 0 && checkRightPlaneFunc(x, y) > 0)
984
{
985
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
986
}
987
else if (checkLeftPlaneFunc(x, y) < 0 || checkRightPlaneFunc(x, y) < 0)
988
{
989
EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);
990
}
991
}
992
}
993
}
994
995
// Write to 4 cull distances
996
TEST_P(ClipCullDistanceTest, FourCullDistances)
997
{
998
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance"));
999
1000
// SwiftShader bug: http://anglebug.com/5451
1001
ANGLE_SKIP_TEST_IF(isSwiftshader());
1002
1003
constexpr char kVS[] = R"(#version 300 es
1004
#extension GL_EXT_clip_cull_distance : require
1005
1006
uniform vec4 u_plane[4];
1007
1008
in vec2 a_position;
1009
1010
void main()
1011
{
1012
gl_Position = vec4(a_position, 0.0, 1.0);
1013
1014
gl_CullDistance[0] = dot(gl_Position, u_plane[0]);
1015
gl_CullDistance[1] = dot(gl_Position, u_plane[1]);
1016
gl_CullDistance[2] = dot(gl_Position, u_plane[2]);
1017
gl_CullDistance[3] = dot(gl_Position, u_plane[3]);
1018
})";
1019
1020
ANGLE_GL_PROGRAM(programRed, kVS, essl3_shaders::fs::Red());
1021
glLinkProgram(programRed);
1022
glUseProgram(programRed);
1023
ASSERT_GL_NO_ERROR();
1024
1025
// Clear to blue
1026
glClearColor(0, 0, 1, 1);
1027
glClear(GL_COLOR_BUFFER_BIT);
1028
1029
constexpr unsigned int kNumVertices = 12;
1030
const std::array<Vector3, kNumVertices> quadVertices = {
1031
{Vector3(-1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f),
1032
Vector3(1.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, -1.0f, 0.0f),
1033
Vector3(1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, -1.0f, 0.0f),
1034
Vector3(-1.0f, -1.0f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-1.0f, 1.0f, 0.0f)}};
1035
1036
GLBuffer vertexBuffer;
1037
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1038
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),
1039
GL_STATIC_DRAW);
1040
ASSERT_GL_NO_ERROR();
1041
1042
GLint positionLocation = glGetAttribLocation(programRed, "a_position");
1043
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1044
ASSERT_GL_NO_ERROR();
1045
1046
glEnableVertexAttribArray(positionLocation);
1047
ASSERT_GL_NO_ERROR();
1048
1049
// Draw full screen quad and small size triangle with color red
1050
// y <= 1.0f
1051
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);
1052
// y >= 0.5f
1053
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);
1054
// y >= 3x-0.5f
1055
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);
1056
// y >= -3x-0.5f
1057
glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);
1058
EXPECT_GL_NO_ERROR();
1059
1060
glDrawArrays(GL_TRIANGLES, 0, kNumVertices);
1061
EXPECT_GL_NO_ERROR();
1062
1063
// Only pixels in the triangle must be red
1064
std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
1065
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
1066
actualColors.data());
1067
for (int x = 0; x < getWindowWidth(); ++x)
1068
{
1069
for (int y = 0; y < getWindowHeight(); ++y)
1070
{
1071
const int currentPosition = y * getWindowHeight() + x;
1072
1073
if (y > x || y >= -x + getWindowHeight() - 1)
1074
{
1075
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
1076
}
1077
else
1078
{
1079
EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);
1080
}
1081
}
1082
}
1083
}
1084
1085
// Verify that EXT_clip_cull_distance works with EXT_geometry_shader
1086
TEST_P(ClipCullDistanceTest, ClipDistanceInteractWithGeometryShader)
1087
{
1088
// TODO: http://anglebug.com/5466
1089
// After implementing EXT_geometry_shader, EXT_clip_cull_distance should be additionally
1090
// implemented to support the geometry shader. And then, this skip can be removed.
1091
ANGLE_SKIP_TEST_IF(IsVulkan());
1092
1093
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance") ||
1094
!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1095
1096
constexpr char kVS[] = R"(#version 310 es
1097
#extension GL_EXT_clip_cull_distance : require
1098
#extension GL_EXT_geometry_shader : require
1099
1100
in vec2 a_position;
1101
uniform vec4 u_plane[4];
1102
1103
void main()
1104
{
1105
gl_Position = vec4(a_position, 0.0, 1.0);
1106
1107
gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);
1108
gl_ClipDistance[1] = dot(gl_Position, u_plane[1]);
1109
gl_ClipDistance[2] = dot(gl_Position, u_plane[2]);
1110
gl_ClipDistance[3] = dot(gl_Position, u_plane[3]);
1111
})";
1112
1113
constexpr char kGS[] = R"(#version 310 es
1114
#extension GL_EXT_clip_cull_distance : require
1115
#extension GL_EXT_geometry_shader : require
1116
1117
layout (triangles) in;
1118
layout (triangle_strip, max_vertices = 3) out;
1119
1120
in gl_PerVertex {
1121
highp vec4 gl_Position;
1122
highp float gl_ClipDistance[];
1123
} gl_in[];
1124
1125
out gl_PerVertex {
1126
highp vec4 gl_Position;
1127
highp float gl_ClipDistance[];
1128
};
1129
1130
uniform vec4 u_plane[4];
1131
1132
void GetNewPosition(int i)
1133
{
1134
gl_Position = 2.0f * gl_in[i].gl_Position;
1135
1136
for (int index = 0 ; index < 4 ; index++)
1137
{
1138
if (gl_in[i].gl_ClipDistance[index] < 0.0f)
1139
{
1140
gl_ClipDistance[index] = dot(gl_Position, u_plane[index]);
1141
}
1142
}
1143
EmitVertex();
1144
}
1145
1146
void main()
1147
{
1148
for (int i = 0 ; i < 3 ; i++)
1149
{
1150
GetNewPosition(i);
1151
}
1152
EndPrimitive();
1153
})";
1154
1155
ANGLE_GL_PROGRAM_WITH_GS(programRed, kVS, kGS, essl31_shaders::fs::Red());
1156
glUseProgram(programRed);
1157
ASSERT_GL_NO_ERROR();
1158
1159
// Enable 3 clip distances
1160
glEnable(GL_CLIP_DISTANCE0_EXT);
1161
glEnable(GL_CLIP_DISTANCE2_EXT);
1162
glEnable(GL_CLIP_DISTANCE3_EXT);
1163
ASSERT_GL_NO_ERROR();
1164
1165
// Disable 1 clip distances
1166
glDisable(GL_CLIP_DISTANCE1_EXT);
1167
ASSERT_GL_NO_ERROR();
1168
1169
// Clear to blue
1170
glClearColor(0, 0, 1, 1);
1171
glClear(GL_COLOR_BUFFER_BIT);
1172
1173
constexpr unsigned int kNumVertices = 12;
1174
const std::array<Vector3, kNumVertices> quadVertices = {
1175
{Vector3(-0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, 0.5f, 0.0f),
1176
Vector3(0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, -0.5f, 0.0f),
1177
Vector3(0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, -0.5f, 0.0f),
1178
Vector3(-0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, 0.5f, 0.0f)}};
1179
1180
GLBuffer vertexBuffer;
1181
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1182
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),
1183
GL_STATIC_DRAW);
1184
ASSERT_GL_NO_ERROR();
1185
1186
GLint positionLocation = glGetAttribLocation(programRed, "a_position");
1187
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1188
ASSERT_GL_NO_ERROR();
1189
1190
glEnableVertexAttribArray(positionLocation);
1191
ASSERT_GL_NO_ERROR();
1192
1193
// Draw full screen quad and small size triangle with color red
1194
// y <= 1.0f
1195
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);
1196
// y >= 0.5f
1197
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);
1198
// y >= 3x-0.5f
1199
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);
1200
// y >= -3x-0.5f
1201
glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);
1202
EXPECT_GL_NO_ERROR();
1203
1204
glDrawArrays(GL_TRIANGLES, 0, kNumVertices);
1205
EXPECT_GL_NO_ERROR();
1206
1207
const int windowWidth = getWindowWidth();
1208
const int windowHeight = getWindowHeight();
1209
auto checkLeftPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {
1210
return (3 * (x - (windowWidth / 2 - 1)) - (windowHeight / 4 + 1) + y);
1211
};
1212
auto checkRightPlaneFunc = [windowWidth, windowHeight](int x, int y) -> float {
1213
return (-3 * (x - (windowWidth / 2)) - (windowHeight / 4 + 1) + y);
1214
};
1215
1216
// Only pixels in the triangle must be red
1217
std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
1218
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
1219
actualColors.data());
1220
for (int x = 0; x < getWindowWidth(); ++x)
1221
{
1222
for (int y = 0; y < getWindowHeight(); ++y)
1223
{
1224
// The drawing method of Swiftshader and Native graphic card is different. So the
1225
// compare function doesn't check the value on the line.
1226
const int currentPosition = y * getWindowHeight() + x;
1227
1228
if (checkLeftPlaneFunc(x, y) > 0 && checkRightPlaneFunc(x, y) > 0)
1229
{
1230
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
1231
}
1232
else if (checkLeftPlaneFunc(x, y) < 0 || checkRightPlaneFunc(x, y) < 0)
1233
{
1234
EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);
1235
}
1236
}
1237
}
1238
}
1239
1240
// Verify that EXT_clip_cull_distance works with EXT_geometry_shader
1241
TEST_P(ClipCullDistanceTest, CullDistanceInteractWithGeometryShader)
1242
{
1243
// TODO: http://anglebug.com/5466
1244
// After implementing EXT_geometry_shader, EXT_clip_cull_distance should be additionally
1245
// implemented to support the geometry shader. And then, this skip can be removed.
1246
ANGLE_SKIP_TEST_IF(IsVulkan());
1247
1248
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clip_cull_distance") ||
1249
!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1250
1251
constexpr char kVS[] = R"(#version 310 es
1252
#extension GL_EXT_clip_cull_distance : require
1253
#extension GL_EXT_geometry_shader : require
1254
1255
in vec2 a_position;
1256
uniform vec4 u_plane[4];
1257
1258
void main()
1259
{
1260
gl_Position = vec4(a_position, 0.0, 1.0);
1261
1262
gl_CullDistance[0] = dot(gl_Position, u_plane[0]);
1263
gl_CullDistance[1] = dot(gl_Position, u_plane[1]);
1264
gl_CullDistance[2] = dot(gl_Position, u_plane[2]);
1265
gl_CullDistance[3] = dot(gl_Position, u_plane[3]);
1266
})";
1267
1268
constexpr char kGS[] = R"(#version 310 es
1269
#extension GL_EXT_clip_cull_distance : require
1270
#extension GL_EXT_geometry_shader : require
1271
1272
layout (triangles) in;
1273
layout (triangle_strip, max_vertices = 3) out;
1274
1275
in gl_PerVertex {
1276
highp vec4 gl_Position;
1277
highp float gl_CullDistance[];
1278
} gl_in[];
1279
1280
out gl_PerVertex {
1281
highp vec4 gl_Position;
1282
highp float gl_CullDistance[];
1283
};
1284
1285
uniform vec4 u_plane[4];
1286
1287
void GetNewPosition(int i)
1288
{
1289
gl_Position = 2.0f * gl_in[i].gl_Position;
1290
1291
for (int index = 0 ; index < 4 ; index++)
1292
{
1293
if (gl_in[i].gl_CullDistance[index] < 0.0f)
1294
{
1295
gl_CullDistance[index] = dot(gl_Position, u_plane[index]);
1296
}
1297
}
1298
EmitVertex();
1299
}
1300
1301
void main()
1302
{
1303
for (int i = 0 ; i < 3 ; i++)
1304
{
1305
GetNewPosition(i);
1306
}
1307
EndPrimitive();
1308
})";
1309
1310
ANGLE_GL_PROGRAM_WITH_GS(programRed, kVS, kGS, essl31_shaders::fs::Red());
1311
glUseProgram(programRed);
1312
ASSERT_GL_NO_ERROR();
1313
1314
// Clear to blue
1315
glClearColor(0, 0, 1, 1);
1316
glClear(GL_COLOR_BUFFER_BIT);
1317
1318
constexpr unsigned int kNumVertices = 12;
1319
const std::array<Vector3, kNumVertices> quadVertices = {
1320
{Vector3(-0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, 0.5f, 0.0f),
1321
Vector3(0.5f, 0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.5f, -0.5f, 0.0f),
1322
Vector3(0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, -0.5f, 0.0f),
1323
Vector3(-0.5f, -0.5f, 0.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(-0.5f, 0.5f, 0.0f)}};
1324
1325
GLBuffer vertexBuffer;
1326
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1327
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * kNumVertices, quadVertices.data(),
1328
GL_STATIC_DRAW);
1329
ASSERT_GL_NO_ERROR();
1330
1331
GLint positionLocation = glGetAttribLocation(programRed, "a_position");
1332
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1333
ASSERT_GL_NO_ERROR();
1334
1335
glEnableVertexAttribArray(positionLocation);
1336
ASSERT_GL_NO_ERROR();
1337
1338
// Draw full screen quad and small size triangle with color red
1339
// y <= 1.0f
1340
glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 0, -1, 0, 1);
1341
// y >= 0.5f
1342
glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), 0, 1, 0, -0.5);
1343
// y >= 3x-0.5f
1344
glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -3, 1, 0, 0.5);
1345
// y >= -3x-0.5f
1346
glUniform4f(glGetUniformLocation(programRed, "u_plane[3]"), 3, 1, 0, 0.5);
1347
EXPECT_GL_NO_ERROR();
1348
1349
glDrawArrays(GL_TRIANGLES, 0, kNumVertices);
1350
EXPECT_GL_NO_ERROR();
1351
1352
// Only pixels in the triangle must be red
1353
std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
1354
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
1355
actualColors.data());
1356
for (int x = 0; x < getWindowWidth(); ++x)
1357
{
1358
for (int y = 0; y < getWindowHeight(); ++y)
1359
{
1360
const int currentPosition = y * getWindowHeight() + x;
1361
1362
if (y > x || y >= -x + getWindowHeight() - 1)
1363
{
1364
EXPECT_EQ(GLColor::red, actualColors[currentPosition]);
1365
}
1366
else
1367
{
1368
EXPECT_EQ(GLColor::blue, actualColors[currentPosition]);
1369
}
1370
}
1371
}
1372
}
1373
1374
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(ClipDistanceTest, WithDirectSPIRVGeneration(ES3_VULKAN()));
1375
1376
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ClipCullDistanceTest);
1377
ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND(ClipCullDistanceTest,
1378
WithDirectSPIRVGeneration(ES3_VULKAN()),
1379
WithDirectSPIRVGeneration(ES31_VULKAN()));
1380
1381