summaryrefslogtreecommitdiffstats
path: root/tests/glsl
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-09 11:34:21 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-09 13:44:59 -0700
commitfcf83dbf9effab3bd98bad2b83b2468b7eb05cfd (patch)
tree41047c94883b86ec085a81597391ce3ef557cd43 /tests/glsl
parent52e8d4b9a27ab0060f874c3a63ab531847be35c0 (diff)
Initial import of code.
Diffstat (limited to 'tests/glsl')
-rw-r--r--tests/glsl/sascha-willems/LICENSE.md21
-rw-r--r--tests/glsl/sascha-willems/README.md8
-rw-r--r--tests/glsl/sascha-willems/base/textoverlay.frag14
-rw-r--r--tests/glsl/sascha-willems/base/textoverlay.vert18
-rw-r--r--tests/glsl/sascha-willems/bloom/colorpass.frag18
-rw-r--r--tests/glsl/sascha-willems/bloom/colorpass.vert31
-rw-r--r--tests/glsl/sascha-willems/bloom/gaussblur.frag48
-rw-r--r--tests/glsl/sascha-willems/bloom/gaussblur.vert18
-rw-r--r--tests/glsl/sascha-willems/bloom/phongpass.frag34
-rw-r--r--tests/glsl/sascha-willems/bloom/phongpass.vert42
-rw-r--r--tests/glsl/sascha-willems/bloom/skybox.frag16
-rw-r--r--tests/glsl/sascha-willems/bloom/skybox.vert28
-rw-r--r--tests/glsl/sascha-willems/computecullandlod/cull.comp127
-rw-r--r--tests/glsl/sascha-willems/computecullandlod/indirectdraw.frag21
-rw-r--r--tests/glsl/sascha-willems/computecullandlod/indirectdraw.vert46
-rw-r--r--tests/glsl/sascha-willems/computenbody/particle.frag18
-rw-r--r--tests/glsl/sascha-willems/computenbody/particle.vert36
-rw-r--r--tests/glsl/sascha-willems/computenbody/particle_calculate.comp75
-rw-r--r--tests/glsl/sascha-willems/computenbody/particle_integrate.comp36
-rw-r--r--tests/glsl/sascha-willems/computeparticles/particle.comp80
-rw-r--r--tests/glsl/sascha-willems/computeparticles/particle.frag19
-rw-r--r--tests/glsl/sascha-willems/computeparticles/particle.vert25
-rw-r--r--tests/glsl/sascha-willems/computeshader/edgedetect.comp48
-rw-r--r--tests/glsl/sascha-willems/computeshader/emboss.comp48
-rw-r--r--tests/glsl/sascha-willems/computeshader/sharpen.comp57
-rw-r--r--tests/glsl/sascha-willems/computeshader/texture.frag16
-rw-r--r--tests/glsl/sascha-willems/computeshader/texture.vert27
-rw-r--r--tests/glsl/sascha-willems/cubemap/reflect.frag36
-rw-r--r--tests/glsl/sascha-willems/cubemap/reflect.vert42
-rw-r--r--tests/glsl/sascha-willems/cubemap/skybox.frag16
-rw-r--r--tests/glsl/sascha-willems/cubemap/skybox.vert27
-rw-r--r--tests/glsl/sascha-willems/debugmarker/colorpass.frag14
-rw-r--r--tests/glsl/sascha-willems/debugmarker/colorpass.vert29
-rw-r--r--tests/glsl/sascha-willems/debugmarker/postprocess.frag43
-rw-r--r--tests/glsl/sascha-willems/debugmarker/postprocess.vert18
-rw-r--r--tests/glsl/sascha-willems/debugmarker/toon.frag40
-rw-r--r--tests/glsl/sascha-willems/debugmarker/toon.vert42
-rw-r--r--tests/glsl/sascha-willems/deferred/debug.frag27
-rw-r--r--tests/glsl/sascha-willems/deferred/debug.vert28
-rw-r--r--tests/glsl/sascha-willems/deferred/deferred.frag76
-rw-r--r--tests/glsl/sascha-willems/deferred/deferred.vert18
-rw-r--r--tests/glsl/sascha-willems/deferred/mrt.frag34
-rw-r--r--tests/glsl/sascha-willems/deferred/mrt.vert53
-rw-r--r--tests/glsl/sascha-willems/deferredmultisampling/debug.frag56
-rw-r--r--tests/glsl/sascha-willems/deferredmultisampling/debug.vert24
-rw-r--r--tests/glsl/sascha-willems/deferredmultisampling/deferred.frag104
-rw-r--r--tests/glsl/sascha-willems/deferredmultisampling/deferred.vert24
-rw-r--r--tests/glsl/sascha-willems/deferredmultisampling/mrt.frag34
-rw-r--r--tests/glsl/sascha-willems/deferredmultisampling/mrt.vert53
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/debug.frag30
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/debug.vert30
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/deferred.frag147
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/deferred.vert27
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/mrt.frag33
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/mrt.vert51
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/shadow.frag12
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/shadow.geom36
-rw-r--r--tests/glsl/sascha-willems/deferredshadows/shadow.vert20
-rw-r--r--tests/glsl/sascha-willems/displacement/base.frag30
-rw-r--r--tests/glsl/sascha-willems/displacement/base.vert19
-rw-r--r--tests/glsl/sascha-willems/displacement/displacement.tesc33
-rw-r--r--tests/glsl/sascha-willems/displacement/displacement.tese40
-rw-r--r--tests/glsl/sascha-willems/distancefieldfonts/bitmap.frag16
-rw-r--r--tests/glsl/sascha-willems/distancefieldfonts/bitmap.vert22
-rw-r--r--tests/glsl/sascha-willems/distancefieldfonts/sdf.frag36
-rw-r--r--tests/glsl/sascha-willems/distancefieldfonts/sdf.vert22
-rw-r--r--tests/glsl/sascha-willems/dynamicuniformbuffer/base.frag14
-rw-r--r--tests/glsl/sascha-willems/dynamicuniformbuffer/base.vert34
-rw-r--r--tests/glsl/sascha-willems/gears/gears.frag25
-rw-r--r--tests/glsl/sascha-willems/gears/gears.vert35
-rw-r--r--tests/glsl/sascha-willems/geometryshader/base.frag14
-rw-r--r--tests/glsl/sascha-willems/geometryshader/base.vert21
-rw-r--r--tests/glsl/sascha-willems/geometryshader/mesh.frag24
-rw-r--r--tests/glsl/sascha-willems/geometryshader/mesh.vert39
-rw-r--r--tests/glsl/sascha-willems/geometryshader/normaldebug.geom38
-rw-r--r--tests/glsl/sascha-willems/hdr/bloom.frag67
-rw-r--r--tests/glsl/sascha-willems/hdr/bloom.vert18
-rw-r--r--tests/glsl/sascha-willems/hdr/composition.frag17
-rw-r--r--tests/glsl/sascha-willems/hdr/composition.vert18
-rw-r--r--tests/glsl/sascha-willems/hdr/gbuffer.frag95
-rw-r--r--tests/glsl/sascha-willems/hdr/gbuffer.vert51
-rw-r--r--tests/glsl/sascha-willems/imgui/scene.frag23
-rw-r--r--tests/glsl/sascha-willems/imgui/scene.vert39
-rw-r--r--tests/glsl/sascha-willems/imgui/ui.frag14
-rw-r--r--tests/glsl/sascha-willems/imgui/ui.vert26
-rw-r--r--tests/glsl/sascha-willems/indirectdraw/ground.frag29
-rw-r--r--tests/glsl/sascha-willems/indirectdraw/ground.vert44
-rw-r--r--tests/glsl/sascha-willems/indirectdraw/indirectdraw.frag31
-rw-r--r--tests/glsl/sascha-willems/indirectdraw/indirectdraw.vert83
-rw-r--r--tests/glsl/sascha-willems/indirectdraw/skysphere.frag18
-rw-r--r--tests/glsl/sascha-willems/indirectdraw/skysphere.vert29
-rw-r--r--tests/glsl/sascha-willems/instancing/instancing.frag27
-rw-r--r--tests/glsl/sascha-willems/instancing/instancing.vert85
-rw-r--r--tests/glsl/sascha-willems/instancing/planet.frag27
-rw-r--r--tests/glsl/sascha-willems/instancing/planet.vert36
-rw-r--r--tests/glsl/sascha-willems/instancing/starfield.frag35
-rw-r--r--tests/glsl/sascha-willems/instancing/starfield.vert10
-rw-r--r--tests/glsl/sascha-willems/mesh/mesh.frag28
-rw-r--r--tests/glsl/sascha-willems/mesh/mesh.vert42
-rw-r--r--tests/glsl/sascha-willems/multithreading/phong.frag24
-rw-r--r--tests/glsl/sascha-willems/multithreading/phong.vert43
-rw-r--r--tests/glsl/sascha-willems/multithreading/starsphere.frag43
-rw-r--r--tests/glsl/sascha-willems/multithreading/starsphere.vert20
-rw-r--r--tests/glsl/sascha-willems/occlusionquery/mesh.frag32
-rw-r--r--tests/glsl/sascha-willems/occlusionquery/mesh.vert42
-rw-r--r--tests/glsl/sascha-willems/occlusionquery/occluder.frag14
-rw-r--r--tests/glsl/sascha-willems/occlusionquery/occluder.vert29
-rw-r--r--tests/glsl/sascha-willems/occlusionquery/simple.frag14
-rw-r--r--tests/glsl/sascha-willems/occlusionquery/simple.vert26
-rw-r--r--tests/glsl/sascha-willems/offscreen/mirror.frag44
-rw-r--r--tests/glsl/sascha-willems/offscreen/mirror.vert29
-rw-r--r--tests/glsl/sascha-willems/offscreen/phong.frag30
-rw-r--r--tests/glsl/sascha-willems/offscreen/phong.vert40
-rw-r--r--tests/glsl/sascha-willems/offscreen/quad.frag16
-rw-r--r--tests/glsl/sascha-willems/offscreen/quad.vert27
-rw-r--r--tests/glsl/sascha-willems/parallax/parallax.frag144
-rw-r--r--tests/glsl/sascha-willems/parallax/parallax.vert38
-rw-r--r--tests/glsl/sascha-willems/particlefire/normalmap.frag45
-rw-r--r--tests/glsl/sascha-willems/particlefire/normalmap.vert60
-rw-r--r--tests/glsl/sascha-willems/particlefire/particle.frag47
-rw-r--r--tests/glsl/sascha-willems/particlefire/particle.vert50
-rw-r--r--tests/glsl/sascha-willems/pbrbasic/pbr.frag128
-rw-r--r--tests/glsl/sascha-willems/pbrbasic/pbr.vert39
-rw-r--r--tests/glsl/sascha-willems/pbribl/filtercube.vert20
-rw-r--r--tests/glsl/sascha-willems/pbribl/genbrdflut.frag91
-rw-r--r--tests/glsl/sascha-willems/pbribl/genbrdflut.vert10
-rw-r--r--tests/glsl/sascha-willems/pbribl/irradiancecube.frag38
-rw-r--r--tests/glsl/sascha-willems/pbribl/pbribl.frag163
-rw-r--r--tests/glsl/sascha-willems/pbribl/pbribl.vert40
-rw-r--r--tests/glsl/sascha-willems/pbribl/prefilterenvmap.frag106
-rw-r--r--tests/glsl/sascha-willems/pbribl/skybox.frag40
-rw-r--r--tests/glsl/sascha-willems/pbribl/skybox.vert28
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/filtercube.vert20
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/genbrdflut.frag91
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/genbrdflut.vert10
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/irradiancecube.frag38
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/pbrtexture.frag179
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/pbrtexture.vert36
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/prefilterenvmap.frag106
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/skybox.frag40
-rw-r--r--tests/glsl/sascha-willems/pbrtexture/skybox.vert28
-rw-r--r--tests/glsl/sascha-willems/pipelines/phong.frag31
-rw-r--r--tests/glsl/sascha-willems/pipelines/phong.vert42
-rw-r--r--tests/glsl/sascha-willems/pipelines/toon.frag40
-rw-r--r--tests/glsl/sascha-willems/pipelines/toon.vert42
-rw-r--r--tests/glsl/sascha-willems/pipelines/wireframe.frag14
-rw-r--r--tests/glsl/sascha-willems/pipelines/wireframe.vert29
-rw-r--r--tests/glsl/sascha-willems/pushconstants/lights.frag41
-rw-r--r--tests/glsl/sascha-willems/pushconstants/lights.vert48
-rw-r--r--tests/glsl/sascha-willems/radialblur/colorpass.frag25
-rw-r--r--tests/glsl/sascha-willems/radialblur/colorpass.vert30
-rw-r--r--tests/glsl/sascha-willems/radialblur/phongpass.frag37
-rw-r--r--tests/glsl/sascha-willems/radialblur/phongpass.vert38
-rw-r--r--tests/glsl/sascha-willems/radialblur/radialblur.frag39
-rw-r--r--tests/glsl/sascha-willems/radialblur/radialblur.vert18
-rw-r--r--tests/glsl/sascha-willems/raytracing/raytracing.comp258
-rw-r--r--tests/glsl/sascha-willems/raytracing/texture.frag16
-rw-r--r--tests/glsl/sascha-willems/raytracing/texture.vert18
-rw-r--r--tests/glsl/sascha-willems/scenerendering/scene.frag35
-rw-r--r--tests/glsl/sascha-willems/scenerendering/scene.vert46
-rw-r--r--tests/glsl/sascha-willems/screenshot/mesh.frag24
-rw-r--r--tests/glsl/sascha-willems/screenshot/mesh.vert40
-rw-r--r--tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.frag17
-rw-r--r--tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.vert28
-rw-r--r--tests/glsl/sascha-willems/shadowmapomni/offscreen.frag17
-rw-r--r--tests/glsl/sascha-willems/shadowmapomni/offscreen.vert36
-rw-r--r--tests/glsl/sascha-willems/shadowmapomni/scene.frag44
-rw-r--r--tests/glsl/sascha-willems/shadowmapomni/scene.vert43
-rw-r--r--tests/glsl/sascha-willems/shadowmapping/offscreen.frag14
-rw-r--r--tests/glsl/sascha-willems/shadowmapping/offscreen.vert23
-rw-r--r--tests/glsl/sascha-willems/shadowmapping/quad.frag25
-rw-r--r--tests/glsl/sascha-willems/shadowmapping/quad.vert28
-rw-r--r--tests/glsl/sascha-willems/shadowmapping/scene.frag72
-rw-r--r--tests/glsl/sascha-willems/shadowmapping/scene.vert52
-rw-r--r--tests/glsl/sascha-willems/skeletalanimation/mesh.frag28
-rw-r--r--tests/glsl/sascha-willems/skeletalanimation/mesh.vert53
-rw-r--r--tests/glsl/sascha-willems/skeletalanimation/texture.frag32
-rw-r--r--tests/glsl/sascha-willems/skeletalanimation/texture.vert40
-rw-r--r--tests/glsl/sascha-willems/specializationconstants/uber.frag75
-rw-r--r--tests/glsl/sascha-willems/specializationconstants/uber.vert42
-rw-r--r--tests/glsl/sascha-willems/sphericalenvmapping/sem.frag23
-rw-r--r--tests/glsl/sascha-willems/sphericalenvmapping/sem.vert35
-rw-r--r--tests/glsl/sascha-willems/ssao/blur.frag29
-rw-r--r--tests/glsl/sascha-willems/ssao/composition.frag56
-rw-r--r--tests/glsl/sascha-willems/ssao/fullscreen.vert18
-rw-r--r--tests/glsl/sascha-willems/ssao/gbuffer.frag30
-rw-r--r--tests/glsl/sascha-willems/ssao/gbuffer.vert43
-rw-r--r--tests/glsl/sascha-willems/ssao/ssao.frag73
-rw-r--r--tests/glsl/sascha-willems/subpasses/composition.frag82
-rw-r--r--tests/glsl/sascha-willems/subpasses/composition.vert18
-rw-r--r--tests/glsl/sascha-willems/subpasses/gbuffer.frag43
-rw-r--r--tests/glsl/sascha-willems/subpasses/gbuffer.vert43
-rw-r--r--tests/glsl/sascha-willems/subpasses/transparent.frag34
-rw-r--r--tests/glsl/sascha-willems/subpasses/transparent.vert28
-rw-r--r--tests/glsl/sascha-willems/terraintessellation/skysphere.frag14
-rw-r--r--tests/glsl/sascha-willems/terraintessellation/skysphere.vert24
-rw-r--r--tests/glsl/sascha-willems/terraintessellation/terrain.frag65
-rw-r--r--tests/glsl/sascha-willems/terraintessellation/terrain.tesc120
-rw-r--r--tests/glsl/sascha-willems/terraintessellation/terrain.tese58
-rw-r--r--tests/glsl/sascha-willems/terraintessellation/terrain.vert24
-rw-r--r--tests/glsl/sascha-willems/tessellation/base.frag22
-rw-r--r--tests/glsl/sascha-willems/tessellation/base.vert24
-rw-r--r--tests/glsl/sascha-willems/tessellation/passthrough.tesc28
-rw-r--r--tests/glsl/sascha-willems/tessellation/passthrough.tese31
-rw-r--r--tests/glsl/sascha-willems/tessellation/pntriangles.tesc87
-rw-r--r--tests/glsl/sascha-willems/tessellation/pntriangles.tese92
-rw-r--r--tests/glsl/sascha-willems/textoverlay/background.frag16
-rw-r--r--tests/glsl/sascha-willems/textoverlay/background.vert18
-rw-r--r--tests/glsl/sascha-willems/textoverlay/mesh.frag27
-rw-r--r--tests/glsl/sascha-willems/textoverlay/mesh.vert39
-rw-r--r--tests/glsl/sascha-willems/textoverlay/text.frag14
-rw-r--r--tests/glsl/sascha-willems/textoverlay/text.vert18
-rw-r--r--tests/glsl/sascha-willems/texture/texture.frag29
-rw-r--r--tests/glsl/sascha-willems/texture/texture.vert45
-rw-r--r--tests/glsl/sascha-willems/texture3d/texture3d.frag29
-rw-r--r--tests/glsl/sascha-willems/texture3d/texture3d.vert44
-rw-r--r--tests/glsl/sascha-willems/texturearray/instancing.frag16
-rw-r--r--tests/glsl/sascha-willems/texturearray/instancing.vert30
-rw-r--r--tests/glsl/sascha-willems/texturemipmapgen/texture.frag30
-rw-r--r--tests/glsl/sascha-willems/texturemipmapgen/texture.vert47
-rw-r--r--tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.frag48
-rw-r--r--tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.vert43
-rw-r--r--tests/glsl/sascha-willems/triangle/triangle.frag14
-rw-r--r--tests/glsl/sascha-willems/triangle/triangle.vert29
-rw-r--r--tests/glsl/sascha-willems/viewportarray/multiview.geom46
-rw-r--r--tests/glsl/sascha-willems/viewportarray/scene.frag21
-rw-r--r--tests/glsl/sascha-willems/viewportarray/scene.vert21
-rw-r--r--tests/glsl/sascha-willems/vulkanscene/logo.frag23
-rw-r--r--tests/glsl/sascha-willems/vulkanscene/logo.vert38
-rw-r--r--tests/glsl/sascha-willems/vulkanscene/mesh.frag45
-rw-r--r--tests/glsl/sascha-willems/vulkanscene/mesh.vert38
-rw-r--r--tests/glsl/sascha-willems/vulkanscene/skybox.frag16
-rw-r--r--tests/glsl/sascha-willems/vulkanscene/skybox.vert21
233 files changed, 9190 insertions, 0 deletions
diff --git a/tests/glsl/sascha-willems/LICENSE.md b/tests/glsl/sascha-willems/LICENSE.md
new file mode 100644
index 000000000..2c4cfd5b7
--- /dev/null
+++ b/tests/glsl/sascha-willems/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Sascha Willems
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/tests/glsl/sascha-willems/README.md b/tests/glsl/sascha-willems/README.md
new file mode 100644
index 000000000..3060f9b3d
--- /dev/null
+++ b/tests/glsl/sascha-willems/README.md
@@ -0,0 +1,8 @@
+# GLSL Shaders from Sascha Willems' Vulkan Tutorials
+
+
+These shaders are taken from the [repository][VulkanTutorials] of Vulkan examples developed by Sascha Willems.
+The original code is licensed according to the terms in the [`LICSENSE.md`](LICENSE.md) file in this directory.
+
+[VulkanTutorials]: https://github.com/SaschaWillems/Vulkan/ "Vulkan C++ examples and demos"
+
diff --git a/tests/glsl/sascha-willems/base/textoverlay.frag b/tests/glsl/sascha-willems/base/textoverlay.frag
new file mode 100644
index 000000000..e5dbb08de
--- /dev/null
+++ b/tests/glsl/sascha-willems/base/textoverlay.frag
@@ -0,0 +1,14 @@
+#version 450 core
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec2 inUV;
+
+layout (binding = 0) uniform sampler2D samplerFont;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main(void)
+{
+ float color = texture(samplerFont, inUV).r;
+ outFragColor = vec4(vec3(color), 1.0);
+}
diff --git a/tests/glsl/sascha-willems/base/textoverlay.vert b/tests/glsl/sascha-willems/base/textoverlay.vert
new file mode 100644
index 000000000..8a20fd8b2
--- /dev/null
+++ b/tests/glsl/sascha-willems/base/textoverlay.vert
@@ -0,0 +1,18 @@
+#version 450 core
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec2 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main(void)
+{
+ gl_Position = vec4(inPos, 0.0, 1.0);
+ outUV = inUV;
+}
diff --git a/tests/glsl/sascha-willems/bloom/colorpass.frag b/tests/glsl/sascha-willems/bloom/colorpass.frag
new file mode 100644
index 000000000..63d518d29
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/colorpass.frag
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D colorMap;
+
+layout (location = 0) in vec3 inColor;
+layout (location = 1) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor.rgb = inColor;
+// outFragColor = texture(colorMap, inUV);// * vec4(inColor, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/bloom/colorpass.vert b/tests/glsl/sascha-willems/bloom/colorpass.vert
new file mode 100644
index 000000000..d2f7f4e6f
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/colorpass.vert
@@ -0,0 +1,31 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+layout (location = 1) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ outColor = inColor;
+ gl_Position = ubo.projection * ubo.view * ubo.model * inPos;
+}
diff --git a/tests/glsl/sascha-willems/bloom/gaussblur.frag b/tests/glsl/sascha-willems/bloom/gaussblur.frag
new file mode 100644
index 000000000..4cf4696cf
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/gaussblur.frag
@@ -0,0 +1,48 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (binding = 0) uniform UBO
+{
+ float blurScale;
+ float blurStrength;
+} ubo;
+
+layout (constant_id = 0) const int blurdirection = 0;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ float weight[5];
+ weight[0] = 0.227027;
+ weight[1] = 0.1945946;
+ weight[2] = 0.1216216;
+ weight[3] = 0.054054;
+ weight[4] = 0.016216;
+
+ vec2 tex_offset = 1.0 / textureSize(samplerColor, 0) * ubo.blurScale; // gets size of single texel
+ vec3 result = texture(samplerColor, inUV).rgb * weight[0]; // current fragment's contribution
+ for(int i = 1; i < 5; ++i)
+ {
+ if (blurdirection == 1)
+ {
+ // H
+ result += texture(samplerColor, inUV + vec2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurStrength;
+ result += texture(samplerColor, inUV - vec2(tex_offset.x * i, 0.0)).rgb * weight[i] * ubo.blurStrength;
+ }
+ else
+ {
+ // V
+ result += texture(samplerColor, inUV + vec2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurStrength;
+ result += texture(samplerColor, inUV - vec2(0.0, tex_offset.y * i)).rgb * weight[i] * ubo.blurStrength;
+ }
+ }
+ outFragColor = vec4(result, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/bloom/gaussblur.vert b/tests/glsl/sascha-willems/bloom/gaussblur.vert
new file mode 100644
index 000000000..548284554
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/gaussblur.vert
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/bloom/phongpass.frag b/tests/glsl/sascha-willems/bloom/phongpass.frag
new file mode 100644
index 000000000..9a449f6d1
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/phongpass.frag
@@ -0,0 +1,34 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D colorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 ambient = vec3(0.0f);
+
+ // Adjust light calculations for glow color
+ if ((inColor.r >= 0.9) || (inColor.g >= 0.9) || (inColor.b >= 0.9))
+ {
+ ambient = inColor * 0.25;
+ }
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.75);
+ outFragColor = vec4(ambient + diffuse + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/bloom/phongpass.vert b/tests/glsl/sascha-willems/bloom/phongpass.vert
new file mode 100644
index 000000000..ac0a77ab9
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/phongpass.vert
@@ -0,0 +1,42 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outColor;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.view * ubo.model * inPos;
+
+ vec3 lightPos = vec3(-5.0, -5.0, 0.0);
+ vec4 pos = ubo.view * ubo.model * inPos;
+ outNormal = mat3(ubo.view * ubo.model) * inNormal;
+ outLightVec = lightPos - pos.xyz;
+ outViewVec = -pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/bloom/skybox.frag b/tests/glsl/sascha-willems/bloom/skybox.frag
new file mode 100644
index 000000000..611eb37db
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/skybox.frag
@@ -0,0 +1,16 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform samplerCube samplerCubeMap;
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerCubeMap, inUVW);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/bloom/skybox.vert b/tests/glsl/sascha-willems/bloom/skybox.vert
new file mode 100644
index 000000000..f06b3d38d
--- /dev/null
+++ b/tests/glsl/sascha-willems/bloom/skybox.vert
@@ -0,0 +1,28 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/computecullandlod/cull.comp b/tests/glsl/sascha-willems/computecullandlod/cull.comp
new file mode 100644
index 000000000..d04beb2ec
--- /dev/null
+++ b/tests/glsl/sascha-willems/computecullandlod/cull.comp
@@ -0,0 +1,127 @@
+//TEST_IGNORE_FILE: Currently failing due to lack of support for math on specialization constants
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (constant_id = 0) const int MAX_LOD_LEVEL = 5;
+
+struct InstanceData
+{
+ vec3 pos;
+ float scale;
+};
+
+// Binding 0: Instance input data for culling
+layout (binding = 0, std140) buffer Instances
+{
+ InstanceData instances[ ];
+};
+
+// Same layout as VkDrawIndexedIndirectCommand
+struct IndexedIndirectCommand
+{
+ uint indexCount;
+ uint instanceCount;
+ uint firstIndex;
+ uint vertexOffset;
+ uint firstInstance;
+};
+
+// Binding 1: Multi draw output
+layout (binding = 1, std430) writeonly buffer IndirectDraws
+{
+ IndexedIndirectCommand indirectDraws[ ];
+};
+
+// Binding 2: Uniform block object with matrices
+layout (binding = 2) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 cameraPos;
+ vec4 frustumPlanes[6];
+} ubo;
+
+// Binding 3: Indirect draw stats
+layout (binding = 3) buffer UBOOut
+{
+ uint drawCount;
+ uint lodCount[MAX_LOD_LEVEL + 1];
+} uboOut;
+
+// Binding 4: level-of-detail information
+struct LOD
+{
+ uint firstIndex;
+ uint indexCount;
+ float distance;
+ float _pad0;
+};
+layout (binding = 4) readonly buffer LODs
+{
+ LOD lods[ ];
+};
+
+layout (local_size_x = 16) in;
+
+bool frustumCheck(vec4 pos, float radius)
+{
+ // Check sphere against frustum planes
+ for (int i = 0; i < 6; i++)
+ {
+ if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+layout (local_size_x = 16) in;
+
+void main()
+{
+ uint idx = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x;
+
+ // Clear stats on first invocation
+ if (idx == 0)
+ {
+ atomicExchange(uboOut.drawCount, 0);
+ for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++)
+ {
+ atomicExchange(uboOut.lodCount[i], 0);
+ }
+ }
+
+ vec4 pos = vec4(instances[idx].pos.xyz, 1.0);
+
+ // Check if object is within current viewing frustum
+ if (frustumCheck(pos, 1.0))
+ {
+ indirectDraws[idx].instanceCount = 1;
+
+ // Increase number of indirect draw counts
+ atomicAdd(uboOut.drawCount, 1);
+
+ // Select appropriate LOD level based on distance to camera
+ uint lodLevel = MAX_LOD_LEVEL;
+ for (uint i = 0; i < MAX_LOD_LEVEL; i++)
+ {
+ if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance)
+ {
+ lodLevel = i;
+ break;
+ }
+ }
+ indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex;
+ indirectDraws[idx].indexCount = lods[lodLevel].indexCount;
+ // Update stats
+ atomicAdd(uboOut.lodCount[lodLevel], 1);
+ }
+ else
+ {
+ indirectDraws[idx].instanceCount = 0;
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computecullandlod/indirectdraw.frag b/tests/glsl/sascha-willems/computecullandlod/indirectdraw.frag
new file mode 100644
index 000000000..c1e2240f3
--- /dev/null
+++ b/tests/glsl/sascha-willems/computecullandlod/indirectdraw.frag
@@ -0,0 +1,21 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 ambient = vec3(0.25);
+ vec3 diffuse = vec3(max(dot(N, L), 0.0));
+ outFragColor = vec4((ambient + diffuse) * inColor, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/computecullandlod/indirectdraw.vert b/tests/glsl/sascha-willems/computecullandlod/indirectdraw.vert
new file mode 100644
index 000000000..3f4a4b8c2
--- /dev/null
+++ b/tests/glsl/sascha-willems/computecullandlod/indirectdraw.vert
@@ -0,0 +1,46 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+// Vertex attributes
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+// Instanced attributes
+layout (location = 4) in vec3 instancePos;
+layout (location = 5) in float instanceScale;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+
+ outNormal = inNormal;
+
+ vec4 pos = vec4((inPos.xyz * instanceScale) + instancePos, 1.0);
+
+ gl_Position = ubo.projection * ubo.modelview * pos;
+
+ vec4 wPos = ubo.modelview * vec4(pos.xyz, 1.0);
+ vec4 lPos = vec4(0.0, 10.0, 50.0, 1.0);
+ outLightVec = lPos.xyz - pos.xyz;
+ outViewVec = -pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/computenbody/particle.frag b/tests/glsl/sascha-willems/computenbody/particle.frag
new file mode 100644
index 000000000..e67d2e00f
--- /dev/null
+++ b/tests/glsl/sascha-willems/computenbody/particle.frag
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerColorMap;
+layout (binding = 1) uniform sampler2D samplerGradientRamp;
+
+layout (location = 0) in float inGradientPos;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main ()
+{
+ vec3 color = texture(samplerGradientRamp, vec2(inGradientPos, 0.0)).rgb;
+ outFragColor.rgb = texture(samplerColorMap, gl_PointCoord).rgb * color;
+}
diff --git a/tests/glsl/sascha-willems/computenbody/particle.vert b/tests/glsl/sascha-willems/computenbody/particle.vert
new file mode 100644
index 000000000..eedd185d9
--- /dev/null
+++ b/tests/glsl/sascha-willems/computenbody/particle.vert
@@ -0,0 +1,36 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec4 inVel;
+
+layout (location = 0) out float outGradientPos;
+
+layout (binding = 2) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec2 screendim;
+} ubo;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+ float gl_PointSize;
+};
+
+void main ()
+{
+ const float spriteSize = 0.005 * inPos.w; // Point size influenced by mass (stored in inPos.w);
+
+ vec4 eyePos = ubo.modelview * vec4(inPos.x, inPos.y, inPos.z, 1.0);
+ vec4 projectedCorner = ubo.projection * vec4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w);
+ gl_PointSize = clamp(ubo.screendim.x * projectedCorner.x / projectedCorner.w, 1.0, 128.0);
+
+ gl_Position = ubo.projection * eyePos;
+
+ outGradientPos = inVel.w;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computenbody/particle_calculate.comp b/tests/glsl/sascha-willems/computenbody/particle_calculate.comp
new file mode 100644
index 000000000..82cbe35a0
--- /dev/null
+++ b/tests/glsl/sascha-willems/computenbody/particle_calculate.comp
@@ -0,0 +1,75 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+struct Particle
+{
+ vec4 pos;
+ vec4 vel;
+};
+
+// Binding 0 : Position storage buffer
+layout(std140, binding = 0) buffer Pos
+{
+ Particle particles[ ];
+};
+
+layout (local_size_x = 256) in;
+
+layout (binding = 1) uniform UBO
+{
+ float deltaT;
+ float destX;
+ float destY;
+ int particleCount;
+} ubo;
+
+layout (constant_id = 0) const int SHARED_DATA_SIZE = 512;
+layout (constant_id = 1) const float GRAVITY = 0.002;
+layout (constant_id = 2) const float POWER = 0.75;
+layout (constant_id = 3) const float SOFTEN = 0.0075;
+
+// Share data between computer shader invocations to speed up caluclations
+shared vec4 sharedData[SHARED_DATA_SIZE];
+
+void main()
+{
+ // Current SSBO index
+ uint index = gl_GlobalInvocationID.x;
+ if (index >= ubo.particleCount)
+ return;
+
+ vec4 position = particles[index].pos;
+ vec4 velocity = particles[index].vel;
+ vec4 acceleration = vec4(0.0);
+
+ for (int i = 0; i < ubo.particleCount; i += SHARED_DATA_SIZE)
+ {
+ if (i + gl_LocalInvocationID.x < ubo.particleCount)
+ {
+ sharedData[gl_LocalInvocationID.x] = particles[i + gl_LocalInvocationID.x].pos;
+ }
+ else
+ {
+ sharedData[gl_LocalInvocationID.x] = vec4(0.0);
+ }
+
+ memoryBarrierShared();
+
+ for (int j = 0; j < gl_WorkGroupSize.x; j++)
+ {
+ vec4 other = sharedData[j];
+ vec3 len = other.xyz - position.xyz;
+ acceleration.xyz += GRAVITY * len * other.w / pow(dot(len, len) + SOFTEN, POWER);
+ }
+ }
+
+ particles[index].vel.xyz += ubo.deltaT * acceleration.xyz;
+
+ // Gradient texture position
+ particles[index].vel.w += 0.1 * ubo.deltaT;
+ if (particles[index].vel.w > 1.0)
+ particles[index].vel.w -= 1.0;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computenbody/particle_integrate.comp b/tests/glsl/sascha-willems/computenbody/particle_integrate.comp
new file mode 100644
index 000000000..7085bee01
--- /dev/null
+++ b/tests/glsl/sascha-willems/computenbody/particle_integrate.comp
@@ -0,0 +1,36 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+struct Particle
+{
+ vec4 pos;
+ vec4 vel;
+};
+
+// Binding 0 : Position storage buffer
+layout(std140, binding = 0) buffer Pos
+{
+ Particle particles[ ];
+};
+
+layout (local_size_x = 256) in;
+
+layout (binding = 1) uniform UBO
+{
+ float deltaT;
+ float destX;
+ float destY;
+ int particleCount;
+} ubo;
+
+void main()
+{
+ int index = int(gl_GlobalInvocationID);
+ vec4 position = particles[index].pos;
+ vec4 velocity = particles[index].vel;
+ position += ubo.deltaT * velocity;
+ particles[index].pos = position;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computeparticles/particle.comp b/tests/glsl/sascha-willems/computeparticles/particle.comp
new file mode 100644
index 000000000..4faf181a4
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeparticles/particle.comp
@@ -0,0 +1,80 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+struct Particle
+{
+ vec2 pos;
+ vec2 vel;
+ vec4 gradientPos;
+};
+
+// Binding 0 : Position storage buffer
+layout(std140, binding = 0) buffer Pos
+{
+ Particle particles[ ];
+};
+
+layout (local_size_x = 256) in;
+
+layout (binding = 1) uniform UBO
+{
+ float deltaT;
+ float destX;
+ float destY;
+ int particleCount;
+} ubo;
+
+vec2 attraction(vec2 pos, vec2 attractPos)
+{
+ vec2 delta = attractPos - pos;
+ const float damp = 0.5;
+ float dDampedDot = dot(delta, delta) + damp;
+ float invDist = 1.0f / sqrt(dDampedDot);
+ float invDistCubed = invDist*invDist*invDist;
+ return delta * invDistCubed * 0.0035;
+}
+
+vec2 repulsion(vec2 pos, vec2 attractPos)
+{
+ vec2 delta = attractPos - pos;
+ float targetDistance = sqrt(dot(delta, delta));
+ return delta * (1.0 / (targetDistance * targetDistance * targetDistance)) * -0.000035;
+}
+
+void main()
+{
+ // Current SSBO index
+ uint index = gl_GlobalInvocationID.x;
+ // Don't try to write beyond particle count
+ if (index >= ubo.particleCount)
+ return;
+
+ // Read position and velocity
+ vec2 vVel = particles[index].vel.xy;
+ vec2 vPos = particles[index].pos.xy;
+
+ vec2 destPos = vec2(ubo.destX, ubo.destY);
+
+ vec2 delta = destPos - vPos;
+ float targetDistance = sqrt(dot(delta, delta));
+ vVel += repulsion(vPos, destPos.xy) * 0.05;
+
+ // Move by velocity
+ vPos += vVel * ubo.deltaT;
+
+ // collide with boundary
+ if ((vPos.x < -1.0) || (vPos.x > 1.0) || (vPos.y < -1.0) || (vPos.y > 1.0))
+ vVel = (-vVel * 0.1) + attraction(vPos, destPos) * 12;
+ else
+ particles[index].pos.xy = vPos;
+
+ // Write back
+ particles[index].vel.xy = vVel;
+ particles[index].gradientPos.x += 0.02 * ubo.deltaT;
+ if (particles[index].gradientPos.x > 1.0)
+ particles[index].gradientPos.x -= 1.0;
+}
+
diff --git a/tests/glsl/sascha-willems/computeparticles/particle.frag b/tests/glsl/sascha-willems/computeparticles/particle.frag
new file mode 100644
index 000000000..ac6077261
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeparticles/particle.frag
@@ -0,0 +1,19 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerColorMap;
+layout (binding = 1) uniform sampler2D samplerGradientRamp;
+
+layout (location = 0) in vec4 inColor;
+layout (location = 1) in float inGradientPos;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main ()
+{
+ vec3 color = texture(samplerGradientRamp, vec2(inGradientPos, 0.0)).rgb;
+ outFragColor.rgb = texture(samplerColorMap, gl_PointCoord).rgb * color;
+}
diff --git a/tests/glsl/sascha-willems/computeparticles/particle.vert b/tests/glsl/sascha-willems/computeparticles/particle.vert
new file mode 100644
index 000000000..b134c4898
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeparticles/particle.vert
@@ -0,0 +1,25 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec2 inPos;
+layout (location = 1) in vec4 inGradientPos;
+
+layout (location = 0) out vec4 outColor;
+layout (location = 1) out float outGradientPos;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+ float gl_PointSize;
+};
+
+void main ()
+{
+ gl_PointSize = 8.0;
+ outColor = vec4(0.035);
+ outGradientPos = inGradientPos.x;
+ gl_Position = vec4(inPos.xy, 1.0, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computeshader/edgedetect.comp b/tests/glsl/sascha-willems/computeshader/edgedetect.comp
new file mode 100644
index 000000000..0c6bb32fa
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeshader/edgedetect.comp
@@ -0,0 +1,48 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (local_size_x = 16, local_size_y = 16) in;
+layout (binding = 0, rgba8) uniform readonly image2D inputImage;
+layout (binding = 1, rgba8) uniform image2D resultImage;
+
+float conv(in float[9] kernel, in float[9] data, in float denom, in float offset)
+{
+ float res = 0.0;
+ for (int i=0; i<9; ++i)
+ {
+ res += kernel[i] * data[i];
+ }
+ return clamp(res/denom + offset, 0.0, 1.0);
+}
+
+struct ImageData
+{
+ float avg[9];
+} imageData;
+
+void main()
+{
+ // Fetch neighbouring texels
+ int n = -1;
+ for (int i=-1; i<2; ++i)
+ {
+ for(int j=-1; j<2; ++j)
+ {
+ n++;
+ vec3 rgb = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x + i, gl_GlobalInvocationID.y + j)).rgb;
+ imageData.avg[n] = (rgb.r + rgb.g + rgb.b) / 3.0;
+ }
+ }
+
+ float[9] kernel;
+ kernel[0] = -1.0/8.0; kernel[1] = -1.0/8.0; kernel[2] = -1.0/8.0;
+ kernel[3] = -1.0/8.0; kernel[4] = 1.0; kernel[5] = -1.0/8.0;
+ kernel[6] = -1.0/8.0; kernel[7] = -1.0/8.0; kernel[8] = -1.0/8.0;
+
+ vec4 res = vec4(vec3(conv(kernel, imageData.avg, 0.1, 0.0)), 1.0);
+
+ imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), res);
+}
diff --git a/tests/glsl/sascha-willems/computeshader/emboss.comp b/tests/glsl/sascha-willems/computeshader/emboss.comp
new file mode 100644
index 000000000..ad0fef510
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeshader/emboss.comp
@@ -0,0 +1,48 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (local_size_x = 16, local_size_y = 16) in;
+layout (binding = 0, rgba8) uniform readonly image2D inputImage;
+layout (binding = 1, rgba8) uniform image2D resultImage;
+
+float conv(in float[9] kernel, in float[9] data, in float denom, in float offset)
+{
+ float res = 0.0;
+ for (int i=0; i<9; ++i)
+ {
+ res += kernel[i] * data[i];
+ }
+ return clamp(res/denom + offset, 0.0, 1.0);
+}
+
+struct ImageData
+{
+ float avg[9];
+} imageData;
+
+void main()
+{
+ // Fetch neighbouring texels
+ int n = -1;
+ for (int i=-1; i<2; ++i)
+ {
+ for(int j=-1; j<2; ++j)
+ {
+ n++;
+ vec3 rgb = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x + i, gl_GlobalInvocationID.y + j)).rgb;
+ imageData.avg[n] = (rgb.r + rgb.g + rgb.b) / 3.0;
+ }
+ }
+
+ float[9] kernel;
+ kernel[0] = -1.0; kernel[1] = 0.0; kernel[2] = 0.0;
+ kernel[3] = 0.0; kernel[4] = -1.0; kernel[5] = 0.0;
+ kernel[6] = 0.0; kernel[7] = 0.0; kernel[8] = 2.0;
+
+ vec4 res = vec4(vec3(conv(kernel, imageData.avg, 1.0, 0.50)), 1.0);
+
+ imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), res);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computeshader/sharpen.comp b/tests/glsl/sascha-willems/computeshader/sharpen.comp
new file mode 100644
index 000000000..dc71ae447
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeshader/sharpen.comp
@@ -0,0 +1,57 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (local_size_x = 16, local_size_y = 16) in;
+layout (binding = 0, rgba8) uniform readonly image2D inputImage;
+layout (binding = 1, rgba8) uniform image2D resultImage;
+
+float conv(in float[9] kernel, in float[9] data, in float denom, in float offset)
+{
+ float res = 0.0;
+ for (int i=0; i<9; ++i)
+ {
+ res += kernel[i] * data[i];
+ }
+ return clamp(res/denom + offset, 0.0, 1.0);
+}
+
+struct ImageData
+{
+ float r[9];
+ float g[9];
+ float b[9];
+} imageData;
+
+void main()
+{
+
+ // Fetch neighbouring texels
+ int n = -1;
+ for (int i=-1; i<2; ++i)
+ {
+ for(int j=-1; j<2; ++j)
+ {
+ n++;
+ vec3 rgb = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x + i, gl_GlobalInvocationID.y + j)).rgb;
+ imageData.r[n] = rgb.r;
+ imageData.g[n] = rgb.g;
+ imageData.b[n] = rgb.b;
+ }
+ }
+
+ float[9] kernel;
+ kernel[0] = -1.0; kernel[1] = -1.0; kernel[2] = -1.0;
+ kernel[3] = -1.0; kernel[4] = 9.0; kernel[5] = -1.0;
+ kernel[6] = -1.0; kernel[7] = -1.0; kernel[8] = -1.0;
+
+ vec4 res = vec4(
+ conv(kernel, imageData.r, 1.0, 0.0),
+ conv(kernel, imageData.g, 1.0, 0.0),
+ conv(kernel, imageData.b, 1.0, 0.0),
+ 1.0);
+
+ imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), res);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computeshader/texture.frag b/tests/glsl/sascha-willems/computeshader/texture.frag
new file mode 100644
index 000000000..6d54f2f33
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeshader/texture.frag
@@ -0,0 +1,16 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerColor, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/computeshader/texture.vert b/tests/glsl/sascha-willems/computeshader/texture.vert
new file mode 100644
index 000000000..c1ad3e070
--- /dev/null
+++ b/tests/glsl/sascha-willems/computeshader/texture.vert
@@ -0,0 +1,27 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/cubemap/reflect.frag b/tests/glsl/sascha-willems/cubemap/reflect.frag
new file mode 100644
index 000000000..2ee1d95e7
--- /dev/null
+++ b/tests/glsl/sascha-willems/cubemap/reflect.frag
@@ -0,0 +1,36 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform samplerCube samplerColor;
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in float inLodBias;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+layout (location = 5) in mat4 inInvModelView;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 cI = normalize (inPos);
+ vec3 cR = reflect (cI, normalize(inNormal));
+
+ cR = vec3(inInvModelView * vec4(cR, 0.0));
+ cR.x *= -1.0;
+
+ vec4 color = texture(samplerColor, cR, inLodBias);
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 ambient = vec3(0.5) * color.rgb;
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.5);
+ outFragColor = vec4(ambient + diffuse * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/cubemap/reflect.vert b/tests/glsl/sascha-willems/cubemap/reflect.vert
new file mode 100644
index 000000000..dcf746738
--- /dev/null
+++ b/tests/glsl/sascha-willems/cubemap/reflect.vert
@@ -0,0 +1,42 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ float lodBias;
+} ubo;
+
+layout (location = 0) out vec3 outPos;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out float outLodBias;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+layout (location = 5) out mat4 outInvModelView;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ outPos = vec3(ubo.model * vec4(inPos, 1.0));
+ outNormal = mat3(ubo.model) * inNormal;
+ outLodBias = ubo.lodBias;
+
+ outInvModelView = inverse(ubo.model);
+
+ vec3 lightPos = vec3(0.0f, -5.0f, 5.0f);
+ outLightVec = lightPos.xyz - outPos.xyz;
+ outViewVec = -outPos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/cubemap/skybox.frag b/tests/glsl/sascha-willems/cubemap/skybox.frag
new file mode 100644
index 000000000..611eb37db
--- /dev/null
+++ b/tests/glsl/sascha-willems/cubemap/skybox.frag
@@ -0,0 +1,16 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform samplerCube samplerCubeMap;
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerCubeMap, inUVW);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/cubemap/skybox.vert b/tests/glsl/sascha-willems/cubemap/skybox.vert
new file mode 100644
index 000000000..7011212e0
--- /dev/null
+++ b/tests/glsl/sascha-willems/cubemap/skybox.vert
@@ -0,0 +1,27 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUVW = inPos;
+ outUVW.x *= -1.0;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/debugmarker/colorpass.frag b/tests/glsl/sascha-willems/debugmarker/colorpass.frag
new file mode 100644
index 000000000..de5dcb4dc
--- /dev/null
+++ b/tests/glsl/sascha-willems/debugmarker/colorpass.frag
@@ -0,0 +1,14 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor.rgb = inColor;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/debugmarker/colorpass.vert b/tests/glsl/sascha-willems/debugmarker/colorpass.vert
new file mode 100644
index 000000000..46b93f8dc
--- /dev/null
+++ b/tests/glsl/sascha-willems/debugmarker/colorpass.vert
@@ -0,0 +1,29 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ {
+ outColor = inColor;
+ }
+ gl_Position = ubo.projection * ubo.model * inPos;
+}
diff --git a/tests/glsl/sascha-willems/debugmarker/postprocess.frag b/tests/glsl/sascha-willems/debugmarker/postprocess.frag
new file mode 100644
index 000000000..0546baaa4
--- /dev/null
+++ b/tests/glsl/sascha-willems/debugmarker/postprocess.frag
@@ -0,0 +1,43 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ // Single pass gauss blur
+
+ const vec2 texOffset = vec2(0.01, 0.01);
+
+ vec2 tc0 = inUV + vec2(-texOffset.s, -texOffset.t);
+ vec2 tc1 = inUV + vec2( 0.0, -texOffset.t);
+ vec2 tc2 = inUV + vec2(+texOffset.s, -texOffset.t);
+ vec2 tc3 = inUV + vec2(-texOffset.s, 0.0);
+ vec2 tc4 = inUV + vec2( 0.0, 0.0);
+ vec2 tc5 = inUV + vec2(+texOffset.s, 0.0);
+ vec2 tc6 = inUV + vec2(-texOffset.s, +texOffset.t);
+ vec2 tc7 = inUV + vec2( 0.0, +texOffset.t);
+ vec2 tc8 = inUV + vec2(+texOffset.s, +texOffset.t);
+
+ vec4 col0 = texture(samplerColor, tc0);
+ vec4 col1 = texture(samplerColor, tc1);
+ vec4 col2 = texture(samplerColor, tc2);
+ vec4 col3 = texture(samplerColor, tc3);
+ vec4 col4 = texture(samplerColor, tc4);
+ vec4 col5 = texture(samplerColor, tc5);
+ vec4 col6 = texture(samplerColor, tc6);
+ vec4 col7 = texture(samplerColor, tc7);
+ vec4 col8 = texture(samplerColor, tc8);
+
+ vec4 sum = (1.0 * col0 + 2.0 * col1 + 1.0 * col2 +
+ 2.0 * col3 + 4.0 * col4 + 2.0 * col5 +
+ 1.0 * col6 + 2.0 * col7 + 1.0 * col8) / 16.0;
+ outFragColor = vec4(sum.rgb, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/debugmarker/postprocess.vert b/tests/glsl/sascha-willems/debugmarker/postprocess.vert
new file mode 100644
index 000000000..6a368e9b6
--- /dev/null
+++ b/tests/glsl/sascha-willems/debugmarker/postprocess.vert
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * vec2(2.0f, 2.0f) + vec2(-1.0f, -1.0f), 0.0f, 1.0f);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/debugmarker/toon.frag b/tests/glsl/sascha-willems/debugmarker/toon.frag
new file mode 100644
index 000000000..ed9832f11
--- /dev/null
+++ b/tests/glsl/sascha-willems/debugmarker/toon.frag
@@ -0,0 +1,40 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ // Desaturate color
+ vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65));
+
+ // High ambient colors because mesh materials are pretty dark
+ vec3 ambient = color * vec3(1.0);
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * color;
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75);
+ outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0);
+
+ float intensity = dot(N,L);
+ float shade = 1.0;
+ shade = intensity < 0.5 ? 0.75 : shade;
+ shade = intensity < 0.35 ? 0.6 : shade;
+ shade = intensity < 0.25 ? 0.5 : shade;
+ shade = intensity < 0.1 ? 0.25 : shade;
+
+ outFragColor.rgb = inColor * 3.0 * shade;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/debugmarker/toon.vert b/tests/glsl/sascha-willems/debugmarker/toon.vert
new file mode 100644
index 000000000..d0b3be251
--- /dev/null
+++ b/tests/glsl/sascha-willems/debugmarker/toon.vert
@@ -0,0 +1,42 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferred/debug.frag b/tests/glsl/sascha-willems/deferred/debug.frag
new file mode 100644
index 000000000..6b77990b5
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferred/debug.frag
@@ -0,0 +1,27 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerPosition;
+layout (binding = 2) uniform sampler2D samplerNormal;
+layout (binding = 3) uniform sampler2D samplerAlbedo;
+
+layout (location = 0) in vec3 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 components[3];
+ components[0] = texture(samplerPosition, inUV.st).rgb;
+ components[1] = texture(samplerNormal, inUV.st).rgb;
+ components[2] = texture(samplerAlbedo, inUV.st).rgb;
+ // Uncomment to display specular component
+ //components[2] = vec3(texture(samplerAlbedo, inUV.st).a);
+
+ // Select component depending on z coordinate of quad
+ highp int index = int(inUV.z);
+ outFragColor.rgb = components[index];
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferred/debug.vert b/tests/glsl/sascha-willems/deferred/debug.vert
new file mode 100644
index 000000000..de1b380f6
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferred/debug.vert
@@ -0,0 +1,28 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 3) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec3(inUV.st, inNormal.z);
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/deferred/deferred.frag b/tests/glsl/sascha-willems/deferred/deferred.frag
new file mode 100644
index 000000000..aead2f872
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferred/deferred.frag
@@ -0,0 +1,76 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerposition;
+layout (binding = 2) uniform sampler2D samplerNormal;
+layout (binding = 3) uniform sampler2D samplerAlbedo;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragcolor;
+
+struct Light {
+ vec4 position;
+ vec3 color;
+ float radius;
+};
+
+layout (binding = 4) uniform UBO
+{
+ Light lights[6];
+ vec4 viewPos;
+} ubo;
+
+
+void main()
+{
+ // Get G-Buffer values
+ vec3 fragPos = texture(samplerposition, inUV).rgb;
+ vec3 normal = texture(samplerNormal, inUV).rgb;
+ vec4 albedo = texture(samplerAlbedo, inUV);
+
+ #define lightCount 6
+ #define ambient 0.0
+
+ // Ambient part
+ vec3 fragcolor = albedo.rgb * ambient;
+
+ for(int i = 0; i < lightCount; ++i)
+ {
+ // Vector to light
+ vec3 L = ubo.lights[i].position.xyz - fragPos;
+ // Distance from light to fragment position
+ float dist = length(L);
+
+ // Viewer to fragment
+ vec3 V = ubo.viewPos.xyz - fragPos;
+ V = normalize(V);
+
+ //if(dist < ubo.lights[i].radius)
+ {
+ // Light to fragment
+ L = normalize(L);
+
+ // Attenuation
+ float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0);
+
+ // Diffuse part
+ vec3 N = normalize(normal);
+ float NdotL = max(0.0, dot(N, L));
+ vec3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten;
+
+ // Specular part
+ // Specular map values are stored in alpha of albedo mrt
+ vec3 R = reflect(-L, N);
+ float NdotR = max(0.0, dot(R, V));
+ vec3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 16.0) * atten;
+
+ fragcolor += diff + spec;
+ }
+ }
+
+ outFragcolor = vec4(fragcolor, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferred/deferred.vert b/tests/glsl/sascha-willems/deferred/deferred.vert
new file mode 100644
index 000000000..548284554
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferred/deferred.vert
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/deferred/mrt.frag b/tests/glsl/sascha-willems/deferred/mrt.frag
new file mode 100644
index 000000000..4bd2a10a5
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferred/mrt.frag
@@ -0,0 +1,34 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+layout (binding = 2) uniform sampler2D samplerNormalMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inWorldPos;
+layout (location = 4) in vec3 inTangent;
+
+layout (location = 0) out vec4 outPosition;
+layout (location = 1) out vec4 outNormal;
+layout (location = 2) out vec4 outAlbedo;
+
+void main()
+{
+ outPosition = vec4(inWorldPos, 1.0);
+
+ // Calculate normal in tangent space
+ vec3 N = normalize(inNormal);
+ N.y = -N.y;
+ vec3 T = normalize(inTangent);
+ vec3 B = cross(N, T);
+ mat3 TBN = mat3(T, B, N);
+ vec3 tnorm = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0));
+ outNormal = vec4(tnorm, 1.0);
+
+ outAlbedo = texture(samplerColor, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferred/mrt.vert b/tests/glsl/sascha-willems/deferred/mrt.vert
new file mode 100644
index 000000000..26f764176
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferred/mrt.vert
@@ -0,0 +1,53 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+layout (location = 4) in vec3 inTangent;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec4 instancePos[3];
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outColor;
+layout (location = 3) out vec3 outWorldPos;
+layout (location = 4) out vec3 outTangent;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ vec4 tmpPos = inPos + ubo.instancePos[gl_InstanceIndex];
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * tmpPos;
+
+ outUV = inUV;
+ outUV.t = 1.0 - outUV.t;
+
+ // Vertex position in world space
+ outWorldPos = vec3(ubo.model * tmpPos);
+ // GL to Vulkan coord space
+ outWorldPos.y = -outWorldPos.y;
+
+ // Normal in world space
+ mat3 mNormal = transpose(inverse(mat3(ubo.model)));
+ outNormal = mNormal * normalize(inNormal);
+ outTangent = mNormal * normalize(inTangent);
+
+ // Currently just vertex color
+ outColor = inColor;
+}
diff --git a/tests/glsl/sascha-willems/deferredmultisampling/debug.frag b/tests/glsl/sascha-willems/deferredmultisampling/debug.frag
new file mode 100644
index 000000000..f404711dd
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredmultisampling/debug.frag
@@ -0,0 +1,56 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2DMS samplerPosition;
+layout (binding = 2) uniform sampler2DMS samplerNormal;
+layout (binding = 3) uniform sampler2DMS samplerAlbedo;
+
+layout (location = 0) in vec3 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+#define NUM_SAMPLES 8
+
+vec4 resolve(sampler2DMS tex, ivec2 uv)
+{
+ vec4 result = vec4(0.0);
+ int count = 0;
+ for (int i = 0; i < NUM_SAMPLES; i++)
+ {
+ vec4 val = texelFetch(tex, uv, i);
+ result += val;
+ count++;
+ }
+ return result / float(NUM_SAMPLES);
+}
+
+void main()
+{
+ ivec2 attDim = textureSize(samplerPosition);
+ ivec2 UV = ivec2(inUV.st * attDim * 2.0);
+
+ highp int index = 0;
+ if (inUV.s > 0.5)
+ {
+ index = 1;
+ UV.s -= attDim.x;
+ }
+ if (inUV.t > 0.5)
+ {
+ index = 2;
+ UV.t -= attDim.y;
+ }
+
+ vec3 components[3];
+ components[0] = resolve(samplerPosition, UV).rgb;
+ components[1] = resolve(samplerNormal, UV).rgb;
+ components[2] = resolve(samplerAlbedo, UV).rgb;
+ // Uncomment to display specular component
+ //components[2] = vec3(texture(samplerAlbedo, inUV.st).a);
+
+ // Select component depending on UV
+ outFragColor.rgb = components[index];
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredmultisampling/debug.vert b/tests/glsl/sascha-willems/deferredmultisampling/debug.vert
new file mode 100644
index 000000000..c62c3364a
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredmultisampling/debug.vert
@@ -0,0 +1,24 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec3((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2, 0.0);
+ gl_Position = vec4(outUV.st * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/deferredmultisampling/deferred.frag b/tests/glsl/sascha-willems/deferredmultisampling/deferred.frag
new file mode 100644
index 000000000..59f855281
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredmultisampling/deferred.frag
@@ -0,0 +1,104 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2DMS samplerPosition;
+layout (binding = 2) uniform sampler2DMS samplerNormal;
+layout (binding = 3) uniform sampler2DMS samplerAlbedo;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragcolor;
+
+struct Light {
+ vec4 position;
+ vec3 color;
+ float radius;
+};
+
+layout (binding = 4) uniform UBO
+{
+ Light lights[6];
+ vec4 viewPos;
+ ivec2 windowSize;
+} ubo;
+
+layout (constant_id = 0) const int NUM_SAMPLES = 8;
+
+#define NUM_LIGHTS 6
+
+// Manual resolve for MSAA samples
+vec4 resolve(sampler2DMS tex, ivec2 uv)
+{
+ vec4 result = vec4(0.0);
+ for (int i = 0; i < NUM_SAMPLES; i++)
+ {
+ vec4 val = texelFetch(tex, uv, i);
+ result += val;
+ }
+ // Average resolved samples
+ return result / float(NUM_SAMPLES);
+}
+
+vec3 calculateLighting(vec3 pos, vec3 normal, vec4 albedo)
+{
+ vec3 result = vec3(0.0);
+
+ for(int i = 0; i < NUM_LIGHTS; ++i)
+ {
+ // Vector to light
+ vec3 L = ubo.lights[i].position.xyz - pos;
+ // Distance from light to fragment position
+ float dist = length(L);
+
+ // Viewer to fragment
+ vec3 V = ubo.viewPos.xyz - pos;
+ V = normalize(V);
+
+ // Light to fragment
+ L = normalize(L);
+
+ // Attenuation
+ float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0);
+
+ // Diffuse part
+ vec3 N = normalize(normal);
+ float NdotL = max(0.0, dot(N, L));
+ vec3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten;
+
+ // Specular part
+ vec3 R = reflect(-L, N);
+ float NdotR = max(0.0, dot(R, V));
+ vec3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 8.0) * atten;
+
+ result += diff + spec;
+ }
+ return result;
+}
+
+void main()
+{
+ ivec2 attDim = textureSize(samplerPosition);
+ ivec2 UV = ivec2(inUV * attDim);
+
+ #define ambient 0.15
+
+ // Ambient part
+ vec4 alb = resolve(samplerAlbedo, UV);
+ vec3 fragColor = vec3(0.0);
+
+ // Calualte lighting for every MSAA sample
+ for (int i = 0; i < NUM_SAMPLES; i++)
+ {
+ vec3 pos = texelFetch(samplerPosition, UV, i).rgb;
+ vec3 normal = texelFetch(samplerNormal, UV, i).rgb;
+ vec4 albedo = texelFetch(samplerAlbedo, UV, i);
+ fragColor += calculateLighting(pos, normal, albedo);
+ }
+
+ fragColor = (alb.rgb * ambient) + fragColor / float(NUM_SAMPLES);
+
+ outFragcolor = vec4(fragColor, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredmultisampling/deferred.vert b/tests/glsl/sascha-willems/deferredmultisampling/deferred.vert
new file mode 100644
index 000000000..af8eef6dd
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredmultisampling/deferred.vert
@@ -0,0 +1,24 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/deferredmultisampling/mrt.frag b/tests/glsl/sascha-willems/deferredmultisampling/mrt.frag
new file mode 100644
index 000000000..4bd2a10a5
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredmultisampling/mrt.frag
@@ -0,0 +1,34 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+layout (binding = 2) uniform sampler2D samplerNormalMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inWorldPos;
+layout (location = 4) in vec3 inTangent;
+
+layout (location = 0) out vec4 outPosition;
+layout (location = 1) out vec4 outNormal;
+layout (location = 2) out vec4 outAlbedo;
+
+void main()
+{
+ outPosition = vec4(inWorldPos, 1.0);
+
+ // Calculate normal in tangent space
+ vec3 N = normalize(inNormal);
+ N.y = -N.y;
+ vec3 T = normalize(inTangent);
+ vec3 B = cross(N, T);
+ mat3 TBN = mat3(T, B, N);
+ vec3 tnorm = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0));
+ outNormal = vec4(tnorm, 1.0);
+
+ outAlbedo = texture(samplerColor, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredmultisampling/mrt.vert b/tests/glsl/sascha-willems/deferredmultisampling/mrt.vert
new file mode 100644
index 000000000..5cc127297
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredmultisampling/mrt.vert
@@ -0,0 +1,53 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+layout (location = 4) in vec3 inTangent;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec4 instancePos[3];
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outColor;
+layout (location = 3) out vec3 outWorldPos;
+layout (location = 4) out vec3 outTangent;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ vec4 tmpPos = vec4(inPos.xyz, 1.0) + ubo.instancePos[gl_InstanceIndex];
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * tmpPos;
+
+ outUV = inUV;
+ outUV.t = 1.0 - outUV.t;
+
+ // Vertex position in world space
+ outWorldPos = vec3(ubo.model * tmpPos);
+ // GL to Vulkan coord space
+ outWorldPos.y = -outWorldPos.y;
+
+ // Normal in world space
+ mat3 mNormal = transpose(inverse(mat3(ubo.model)));
+ outNormal = mNormal * normalize(inNormal);
+ outTangent = mNormal * normalize(inTangent);
+
+ // Currently just vertex color
+ outColor = inColor;
+}
diff --git a/tests/glsl/sascha-willems/deferredshadows/debug.frag b/tests/glsl/sascha-willems/deferredshadows/debug.frag
new file mode 100644
index 000000000..f9136b24d
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/debug.frag
@@ -0,0 +1,30 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerPosition;
+layout (binding = 2) uniform sampler2D samplerNormal;
+layout (binding = 3) uniform sampler2D samplerAlbedo;
+layout (binding = 5) uniform sampler2DArray samplerDepth;
+
+layout (location = 0) in vec3 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+float LinearizeDepth(float depth)
+{
+ float n = 0.1; // camera z near
+ float f = 64.0; // camera z far
+ float z = depth;
+ return (2.0 * n) / (f + n - z * (f - n));
+}
+
+void main()
+{
+ // Display depth from light's point-of-view
+ // inUV.w = number of light source
+ float depth = texture(samplerDepth, vec3(inUV)).r;
+ outFragColor = vec4(vec3(1.0 - LinearizeDepth(depth)), 0.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredshadows/debug.vert b/tests/glsl/sascha-willems/deferredshadows/debug.vert
new file mode 100644
index 000000000..8742202c2
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/debug.vert
@@ -0,0 +1,30 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+} ubo;
+
+layout (location = 0) out vec3 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec3(inUV.st, gl_InstanceIndex);
+ vec4 tmpPos = vec4(inPos, 1.0);
+ tmpPos.y += gl_InstanceIndex;
+ tmpPos.xy *= vec2(1.0/4.0, 1.0/3.0);
+ gl_Position = ubo.projection * ubo.modelview * tmpPos;
+}
diff --git a/tests/glsl/sascha-willems/deferredshadows/deferred.frag b/tests/glsl/sascha-willems/deferredshadows/deferred.frag
new file mode 100644
index 000000000..ba3998bd6
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/deferred.frag
@@ -0,0 +1,147 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerposition;
+layout (binding = 2) uniform sampler2D samplerNormal;
+layout (binding = 3) uniform sampler2D samplerAlbedo;
+// Depth from the light's point of view
+//layout (binding = 5) uniform sampler2DShadow samplerShadowMap;
+layout (binding = 5) uniform sampler2DArray samplerShadowMap;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+#define LIGHT_COUNT 3
+#define SHADOW_FACTOR 0.25
+#define AMBIENT_LIGHT 0.1
+#define USE_PCF
+
+struct Light
+{
+ vec4 position;
+ vec4 target;
+ vec4 color;
+ mat4 viewMatrix;
+};
+
+layout (binding = 4) uniform UBO
+{
+ vec4 viewPos;
+ Light lights[LIGHT_COUNT];
+ int useShadows;
+} ubo;
+
+float textureProj(vec4 P, float layer, vec2 offset)
+{
+ float shadow = 1.0;
+ vec4 shadowCoord = P / P.w;
+ shadowCoord.st = shadowCoord.st * 0.5 + 0.5;
+
+ if (shadowCoord.z > -1.0 && shadowCoord.z < 1.0)
+ {
+ float dist = texture(samplerShadowMap, vec3(shadowCoord.st + offset, layer)).r;
+ if (shadowCoord.w > 0.0 && dist < shadowCoord.z)
+ {
+ shadow = SHADOW_FACTOR;
+ }
+ }
+ return shadow;
+}
+
+float filterPCF(vec4 sc, float layer)
+{
+ ivec2 texDim = textureSize(samplerShadowMap, 0).xy;
+ float scale = 1.5;
+ float dx = scale * 1.0 / float(texDim.x);
+ float dy = scale * 1.0 / float(texDim.y);
+
+ float shadowFactor = 0.0;
+ int count = 0;
+ int range = 1;
+
+ for (int x = -range; x <= range; x++)
+ {
+ for (int y = -range; y <= range; y++)
+ {
+ shadowFactor += textureProj(sc, layer, vec2(dx*x, dy*y));
+ count++;
+ }
+
+ }
+ return shadowFactor / count;
+}
+
+void main()
+{
+ // Get G-Buffer values
+ vec3 fragPos = texture(samplerposition, inUV).rgb;
+ vec3 normal = texture(samplerNormal, inUV).rgb;
+ vec4 albedo = texture(samplerAlbedo, inUV);
+
+ // Ambient part
+ vec3 fragcolor = albedo.rgb * AMBIENT_LIGHT;
+
+ vec3 N = normalize(normal);
+
+ float shadow = 0.0;
+
+ for(int i = 0; i < LIGHT_COUNT; ++i)
+ {
+ // Vector to light
+ vec3 L = ubo.lights[i].position.xyz - fragPos;
+ // Distance from light to fragment position
+ float dist = length(L);
+ L = normalize(L);
+
+ // Viewer to fragment
+ vec3 V = ubo.viewPos.xyz - fragPos;
+ V = normalize(V);
+
+ float lightCosInnerAngle = cos(radians(15.0));
+ float lightCosOuterAngle = cos(radians(25.0));
+ float lightRange = 100.0;
+
+ // Direction vector from source to target
+ vec3 dir = normalize(ubo.lights[i].position.xyz - ubo.lights[i].target.xyz);
+
+ // Dual cone spot light with smooth transition between inner and outer angle
+ float cosDir = dot(L, dir);
+ float spotEffect = smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir);
+ float heightAttenuation = smoothstep(lightRange, 0.0f, dist);
+
+ // Diffuse lighting
+ float NdotL = max(0.0, dot(N, L));
+ vec3 diff = vec3(NdotL);
+
+ // Specular lighting
+ vec3 R = reflect(-L, N);
+ float NdotR = max(0.0, dot(R, V));
+ vec3 spec = vec3(pow(NdotR, 16.0) * albedo.a * 2.5);
+
+ fragcolor += vec3((diff + spec) * spotEffect * heightAttenuation) * ubo.lights[i].color.rgb * albedo.rgb;
+ }
+
+ // Shadow calculations in a separate pass
+ if (ubo.useShadows > 0)
+ {
+ for(int i = 0; i < LIGHT_COUNT; ++i)
+ {
+ vec4 shadowClip = ubo.lights[i].viewMatrix * vec4(fragPos, 1.0);
+
+ float shadowFactor;
+ #ifdef USE_PCF
+ shadowFactor= filterPCF(shadowClip, i);
+ #else
+ shadowFactor = textureProj(shadowClip, i, vec2(0.0));
+ #endif
+
+ fragcolor *= shadowFactor;
+ }
+ }
+
+ outFragColor.rgb = fragcolor;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredshadows/deferred.vert b/tests/glsl/sascha-willems/deferredshadows/deferred.vert
new file mode 100644
index 000000000..cd17f9726
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/deferred.vert
@@ -0,0 +1,27 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/deferredshadows/mrt.frag b/tests/glsl/sascha-willems/deferredshadows/mrt.frag
new file mode 100644
index 000000000..7a31f54e9
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/mrt.frag
@@ -0,0 +1,33 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+layout (binding = 2) uniform sampler2D samplerNormalMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inWorldPos;
+layout (location = 4) in vec3 inTangent;
+
+layout (location = 0) out vec4 outPosition;
+layout (location = 1) out vec4 outNormal;
+layout (location = 2) out vec4 outAlbedo;
+
+void main()
+{
+ outPosition = vec4(inWorldPos, 1.0);
+
+ // Calculate normal in tangent space
+ vec3 N = normalize(inNormal);
+ vec3 T = normalize(inTangent);
+ vec3 B = cross(N, T);
+ mat3 TBN = mat3(T, B, N);
+ vec3 tnorm = TBN * normalize(texture(samplerNormalMap, inUV).xyz * 2.0 - vec3(1.0));
+ outNormal = vec4(tnorm, 1.0);
+
+ outAlbedo = texture(samplerColor, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredshadows/mrt.vert b/tests/glsl/sascha-willems/deferredshadows/mrt.vert
new file mode 100644
index 000000000..815c2833f
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/mrt.vert
@@ -0,0 +1,51 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+layout (location = 4) in vec3 inTangent;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec4 instancePos[3];
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outColor;
+layout (location = 3) out vec3 outWorldPos;
+layout (location = 4) out vec3 outTangent;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ vec4 tmpPos = inPos + ubo.instancePos[gl_InstanceIndex];
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * tmpPos;
+
+ outUV = inUV;
+ outUV.t = 1.0 - outUV.t;
+
+ // Vertex position in world space
+ outWorldPos = vec3(ubo.model * tmpPos);
+
+ // Normal in world space
+ mat3 mNormal = transpose(inverse(mat3(ubo.model)));
+ outNormal = mNormal * normalize(inNormal);
+ outTangent = mNormal * normalize(inTangent);
+
+ // Currently just vertex color
+ outColor = inColor;
+}
diff --git a/tests/glsl/sascha-willems/deferredshadows/shadow.frag b/tests/glsl/sascha-willems/deferredshadows/shadow.frag
new file mode 100644
index 000000000..23217ad42
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/shadow.frag
@@ -0,0 +1,12 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout(location = 0) out float fragmentdepth;
+
+void main()
+{
+ fragmentdepth = gl_FragCoord.z;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredshadows/shadow.geom b/tests/glsl/sascha-willems/deferredshadows/shadow.geom
new file mode 100644
index 000000000..7f71c108a
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/shadow.geom
@@ -0,0 +1,36 @@
+#version 420
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+#define LIGHT_COUNT 3
+
+layout (triangles, invocations = LIGHT_COUNT) in;
+layout (triangle_strip, max_vertices = 3) out;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 mvp[LIGHT_COUNT];
+ vec4 instancePos[3];
+} ubo;
+
+layout (location = 0) in int inInstanceIndex[];
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ vec4 instancedPos = ubo.instancePos[inInstanceIndex[0]];
+ for (int i = 0; i < gl_in.length(); i++)
+ {
+ gl_Layer = gl_InvocationID;
+ vec4 tmpPos = gl_in[i].gl_Position + instancedPos;
+ gl_Position = ubo.mvp[gl_InvocationID] * tmpPos;
+ EmitVertex();
+ }
+ EndPrimitive();
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/deferredshadows/shadow.vert b/tests/glsl/sascha-willems/deferredshadows/shadow.vert
new file mode 100644
index 000000000..b16c66414
--- /dev/null
+++ b/tests/glsl/sascha-willems/deferredshadows/shadow.vert
@@ -0,0 +1,20 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+
+layout (location = 0) out int outInstanceIndex;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outInstanceIndex = gl_InstanceIndex;
+ gl_Position = inPos;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/displacement/base.frag b/tests/glsl/sascha-willems/displacement/base.frag
new file mode 100644
index 000000000..3ab30270c
--- /dev/null
+++ b/tests/glsl/sascha-willems/displacement/base.frag
@@ -0,0 +1,30 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 2) uniform sampler2D colorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inEyePos;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(vec3(1.0));
+
+ outFragColor.rgb = texture(colorMap, inUV).rgb;
+
+ vec3 Eye = normalize(-inEyePos);
+ vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
+
+ vec4 IAmbient = vec4(0.0, 0.0, 0.0, 1.0);
+ vec4 IDiffuse = vec4(1.0) * max(dot(inNormal, inLightVec), 0.0);
+
+ outFragColor = vec4((IAmbient + IDiffuse) * vec4(texture(colorMap, inUV).rgb, 1.0));
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/displacement/base.vert b/tests/glsl/sascha-willems/displacement/base.vert
new file mode 100644
index 000000000..c684afabb
--- /dev/null
+++ b/tests/glsl/sascha-willems/displacement/base.vert
@@ -0,0 +1,19 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+
+void main(void)
+{
+ gl_Position = vec4(inPos.xyz, 1.0);
+ outUV = inUV * 3.0;
+ outNormal = inNormal;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/displacement/displacement.tesc b/tests/glsl/sascha-willems/displacement/displacement.tesc
new file mode 100644
index 000000000..73bf237c0
--- /dev/null
+++ b/tests/glsl/sascha-willems/displacement/displacement.tesc
@@ -0,0 +1,33 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform UBO
+{
+ float tessLevel;
+} ubo;
+
+layout (vertices = 3) out;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec2 inUV[];
+
+layout (location = 0) out vec3 outNormal[3];
+layout (location = 1) out vec2 outUV[3];
+
+void main()
+{
+ if (gl_InvocationID == 0)
+ {
+ gl_TessLevelInner[0] = ubo.tessLevel;
+ gl_TessLevelOuter[0] = ubo.tessLevel;
+ gl_TessLevelOuter[1] = ubo.tessLevel;
+ gl_TessLevelOuter[2] = ubo.tessLevel;
+ }
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ outNormal[gl_InvocationID] = inNormal[gl_InvocationID];
+ outUV[gl_InvocationID] = inUV[gl_InvocationID];
+}
diff --git a/tests/glsl/sascha-willems/displacement/displacement.tese b/tests/glsl/sascha-willems/displacement/displacement.tese
new file mode 100644
index 000000000..bd061ec2a
--- /dev/null
+++ b/tests/glsl/sascha-willems/displacement/displacement.tese
@@ -0,0 +1,40 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+ float tessAlpha;
+ float tessStrength;
+} ubo;
+
+layout (binding = 2) uniform sampler2D displacementMap;
+
+layout(triangles, equal_spacing, ccw) in;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec2 inUV[];
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outEyesPos;
+layout (location = 3) out vec3 outLightVec;
+
+void main()
+{
+ gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + (gl_TessCoord.y * gl_in[1].gl_Position) + (gl_TessCoord.z * gl_in[2].gl_Position);
+ outUV = gl_TessCoord.x * inUV[0] + gl_TessCoord.y * inUV[1] + gl_TessCoord.z * inUV[2];
+ outNormal = gl_TessCoord.x * inNormal[0] + gl_TessCoord.y * inNormal[1] + gl_TessCoord.z * inNormal[2];
+
+ gl_Position.xyz += normalize(outNormal) * (max(textureLod(displacementMap, outUV.st, 0.0).a, 0.0) * ubo.tessStrength);
+
+ outEyesPos = (gl_Position).xyz;
+ outLightVec = normalize(ubo.lightPos.xyz - outEyesPos);
+
+ gl_Position = ubo.projection * ubo.model * gl_Position;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/distancefieldfonts/bitmap.frag b/tests/glsl/sascha-willems/distancefieldfonts/bitmap.frag
new file mode 100644
index 000000000..5f6303c3c
--- /dev/null
+++ b/tests/glsl/sascha-willems/distancefieldfonts/bitmap.frag
@@ -0,0 +1,16 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = vec4(texture(samplerColor, inUV).a);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/distancefieldfonts/bitmap.vert b/tests/glsl/sascha-willems/distancefieldfonts/bitmap.vert
new file mode 100644
index 000000000..4ed4e6246
--- /dev/null
+++ b/tests/glsl/sascha-willems/distancefieldfonts/bitmap.vert
@@ -0,0 +1,22 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+void main()
+{
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/distancefieldfonts/sdf.frag b/tests/glsl/sascha-willems/distancefieldfonts/sdf.frag
new file mode 100644
index 000000000..a0a4babb4
--- /dev/null
+++ b/tests/glsl/sascha-willems/distancefieldfonts/sdf.frag
@@ -0,0 +1,36 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (binding = 2) uniform UBO
+{
+ vec4 outlineColor;
+ float outlineWidth;
+ float outline;
+} ubo;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ float distance = texture(samplerColor, inUV).a;
+ float smoothWidth = fwidth(distance);
+ float alpha = smoothstep(0.5 - smoothWidth, 0.5 + smoothWidth, distance);
+ vec3 rgb = vec3(alpha);
+
+ if (ubo.outline > 0.0)
+ {
+ float w = 1.0 - ubo.outlineWidth;
+ alpha = smoothstep(w - smoothWidth, w + smoothWidth, distance);
+ rgb += mix(vec3(alpha), ubo.outlineColor.rgb, alpha);
+ }
+
+ outFragColor = vec4(rgb, alpha);
+
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/distancefieldfonts/sdf.vert b/tests/glsl/sascha-willems/distancefieldfonts/sdf.vert
new file mode 100644
index 000000000..4ed4e6246
--- /dev/null
+++ b/tests/glsl/sascha-willems/distancefieldfonts/sdf.vert
@@ -0,0 +1,22 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+void main()
+{
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/dynamicuniformbuffer/base.frag b/tests/glsl/sascha-willems/dynamicuniformbuffer/base.frag
new file mode 100644
index 000000000..496c70b14
--- /dev/null
+++ b/tests/glsl/sascha-willems/dynamicuniformbuffer/base.frag
@@ -0,0 +1,14 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = vec4(inColor, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/dynamicuniformbuffer/base.vert b/tests/glsl/sascha-willems/dynamicuniformbuffer/base.vert
new file mode 100644
index 000000000..5440e88d2
--- /dev/null
+++ b/tests/glsl/sascha-willems/dynamicuniformbuffer/base.vert
@@ -0,0 +1,34 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inColor;
+
+layout (binding = 0) uniform UboView
+{
+ mat4 projection;
+ mat4 view;
+} uboView;
+
+layout (binding = 1) uniform UboInstance
+{
+ mat4 model;
+} uboInstance;
+
+layout (location = 0) out vec3 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+ mat4 modelView = uboView.view * uboInstance.model;
+ vec3 worldPos = vec3(modelView * vec4(inPos, 1.0));
+ gl_Position = uboView.projection * modelView * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/gears/gears.frag b/tests/glsl/sascha-willems/gears/gears.frag
new file mode 100644
index 000000000..db3dcd5e2
--- /dev/null
+++ b/tests/glsl/sascha-willems/gears/gears.frag
@@ -0,0 +1,25 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inEyePos;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 Eye = normalize(-inEyePos);
+ vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
+
+ vec4 IAmbient = vec4(0.2, 0.2, 0.2, 1.0);
+ vec4 IDiffuse = vec4(0.5, 0.5, 0.5, 0.5) * max(dot(inNormal, inLightVec), 0.0);
+ float specular = 0.25;
+ vec4 ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 0.8) * specular;
+
+ outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/gears/gears.vert b/tests/glsl/sascha-willems/gears/gears.vert
new file mode 100644
index 000000000..3799e0000
--- /dev/null
+++ b/tests/glsl/sascha-willems/gears/gears.vert
@@ -0,0 +1,35 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 normal;
+ mat4 view;
+ vec3 lightpos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outEyePos;
+layout (location = 3) out vec3 outLightVec;
+
+void main()
+{
+ outNormal = normalize(mat3(ubo.normal) * inNormal);
+ outColor = inColor;
+ mat4 modelView = ubo.view * ubo.model;
+ vec4 pos = modelView * inPos;
+ outEyePos = vec3(modelView * pos);
+ vec4 lightPos = vec4(ubo.lightpos, 1.0) * modelView;
+ outLightVec = normalize(lightPos.xyz - outEyePos);
+ gl_Position = ubo.projection * pos;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/geometryshader/base.frag b/tests/glsl/sascha-willems/geometryshader/base.frag
new file mode 100644
index 000000000..768117a92
--- /dev/null
+++ b/tests/glsl/sascha-willems/geometryshader/base.frag
@@ -0,0 +1,14 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main(void)
+{
+ outFragColor = vec4(inColor, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/geometryshader/base.vert b/tests/glsl/sascha-willems/geometryshader/base.vert
new file mode 100644
index 000000000..a3ba3830f
--- /dev/null
+++ b/tests/glsl/sascha-willems/geometryshader/base.vert
@@ -0,0 +1,21 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+
+layout (location = 0) out vec3 outNormal;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main(void)
+{
+ outNormal = inNormal;
+ gl_Position = vec4(inPos.xyz, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/geometryshader/mesh.frag b/tests/glsl/sascha-willems/geometryshader/mesh.frag
new file mode 100644
index 000000000..d31ff7124
--- /dev/null
+++ b/tests/glsl/sascha-willems/geometryshader/mesh.frag
@@ -0,0 +1,24 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 ambient = vec3(0.1);
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75);
+ outFragColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/geometryshader/mesh.vert b/tests/glsl/sascha-willems/geometryshader/mesh.vert
new file mode 100644
index 000000000..4caae7b2e
--- /dev/null
+++ b/tests/glsl/sascha-willems/geometryshader/mesh.vert
@@ -0,0 +1,39 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (set = 0, binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ gl_Position = ubo.projection * ubo.model * inPos;
+
+ vec4 pos = ubo.model * vec4(inPos.xyz, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+
+ vec3 lightPos = vec3(1.0f, -1.0f, 1.0f);
+ outLightVec = lightPos.xyz - pos.xyz;
+ outViewVec = -pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/geometryshader/normaldebug.geom b/tests/glsl/sascha-willems/geometryshader/normaldebug.geom
new file mode 100644
index 000000000..d3c487731
--- /dev/null
+++ b/tests/glsl/sascha-willems/geometryshader/normaldebug.geom
@@ -0,0 +1,38 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (triangles) in;
+layout (line_strip, max_vertices = 6) out;
+
+layout (binding = 1) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) in vec3 inNormal[];
+
+layout (location = 0) out vec3 outColor;
+
+void main(void)
+{
+ float normalLength = 0.02;
+ for(int i=0; i<gl_in.length(); i++)
+ {
+ vec3 pos = gl_in[i].gl_Position.xyz;
+ vec3 normal = inNormal[i].xyz;
+
+ gl_Position = ubo.projection * (ubo.model * vec4(pos, 1.0));
+ outColor = vec3(1.0, 0.0, 0.0);
+ EmitVertex();
+
+ gl_Position = ubo.projection * (ubo.model * vec4(pos + normal * normalLength, 1.0));
+ outColor = vec3(0.0, 0.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/hdr/bloom.frag b/tests/glsl/sascha-willems/hdr/bloom.frag
new file mode 100644
index 000000000..bc26005e6
--- /dev/null
+++ b/tests/glsl/sascha-willems/hdr/bloom.frag
@@ -0,0 +1,67 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerColor0;
+layout (binding = 1) uniform sampler2D samplerColor1;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outColor;
+
+layout (constant_id = 0) const int dir = 0;
+
+void main(void)
+{
+ // From the OpenGL Super bible
+ const float weights[] = float[](0.0024499299678342,
+ 0.0043538453346397,
+ 0.0073599963704157,
+ 0.0118349786570722,
+ 0.0181026699707781,
+ 0.0263392293891488,
+ 0.0364543006660986,
+ 0.0479932050577658,
+ 0.0601029809166942,
+ 0.0715974486241365,
+ 0.0811305381519717,
+ 0.0874493212267511,
+ 0.0896631113333857,
+ 0.0874493212267511,
+ 0.0811305381519717,
+ 0.0715974486241365,
+ 0.0601029809166942,
+ 0.0479932050577658,
+ 0.0364543006660986,
+ 0.0263392293891488,
+ 0.0181026699707781,
+ 0.0118349786570722,
+ 0.0073599963704157,
+ 0.0043538453346397,
+ 0.0024499299678342);
+
+
+ const float blurScale = 0.003;
+ const float blurStrength = 1.0;
+
+ float ar = 1.0;
+ // Aspect ratio for vertical blur pass
+ if (dir == 1)
+ {
+ vec2 ts = textureSize(samplerColor1, 0);
+ ar = ts.y / ts.x;
+ }
+
+ vec2 P = inUV.yx - vec2(0, (weights.length() >> 1) * ar * blurScale);
+
+ vec4 color = vec4(0.0);
+ for (int i = 0; i < weights.length(); i++)
+ {
+ vec2 dv = vec2(0.0, i * blurScale) * ar;
+ color += texture(samplerColor1, P + dv) * weights[i] * blurStrength;
+ }
+
+ outColor = color;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/hdr/bloom.vert b/tests/glsl/sascha-willems/hdr/bloom.vert
new file mode 100644
index 000000000..548284554
--- /dev/null
+++ b/tests/glsl/sascha-willems/hdr/bloom.vert
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/hdr/composition.frag b/tests/glsl/sascha-willems/hdr/composition.frag
new file mode 100644
index 000000000..13f2f5838
--- /dev/null
+++ b/tests/glsl/sascha-willems/hdr/composition.frag
@@ -0,0 +1,17 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerColor0;
+layout (binding = 1) uniform sampler2D samplerColor1;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outColor;
+
+void main()
+{
+ outColor = texture(samplerColor0, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/hdr/composition.vert b/tests/glsl/sascha-willems/hdr/composition.vert
new file mode 100644
index 000000000..548284554
--- /dev/null
+++ b/tests/glsl/sascha-willems/hdr/composition.vert
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/hdr/gbuffer.frag b/tests/glsl/sascha-willems/hdr/gbuffer.frag
new file mode 100644
index 000000000..476534d76
--- /dev/null
+++ b/tests/glsl/sascha-willems/hdr/gbuffer.frag
@@ -0,0 +1,95 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform samplerCube samplerEnvMap;
+
+layout (location = 0) in vec3 inUVW;
+layout (location = 1) in vec3 inPos;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+layout (location = 5) in mat4 inInvModelView;
+
+layout (location = 0) out vec4 outColor0;
+layout (location = 1) out vec4 outColor1;
+
+layout (constant_id = 0) const int type = 0;
+
+#define PI 3.1415926
+#define TwoPI (2.0 * PI)
+
+layout (binding = 2) uniform UBO {
+ float exposure;
+} ubo;
+
+void main()
+{
+ vec4 color;
+ vec3 wcNormal;
+
+ switch (type) {
+ case 0: // Skybox
+ {
+ vec3 normal = normalize(inUVW);
+ color = texture(samplerEnvMap, normal);
+ }
+ break;
+
+ case 1: // Reflect
+ {
+ vec3 wViewVec = mat3(inInvModelView) * normalize(inViewVec);
+ vec3 normal = normalize(inNormal);
+ vec3 wNormal = mat3(inInvModelView) * normal;
+
+ float NdotL = max(dot(normal, inLightVec), 0.0);
+
+ vec3 eyeDir = normalize(inViewVec);
+ vec3 halfVec = normalize(inLightVec + eyeDir);
+ float NdotH = max(dot(normal, halfVec), 0.0);
+ float NdotV = max(dot(normal, eyeDir), 0.0);
+ float VdotH = max(dot(eyeDir, halfVec), 0.0);
+
+ // Geometric attenuation
+ float NH2 = 2.0 * NdotH;
+ float g1 = (NH2 * NdotV) / VdotH;
+ float g2 = (NH2 * NdotL) / VdotH;
+ float geoAtt = min(1.0, min(g1, g2));
+
+ const float F0 = 0.6;
+ const float k = 0.2;
+
+ // Fresnel (schlick approximation)
+ float fresnel = pow(1.0 - VdotH, 5.0);
+ fresnel *= (1.0 - F0);
+ fresnel += F0;
+
+ float spec = (fresnel * geoAtt) / (NdotV * NdotL * 3.14);
+
+ color = texture(samplerEnvMap, reflect(-wViewVec, wNormal));
+
+ color = vec4(color.rgb * NdotL * (k + spec * (1.0 - k)), 1.0);
+ }
+ break;
+
+ case 2: // Refract
+ {
+ vec3 wViewVec = mat3(inInvModelView) * normalize(inViewVec);
+ vec3 wNormal = mat3(inInvModelView) * inNormal;
+ color = texture(samplerEnvMap, refract(-wViewVec, wNormal, 1.0/1.6));
+ }
+ break;
+ }
+
+
+ // Color with manual exposure into attachment 0
+ outColor0.rgb = vec3(1.0) - exp(-color.rgb * ubo.exposure);
+
+ // Bright parts for bloom into attachment 1
+ float l = dot(outColor0.rgb, vec3(0.2126, 0.7152, 0.0722));
+ float threshold = 0.75;
+ outColor1.rgb = (l > threshold) ? outColor0.rgb : vec3(0.0);
+ outColor1.a = 1.0;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/hdr/gbuffer.vert b/tests/glsl/sascha-willems/hdr/gbuffer.vert
new file mode 100644
index 000000000..862203774
--- /dev/null
+++ b/tests/glsl/sascha-willems/hdr/gbuffer.vert
@@ -0,0 +1,51 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+
+layout (constant_id = 0) const int type = 0;
+
+layout (binding = 0) uniform UBO {
+ mat4 projection;
+ mat4 modelview;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+layout (location = 1) out vec3 outPos;
+layout (location = 2) out vec3 outNormal;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+layout (location = 5) out mat4 outInvModelView;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUVW = inPos;
+
+ switch(type) {
+ case 0: // Skybox
+ outPos = vec3(mat3(ubo.modelview) * inPos);
+ gl_Position = vec4(ubo.projection * vec4(outPos, 1.0));
+ break;
+ case 1: // Object
+ outPos = vec3(ubo.modelview * vec4(inPos, 1.0));
+ gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
+ break;
+ }
+ outPos = vec3(ubo.modelview * vec4(inPos, 1.0));
+ outNormal = mat3(ubo.modelview) * inNormal;
+
+ outInvModelView = inverse(ubo.modelview);
+
+ vec3 lightPos = vec3(0.0f, -5.0f, 5.0f);
+ outLightVec = lightPos.xyz - outPos.xyz;
+ outViewVec = -outPos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/imgui/scene.frag b/tests/glsl/sascha-willems/imgui/scene.frag
new file mode 100644
index 000000000..77eded98b
--- /dev/null
+++ b/tests/glsl/sascha-willems/imgui/scene.frag
@@ -0,0 +1,23 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ float diffuse = max(dot(N, L), 0.0);
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75);
+ outFragColor = vec4(diffuse * inColor + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/imgui/scene.vert b/tests/glsl/sascha-willems/imgui/scene.vert
new file mode 100644
index 000000000..921b1dbe6
--- /dev/null
+++ b/tests/glsl/sascha-willems/imgui/scene.vert
@@ -0,0 +1,39 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/imgui/ui.frag b/tests/glsl/sascha-willems/imgui/ui.frag
new file mode 100644
index 000000000..51e89bd7b
--- /dev/null
+++ b/tests/glsl/sascha-willems/imgui/ui.frag
@@ -0,0 +1,14 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (binding = 0) uniform sampler2D fontSampler;
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in vec4 inColor;
+
+layout (location = 0) out vec4 outColor;
+
+void main()
+{
+ outColor = inColor * texture(fontSampler, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/imgui/ui.vert b/tests/glsl/sascha-willems/imgui/ui.vert
new file mode 100644
index 000000000..cf95e08d3
--- /dev/null
+++ b/tests/glsl/sascha-willems/imgui/ui.vert
@@ -0,0 +1,26 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec2 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec4 inColor;
+
+layout (push_constant) uniform PushConstants {
+ vec2 scale;
+ vec2 translate;
+} pushConstants;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out vec4 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ outColor = inColor;
+ gl_Position = vec4(inPos * pushConstants.scale + pushConstants.translate, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/indirectdraw/ground.frag b/tests/glsl/sascha-willems/indirectdraw/ground.frag
new file mode 100644
index 000000000..47589e181
--- /dev/null
+++ b/tests/glsl/sascha-willems/indirectdraw/ground.frag
@@ -0,0 +1,29 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 2) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ // Last array layer is terrain tex
+ vec4 color = texture(samplerColor, inUV);
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 ambient = vec3(0.65);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.1);
+ outFragColor = vec4((ambient + diffuse) * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/indirectdraw/ground.vert b/tests/glsl/sascha-willems/indirectdraw/ground.vert
new file mode 100644
index 000000000..fa6bbe5c6
--- /dev/null
+++ b/tests/glsl/sascha-willems/indirectdraw/ground.vert
@@ -0,0 +1,44 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+// Vertex attributes
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+ outUV = inUV * 32.0;
+ outNormal = inNormal;
+
+ vec4 pos = vec4(inPos.xyz, 1.0);
+
+ gl_Position = ubo.projection * ubo.modelview * pos;
+
+ vec4 wPos = ubo.modelview * vec4(pos.xyz, 1.0);
+ vec4 lPos = vec4(0.0, -5.0, 0.0, 1.0);
+ outLightVec = lPos.xyz - pos.xyz;
+ outViewVec = -pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/indirectdraw/indirectdraw.frag b/tests/glsl/sascha-willems/indirectdraw/indirectdraw.frag
new file mode 100644
index 000000000..3c7913201
--- /dev/null
+++ b/tests/glsl/sascha-willems/indirectdraw/indirectdraw.frag
@@ -0,0 +1,31 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2DArray samplerArray;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerArray, inUV);
+
+ if (color.a < 0.5)
+ {
+ discard;
+ }
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 ambient = vec3(0.65);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ outFragColor = vec4((ambient + diffuse) * color.rgb, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/indirectdraw/indirectdraw.vert b/tests/glsl/sascha-willems/indirectdraw/indirectdraw.vert
new file mode 100644
index 000000000..a4d7e9132
--- /dev/null
+++ b/tests/glsl/sascha-willems/indirectdraw/indirectdraw.vert
@@ -0,0 +1,83 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+// Vertex attributes
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+// Instanced attributes
+layout (location = 4) in vec3 instancePos;
+layout (location = 5) in vec3 instanceRot;
+layout (location = 6) in float instanceScale;
+layout (location = 7) in int instanceTexIndex;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+ outUV = vec3(inUV, instanceTexIndex);
+ outUV.t = 1.0 - outUV.t;
+
+ mat4 mx, my, mz;
+
+ // rotate around x
+ float s = sin(instanceRot.x);
+ float c = cos(instanceRot.x);
+
+ mx[0] = vec4(c, s, 0.0, 0.0);
+ mx[1] = vec4(-s, c, 0.0, 0.0);
+ mx[2] = vec4(0.0, 0.0, 1.0, 0.0);
+ mx[3] = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // rotate around y
+ s = sin(instanceRot.y);
+ c = cos(instanceRot.y);
+
+ my[0] = vec4(c, 0.0, s, 0.0);
+ my[1] = vec4(0.0, 1.0, 0.0, 0.0);
+ my[2] = vec4(-s, 0.0, c, 0.0);
+ my[3] = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // rot around z
+ s = sin(instanceRot.z);
+ c = cos(instanceRot.z);
+
+ mz[0] = vec4(1.0, 0.0, 0.0, 0.0);
+ mz[1] = vec4(0.0, c, s, 0.0);
+ mz[2] = vec4(0.0, -s, c, 0.0);
+ mz[3] = vec4(0.0, 0.0, 0.0, 1.0);
+
+ mat4 rotMat = mz * my * mx;
+
+ outNormal = inNormal * mat3(rotMat);
+
+ vec4 pos = vec4((inPos.xyz * instanceScale) + instancePos, 1.0) * rotMat;
+
+ gl_Position = ubo.projection * ubo.modelview * pos;
+
+ vec4 wPos = ubo.modelview * vec4(pos.xyz, 1.0);
+ vec4 lPos = vec4(0.0, -5.0, 0.0, 1.0);
+ outLightVec = lPos.xyz - pos.xyz;
+ outViewVec = -pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/indirectdraw/skysphere.frag b/tests/glsl/sascha-willems/indirectdraw/skysphere.frag
new file mode 100644
index 000000000..5c6f4cc7b
--- /dev/null
+++ b/tests/glsl/sascha-willems/indirectdraw/skysphere.frag
@@ -0,0 +1,18 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 2) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ const vec4 gradientStart = vec4(0.93, 0.9, 0.81, 1.0);
+ const vec4 gradientEnd = vec4(0.35, 0.5, 1.0, 1.0);
+ outFragColor = mix(gradientStart, gradientEnd, min(0.5 - inUV.t, 0.5)/0.15 + 0.5);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/indirectdraw/skysphere.vert b/tests/glsl/sascha-willems/indirectdraw/skysphere.vert
new file mode 100644
index 000000000..03e563b39
--- /dev/null
+++ b/tests/glsl/sascha-willems/indirectdraw/skysphere.vert
@@ -0,0 +1,29 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+// Vertex attributes
+layout (location = 0) in vec4 inPos;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2(inUV.s, 1.0-inUV.t);
+ // Skysphere always at center, only use rotation part of modelview matrix
+ gl_Position = ubo.projection * mat4(mat3(ubo.modelview)) * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/instancing/instancing.frag b/tests/glsl/sascha-willems/instancing/instancing.frag
new file mode 100644
index 000000000..cdec8971b
--- /dev/null
+++ b/tests/glsl/sascha-willems/instancing/instancing.frag
@@ -0,0 +1,27 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2DArray samplerArray;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerArray, inUV) * vec4(inColor, 1.0);
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.1) * inColor;
+ vec3 specular = (dot(N,L) > 0.0) ? pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75) * color.r : vec3(0.0);
+ outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/instancing/instancing.vert b/tests/glsl/sascha-willems/instancing/instancing.vert
new file mode 100644
index 000000000..9f7516453
--- /dev/null
+++ b/tests/glsl/sascha-willems/instancing/instancing.vert
@@ -0,0 +1,85 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+// Vertex attributes
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+// Instanced attributes
+layout (location = 4) in vec3 instancePos;
+layout (location = 5) in vec3 instanceRot;
+layout (location = 6) in float instanceScale;
+layout (location = 7) in int instanceTexIndex;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 lightPos;
+ float locSpeed;
+ float globSpeed;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+void main()
+{
+ outColor = inColor;
+ outUV = vec3(inUV, instanceTexIndex);
+
+ mat3 mx, my, mz;
+
+ // rotate around x
+ float s = sin(instanceRot.x + ubo.locSpeed);
+ float c = cos(instanceRot.x + ubo.locSpeed);
+
+ mx[0] = vec3(c, s, 0.0);
+ mx[1] = vec3(-s, c, 0.0);
+ mx[2] = vec3(0.0, 0.0, 1.0);
+
+ // rotate around y
+ s = sin(instanceRot.y + ubo.locSpeed);
+ c = cos(instanceRot.y + ubo.locSpeed);
+
+ my[0] = vec3(c, 0.0, s);
+ my[1] = vec3(0.0, 1.0, 0.0);
+ my[2] = vec3(-s, 0.0, c);
+
+ // rot around z
+ s = sin(instanceRot.z + ubo.locSpeed);
+ c = cos(instanceRot.z + ubo.locSpeed);
+
+ mz[0] = vec3(1.0, 0.0, 0.0);
+ mz[1] = vec3(0.0, c, s);
+ mz[2] = vec3(0.0, -s, c);
+
+ mat3 rotMat = mz * my * mx;
+
+ mat4 gRotMat;
+ s = sin(instanceRot.y + ubo.globSpeed);
+ c = cos(instanceRot.y + ubo.globSpeed);
+ gRotMat[0] = vec4(c, 0.0, s, 0.0);
+ gRotMat[1] = vec4(0.0, 1.0, 0.0, 0.0);
+ gRotMat[2] = vec4(-s, 0.0, c, 0.0);
+ gRotMat[3] = vec4(0.0, 0.0, 0.0, 1.0);
+
+ vec4 locPos = vec4(inPos.xyz * rotMat, 1.0);
+ vec4 pos = vec4((locPos.xyz * instanceScale) + instancePos, 1.0);
+
+ gl_Position = ubo.projection * ubo.modelview * gRotMat * pos;
+ outNormal = mat3(ubo.modelview * gRotMat) * inverse(rotMat) * inNormal;
+
+ pos = ubo.modelview * vec4(inPos.xyz + instancePos, 1.0);
+ vec3 lPos = mat3(ubo.modelview) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/instancing/planet.frag b/tests/glsl/sascha-willems/instancing/planet.frag
new file mode 100644
index 000000000..eb6d19242
--- /dev/null
+++ b/tests/glsl/sascha-willems/instancing/planet.frag
@@ -0,0 +1,27 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0) * 1.5;
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 4.0) * vec3(0.5) * color.r;
+ outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/instancing/planet.vert b/tests/glsl/sascha-willems/instancing/planet.vert
new file mode 100644
index 000000000..ad0177933
--- /dev/null
+++ b/tests/glsl/sascha-willems/instancing/planet.vert
@@ -0,0 +1,36 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+void main()
+{
+ outColor = inColor;
+ outUV = inUV * vec2(10.0, 6.0);
+ gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.modelview * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.modelview) * inNormal;
+ vec3 lPos = mat3(ubo.modelview) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/instancing/starfield.frag b/tests/glsl/sascha-willems/instancing/starfield.frag
new file mode 100644
index 000000000..bb4c2823a
--- /dev/null
+++ b/tests/glsl/sascha-willems/instancing/starfield.frag
@@ -0,0 +1,35 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outFragColor;
+
+#define HASHSCALE3 vec3(443.897, 441.423, 437.195)
+#define STARFREQUENCY 0.01
+
+// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW)
+float hash33(vec3 p3)
+{
+ p3 = fract(p3 * HASHSCALE3);
+ p3 += dot(p3, p3.yxz+vec3(19.19));
+ return fract((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x);
+}
+
+vec3 starField(vec3 pos)
+{
+ vec3 color = vec3(0.0);
+ float threshhold = (1.0 - STARFREQUENCY);
+ float rnd = hash33(pos);
+ if (rnd >= threshhold)
+ {
+ float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0);
+ color += vec3(starCol);
+ }
+ return color;
+}
+
+void main()
+{
+ outFragColor = vec4(starField(inUVW), 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/instancing/starfield.vert b/tests/glsl/sascha-willems/instancing/starfield.vert
new file mode 100644
index 000000000..82721aefd
--- /dev/null
+++ b/tests/glsl/sascha-willems/instancing/starfield.vert
@@ -0,0 +1,10 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) out vec3 outUVW;
+
+void main()
+{
+ outUVW = vec3((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUVW.st * 2.0f - 1.0f, 0.0f, 1.0f);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/mesh/mesh.frag b/tests/glsl/sascha-willems/mesh/mesh.frag
new file mode 100644
index 000000000..01fd2046f
--- /dev/null
+++ b/tests/glsl/sascha-willems/mesh/mesh.frag
@@ -0,0 +1,28 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0);
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75);
+ outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/mesh/mesh.vert b/tests/glsl/sascha-willems/mesh/mesh.vert
new file mode 100644
index 000000000..d0b3be251
--- /dev/null
+++ b/tests/glsl/sascha-willems/mesh/mesh.vert
@@ -0,0 +1,42 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/multithreading/phong.frag b/tests/glsl/sascha-willems/multithreading/phong.frag
new file mode 100644
index 000000000..663fd81b9
--- /dev/null
+++ b/tests/glsl/sascha-willems/multithreading/phong.frag
@@ -0,0 +1,24 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.75);
+ outFragColor = vec4(diffuse + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/multithreading/phong.vert b/tests/glsl/sascha-willems/multithreading/phong.vert
new file mode 100644
index 000000000..67f803dfd
--- /dev/null
+++ b/tests/glsl/sascha-willems/multithreading/phong.vert
@@ -0,0 +1,43 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (std140, push_constant) uniform PushConsts
+{
+ mat4 mvp;
+ vec3 color;
+} pushConsts;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+void main()
+{
+ outNormal = inNormal;
+
+ if ( (inColor.r == 1.0) && (inColor.g == 0.0) && (inColor.b == 0.0))
+ {
+ outColor = pushConsts.color;
+ }
+ else
+ {
+ outColor = inColor;
+ }
+
+ gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = pushConsts.mvp * vec4(inPos, 1.0);
+ outNormal = mat3(pushConsts.mvp) * inNormal;
+// vec3 lPos = ubo.lightPos.xyz;
+vec3 lPos = vec3(0.0);
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/multithreading/starsphere.frag b/tests/glsl/sascha-willems/multithreading/starsphere.frag
new file mode 100644
index 000000000..7136a0499
--- /dev/null
+++ b/tests/glsl/sascha-willems/multithreading/starsphere.frag
@@ -0,0 +1,43 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outFragColor;
+
+#define HASHSCALE3 vec3(443.897, 441.423, 437.195)
+#define STARFREQUENCY 0.01
+
+// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW)
+float hash33(vec3 p3)
+{
+ p3 = fract(p3 * HASHSCALE3);
+ p3 += dot(p3, p3.yxz+vec3(19.19));
+ return fract((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x);
+}
+
+vec3 starField(vec3 pos)
+{
+ vec3 color = vec3(0.0);
+ float threshhold = (1.0 - STARFREQUENCY);
+ float rnd = hash33(pos);
+ if (rnd >= threshhold)
+ {
+ float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0);
+ color += vec3(starCol);
+ }
+ return color;
+}
+
+void main()
+{
+ // Fake atmosphere at the bottom
+ vec3 atmosphere = clamp(vec3(0.1, 0.15, 0.4) * (inUVW.t - 5.0), 0.0, 1.0);
+
+ vec3 color = starField(inUVW) + atmosphere;
+
+ outFragColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/multithreading/starsphere.vert b/tests/glsl/sascha-willems/multithreading/starsphere.vert
new file mode 100644
index 000000000..c80106f45
--- /dev/null
+++ b/tests/glsl/sascha-willems/multithreading/starsphere.vert
@@ -0,0 +1,20 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (std140, push_constant) uniform PushConsts
+{
+ mat4 mvp;
+} pushConsts;
+
+layout (location = 0) out vec3 outUVW;
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/occlusionquery/mesh.frag b/tests/glsl/sascha-willems/occlusionquery/mesh.frag
new file mode 100644
index 000000000..af644729d
--- /dev/null
+++ b/tests/glsl/sascha-willems/occlusionquery/mesh.frag
@@ -0,0 +1,32 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in float inVisible;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+
+void main()
+{
+ if (inVisible > 0.0)
+ {
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 8.0) * vec3(0.75);
+ outFragColor = vec4(diffuse + specular, 1.0);
+ }
+ else
+ {
+ outFragColor = vec4(vec3(0.1), 1.0);
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/occlusionquery/mesh.vert b/tests/glsl/sascha-willems/occlusionquery/mesh.vert
new file mode 100644
index 000000000..02a930fe9
--- /dev/null
+++ b/tests/glsl/sascha-willems/occlusionquery/mesh.vert
@@ -0,0 +1,42 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 lightPos;
+ float visible;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out float outVisible;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outVisible = ubo.visible;
+
+ gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.modelview * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.modelview) * inNormal;
+ outLightVec = ubo.lightPos.xyz - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/occlusionquery/occluder.frag b/tests/glsl/sascha-willems/occlusionquery/occluder.frag
new file mode 100644
index 000000000..37b13e5c0
--- /dev/null
+++ b/tests/glsl/sascha-willems/occlusionquery/occluder.frag
@@ -0,0 +1,14 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = vec4(inColor, 0.5);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/occlusionquery/occluder.vert b/tests/glsl/sascha-willems/occlusionquery/occluder.vert
new file mode 100644
index 000000000..8adca67d2
--- /dev/null
+++ b/tests/glsl/sascha-willems/occlusionquery/occluder.vert
@@ -0,0 +1,29 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+ gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/occlusionquery/simple.frag b/tests/glsl/sascha-willems/occlusionquery/simple.frag
new file mode 100644
index 000000000..108acc1c1
--- /dev/null
+++ b/tests/glsl/sascha-willems/occlusionquery/simple.frag
@@ -0,0 +1,14 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = vec4(1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/occlusionquery/simple.vert b/tests/glsl/sascha-willems/occlusionquery/simple.vert
new file mode 100644
index 000000000..b869b7a9c
--- /dev/null
+++ b/tests/glsl/sascha-willems/occlusionquery/simple.vert
@@ -0,0 +1,26 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/offscreen/mirror.frag b/tests/glsl/sascha-willems/offscreen/mirror.frag
new file mode 100644
index 000000000..c8b31bd2b
--- /dev/null
+++ b/tests/glsl/sascha-willems/offscreen/mirror.frag
@@ -0,0 +1,44 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+layout (binding = 2) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in vec4 inPos;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 tmp = vec4(1.0 / inPos.w);
+ vec4 projCoord = inPos * tmp;
+
+ // Scale and bias
+ projCoord += vec4(1.0);
+ projCoord *= vec4(0.5);
+
+ // Slow single pass blur
+ // For demonstration purposes only
+ const float blurSize = 1.0 / 512.0;
+
+ vec4 color = texture(samplerColorMap, inUV);
+ outFragColor = color * 0.25;
+
+ if (gl_FrontFacing)
+ {
+ // Only render mirrored scene on front facing (upper) side of mirror surface
+ vec4 reflection = vec4(0.0);
+ for (int x = -3; x <= 3; x++)
+ {
+ for (int y = -3; y <= 3; y++)
+ {
+ reflection += texture(samplerColor, vec2(projCoord.s + x * blurSize, projCoord.t + y * blurSize)) / 49.0;
+ }
+ }
+ outFragColor += reflection * 1.5 * (color.r);
+ };
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/offscreen/mirror.vert b/tests/glsl/sascha-willems/offscreen/mirror.vert
new file mode 100644
index 000000000..a4c0cb7f5
--- /dev/null
+++ b/tests/glsl/sascha-willems/offscreen/mirror.vert
@@ -0,0 +1,29 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out vec4 outPos;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ outPos = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+ gl_Position = outPos;
+}
diff --git a/tests/glsl/sascha-willems/offscreen/phong.frag b/tests/glsl/sascha-willems/offscreen/phong.frag
new file mode 100644
index 000000000..43fc662a9
--- /dev/null
+++ b/tests/glsl/sascha-willems/offscreen/phong.frag
@@ -0,0 +1,30 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inEyePos;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 Eye = normalize(-inEyePos);
+ vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
+
+ vec4 IAmbient = vec4(0.1, 0.1, 0.1, 1.0);
+ vec4 IDiffuse = vec4(max(dot(inNormal, inLightVec), 0.0));
+ float specular = 0.75;
+ vec4 ISpecular = vec4(0.0);
+ if (dot(inEyePos, inNormal) < 0.0)
+ {
+ ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 16.0) * specular;
+ }
+
+ outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular);
+
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/offscreen/phong.vert b/tests/glsl/sascha-willems/offscreen/phong.vert
new file mode 100644
index 000000000..5bef0fa1e
--- /dev/null
+++ b/tests/glsl/sascha-willems/offscreen/phong.vert
@@ -0,0 +1,40 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outEyePos;
+layout (location = 3) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+ float gl_ClipDistance[];
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ gl_Position = ubo.projection * ubo.model * inPos;
+ outEyePos = vec3(ubo.model * inPos);
+ outLightVec = normalize(ubo.lightPos.xyz - outEyePos);
+
+ // Clip against reflection plane
+ vec4 clipPlane = vec4(0.0, -1.0, 0.0, 1.5);
+ gl_ClipDistance[0] = dot(inPos, clipPlane);
+}
diff --git a/tests/glsl/sascha-willems/offscreen/quad.frag b/tests/glsl/sascha-willems/offscreen/quad.frag
new file mode 100644
index 000000000..6d54f2f33
--- /dev/null
+++ b/tests/glsl/sascha-willems/offscreen/quad.frag
@@ -0,0 +1,16 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerColor, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/offscreen/quad.vert b/tests/glsl/sascha-willems/offscreen/quad.vert
new file mode 100644
index 000000000..c1ad3e070
--- /dev/null
+++ b/tests/glsl/sascha-willems/offscreen/quad.vert
@@ -0,0 +1,27 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/parallax/parallax.frag b/tests/glsl/sascha-willems/parallax/parallax.frag
new file mode 100644
index 000000000..79dcab907
--- /dev/null
+++ b/tests/glsl/sascha-willems/parallax/parallax.frag
@@ -0,0 +1,144 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (binding = 1) uniform sampler2D sColorMap;
+layout (binding = 2) uniform sampler2D sNormalHeightMap;
+
+layout (binding = 3) uniform UBO
+{
+ float heightScale;
+ float parallaxBias;
+ float numLayers;
+ int mappingMode;
+} ubo;
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in vec3 inTangentLightPos;
+layout (location = 2) in vec3 inTangentViewPos;
+layout (location = 3) in vec3 inTangentFragPos;
+
+layout (location = 0) out vec4 outColor;
+
+vec2 parallax_uv(vec2 uv, vec3 view_dir, int type)
+{
+ if (type == 2) {
+ // Parallax mapping
+ float depth = 1.0 - texture(sNormalHeightMap, uv).a;
+ vec2 p = view_dir.xy * (depth * (ubo.heightScale * 0.5) + ubo.parallaxBias) / view_dir.z;
+ return uv - p;
+ } else {
+ float layer_depth = 1.0 / ubo.numLayers;
+ float cur_layer_depth = 0.0;
+ vec2 delta_uv = view_dir.xy * ubo.heightScale / (view_dir.z * ubo.numLayers);
+ vec2 cur_uv = uv;
+
+ float depth_from_tex = 1.0 - texture(sNormalHeightMap, cur_uv).a;
+
+ for (int i = 0; i < 32; i++) {
+ cur_layer_depth += layer_depth;
+ cur_uv -= delta_uv;
+ depth_from_tex = 1.0 - texture(sNormalHeightMap, cur_uv).a;
+ if (depth_from_tex < cur_layer_depth) {
+ break;
+ }
+ }
+
+ if (type == 3) {
+ // Steep parallax mapping
+ return cur_uv;
+ } else {
+ // Parallax occlusion mapping
+ vec2 prev_uv = cur_uv + delta_uv;
+ float next = depth_from_tex - cur_layer_depth;
+ float prev = 1.0 - texture(sNormalHeightMap, prev_uv).a - cur_layer_depth + layer_depth;
+ float weight = next / (next - prev);
+ return mix(cur_uv, prev_uv, weight);
+ }
+ }
+}
+
+vec2 parallaxMapping(vec2 uv, vec3 viewDir)
+{
+ float height = 1.0 - texture(sNormalHeightMap, uv).a;
+ vec2 p = viewDir.xy * (height * (ubo.heightScale * 0.5) + ubo.parallaxBias) / viewDir.z;
+ return uv - p;
+}
+
+vec2 steepParallaxMapping(vec2 uv, vec3 viewDir)
+{
+ float layerDepth = 1.0 / ubo.numLayers;
+ float currLayerDepth = 0.0;
+ vec2 deltaUV = viewDir.xy * ubo.heightScale / (viewDir.z * ubo.numLayers);
+ vec2 currUV = uv;
+ float height = 1.0 - texture(sNormalHeightMap, currUV).a;
+ for (int i = 0; i < ubo.numLayers; i++) {
+ currLayerDepth += layerDepth;
+ currUV -= deltaUV;
+ height = 1.0 - texture(sNormalHeightMap, currUV).a;
+ if (height < currLayerDepth) {
+ break;
+ }
+ }
+ return currUV;
+}
+
+vec2 parallaxOcclusionMapping(vec2 uv, vec3 viewDir)
+{
+ float layerDepth = 1.0 / ubo.numLayers;
+ float currLayerDepth = 0.0;
+ vec2 deltaUV = viewDir.xy * ubo.heightScale / (viewDir.z * ubo.numLayers);
+ vec2 currUV = uv;
+ float height = 1.0 - texture(sNormalHeightMap, currUV).a;
+ for (int i = 0; i < ubo.numLayers; i++) {
+ currLayerDepth += layerDepth;
+ currUV -= deltaUV;
+ height = 1.0 - texture(sNormalHeightMap, currUV).a;
+ if (height < currLayerDepth) {
+ break;
+ }
+ }
+ vec2 prevUV = currUV + deltaUV;
+ float nextDepth = height - currLayerDepth;
+ float prevDepth = 1.0 - texture(sNormalHeightMap, prevUV).a - currLayerDepth + layerDepth;
+ return mix(currUV, prevUV, nextDepth / (nextDepth - prevDepth));
+}
+
+void main(void)
+{
+ vec3 V = normalize(inTangentViewPos - inTangentFragPos);
+ vec2 uv = inUV;
+
+ if (ubo.mappingMode == 0) {
+ // Color only
+ outColor = texture(sColorMap, inUV);
+ } else {
+ switch(ubo.mappingMode) {
+ case 2:
+ uv = parallaxMapping(inUV, V);
+ break;
+ case 3:
+ uv = steepParallaxMapping(inUV, V);
+ break;
+ case 4:
+ uv = parallaxOcclusionMapping(inUV, V);
+ break;
+ }
+
+ // Discard fragments at texture border
+ if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
+ discard;
+ }
+
+ vec3 N = normalize(texture(sNormalHeightMap, uv).rgb * 2.0 - 1.0);
+ vec3 L = normalize(inTangentLightPos - inTangentFragPos);
+ vec3 R = reflect(-L, N);
+ vec3 H = normalize(L + V);
+
+ vec3 color = texture(sColorMap, uv).rgb;
+ vec3 ambient = 0.2 * color;
+ vec3 diffuse = max(dot(L, N), 0.0) * color;
+ vec3 specular = vec3(0.15) * pow(max(dot(N, H), 0.0), 32.0);
+
+ outColor = vec4(ambient + diffuse + specular, 1.0f);
+ }
+}
diff --git a/tests/glsl/sascha-willems/parallax/parallax.vert b/tests/glsl/sascha-willems/parallax/parallax.vert
new file mode 100644
index 000000000..3032d9c6e
--- /dev/null
+++ b/tests/glsl/sascha-willems/parallax/parallax.vert
@@ -0,0 +1,38 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in vec3 inTangent;
+layout (location = 4) in vec3 inBiTangent;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ vec4 lightPos;
+ vec4 cameraPos;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out vec3 outTangentLightPos;
+layout (location = 2) out vec3 outTangentViewPos;
+layout (location = 3) out vec3 outTangentFragPos;
+
+void main(void)
+{
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos, 1.0f);
+ outTangentFragPos = vec3(ubo.model * vec4(inPos, 1.0));
+ outUV = inUV;
+
+ vec3 T = normalize(mat3(ubo.model) * inTangent);
+ vec3 B = normalize(mat3(ubo.model) * inBiTangent);
+ vec3 N = normalize(mat3(ubo.model) * inNormal);
+ mat3 TBN = transpose(mat3(T, B, N));
+
+ outTangentLightPos = TBN * ubo.lightPos.xyz;
+ outTangentViewPos = TBN * ubo.cameraPos.xyz;
+ outTangentFragPos = TBN * outTangentFragPos;
+}
diff --git a/tests/glsl/sascha-willems/particlefire/normalmap.frag b/tests/glsl/sascha-willems/particlefire/normalmap.frag
new file mode 100644
index 000000000..9f3af4cf1
--- /dev/null
+++ b/tests/glsl/sascha-willems/particlefire/normalmap.frag
@@ -0,0 +1,45 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D sColorMap;
+layout (binding = 2) uniform sampler2D sNormalHeightMap;
+
+#define lightRadius 45.0
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in vec3 inLightVec;
+layout (location = 2) in vec3 inLightVecB;
+layout (location = 5) in vec3 inLightDir;
+layout (location = 6) in vec3 inViewVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main(void)
+{
+ vec3 specularColor = vec3(0.85, 0.5, 0.0);
+
+ float invRadius = 1.0/lightRadius;
+ float ambient = 0.25;
+
+ vec3 rgb, normal;
+
+ rgb = texture(sColorMap, inUV).rgb;
+ normal = normalize((texture(sNormalHeightMap, inUV).rgb - 0.5) * 2.0);
+
+ float distSqr = dot(inLightVecB, inLightVecB);
+ vec3 lVec = inLightVecB * inversesqrt(distSqr);
+
+ float atten = max(clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0), ambient);
+ float diffuse = clamp(dot(lVec, normal), 0.0, 1.0);
+
+ vec3 light = normalize(-inLightVec);
+ vec3 view = normalize(inViewVec);
+ vec3 reflectDir = reflect(-light, normal);
+
+ float specular = pow(max(dot(view, reflectDir), 0.0), 4.0);
+
+ outFragColor = vec4((rgb * atten + (diffuse * rgb + 0.5 * specular * specularColor.rgb)) * atten, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/particlefire/normalmap.vert b/tests/glsl/sascha-willems/particlefire/normalmap.vert
new file mode 100644
index 000000000..a93c16b00
--- /dev/null
+++ b/tests/glsl/sascha-willems/particlefire/normalmap.vert
@@ -0,0 +1,60 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in vec3 inTangent;
+layout (location = 4) in vec3 inBiTangent;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 normal;
+ vec4 lightPos;
+ vec4 cameraPos;
+} ubo;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+ float gl_PointSize;
+};
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out vec3 outLightVec;
+layout (location = 2) out vec3 outLightVecB;
+layout (location = 5) out vec3 outLightDir;
+layout (location = 6) out vec3 outViewVec;
+
+void main(void)
+{
+ vec3 vertexPosition = vec3(ubo.model * vec4(inPos, 1.0));
+ outLightDir = normalize(ubo.lightPos.xyz - vertexPosition);
+
+ // Setup (t)angent-(b)inormal-(n)ormal matrix for converting
+ // object coordinates into tangent space
+ mat3 tbnMatrix;
+ tbnMatrix[0] = mat3(ubo.normal) * inTangent;
+ tbnMatrix[1] = mat3(ubo.normal) * inBiTangent;
+ tbnMatrix[2] = mat3(ubo.normal) * inNormal;
+
+ outLightVec.xyz = vec3(ubo.lightPos.xyz - vertexPosition.xyz) * tbnMatrix;
+
+ vec3 lightDist = ubo.lightPos.xyz - inPos.xyz;
+ outLightVecB.x = dot(inTangent.xyz, lightDist);
+ outLightVecB.y = dot(inBiTangent.xyz, lightDist);
+ outLightVecB.z = dot(inNormal, lightDist);
+
+ outViewVec.x = dot(inTangent, inPos.xyz);
+ outViewVec.y = dot(inBiTangent, inPos.xyz);
+ outViewVec.z = dot(inNormal, inPos.xyz);
+
+ outUV = inUV;
+
+ gl_Position = ubo.projection * ubo.model * vec4(inPos, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/particlefire/particle.frag b/tests/glsl/sascha-willems/particlefire/particle.frag
new file mode 100644
index 000000000..104fe406c
--- /dev/null
+++ b/tests/glsl/sascha-willems/particlefire/particle.frag
@@ -0,0 +1,47 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerSmoke;
+layout (binding = 2) uniform sampler2D samplerFire;
+
+layout (location = 0) in vec4 inColor;
+layout (location = 1) in float inAlpha;
+layout (location = 2) in flat int inType;
+layout (location = 3) in float inRotation;
+
+
+layout (location = 0) out vec4 outFragColor;
+
+void main ()
+{
+ vec4 color;
+ float alpha = (inAlpha <= 1.0) ? inAlpha : 2.0 - inAlpha;
+
+ // Rotate texture coordinates
+ // Rotate UV
+ float rotCenter = 0.5;
+ float rotCos = cos(inRotation);
+ float rotSin = sin(inRotation);
+ vec2 rotUV = vec2(
+ rotCos * (gl_PointCoord.x - rotCenter) + rotSin * (gl_PointCoord.y - rotCenter) + rotCenter,
+ rotCos * (gl_PointCoord.y - rotCenter) - rotSin * (gl_PointCoord.x - rotCenter) + rotCenter);
+
+
+ if (inType == 0)
+ {
+ // Flame
+ color = texture(samplerFire, rotUV);
+ outFragColor.a = 0.0;
+ }
+ else
+ {
+ // Smoke
+ color = texture(samplerSmoke, rotUV);
+ outFragColor.a = color.a * alpha;
+ }
+
+ outFragColor.rgb = color.rgb * inColor.rgb * alpha;
+}
diff --git a/tests/glsl/sascha-willems/particlefire/particle.vert b/tests/glsl/sascha-willems/particlefire/particle.vert
new file mode 100644
index 000000000..a5d3c561b
--- /dev/null
+++ b/tests/glsl/sascha-willems/particlefire/particle.vert
@@ -0,0 +1,50 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec4 inColor;
+layout (location = 2) in float inAlpha;
+layout (location = 3) in float inSize;
+layout (location = 4) in float inRotation;
+layout (location = 5) in int inType;
+
+layout (location = 0) out vec4 outColor;
+layout (location = 1) out float outAlpha;
+layout (location = 2) out flat int outType;
+layout (location = 3) out float outRotation;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec2 viewportDim;
+ float pointSize;
+} ubo;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+ float gl_PointSize;
+};
+
+void main ()
+{
+ outColor = inColor;
+ outAlpha = inAlpha;
+ outType = inType;
+ outRotation = inRotation;
+
+ gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0);
+
+ // Base size of the point sprites
+ float spriteSize = 8.0 * inSize;
+
+ // Scale particle size depending on camera projection
+ vec4 eyePos = ubo.modelview * vec4(inPos.xyz, 1.0);
+ vec4 projectedCorner = ubo.projection * vec4(0.5 * spriteSize, 0.5 * spriteSize, eyePos.z, eyePos.w);
+ gl_PointSize = ubo.viewportDim.x * projectedCorner.x / projectedCorner.w;
+
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbrbasic/pbr.frag b/tests/glsl/sascha-willems/pbrbasic/pbr.frag
new file mode 100644
index 000000000..06a69e1e9
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrbasic/pbr.frag
@@ -0,0 +1,128 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec3 inWorldPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec3 camPos;
+} ubo;
+
+layout (binding = 1) uniform UBOShared {
+ vec4 lights[4];
+} uboParams;
+
+layout (location = 0) out vec4 outColor;
+
+layout(push_constant) uniform PushConsts {
+ layout(offset = 12) float roughness;
+ layout(offset = 16) float metallic;
+ layout(offset = 20) float r;
+ layout(offset = 24) float g;
+ layout(offset = 28) float b;
+} material;
+
+const float PI = 3.14159265359;
+
+//#define ROUGHNESS_PATTERN 1
+
+vec3 materialcolor()
+{
+ return vec3(material.r, material.g, material.b);
+}
+
+// Normal Distribution function --------------------------------------
+float D_GGX(float dotNH, float roughness)
+{
+ float alpha = roughness * roughness;
+ float alpha2 = alpha * alpha;
+ float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0;
+ return (alpha2)/(PI * denom*denom);
+}
+
+// Geometric Shadowing function --------------------------------------
+float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
+{
+ float r = (roughness + 1.0);
+ float k = (r*r) / 8.0;
+ float GL = dotNL / (dotNL * (1.0 - k) + k);
+ float GV = dotNV / (dotNV * (1.0 - k) + k);
+ return GL * GV;
+}
+
+// Fresnel function ----------------------------------------------------
+vec3 F_Schlick(float cosTheta, float metallic)
+{
+ vec3 F0 = mix(vec3(0.04), materialcolor(), metallic); // * material.specular
+ vec3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
+ return F;
+}
+
+// Specular BRDF composition --------------------------------------------
+
+vec3 BRDF(vec3 L, vec3 V, vec3 N, float metallic, float roughness)
+{
+ // Precalculate vectors and dot products
+ vec3 H = normalize (V + L);
+ float dotNV = clamp(dot(N, V), 0.0, 1.0);
+ float dotNL = clamp(dot(N, L), 0.0, 1.0);
+ float dotLH = clamp(dot(L, H), 0.0, 1.0);
+ float dotNH = clamp(dot(N, H), 0.0, 1.0);
+
+ // Light color fixed
+ vec3 lightColor = vec3(1.0);
+
+ vec3 color = vec3(0.0);
+
+ if (dotNL > 0.0)
+ {
+ float rroughness = max(0.05, roughness);
+ // D = Normal distribution (Distribution of the microfacets)
+ float D = D_GGX(dotNH, roughness);
+ // G = Geometric shadowing term (Microfacets shadowing)
+ float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+ // F = Fresnel factor (Reflectance depending on angle of incidence)
+ vec3 F = F_Schlick(dotNV, metallic);
+
+ vec3 spec = D * F * G / (4.0 * dotNL * dotNV);
+
+ color += spec * dotNL * lightColor;
+ }
+
+ return color;
+}
+
+// ----------------------------------------------------------------------------
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 V = normalize(ubo.camPos - inWorldPos);
+
+ float roughness = material.roughness;
+
+ // Add striped pattern to roughness based on vertex position
+#ifdef ROUGHNESS_PATTERN
+ roughness = max(roughness, step(fract(inWorldPos.y * 2.02), 0.5));
+#endif
+
+ // Specular contribution
+ vec3 Lo = vec3(0.0);
+ for (int i = 0; i < uboParams.lights.length(); i++) {
+ vec3 L = normalize(uboParams.lights[i].xyz - inWorldPos);
+ Lo += BRDF(L, V, N, material.metallic, roughness);
+ };
+
+ // Combine with ambient
+ vec3 color = materialcolor() * 0.02;
+ color += Lo;
+
+ // Gamma correct
+ color = pow(color, vec3(0.4545));
+
+ outColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbrbasic/pbr.vert b/tests/glsl/sascha-willems/pbrbasic/pbr.vert
new file mode 100644
index 000000000..9a85b892a
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrbasic/pbr.vert
@@ -0,0 +1,39 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec3 camPos;
+} ubo;
+
+layout (location = 0) out vec3 outWorldPos;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out vec2 outUV;
+
+layout(push_constant) uniform PushConsts {
+ vec3 objPos;
+} pushConsts;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0));
+ outWorldPos = locPos + pushConsts.objPos;
+ outNormal = mat3(ubo.model) * inNormal;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbribl/filtercube.vert b/tests/glsl/sascha-willems/pbribl/filtercube.vert
new file mode 100644
index 000000000..07f02c8b5
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/filtercube.vert
@@ -0,0 +1,20 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec3 inPos;
+
+layout(push_constant) uniform PushConsts {
+ layout (offset = 0) mat4 mvp;
+} pushConsts;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex {
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbribl/genbrdflut.frag b/tests/glsl/sascha-willems/pbribl/genbrdflut.frag
new file mode 100644
index 000000000..25f00af1f
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/genbrdflut.frag
@@ -0,0 +1,91 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec2 inUV;
+layout (location = 0) out vec4 outColor;
+layout (constant_id = 0) const uint NUM_SAMPLES = 1024u;
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+ float a = 12.9898;
+ float b = 78.233;
+ float c = 43758.5453;
+ float dt= dot(co.xy ,vec2(a,b));
+ float sn= mod(dt,3.14);
+ return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N)
+{
+ // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+ uint bits = (i << 16u) | (i >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ float rdi = float(bits) * 2.3283064365386963e-10;
+ return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
+{
+ // Maps a 2D point to a hemisphere with spread based on roughness
+ float alpha = roughness * roughness;
+ float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+ vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+ // Tangent space
+ vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangentX = normalize(cross(up, normal));
+ vec3 tangentY = normalize(cross(normal, tangentX));
+
+ // Convert to world Space
+ return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Geometric Shadowing function
+float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
+{
+ float k = (roughness * roughness) / 2.0;
+ float GL = dotNL / (dotNL * (1.0 - k) + k);
+ float GV = dotNV / (dotNV * (1.0 - k) + k);
+ return GL * GV;
+}
+
+vec2 BRDF(float NoV, float roughness)
+{
+ // Normal always points along z-axis for the 2D lookup
+ const vec3 N = vec3(0.0, 0.0, 1.0);
+ vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV);
+
+ vec2 LUT = vec2(0.0);
+ for(uint i = 0u; i < NUM_SAMPLES; i++) {
+ vec2 Xi = hammersley2d(i, NUM_SAMPLES);
+ vec3 H = importanceSample_GGX(Xi, roughness, N);
+ vec3 L = 2.0 * dot(V, H) * H - V;
+
+ float dotNL = max(dot(N, L), 0.0);
+ float dotNV = max(dot(N, V), 0.0);
+ float dotVH = max(dot(V, H), 0.0);
+ float dotNH = max(dot(H, N), 0.0);
+
+ if (dotNL > 0.0) {
+ float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+ float G_Vis = (G * dotVH) / (dotNH * dotNV);
+ float Fc = pow(1.0 - dotVH, 5.0);
+ LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis);
+ }
+ }
+ return LUT / float(NUM_SAMPLES);
+}
+
+void main()
+{
+ outColor = vec4(BRDF(inUV.s, 1.0-inUV.t), 0.0, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbribl/genbrdflut.vert b/tests/glsl/sascha-willems/pbribl/genbrdflut.vert
new file mode 100644
index 000000000..8576b78b4
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/genbrdflut.vert
@@ -0,0 +1,10 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) out vec2 outUV;
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbribl/irradiancecube.frag b/tests/glsl/sascha-willems/pbribl/irradiancecube.frag
new file mode 100644
index 000000000..926c68c4c
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/irradiancecube.frag
@@ -0,0 +1,38 @@
+// Generates an irradiance cube from an environment map using convolution
+
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec3 inPos;
+layout (location = 0) out vec4 outColor;
+layout (binding = 0) uniform samplerCube samplerEnv;
+
+layout(push_constant) uniform PushConsts {
+ layout (offset = 64) float deltaPhi;
+ layout (offset = 68) float deltaTheta;
+} consts;
+
+#define PI 3.1415926535897932384626433832795
+
+void main()
+{
+ vec3 N = normalize(inPos);
+ vec3 up = vec3(0.0, 1.0, 0.0);
+ vec3 right = normalize(cross(up, N));
+ up = cross(N, right);
+
+ const float TWO_PI = PI * 2.0;
+ const float HALF_PI = PI * 0.5;
+
+ vec3 color = vec3(0.0);
+ uint sampleCount = 0u;
+ for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) {
+ for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) {
+ vec3 tempVec = cos(phi) * right + sin(phi) * up;
+ vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec;
+ color += texture(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta);
+ sampleCount++;
+ }
+ }
+ outColor = vec4(PI * color / float(sampleCount), 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbribl/pbribl.frag b/tests/glsl/sascha-willems/pbribl/pbribl.frag
new file mode 100644
index 000000000..d04c46256
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/pbribl.frag
@@ -0,0 +1,163 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec3 inWorldPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO {
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec3 camPos;
+} ubo;
+
+layout (binding = 1) uniform UBOParams {
+ vec4 lights[4];
+ float exposure;
+ float gamma;
+} uboParams;
+
+layout(push_constant) uniform PushConsts {
+ layout(offset = 12) float roughness;
+ layout(offset = 16) float metallic;
+ layout(offset = 20) float specular;
+ layout(offset = 24) float r;
+ layout(offset = 28) float g;
+ layout(offset = 32) float b;
+} material;
+
+layout (binding = 2) uniform samplerCube samplerIrradiance;
+layout (binding = 3) uniform sampler2D samplerBRDFLUT;
+layout (binding = 4) uniform samplerCube prefilteredMap;
+
+layout (location = 0) out vec4 outColor;
+
+#define PI 3.1415926535897932384626433832795
+#define ALBEDO vec3(material.r, material.g, material.b)
+
+// From http://filmicgames.com/archives/75
+vec3 Uncharted2Tonemap(vec3 x)
+{
+ float A = 0.15;
+ float B = 0.50;
+ float C = 0.10;
+ float D = 0.20;
+ float E = 0.02;
+ float F = 0.30;
+ return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
+}
+
+// Normal Distribution function --------------------------------------
+float D_GGX(float dotNH, float roughness)
+{
+ float alpha = roughness * roughness;
+ float alpha2 = alpha * alpha;
+ float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0;
+ return (alpha2)/(PI * denom*denom);
+}
+
+// Geometric Shadowing function --------------------------------------
+float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
+{
+ float r = (roughness + 1.0);
+ float k = (r*r) / 8.0;
+ float GL = dotNL / (dotNL * (1.0 - k) + k);
+ float GV = dotNV / (dotNV * (1.0 - k) + k);
+ return GL * GV;
+}
+
+// Fresnel function ----------------------------------------------------
+vec3 F_Schlick(float cosTheta, vec3 F0)
+{
+ return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
+}
+vec3 F_SchlickR(float cosTheta, vec3 F0, float roughness)
+{
+ return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
+}
+
+vec3 prefilteredReflection(vec3 R, float roughness)
+{
+ const float MAX_REFLECTION_LOD = 9.0; // todo: param/const
+ float lod = roughness * MAX_REFLECTION_LOD;
+ float lodf = floor(lod);
+ float lodc = ceil(lod);
+ vec3 a = textureLod(prefilteredMap, R, lodf).rgb;
+ vec3 b = textureLod(prefilteredMap, R, lodc).rgb;
+ return mix(a, b, lod - lodf);
+}
+
+vec3 specularContribution(vec3 L, vec3 V, vec3 N, vec3 F0, float metallic, float roughness)
+{
+ // Precalculate vectors and dot products
+ vec3 H = normalize (V + L);
+ float dotNH = clamp(dot(N, H), 0.0, 1.0);
+ float dotNV = clamp(dot(N, V), 0.0, 1.0);
+ float dotNL = clamp(dot(N, L), 0.0, 1.0);
+
+ // Light color fixed
+ vec3 lightColor = vec3(1.0);
+
+ vec3 color = vec3(0.0);
+
+ if (dotNL > 0.0) {
+ // D = Normal distribution (Distribution of the microfacets)
+ float D = D_GGX(dotNH, roughness);
+ // G = Geometric shadowing term (Microfacets shadowing)
+ float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+ // F = Fresnel factor (Reflectance depending on angle of incidence)
+ vec3 F = F_Schlick(dotNV, F0);
+ vec3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001);
+ vec3 kD = (vec3(1.0) - F) * (1.0 - metallic);
+ color += (kD * ALBEDO / PI + spec) * dotNL;
+ }
+
+ return color;
+}
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 V = normalize(ubo.camPos - inWorldPos);
+ vec3 R = reflect(-V, N);
+
+ float metallic = material.metallic;
+ float roughness = material.roughness;
+
+ vec3 F0 = vec3(0.04);
+ F0 = mix(F0, ALBEDO, metallic);
+
+ vec3 Lo = vec3(0.0);
+ for(int i = 0; i < uboParams.lights[i].length(); i++) {
+ vec3 L = normalize(uboParams.lights[i].xyz - inWorldPos);
+ Lo += specularContribution(L, V, N, F0, metallic, roughness);
+ }
+
+ vec2 brdf = texture(samplerBRDFLUT, vec2(max(dot(N, V), 0.0), roughness)).rg;
+ vec3 reflection = prefilteredReflection(R, roughness).rgb;
+ vec3 irradiance = texture(samplerIrradiance, N).rgb;
+
+ // Diffuse based on irradiance
+ vec3 diffuse = irradiance * ALBEDO;
+
+ vec3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness);
+
+ // Specular reflectance
+ vec3 specular = reflection * (F * brdf.x + brdf.y);
+
+ // Ambient part
+ vec3 kD = 1.0 - F;
+ kD *= 1.0 - metallic;
+ vec3 ambient = (kD * diffuse + specular);
+
+ vec3 color = ambient + Lo;
+
+ // Tone mapping
+ color = Uncharted2Tonemap(color * uboParams.exposure);
+ color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f)));
+ // Gamma correction
+ color = pow(color, vec3(1.0f / uboParams.gamma));
+
+ outColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbribl/pbribl.vert b/tests/glsl/sascha-willems/pbribl/pbribl.vert
new file mode 100644
index 000000000..c8d65cc32
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/pbribl.vert
@@ -0,0 +1,40 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec3 camPos;
+} ubo;
+
+layout (location = 0) out vec3 outWorldPos;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out vec2 outUV;
+
+layout(push_constant) uniform PushConsts {
+ vec3 objPos;
+} pushConsts;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0));
+ outWorldPos = locPos + pushConsts.objPos;
+ outNormal = mat3(ubo.model) * inNormal;
+ outUV = inUV;
+ outUV.t = 1.0 - inUV.t;
+ gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbribl/prefilterenvmap.frag b/tests/glsl/sascha-willems/pbribl/prefilterenvmap.frag
new file mode 100644
index 000000000..d5231a2d1
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/prefilterenvmap.frag
@@ -0,0 +1,106 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec3 inPos;
+layout (location = 0) out vec4 outColor;
+
+layout (binding = 0) uniform samplerCube samplerEnv;
+
+layout(push_constant) uniform PushConsts {
+ layout (offset = 64) float roughness;
+ layout (offset = 68) uint numSamples;
+} consts;
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+ float a = 12.9898;
+ float b = 78.233;
+ float c = 43758.5453;
+ float dt= dot(co.xy ,vec2(a,b));
+ float sn= mod(dt,3.14);
+ return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N)
+{
+ // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+ uint bits = (i << 16u) | (i >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ float rdi = float(bits) * 2.3283064365386963e-10;
+ return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
+{
+ // Maps a 2D point to a hemisphere with spread based on roughness
+ float alpha = roughness * roughness;
+ float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+ vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+ // Tangent space
+ vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangentX = normalize(cross(up, normal));
+ vec3 tangentY = normalize(cross(normal, tangentX));
+
+ // Convert to world Space
+ return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Normal Distribution function
+float D_GGX(float dotNH, float roughness)
+{
+ float alpha = roughness * roughness;
+ float alpha2 = alpha * alpha;
+ float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0;
+ return (alpha2)/(PI * denom*denom);
+}
+
+vec3 prefilterEnvMap(vec3 R, float roughness)
+{
+ vec3 N = R;
+ vec3 V = R;
+ vec3 color = vec3(0.0);
+ float totalWeight = 0.0;
+ float envMapDim = float(textureSize(samplerEnv, 0).s);
+ for(uint i = 0u; i < consts.numSamples; i++) {
+ vec2 Xi = hammersley2d(i, consts.numSamples);
+ vec3 H = importanceSample_GGX(Xi, roughness, N);
+ vec3 L = 2.0 * dot(V, H) * H - V;
+ float dotNL = clamp(dot(N, L), 0.0, 1.0);
+ if(dotNL > 0.0) {
+ // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/
+
+ float dotNH = clamp(dot(N, H), 0.0, 1.0);
+ float dotVH = clamp(dot(V, H), 0.0, 1.0);
+
+ // Probability Distribution Function
+ float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001;
+ // Slid angle of current smple
+ float omegaS = 1.0 / (float(consts.numSamples) * pdf);
+ // Solid angle of 1 pixel across all cube faces
+ float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
+ // Biased (+1.0) mip level for better result
+ float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
+ color += textureLod(samplerEnv, L, mipLevel).rgb * dotNL;
+ totalWeight += dotNL;
+
+ }
+ }
+ return (color / totalWeight);
+}
+
+
+void main()
+{
+ vec3 N = normalize(inPos);
+ outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbribl/skybox.frag b/tests/glsl/sascha-willems/pbribl/skybox.frag
new file mode 100644
index 000000000..a66c8bdaa
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/skybox.frag
@@ -0,0 +1,40 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (binding = 2) uniform samplerCube samplerEnv;
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outColor;
+
+layout (binding = 1) uniform UBOParams {
+ vec4 lights[4];
+ float exposure;
+ float gamma;
+} uboParams;
+
+// From http://filmicworlds.com/blog/filmic-tonemapping-operators/
+vec3 Uncharted2Tonemap(vec3 color)
+{
+ float A = 0.15;
+ float B = 0.50;
+ float C = 0.10;
+ float D = 0.20;
+ float E = 0.02;
+ float F = 0.30;
+ float W = 11.2;
+ return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F;
+}
+
+void main()
+{
+ vec3 color = texture(samplerEnv, inUVW).rgb;
+
+ // Tone mapping
+ color = Uncharted2Tonemap(color * uboParams.exposure);
+ color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f)));
+ // Gamma correction
+ color = pow(color, vec3(1.0f / uboParams.gamma));
+
+ outColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbribl/skybox.vert b/tests/glsl/sascha-willems/pbribl/skybox.vert
new file mode 100644
index 000000000..1802e74e4
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbribl/skybox.vert
@@ -0,0 +1,28 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbrtexture/filtercube.vert b/tests/glsl/sascha-willems/pbrtexture/filtercube.vert
new file mode 100644
index 000000000..07f02c8b5
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/filtercube.vert
@@ -0,0 +1,20 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec3 inPos;
+
+layout(push_constant) uniform PushConsts {
+ layout (offset = 0) mat4 mvp;
+} pushConsts;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex {
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbrtexture/genbrdflut.frag b/tests/glsl/sascha-willems/pbrtexture/genbrdflut.frag
new file mode 100644
index 000000000..25f00af1f
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/genbrdflut.frag
@@ -0,0 +1,91 @@
+#version 450
+//TEST:COMPARE_GLSL:
+
+layout (location = 0) in vec2 inUV;
+layout (location = 0) out vec4 outColor;
+layout (constant_id = 0) const uint NUM_SAMPLES = 1024u;
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+ float a = 12.9898;
+ float b = 78.233;
+ float c = 43758.5453;
+ float dt= dot(co.xy ,vec2(a,b));
+ float sn= mod(dt,3.14);
+ return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N)
+{
+ // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+ uint bits = (i << 16u) | (i >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ float rdi = float(bits) * 2.3283064365386963e-10;
+ return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
+{
+ // Maps a 2D point to a hemisphere with spread based on roughness
+ float alpha = roughness * roughness;
+ float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+ vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+ // Tangent space
+ vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangentX = normalize(cross(up, normal));
+ vec3 tangentY = normalize(cross(normal, tangentX));
+
+ // Convert to world Space
+ return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Geometric Shadowing function
+float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
+{
+ float k = (roughness * roughness) / 2.0;
+ float GL = dotNL / (dotNL * (1.0 - k) + k);
+ float GV = dotNV / (dotNV * (1.0 - k) + k);
+ return GL * GV;
+}
+
+vec2 BRDF(float NoV, float roughness)
+{
+ // Normal always points along z-axis for the 2D lookup
+ const vec3 N = vec3(0.0, 0.0, 1.0);
+ vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV);
+
+ vec2 LUT = vec2(0.0);
+ for(uint i = 0u; i < NUM_SAMPLES; i++) {
+ vec2 Xi = hammersley2d(i, NUM_SAMPLES);
+ vec3 H = importanceSample_GGX(Xi, roughness, N);
+ vec3 L = 2.0 * dot(V, H) * H - V;
+
+ float dotNL = max(dot(N, L), 0.0);
+ float dotNV = max(dot(N, V), 0.0);
+ float dotVH = max(dot(V, H), 0.0);
+ float dotNH = max(dot(H, N), 0.0);
+
+ if (dotNL > 0.0) {
+ float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+ float G_Vis = (G * dotVH) / (dotNH * dotNV);
+ float Fc = pow(1.0 - dotVH, 5.0);
+ LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis);
+ }
+ }
+ return LUT / float(NUM_SAMPLES);
+}
+
+void main()
+{
+ outColor = vec4(BRDF(inUV.s, 1.0-inUV.t), 0.0, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbrtexture/genbrdflut.vert b/tests/glsl/sascha-willems/pbrtexture/genbrdflut.vert
new file mode 100644
index 000000000..2eeb90cf3
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/genbrdflut.vert
@@ -0,0 +1,10 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (location = 0) out vec2 outUV;
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbrtexture/irradiancecube.frag b/tests/glsl/sascha-willems/pbrtexture/irradiancecube.frag
new file mode 100644
index 000000000..e94c0f93c
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/irradiancecube.frag
@@ -0,0 +1,38 @@
+//TEST:COMPARE_GLSL:
+// Generates an irradiance cube from an environment map using convolution
+
+#version 450
+
+layout (location = 0) in vec3 inPos;
+layout (location = 0) out vec4 outColor;
+layout (binding = 0) uniform samplerCube samplerEnv;
+
+layout(push_constant) uniform PushConsts {
+ layout (offset = 64) float deltaPhi;
+ layout (offset = 68) float deltaTheta;
+} consts;
+
+#define PI 3.1415926535897932384626433832795
+
+void main()
+{
+ vec3 N = normalize(inPos);
+ vec3 up = vec3(0.0, 1.0, 0.0);
+ vec3 right = normalize(cross(up, N));
+ up = cross(N, right);
+
+ const float TWO_PI = PI * 2.0;
+ const float HALF_PI = PI * 0.5;
+
+ vec3 color = vec3(0.0);
+ uint sampleCount = 0u;
+ for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) {
+ for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) {
+ vec3 tempVec = cos(phi) * right + sin(phi) * up;
+ vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec;
+ color += texture(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta);
+ sampleCount++;
+ }
+ }
+ outColor = vec4(PI * color / float(sampleCount), 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbrtexture/pbrtexture.frag b/tests/glsl/sascha-willems/pbrtexture/pbrtexture.frag
new file mode 100644
index 000000000..eb0a14bcc
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/pbrtexture.frag
@@ -0,0 +1,179 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (location = 0) in vec3 inWorldPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO {
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec3 camPos;
+} ubo;
+
+layout (binding = 1) uniform UBOParams {
+ vec4 lights[4];
+ float exposure;
+ float gamma;
+} uboParams;
+
+layout (binding = 2) uniform samplerCube samplerIrradiance;
+layout (binding = 3) uniform sampler2D samplerBRDFLUT;
+layout (binding = 4) uniform samplerCube prefilteredMap;
+
+layout (binding = 5) uniform sampler2D albedoMap;
+layout (binding = 6) uniform sampler2D normalMap;
+layout (binding = 7) uniform sampler2D aoMap;
+layout (binding = 8) uniform sampler2D metallicMap;
+layout (binding = 9) uniform sampler2D roughnessMap;
+
+
+layout (location = 0) out vec4 outColor;
+
+#define PI 3.1415926535897932384626433832795
+#define ALBEDO pow(texture(albedoMap, inUV).rgb, vec3(2.2))
+
+// From http://filmicgames.com/archives/75
+vec3 Uncharted2Tonemap(vec3 x)
+{
+ float A = 0.15;
+ float B = 0.50;
+ float C = 0.10;
+ float D = 0.20;
+ float E = 0.02;
+ float F = 0.30;
+ return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
+}
+
+// Normal Distribution function --------------------------------------
+float D_GGX(float dotNH, float roughness)
+{
+ float alpha = roughness * roughness;
+ float alpha2 = alpha * alpha;
+ float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0;
+ return (alpha2)/(PI * denom*denom);
+}
+
+// Geometric Shadowing function --------------------------------------
+float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
+{
+ float r = (roughness + 1.0);
+ float k = (r*r) / 8.0;
+ float GL = dotNL / (dotNL * (1.0 - k) + k);
+ float GV = dotNV / (dotNV * (1.0 - k) + k);
+ return GL * GV;
+}
+
+// Fresnel function ----------------------------------------------------
+vec3 F_Schlick(float cosTheta, vec3 F0)
+{
+ return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
+}
+vec3 F_SchlickR(float cosTheta, vec3 F0, float roughness)
+{
+ return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
+}
+
+vec3 prefilteredReflection(vec3 R, float roughness)
+{
+ const float MAX_REFLECTION_LOD = 9.0; // todo: param/const
+ float lod = roughness * MAX_REFLECTION_LOD;
+ float lodf = floor(lod);
+ float lodc = ceil(lod);
+ vec3 a = textureLod(prefilteredMap, R, lodf).rgb;
+ vec3 b = textureLod(prefilteredMap, R, lodc).rgb;
+ return mix(a, b, lod - lodf);
+}
+
+vec3 specularContribution(vec3 L, vec3 V, vec3 N, vec3 F0, float metallic, float roughness)
+{
+ // Precalculate vectors and dot products
+ vec3 H = normalize (V + L);
+ float dotNH = clamp(dot(N, H), 0.0, 1.0);
+ float dotNV = clamp(dot(N, V), 0.0, 1.0);
+ float dotNL = clamp(dot(N, L), 0.0, 1.0);
+
+ // Light color fixed
+ vec3 lightColor = vec3(1.0);
+
+ vec3 color = vec3(0.0);
+
+ if (dotNL > 0.0) {
+ // D = Normal distribution (Distribution of the microfacets)
+ float D = D_GGX(dotNH, roughness);
+ // G = Geometric shadowing term (Microfacets shadowing)
+ float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+ // F = Fresnel factor (Reflectance depending on angle of incidence)
+ vec3 F = F_Schlick(dotNV, F0);
+ vec3 spec = D * F * G / (4.0 * dotNL * dotNV + 0.001);
+ vec3 kD = (vec3(1.0) - F) * (1.0 - metallic);
+ color += (kD * ALBEDO / PI + spec) * dotNL;
+ }
+
+ return color;
+}
+
+// See http://www.thetenthplanet.de/archives/1180
+vec3 perturbNormal()
+{
+ vec3 tangentNormal = texture(normalMap, inUV).xyz * 2.0 - 1.0;
+
+ vec3 q1 = dFdx(inWorldPos);
+ vec3 q2 = dFdy(inWorldPos);
+ vec2 st1 = dFdx(inUV);
+ vec2 st2 = dFdy(inUV);
+
+ vec3 N = normalize(inNormal);
+ vec3 T = normalize(q1 * st2.t - q2 * st1.t);
+ vec3 B = -normalize(cross(N, T));
+ mat3 TBN = mat3(T, B, N);
+
+ return normalize(TBN * tangentNormal);
+}
+
+void main()
+{
+ vec3 N = perturbNormal();
+ vec3 V = normalize(ubo.camPos - inWorldPos);
+ vec3 R = reflect(-V, N);
+
+ float metallic = texture(metallicMap, inUV).r;
+ float roughness = texture(roughnessMap, inUV).r;
+
+ vec3 F0 = vec3(0.04);
+ F0 = mix(F0, ALBEDO, metallic);
+
+ vec3 Lo = vec3(0.0);
+ for(int i = 0; i < uboParams.lights[i].length(); i++) {
+ vec3 L = normalize(uboParams.lights[i].xyz - inWorldPos);
+ Lo += specularContribution(L, V, N, F0, metallic, roughness);
+ }
+
+ vec2 brdf = texture(samplerBRDFLUT, vec2(max(dot(N, V), 0.0), roughness)).rg;
+ vec3 reflection = prefilteredReflection(R, roughness).rgb;
+ vec3 irradiance = texture(samplerIrradiance, N).rgb;
+
+ // Diffuse based on irradiance
+ vec3 diffuse = irradiance * ALBEDO;
+
+ vec3 F = F_SchlickR(max(dot(N, V), 0.0), F0, roughness);
+
+ // Specular reflectance
+ vec3 specular = reflection * (F * brdf.x + brdf.y);
+
+ // Ambient part
+ vec3 kD = 1.0 - F;
+ kD *= 1.0 - metallic;
+ vec3 ambient = (kD * diffuse + specular) * texture(aoMap, inUV).rrr;
+
+ vec3 color = ambient + Lo;
+
+ // Tone mapping
+ color = Uncharted2Tonemap(color * uboParams.exposure);
+ color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f)));
+ // Gamma correction
+ color = pow(color, vec3(1.0f / uboParams.gamma));
+
+ outColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbrtexture/pbrtexture.vert b/tests/glsl/sascha-willems/pbrtexture/pbrtexture.vert
new file mode 100644
index 000000000..9962220a8
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/pbrtexture.vert
@@ -0,0 +1,36 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec3 camPos;
+} ubo;
+
+layout (location = 0) out vec3 outWorldPos;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ vec3 locPos = vec3(ubo.model * vec4(inPos, 1.0));
+ outWorldPos = locPos;
+ outNormal = mat3(ubo.model) * inNormal;
+ outUV = inUV;
+ outUV.t = 1.0 - inUV.t;
+ gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbrtexture/prefilterenvmap.frag b/tests/glsl/sascha-willems/pbrtexture/prefilterenvmap.frag
new file mode 100644
index 000000000..912780c82
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/prefilterenvmap.frag
@@ -0,0 +1,106 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (location = 0) in vec3 inPos;
+layout (location = 0) out vec4 outColor;
+
+layout (binding = 0) uniform samplerCube samplerEnv;
+
+layout(push_constant) uniform PushConsts {
+ layout (offset = 64) float roughness;
+ layout (offset = 68) uint numSamples;
+} consts;
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+ float a = 12.9898;
+ float b = 78.233;
+ float c = 43758.5453;
+ float dt= dot(co.xy ,vec2(a,b));
+ float sn= mod(dt,3.14);
+ return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N)
+{
+ // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+ uint bits = (i << 16u) | (i >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ float rdi = float(bits) * 2.3283064365386963e-10;
+ return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal)
+{
+ // Maps a 2D point to a hemisphere with spread based on roughness
+ float alpha = roughness * roughness;
+ float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+ float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+ float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+ vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+ // Tangent space
+ vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ vec3 tangentX = normalize(cross(up, normal));
+ vec3 tangentY = normalize(cross(normal, tangentX));
+
+ // Convert to world Space
+ return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Normal Distribution function
+float D_GGX(float dotNH, float roughness)
+{
+ float alpha = roughness * roughness;
+ float alpha2 = alpha * alpha;
+ float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0;
+ return (alpha2)/(PI * denom*denom);
+}
+
+vec3 prefilterEnvMap(vec3 R, float roughness)
+{
+ vec3 N = R;
+ vec3 V = R;
+ vec3 color = vec3(0.0);
+ float totalWeight = 0.0;
+ float envMapDim = float(textureSize(samplerEnv, 0).s);
+ for(uint i = 0u; i < consts.numSamples; i++) {
+ vec2 Xi = hammersley2d(i, consts.numSamples);
+ vec3 H = importanceSample_GGX(Xi, roughness, N);
+ vec3 L = 2.0 * dot(V, H) * H - V;
+ float dotNL = clamp(dot(N, L), 0.0, 1.0);
+ if(dotNL > 0.0) {
+ // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/
+
+ float dotNH = clamp(dot(N, H), 0.0, 1.0);
+ float dotVH = clamp(dot(V, H), 0.0, 1.0);
+
+ // Probability Distribution Function
+ float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001;
+ // Slid angle of current smple
+ float omegaS = 1.0 / (float(consts.numSamples) * pdf);
+ // Solid angle of 1 pixel across all cube faces
+ float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
+ // Biased (+1.0) mip level for better result
+ float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
+ color += textureLod(samplerEnv, L, mipLevel).rgb * dotNL;
+ totalWeight += dotNL;
+
+ }
+ }
+ return (color / totalWeight);
+}
+
+
+void main()
+{
+ vec3 N = normalize(inPos);
+ outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pbrtexture/skybox.frag b/tests/glsl/sascha-willems/pbrtexture/skybox.frag
new file mode 100644
index 000000000..d80d44487
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/skybox.frag
@@ -0,0 +1,40 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (binding = 2) uniform samplerCube samplerEnv;
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outColor;
+
+layout (binding = 1) uniform UBOParams {
+ vec4 lights[4];
+ float exposure;
+ float gamma;
+} uboParams;
+
+// From http://filmicworlds.com/blog/filmic-tonemapping-operators/
+vec3 Uncharted2Tonemap(vec3 color)
+{
+ float A = 0.15;
+ float B = 0.50;
+ float C = 0.10;
+ float D = 0.20;
+ float E = 0.02;
+ float F = 0.30;
+ float W = 11.2;
+ return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F;
+}
+
+void main()
+{
+ vec3 color = texture(samplerEnv, inUVW).rgb;
+
+ // Tone mapping
+ color = Uncharted2Tonemap(color * uboParams.exposure);
+ color = color * (1.0f / Uncharted2Tonemap(vec3(11.2f)));
+ // Gamma correction
+ color = pow(color, vec3(1.0f / uboParams.gamma));
+
+ outColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pbrtexture/skybox.vert b/tests/glsl/sascha-willems/pbrtexture/skybox.vert
new file mode 100644
index 000000000..e77f89773
--- /dev/null
+++ b/tests/glsl/sascha-willems/pbrtexture/skybox.vert
@@ -0,0 +1,28 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/pipelines/phong.frag b/tests/glsl/sascha-willems/pipelines/phong.frag
new file mode 100644
index 000000000..f8dddd1cf
--- /dev/null
+++ b/tests/glsl/sascha-willems/pipelines/phong.frag
@@ -0,0 +1,31 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ // Desaturate color
+ vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65));
+
+ // High ambient colors because mesh materials are pretty dark
+ vec3 ambient = color * vec3(1.0);
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * color;
+ vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(0.35);
+ outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pipelines/phong.vert b/tests/glsl/sascha-willems/pipelines/phong.vert
new file mode 100644
index 000000000..44fd2e692
--- /dev/null
+++ b/tests/glsl/sascha-willems/pipelines/phong.vert
@@ -0,0 +1,42 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pipelines/toon.frag b/tests/glsl/sascha-willems/pipelines/toon.frag
new file mode 100644
index 000000000..bb19e9a2f
--- /dev/null
+++ b/tests/glsl/sascha-willems/pipelines/toon.frag
@@ -0,0 +1,40 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ // Desaturate color
+ vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65));
+
+ // High ambient colors because mesh materials are pretty dark
+ vec3 ambient = color * vec3(1.0);
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * color;
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75);
+ outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0);
+
+ float intensity = dot(N,L);
+ float shade = 1.0;
+ shade = intensity < 0.5 ? 0.75 : shade;
+ shade = intensity < 0.35 ? 0.6 : shade;
+ shade = intensity < 0.25 ? 0.5 : shade;
+ shade = intensity < 0.1 ? 0.25 : shade;
+
+ outFragColor.rgb = inColor * 3.0 * shade;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pipelines/toon.vert b/tests/glsl/sascha-willems/pipelines/toon.vert
new file mode 100644
index 000000000..44fd2e692
--- /dev/null
+++ b/tests/glsl/sascha-willems/pipelines/toon.vert
@@ -0,0 +1,42 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pipelines/wireframe.frag b/tests/glsl/sascha-willems/pipelines/wireframe.frag
new file mode 100644
index 000000000..7158d7ac9
--- /dev/null
+++ b/tests/glsl/sascha-willems/pipelines/wireframe.frag
@@ -0,0 +1,14 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor.rgb = inColor * 1.5;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pipelines/wireframe.vert b/tests/glsl/sascha-willems/pipelines/wireframe.vert
new file mode 100644
index 000000000..6ec18a4bf
--- /dev/null
+++ b/tests/glsl/sascha-willems/pipelines/wireframe.vert
@@ -0,0 +1,29 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ {
+ outColor = inColor;
+ }
+ gl_Position = ubo.projection * ubo.model * inPos;
+}
diff --git a/tests/glsl/sascha-willems/pushconstants/lights.frag b/tests/glsl/sascha-willems/pushconstants/lights.frag
new file mode 100644
index 000000000..9624b51be
--- /dev/null
+++ b/tests/glsl/sascha-willems/pushconstants/lights.frag
@@ -0,0 +1,41 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+#define lightCount 6
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (location = 3) in vec4 inLightVec[lightCount];
+
+layout (location = 0) out vec4 outFragColor;
+
+#define MAX_LIGHT_DIST 9.0 * 9.0
+
+void main()
+{
+ vec3 lightColor[lightCount];
+ lightColor[0] = vec3(1.0, 0.0, 0.0);
+ lightColor[1] = vec3(0.0, 1.0, 0.0);
+ lightColor[2] = vec3(0.0, 0.0, 1.0);
+ lightColor[3] = vec3(1.0, 0.0, 1.0);
+ lightColor[4] = vec3(0.0, 1.0, 1.0);
+ lightColor[5] = vec3(1.0, 1.0, 0.0);
+
+ vec3 diffuse = vec3(0.0);
+ // Just some very basic attenuation
+ for (int i = 0; i < lightCount; ++i)
+ {
+ float lRadius = MAX_LIGHT_DIST * inLightVec[i].w;
+
+ float dist = min(dot(inLightVec[i], inLightVec[i]), lRadius) / lRadius;
+ float distFactor = 1.0 - dist;
+
+ diffuse += lightColor[i] * distFactor;
+ }
+
+ outFragColor.rgb = diffuse;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/pushconstants/lights.vert b/tests/glsl/sascha-willems/pushconstants/lights.vert
new file mode 100644
index 000000000..693e69d5d
--- /dev/null
+++ b/tests/glsl/sascha-willems/pushconstants/lights.vert
@@ -0,0 +1,48 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 3) in vec3 inColor;
+
+#define lightCount 6
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightColor[lightCount];
+} ubo;
+
+layout(push_constant) uniform PushConsts {
+ vec4 lightPos[lightCount];
+} pushConsts;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 2) out vec3 outColor;
+
+layout (location = 3) out vec4 outLightVec[lightCount];
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ for (int i = 0; i < lightCount; ++i)
+ {
+ vec4 worldPos = ubo.model * vec4(inPos.xyz, 1.0);
+ outLightVec[i].xyz = pushConsts.lightPos[i].xyz - inPos.xyz;
+ // Store light radius in w
+ outLightVec[i].w = pushConsts.lightPos[i].w;
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/radialblur/colorpass.frag b/tests/glsl/sascha-willems/radialblur/colorpass.frag
new file mode 100644
index 000000000..5d56315fd
--- /dev/null
+++ b/tests/glsl/sascha-willems/radialblur/colorpass.frag
@@ -0,0 +1,25 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerGradientRamp;
+
+layout (location = 0) in vec3 inColor;
+layout (location = 1) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ // Use max. color channel value to detect bright glow emitters
+ if ((inColor.r >= 0.9) || (inColor.g >= 0.9) || (inColor.b >= 0.9))
+ {
+ outFragColor.rgb = texture(samplerGradientRamp, inUV).rgb;
+ }
+ else
+ {
+ outFragColor.rgb = inColor;
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/radialblur/colorpass.vert b/tests/glsl/sascha-willems/radialblur/colorpass.vert
new file mode 100644
index 000000000..68d4f2e56
--- /dev/null
+++ b/tests/glsl/sascha-willems/radialblur/colorpass.vert
@@ -0,0 +1,30 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 2) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ float gradientPos;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+layout (location = 1) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+ outUV = vec2(ubo.gradientPos, 0.0f);
+ gl_Position = ubo.projection * ubo.model * vec4(inPos, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/radialblur/phongpass.frag b/tests/glsl/sascha-willems/radialblur/phongpass.frag
new file mode 100644
index 000000000..83e96fc58
--- /dev/null
+++ b/tests/glsl/sascha-willems/radialblur/phongpass.frag
@@ -0,0 +1,37 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerGradientRamp;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inEyePos;
+layout (location = 3) in vec3 inLightVec;
+layout (location = 4) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ // No light calculations for glow color
+ // Use max. color channel value
+ // to detect bright glow emitters
+ if ((inColor.r >= 0.9) || (inColor.g >= 0.9) || (inColor.b >= 0.9))
+ {
+ outFragColor.rgb = texture(samplerGradientRamp, inUV).rgb;
+ }
+ else
+ {
+ vec3 Eye = normalize(-inEyePos);
+ vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
+
+ vec4 IAmbient = vec4(0.2, 0.2, 0.2, 1.0);
+ vec4 IDiffuse = vec4(0.5, 0.5, 0.5, 0.5) * max(dot(inNormal, inLightVec), 0.0);
+ float specular = 0.25;
+ vec4 ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 4.0) * specular;
+ outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular);
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/radialblur/phongpass.vert b/tests/glsl/sascha-willems/radialblur/phongpass.vert
new file mode 100644
index 000000000..a375c39cf
--- /dev/null
+++ b/tests/glsl/sascha-willems/radialblur/phongpass.vert
@@ -0,0 +1,38 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 pos;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ float gradientPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outEyePos;
+layout (location = 3) out vec3 outLightVec;
+layout (location = 4) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = vec2(ubo.gradientPos, 0.0);
+ gl_Position = ubo.projection * ubo.model * pos;
+ outEyePos = vec3(ubo.model * pos);
+ vec4 lightPos = vec4(0.0, 0.0, -5.0, 1.0);// * ubo.model;
+ outLightVec = normalize(lightPos.xyz - pos.xyz);
+}
diff --git a/tests/glsl/sascha-willems/radialblur/radialblur.frag b/tests/glsl/sascha-willems/radialblur/radialblur.frag
new file mode 100644
index 000000000..bc1e884e9
--- /dev/null
+++ b/tests/glsl/sascha-willems/radialblur/radialblur.frag
@@ -0,0 +1,39 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (binding = 0) uniform UBO
+{
+ float radialBlurScale;
+ float radialBlurStrength;
+ vec2 radialOrigin;
+} ubo;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ ivec2 texDim = textureSize(samplerColor, 0);
+ vec2 radialSize = vec2(1.0 / texDim.s, 1.0 / texDim.t);
+
+ vec2 UV = inUV;
+
+ vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
+ UV += radialSize * 0.5 - ubo.radialOrigin;
+
+ #define samples 32
+
+ for (int i = 0; i < samples; i++)
+ {
+ float scale = 1.0 - ubo.radialBlurScale * (float(i) / float(samples-1));
+ color += texture(samplerColor, UV * scale + ubo.radialOrigin);
+ }
+
+ outFragColor = (color / samples) * ubo.radialBlurStrength;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/radialblur/radialblur.vert b/tests/glsl/sascha-willems/radialblur/radialblur.vert
new file mode 100644
index 000000000..117eb02ec
--- /dev/null
+++ b/tests/glsl/sascha-willems/radialblur/radialblur.vert
@@ -0,0 +1,18 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/raytracing/raytracing.comp b/tests/glsl/sascha-willems/raytracing/raytracing.comp
new file mode 100644
index 000000000..8ef6c19e8
--- /dev/null
+++ b/tests/glsl/sascha-willems/raytracing/raytracing.comp
@@ -0,0 +1,258 @@
+//TEST:COMPARE_GLSL:
+// Shader is looseley based on the ray tracing coding session by Inigo Quilez (www.iquilezles.org)
+
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (local_size_x = 16, local_size_y = 16) in;
+layout (binding = 0, rgba8) uniform writeonly image2D resultImage;
+
+#define EPSILON 0.0001
+#define MAXLEN 1000.0
+#define SHADOW 0.5
+#define RAYBOUNCES 2
+#define REFLECTIONS true
+#define REFLECTIONSTRENGTH 0.4
+#define REFLECTIONFALLOFF 0.5
+
+struct Camera
+{
+ vec3 pos;
+ vec3 lookat;
+ float fov;
+};
+
+layout (binding = 1) uniform UBO
+{
+ vec3 lightPos;
+ float aspectRatio;
+ vec4 fogColor;
+ Camera camera;
+ mat4 rotMat;
+} ubo;
+
+struct Sphere
+{
+ vec3 pos;
+ float radius;
+ vec3 diffuse;
+ float specular;
+ int id;
+};
+
+struct Plane
+{
+ vec3 normal;
+ float distance;
+ vec3 diffuse;
+ float specular;
+ int id;
+};
+
+layout (std140, binding = 2) buffer Spheres
+{
+ Sphere spheres[ ];
+};
+
+layout (std140, binding = 3) buffer Planes
+{
+ Plane planes[ ];
+};
+
+void reflectRay(inout vec3 rayD, in vec3 mormal)
+{
+ rayD = rayD + 2.0 * -dot(mormal, rayD) * mormal;
+}
+
+// Lighting =========================================================
+
+float lightDiffuse(vec3 normal, vec3 lightDir)
+{
+ return clamp(dot(normal, lightDir), 0.1, 1.0);
+}
+
+float lightSpecular(vec3 normal, vec3 lightDir, float specularFactor)
+{
+ vec3 viewVec = normalize(ubo.camera.pos);
+ vec3 halfVec = normalize(lightDir + viewVec);
+ return pow(clamp(dot(normal, halfVec), 0.0, 1.0), specularFactor);
+}
+
+// Sphere ===========================================================
+
+float sphereIntersect(in vec3 rayO, in vec3 rayD, in Sphere sphere)
+{
+ vec3 oc = rayO - sphere.pos;
+ float b = 2.0 * dot(oc, rayD);
+ float c = dot(oc, oc) - sphere.radius*sphere.radius;
+ float h = b*b - 4.0*c;
+ if (h < 0.0)
+ {
+ return -1.0;
+ }
+ float t = (-b - sqrt(h)) / 2.0;
+
+ return t;
+}
+
+vec3 sphereNormal(in vec3 pos, in Sphere sphere)
+{
+ return (pos - sphere.pos) / sphere.radius;
+}
+
+// Plane ===========================================================
+
+float planeIntersect(vec3 rayO, vec3 rayD, Plane plane)
+{
+ float d = dot(rayD, plane.normal);
+
+ if (d == 0.0)
+ return 0.0;
+
+ float t = -(plane.distance + dot(rayO, plane.normal)) / d;
+
+ if (t < 0.0)
+ return 0.0;
+
+ return t;
+}
+
+
+int intersect(in vec3 rayO, in vec3 rayD, inout float resT)
+{
+ int id = -1;
+
+ for (int i = 0; i < spheres.length(); i++)
+ {
+ float tSphere = sphereIntersect(rayO, rayD, spheres[i]);
+ if ((tSphere > EPSILON) && (tSphere < resT))
+ {
+ id = spheres[i].id;
+ resT = tSphere;
+ }
+ }
+
+ for (int i = 0; i < planes.length(); i++)
+ {
+ float tplane = planeIntersect(rayO, rayD, planes[i]);
+ if ((tplane > EPSILON) && (tplane < resT))
+ {
+ id = planes[i].id;
+ resT = tplane;
+ }
+ }
+
+ return id;
+}
+
+float calcShadow(in vec3 rayO, in vec3 rayD, in int objectId, inout float t)
+{
+ for (int i = 0; i < spheres.length(); i++)
+ {
+ if (spheres[i].id == objectId)
+ continue;
+ float tSphere = sphereIntersect(rayO, rayD, spheres[i]);
+ if ((tSphere > EPSILON) && (tSphere < t))
+ {
+ t = tSphere;
+ return SHADOW;
+ }
+ }
+ return 1.0;
+}
+
+vec3 fog(in float t, in vec3 color)
+{
+ return mix(color, ubo.fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0));
+}
+
+vec3 renderScene(inout vec3 rayO, inout vec3 rayD, inout int id)
+{
+ vec3 color = vec3(0.0);
+ float t = MAXLEN;
+
+ // Get intersected object ID
+ int objectID = intersect(rayO, rayD, t);
+
+ if (objectID == -1)
+ {
+ return color;
+ }
+
+ vec3 pos = rayO + t * rayD;
+ vec3 lightVec = normalize(ubo.lightPos - pos);
+ vec3 normal;
+
+ // Planes
+
+ // Spheres
+
+ for (int i = 0; i < planes.length(); i++)
+ {
+ if (objectID == planes[i].id)
+ {
+ normal = planes[i].normal;
+ float diffuse = lightDiffuse(normal, lightVec);
+ float specular = lightSpecular(normal, lightVec, planes[i].specular);
+ color = diffuse * planes[i].diffuse + specular;
+ }
+ }
+
+ for (int i = 0; i < spheres.length(); i++)
+ {
+ if (objectID == spheres[i].id)
+ {
+ normal = sphereNormal(pos, spheres[i]);
+ float diffuse = lightDiffuse(normal, lightVec);
+ float specular = lightSpecular(normal, lightVec, spheres[i].specular);
+ color = diffuse * spheres[i].diffuse + specular;
+ }
+ }
+
+ if (id == -1)
+ return color;
+
+ id = objectID;
+
+ // Shadows
+ t = length(ubo.lightPos - pos);
+ color *= calcShadow(pos, lightVec, id, t);
+
+ // Fog
+ color = fog(t, color);
+
+ // Reflect ray for next render pass
+ reflectRay(rayD, normal);
+ rayO = pos;
+
+ return color;
+}
+
+void main()
+{
+ ivec2 dim = imageSize(resultImage);
+ vec2 uv = vec2(gl_GlobalInvocationID.xy) / dim;
+
+ vec3 rayO = ubo.camera.pos;
+ vec3 rayD = normalize(vec3((-1.0 + 2.0 * uv) * vec2(ubo.aspectRatio, 1.0), -1.0));
+
+ // Basic color path
+ int id = 0;
+ vec3 finalColor = renderScene(rayO, rayD, id);
+
+ // Reflection
+ if (REFLECTIONS)
+ {
+ float reflectionStrength = REFLECTIONSTRENGTH;
+ for (int i = 0; i < RAYBOUNCES; i++)
+ {
+ vec3 reflectionColor = renderScene(rayO, rayD, id);
+ finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * mix(reflectionColor, finalColor, 1.0 - reflectionStrength);
+ reflectionStrength *= REFLECTIONFALLOFF;
+ }
+ }
+
+ imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(finalColor, 0.0));
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/raytracing/texture.frag b/tests/glsl/sascha-willems/raytracing/texture.frag
new file mode 100644
index 000000000..06635bf4b
--- /dev/null
+++ b/tests/glsl/sascha-willems/raytracing/texture.frag
@@ -0,0 +1,16 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerColor, vec2(inUV.s, 1.0 - inUV.t));
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/raytracing/texture.vert b/tests/glsl/sascha-willems/raytracing/texture.vert
new file mode 100644
index 000000000..cbf5c0a0d
--- /dev/null
+++ b/tests/glsl/sascha-willems/raytracing/texture.vert
@@ -0,0 +1,18 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/scenerendering/scene.frag b/tests/glsl/sascha-willems/scenerendering/scene.frag
new file mode 100644
index 000000000..032ce45a9
--- /dev/null
+++ b/tests/glsl/sascha-willems/scenerendering/scene.frag
@@ -0,0 +1,35 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (set = 1, binding = 0) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout(push_constant) uniform Material
+{
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+ float opacity;
+} material;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0);
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * material.diffuse.rgb;
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * material.specular.rgb;
+ outFragColor = vec4((material.ambient.rgb + diffuse) * color.rgb + specular, 1.0-material.opacity);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/scenerendering/scene.vert b/tests/glsl/sascha-willems/scenerendering/scene.vert
new file mode 100644
index 000000000..50852f78c
--- /dev/null
+++ b/tests/glsl/sascha-willems/scenerendering/scene.vert
@@ -0,0 +1,46 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (set = 0, binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = inUV;
+
+ mat4 modelView = ubo.view * ubo.model;
+
+ gl_Position = ubo.projection * modelView * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = modelView * vec4(inPos, 0.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - (ubo.model * vec4(inPos, 1.0)).xyz;
+ outViewVec = -(ubo.model * vec4(inPos, 1.0)).xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/screenshot/mesh.frag b/tests/glsl/sascha-willems/screenshot/mesh.frag
new file mode 100644
index 000000000..3504b70cf
--- /dev/null
+++ b/tests/glsl/sascha-willems/screenshot/mesh.frag
@@ -0,0 +1,24 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 ambient = vec3(0.1);
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75);
+ outFragColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/screenshot/mesh.vert b/tests/glsl/sascha-willems/screenshot/mesh.vert
new file mode 100644
index 000000000..a0c75ab18
--- /dev/null
+++ b/tests/glsl/sascha-willems/screenshot/mesh.vert
@@ -0,0 +1,40 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (set = 0, binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ gl_Position = ubo.projection * ubo.view * ubo.model * inPos;
+
+ vec4 pos = ubo.view * ubo.model * vec4(inPos.xyz, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+
+ vec3 lightPos = vec3(1.0f, -1.0f, 1.0f);
+ outLightVec = lightPos.xyz - pos.xyz;
+ outViewVec = -pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.frag b/tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.frag
new file mode 100644
index 000000000..740cd09e1
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.frag
@@ -0,0 +1,17 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform samplerCube shadowCubeMap;
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ float dist = length(texture(shadowCubeMap, inUVW).rgb) * 0.005;
+ outFragColor = vec4(vec3(dist), 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.vert b/tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.vert
new file mode 100644
index 000000000..b5f889174
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapomni/cubemapdisplay.vert
@@ -0,0 +1,28 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
+
diff --git a/tests/glsl/sascha-willems/shadowmapomni/offscreen.frag b/tests/glsl/sascha-willems/shadowmapomni/offscreen.frag
new file mode 100644
index 000000000..6426c4118
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapomni/offscreen.frag
@@ -0,0 +1,17 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out float outFragColor;
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inLightPos;
+
+void main()
+{
+ // Store distance to light as 32 bit float value
+ vec3 lightVec = inPos.xyz - inLightPos;
+ outFragColor = length(lightVec);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapomni/offscreen.vert b/tests/glsl/sascha-willems/shadowmapomni/offscreen.vert
new file mode 100644
index 000000000..7513070dc
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapomni/offscreen.vert
@@ -0,0 +1,36 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (location = 0) out vec4 outPos;
+layout (location = 1) out vec3 outLightPos;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout(push_constant) uniform PushConsts
+{
+ mat4 view;
+} pushConsts;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ gl_Position = ubo.projection * pushConsts.view * ubo.model * vec4(inPos, 1.0);
+
+ outPos = vec4(inPos, 1.0);
+ outLightPos = ubo.lightPos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapomni/scene.frag b/tests/glsl/sascha-willems/shadowmapomni/scene.frag
new file mode 100644
index 000000000..1bdc44bdb
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapomni/scene.frag
@@ -0,0 +1,44 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform samplerCube shadowCubeMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inEyePos;
+layout (location = 3) in vec3 inLightVec;
+layout (location = 4) in vec3 inWorldPos;
+layout (location = 5) in vec3 inLightPos;
+
+layout (location = 0) out vec4 outFragColor;
+
+#define EPSILON 0.15
+#define SHADOW_OPACITY 0.5
+
+void main()
+{
+ // Lighting
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(vec3(1.0));
+
+ vec3 Eye = normalize(-inEyePos);
+ vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
+
+ vec4 IAmbient = vec4(vec3(0.05), 1.0);
+ vec4 IDiffuse = vec4(1.0) * max(dot(inNormal, inLightVec), 0.0);
+
+ outFragColor = vec4(IAmbient + IDiffuse * vec4(inColor, 1.0));
+
+ // Shadow
+ vec3 lightVec = inWorldPos - inLightPos;
+ float sampledDist = texture(shadowCubeMap, lightVec).r;
+ float dist = length(lightVec);
+
+ // Check if fragment is in shadow
+ float shadow = (dist <= sampledDist + EPSILON) ? 1.0 : SHADOW_OPACITY;
+
+ outFragColor.rgb *= shadow;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapomni/scene.vert b/tests/glsl/sascha-willems/shadowmapomni/scene.vert
new file mode 100644
index 000000000..aed2c97ae
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapomni/scene.vert
@@ -0,0 +1,43 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outEyePos;
+layout (location = 3) out vec3 outLightVec;
+layout (location = 4) out vec3 outWorldPos;
+layout (location = 5) out vec3 outLightPos;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+ outNormal = inNormal;
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0);
+ outEyePos = vec3(ubo.model * vec4(inPos, 1.0f));
+ outLightVec = normalize(ubo.lightPos.xyz - inPos.xyz);
+ outWorldPos = inPos;
+
+ outLightPos = ubo.lightPos.xyz;
+}
+
diff --git a/tests/glsl/sascha-willems/shadowmapping/offscreen.frag b/tests/glsl/sascha-willems/shadowmapping/offscreen.frag
new file mode 100644
index 000000000..81c8f55a3
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapping/offscreen.frag
@@ -0,0 +1,14 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout(location = 0) out vec4 color;
+//layout(location = 0) out float fragmentdepth;
+
+void main()
+{
+// fragmentdepth = gl_FragCoord.z;
+ color = vec4(1.0, 0.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapping/offscreen.vert b/tests/glsl/sascha-willems/shadowmapping/offscreen.vert
new file mode 100644
index 000000000..e5d18fc88
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapping/offscreen.vert
@@ -0,0 +1,23 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 depthMVP;
+} ubo;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+
+void main()
+{
+ gl_Position = ubo.depthMVP * vec4(inPos, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapping/quad.frag b/tests/glsl/sascha-willems/shadowmapping/quad.frag
new file mode 100644
index 000000000..3074bd5ee
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapping/quad.frag
@@ -0,0 +1,25 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+float LinearizeDepth(float depth)
+{
+ float n = 1.0; // camera z near
+ float f = 128.0; // camera z far
+ float z = depth;
+ return (2.0 * n) / (f + n - z * (f - n));
+}
+
+void main()
+{
+ float depth = texture(samplerColor, inUV).r;
+ outFragColor = vec4(vec3(1.0-LinearizeDepth(depth)), 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapping/quad.vert b/tests/glsl/sascha-willems/shadowmapping/quad.vert
new file mode 100644
index 000000000..7c1286a4c
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapping/quad.vert
@@ -0,0 +1,28 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+
+void main()
+{
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/shadowmapping/scene.frag b/tests/glsl/sascha-willems/shadowmapping/scene.frag
new file mode 100644
index 000000000..58e2986ce
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapping/scene.frag
@@ -0,0 +1,72 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D shadowMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+layout (location = 4) in vec4 inShadowCoord;
+
+layout (constant_id = 0) const int enablePCF = 0;
+
+layout (location = 0) out vec4 outFragColor;
+
+#define ambient 0.1
+
+float textureProj(vec4 P, vec2 off)
+{
+ float shadow = 1.0;
+ vec4 shadowCoord = P / P.w;
+ if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 )
+ {
+ float dist = texture( shadowMap, shadowCoord.st + off ).r;
+ if ( shadowCoord.w > 0.0 && dist < shadowCoord.z )
+ {
+ shadow = ambient;
+ }
+ }
+ return shadow;
+}
+
+float filterPCF(vec4 sc)
+{
+ ivec2 texDim = textureSize(shadowMap, 0);
+ float scale = 1.5;
+ float dx = scale * 1.0 / float(texDim.x);
+ float dy = scale * 1.0 / float(texDim.y);
+
+ float shadowFactor = 0.0;
+ int count = 0;
+ int range = 1;
+
+ for (int x = -range; x <= range; x++)
+ {
+ for (int y = -range; y <= range; y++)
+ {
+ shadowFactor += textureProj(sc, vec2(dx*x, dy*y));
+ count++;
+ }
+
+ }
+ return shadowFactor / count;
+}
+
+void main()
+{
+ float shadow = (enablePCF == 1) ? filterPCF(inShadowCoord / inShadowCoord.w) : textureProj(inShadowCoord / inShadowCoord.w, vec2(0.0));
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = normalize(-reflect(L, N));
+ vec3 diffuse = max(dot(N, L), ambient) * inColor;
+// vec3 specular = pow(max(dot(R, V), 0.0), 50.0) * vec3(0.75);
+
+ outFragColor = vec4(diffuse * shadow, 1.0);
+
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/shadowmapping/scene.vert b/tests/glsl/sascha-willems/shadowmapping/scene.vert
new file mode 100644
index 000000000..6fda339c3
--- /dev/null
+++ b/tests/glsl/sascha-willems/shadowmapping/scene.vert
@@ -0,0 +1,52 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ mat4 lightSpace;
+ vec3 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+layout (location = 4) out vec4 outShadowCoord;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+const mat4 biasMat = mat4(
+ 0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.5, 0.5, 0.0, 1.0 );
+
+void main()
+{
+ outColor = inColor;
+ outNormal = inNormal;
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ outLightVec = normalize(ubo.lightPos - inPos);
+ outViewVec = -pos.xyz;
+
+ outShadowCoord = ( biasMat * ubo.lightSpace * ubo.model ) * vec4(inPos, 1.0);
+}
+
diff --git a/tests/glsl/sascha-willems/skeletalanimation/mesh.frag b/tests/glsl/sascha-willems/skeletalanimation/mesh.frag
new file mode 100644
index 000000000..c25560d09
--- /dev/null
+++ b/tests/glsl/sascha-willems/skeletalanimation/mesh.frag
@@ -0,0 +1,28 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColorMap, inUV) * vec4(inColor, 1.0);
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);// * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(0.5);
+ outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/skeletalanimation/mesh.vert b/tests/glsl/sascha-willems/skeletalanimation/mesh.vert
new file mode 100644
index 000000000..ca11e0b42
--- /dev/null
+++ b/tests/glsl/sascha-willems/skeletalanimation/mesh.vert
@@ -0,0 +1,53 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+layout (location = 4) in vec4 inBoneWeights;
+layout (location = 5) in ivec4 inBoneIDs;
+
+#define MAX_BONES 64
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ mat4 bones[MAX_BONES];
+ vec4 lightPos;
+ vec4 viewPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ mat4 boneTransform = ubo.bones[inBoneIDs[0]] * inBoneWeights[0];
+ boneTransform += ubo.bones[inBoneIDs[1]] * inBoneWeights[1];
+ boneTransform += ubo.bones[inBoneIDs[2]] * inBoneWeights[2];
+ boneTransform += ubo.bones[inBoneIDs[3]] * inBoneWeights[3];
+
+ outColor = inColor;
+ outUV = inUV;
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * boneTransform * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(inverse(transpose(ubo.model * boneTransform))) * inNormal;
+ outLightVec = ubo.lightPos.xyz - pos.xyz;
+ outViewVec = ubo.viewPos.xyz - pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/skeletalanimation/texture.frag b/tests/glsl/sascha-willems/skeletalanimation/texture.frag
new file mode 100644
index 000000000..1adb226bb
--- /dev/null
+++ b/tests/glsl/sascha-willems/skeletalanimation/texture.frag
@@ -0,0 +1,32 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColorMap, inUV);
+
+ float distSqr = dot(inLightVec, inLightVec);
+ vec3 lVec = inLightVec * inversesqrt(distSqr);
+
+ const float attInvRadius = 1.0/5000.0;
+ float atten = max(clamp(1.0 - attInvRadius * sqrt(distSqr), 0.0, 1.0), 0.0);
+
+ // Fake drop shadow
+ const float shadowInvRadius = 1.0/2500.0;
+ float dropshadow = max(clamp(1.0 - shadowInvRadius * sqrt(distSqr), 0.0, 1.0), 0.0);
+
+ outFragColor = vec4(color.rgba * (1.0 - dropshadow));
+ outFragColor.rgb *= atten;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/skeletalanimation/texture.vert b/tests/glsl/sascha-willems/skeletalanimation/texture.vert
new file mode 100644
index 000000000..67b3f2334
--- /dev/null
+++ b/tests/glsl/sascha-willems/skeletalanimation/texture.vert
@@ -0,0 +1,40 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+ vec4 lightPos;
+ vec4 viewPos;
+ vec2 uvOffset;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV + ubo.uvOffset;
+ vec4 pos = vec4(inPos, 1.0);
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(pos);
+
+ outNormal = mat3(ubo.model) * inNormal;
+ outLightVec = ubo.lightPos.xyz - pos.xyz;
+ outViewVec = ubo.viewPos.xyz - pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/specializationconstants/uber.frag b/tests/glsl/sascha-willems/specializationconstants/uber.frag
new file mode 100644
index 000000000..9661dff03
--- /dev/null
+++ b/tests/glsl/sascha-willems/specializationconstants/uber.frag
@@ -0,0 +1,75 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColormap;
+layout (binding = 2) uniform sampler2D samplerDiscard;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+// We use this constant to control the flow of the shader depending on the
+// lighting model selected at pipeline creation time
+layout (constant_id = 0) const int LIGHTING_MODEL = 0;
+// Parameter for the toon shading part of the shader
+layout (constant_id = 1) const float PARAM_TOON_DESATURATION = 0.0f;
+
+void main()
+{
+ switch (LIGHTING_MODEL) {
+ case 0: // Phong
+ {
+ vec3 ambient = inColor * vec3(0.25);
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * inColor;
+ vec3 specular = pow(max(dot(R, V), 0.0), 32.0) * vec3(0.75);
+ outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0);
+ break;
+ }
+ case 1: // Toon
+ {
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ float intensity = dot(N,L);
+ vec3 color;
+ if (intensity > 0.98)
+ color = inColor * 1.5;
+ else if (intensity > 0.9)
+ color = inColor * 1.0;
+ else if (intensity > 0.5)
+ color = inColor * 0.6;
+ else if (intensity > 0.25)
+ color = inColor * 0.4;
+ else
+ color = inColor * 0.2;
+ // Desaturate a bit
+ color = vec3(mix(color, vec3(dot(vec3(0.2126,0.7152,0.0722), color)), PARAM_TOON_DESATURATION));
+ outFragColor.rgb = color;
+ break;
+ }
+ case 2: // Textured
+ {
+ vec4 color = texture(samplerColormap, inUV).rrra;
+ vec3 ambient = color.rgb * vec3(0.25) * inColor;
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * color.rgb;
+ float specular = pow(max(dot(R, V), 0.0), 32.0) * color.a;
+ outFragColor = vec4(ambient + diffuse + vec3(specular), 1.0);
+ break;
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/specializationconstants/uber.vert b/tests/glsl/sascha-willems/specializationconstants/uber.vert
new file mode 100644
index 000000000..44fd2e692
--- /dev/null
+++ b/tests/glsl/sascha-willems/specializationconstants/uber.vert
@@ -0,0 +1,42 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec2 outUV;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outColor = inColor;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(ubo.model) * inNormal;
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/sphericalenvmapping/sem.frag b/tests/glsl/sascha-willems/sphericalenvmapping/sem.frag
new file mode 100644
index 000000000..6735ee03c
--- /dev/null
+++ b/tests/glsl/sascha-willems/sphericalenvmapping/sem.frag
@@ -0,0 +1,23 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2DArray matCap;
+
+layout (location = 0) in vec3 inColor;
+layout (location = 1) in vec3 inEyePos;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in flat int inTexIndex;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 r = reflect( inEyePos, inNormal );
+ vec3 r2 = vec3( r.x, r.y, r.z + 1.0 );
+ float m = 2.0 * length( r2 );
+ vec2 vN = r.xy / m + .5;
+ outFragColor = vec4( texture( matCap, vec3(vN, inTexIndex)).rgb * (clamp(inColor.r * 2, 0.0, 1.0)), 1.0 );
+}
diff --git a/tests/glsl/sascha-willems/sphericalenvmapping/sem.vert b/tests/glsl/sascha-willems/sphericalenvmapping/sem.vert
new file mode 100644
index 000000000..bb94e3f0e
--- /dev/null
+++ b/tests/glsl/sascha-willems/sphericalenvmapping/sem.vert
@@ -0,0 +1,35 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 normal;
+ mat4 view;
+ int texIndex;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+layout (location = 1) out vec3 outEyePos;
+layout (location = 2) out vec3 outNormal;
+layout (location = 3) out flat int outTexIndex;
+
+void main()
+{
+ outColor = inColor;
+ mat4 modelView = ubo.view * ubo.model;
+ outEyePos = normalize( vec3( modelView * inPos ) );
+ outTexIndex = ubo.texIndex;
+ outNormal = normalize( mat3(ubo.normal) * inNormal );
+ vec3 r = reflect( outEyePos, outNormal );
+ float m = 2.0 * sqrt( pow(r.x, 2.0) + pow(r.y, 2.0) + pow(r.z + 1.0, 2.0));
+ gl_Position = ubo.projection * modelView * inPos;
+}
diff --git a/tests/glsl/sascha-willems/ssao/blur.frag b/tests/glsl/sascha-willems/ssao/blur.frag
new file mode 100644
index 000000000..23b808d9b
--- /dev/null
+++ b/tests/glsl/sascha-willems/ssao/blur.frag
@@ -0,0 +1,29 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerSSAO;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out float outFragColor;
+
+void main()
+{
+ const int blurRange = 2;
+ int n = 0;
+ vec2 texelSize = 1.0 / vec2(textureSize(samplerSSAO, 0));
+ float result = 0.0;
+ for (int x = -blurRange; x < blurRange; x++)
+ {
+ for (int y = -blurRange; y < blurRange; y++)
+ {
+ vec2 offset = vec2(float(x), float(y)) * texelSize;
+ result += texture(samplerSSAO, inUV + offset).r;
+ n++;
+ }
+ }
+ outFragColor = result / (float(n));
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/ssao/composition.frag b/tests/glsl/sascha-willems/ssao/composition.frag
new file mode 100644
index 000000000..edf49b5d3
--- /dev/null
+++ b/tests/glsl/sascha-willems/ssao/composition.frag
@@ -0,0 +1,56 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerposition;
+layout (binding = 1) uniform sampler2D samplerNormal;
+layout (binding = 2) uniform sampler2D samplerAlbedo;
+layout (binding = 3) uniform sampler2D samplerSSAO;
+layout (binding = 4) uniform sampler2D samplerSSAOBlur;
+layout (binding = 5) uniform UBO
+{
+ mat4 _dummy;
+ uint ssao;
+ uint ssaoOnly;
+ uint ssaoBlur;
+} uboParams;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 fragPos = texture(samplerposition, inUV).rgb;
+ vec3 normal = normalize(texture(samplerNormal, inUV).rgb * 2.0 - 1.0);
+ vec4 albedo = texture(samplerAlbedo, inUV);
+
+ float ssao = (uboParams.ssaoBlur == 1) ? texture(samplerSSAOBlur, inUV).r : texture(samplerSSAO, inUV).r;
+
+ vec3 lightPos = vec3(0.0);
+ vec3 L = normalize(lightPos - fragPos);
+ float NdotL = max(0.5, dot(normal, L));
+
+ if (uboParams.ssaoOnly == 1)
+ {
+ outFragColor.rgb = ssao.rrr;
+ }
+ else
+ {
+ vec3 baseColor = albedo.rgb * NdotL;
+
+ if (uboParams.ssao == 1)
+ {
+ outFragColor.rgb = ssao.rrr;
+
+ if (uboParams.ssaoOnly != 1)
+ outFragColor.rgb *= baseColor;
+ }
+ else
+ {
+ outFragColor.rgb = baseColor;
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/ssao/fullscreen.vert b/tests/glsl/sascha-willems/ssao/fullscreen.vert
new file mode 100644
index 000000000..117eb02ec
--- /dev/null
+++ b/tests/glsl/sascha-willems/ssao/fullscreen.vert
@@ -0,0 +1,18 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
diff --git a/tests/glsl/sascha-willems/ssao/gbuffer.frag b/tests/glsl/sascha-willems/ssao/gbuffer.frag
new file mode 100644
index 000000000..9e81b9231
--- /dev/null
+++ b/tests/glsl/sascha-willems/ssao/gbuffer.frag
@@ -0,0 +1,30 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inPos;
+
+layout (location = 0) out vec4 outPosition;
+layout (location = 1) out vec4 outNormal;
+layout (location = 2) out vec4 outAlbedo;
+
+const float NEAR_PLANE = 0.1f; //todo: specialization const
+const float FAR_PLANE = 64.0f; //todo: specialization const
+
+float linearDepth(float depth)
+{
+ float z = depth * 2.0f - 1.0f;
+ return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
+}
+
+void main()
+{
+ outPosition = vec4(inPos, linearDepth(gl_FragCoord.z));
+ outNormal = vec4(normalize(inNormal) * 0.5 + 0.5, 1.0);
+ outAlbedo = vec4(inColor * 2.0, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/ssao/gbuffer.vert b/tests/glsl/sascha-willems/ssao/gbuffer.vert
new file mode 100644
index 000000000..3160cf949
--- /dev/null
+++ b/tests/glsl/sascha-willems/ssao/gbuffer.vert
@@ -0,0 +1,43 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outColor;
+layout (location = 3) out vec3 outPos;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ gl_Position = ubo.projection * ubo.view * ubo.model * inPos;
+
+ outUV = inUV;
+
+ // Vertex position in view space
+ outPos = vec3(ubo.view * ubo.model * inPos);
+
+ // Normal in view space
+ mat3 normalMatrix = transpose(inverse(mat3(ubo.view * ubo.model)));
+ outNormal = normalMatrix * inNormal;
+
+ outColor = inColor;
+}
diff --git a/tests/glsl/sascha-willems/ssao/ssao.frag b/tests/glsl/sascha-willems/ssao/ssao.frag
new file mode 100644
index 000000000..cdcbfd3ec
--- /dev/null
+++ b/tests/glsl/sascha-willems/ssao/ssao.frag
@@ -0,0 +1,73 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 0) uniform sampler2D samplerPositionDepth;
+layout (binding = 1) uniform sampler2D samplerNormal;
+layout (binding = 2) uniform sampler2D ssaoNoise;
+
+layout (constant_id = 0) const int SSAO_KERNEL_SIZE = 64;
+layout (constant_id = 1) const float SSAO_RADIUS = 0.5;
+
+layout (binding = 3) uniform UBOSSAOKernel
+{
+ vec4 samples[SSAO_KERNEL_SIZE];
+} uboSSAOKernel;
+
+layout (binding = 4) uniform UBO
+{
+ mat4 projection;
+} ubo;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out float outFragColor;
+
+void main()
+{
+ // Get G-Buffer values
+ vec3 fragPos = texture(samplerPositionDepth, inUV).rgb;
+ vec3 normal = normalize(texture(samplerNormal, inUV).rgb * 2.0 - 1.0);
+
+ // Get a random vector using a noise lookup
+ ivec2 texDim = textureSize(samplerPositionDepth, 0);
+ ivec2 noiseDim = textureSize(ssaoNoise, 0);
+ const vec2 noiseUV = vec2(float(texDim.x)/float(noiseDim.x), float(texDim.y)/(noiseDim.y)) * inUV;
+ vec3 randomVec = texture(ssaoNoise, noiseUV).xyz * 2.0 - 1.0;
+
+ // Create TBN matrix
+ vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
+ vec3 bitangent = cross(tangent, normal);
+ mat3 TBN = mat3(tangent, bitangent, normal);
+
+ // Calculate occlusion value
+ float occlusion = 0.0f;
+ for(int i = 0; i < SSAO_KERNEL_SIZE; i++)
+ {
+ vec3 samplePos = TBN * uboSSAOKernel.samples[i].xyz;
+ samplePos = fragPos + samplePos * SSAO_RADIUS;
+
+ // project
+ vec4 offset = vec4(samplePos, 1.0f);
+ offset = ubo.projection * offset;
+ offset.xyz /= offset.w;
+ offset.xyz = offset.xyz * 0.5f + 0.5f;
+
+ float sampleDepth = -texture(samplerPositionDepth, offset.xy).w;
+
+#define RANGE_CHECK 1
+#ifdef RANGE_CHECK
+ // Range check
+ float rangeCheck = smoothstep(0.0f, 1.0f, SSAO_RADIUS / abs(fragPos.z - sampleDepth));
+ occlusion += (sampleDepth >= samplePos.z ? 1.0f : 0.0f) * rangeCheck;
+#else
+ occlusion += (sampleDepth >= samplePos.z ? 1.0f : 0.0f);
+#endif
+ }
+ occlusion = 1.0 - (occlusion / float(SSAO_KERNEL_SIZE));
+
+ outFragColor = occlusion;
+}
+
diff --git a/tests/glsl/sascha-willems/subpasses/composition.frag b/tests/glsl/sascha-willems/subpasses/composition.frag
new file mode 100644
index 000000000..0a538471a
--- /dev/null
+++ b/tests/glsl/sascha-willems/subpasses/composition.frag
@@ -0,0 +1,82 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (input_attachment_index = 0, binding = 0) uniform subpassInput samplerposition;
+layout (input_attachment_index = 1, binding = 1) uniform subpassInput samplerNormal;
+layout (input_attachment_index = 2, binding = 2) uniform subpassInput samplerAlbedo;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragcolor;
+layout (location = 1) out vec4 outPosition;
+layout (location = 2) out vec4 outNormal;
+layout (location = 3) out vec4 outAlbedo;
+
+layout (constant_id = 0) const int NUM_LIGHTS = 64;
+
+struct Light {
+ vec4 position;
+ vec3 color;
+ float radius;
+};
+
+layout (binding = 3) uniform UBO
+{
+ vec4 viewPos;
+ Light lights[NUM_LIGHTS];
+} ubo;
+
+
+void main()
+{
+ // Read G-Buffer values from previous sub pass
+ vec3 fragPos = subpassLoad(samplerposition).rgb;
+ vec3 normal = subpassLoad(samplerNormal).rgb;
+ vec4 albedo = subpassLoad(samplerAlbedo);
+
+ #define ambient 0.15
+
+ // Ambient part
+ vec3 fragcolor = albedo.rgb * ambient;
+
+ for(int i = 0; i < NUM_LIGHTS; ++i)
+ {
+ // Vector to light
+ vec3 L = ubo.lights[i].position.xyz - fragPos;
+ // Distance from light to fragment position
+ float dist = length(L);
+
+ // Viewer to fragment
+ vec3 V = ubo.viewPos.xyz - fragPos;
+ V = normalize(V);
+
+ // Light to fragment
+ L = normalize(L);
+
+ // Attenuation
+ float atten = ubo.lights[i].radius / (pow(dist, 2.0) + 1.0);
+
+ // Diffuse part
+ vec3 N = normalize(normal);
+ float NdotL = max(0.0, dot(N, L));
+ vec3 diff = ubo.lights[i].color * albedo.rgb * NdotL * atten;
+
+ // Specular part
+ // Specular map values are stored in alpha of albedo mrt
+ vec3 R = reflect(-L, N);
+ float NdotR = max(0.0, dot(R, V));
+ //vec3 spec = ubo.lights[i].color * albedo.a * pow(NdotR, 32.0) * atten;
+
+ fragcolor += diff;// + spec;
+ }
+
+ outFragcolor = vec4(fragcolor, 1.0);
+
+ // Write G-Buffer attachments to avoid undefined behaviour (validation error)
+ outPosition = vec4(0.0);
+ outNormal = vec4(0.0);
+ outAlbedo = vec4(0.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/subpasses/composition.vert b/tests/glsl/sascha-willems/subpasses/composition.vert
new file mode 100644
index 000000000..f463f9182
--- /dev/null
+++ b/tests/glsl/sascha-willems/subpasses/composition.vert
@@ -0,0 +1,18 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/subpasses/gbuffer.frag b/tests/glsl/sascha-willems/subpasses/gbuffer.frag
new file mode 100644
index 000000000..389d1aa80
--- /dev/null
+++ b/tests/glsl/sascha-willems/subpasses/gbuffer.frag
@@ -0,0 +1,43 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+layout (binding = 2) uniform sampler2D samplerNormalMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inWorldPos;
+
+layout (location = 0) out vec4 outColor;
+layout (location = 1) out vec4 outPosition;
+layout (location = 2) out vec4 outNormal;
+layout (location = 3) out vec4 outAlbedo;
+
+layout (constant_id = 0) const float NEAR_PLANE = 0.1f;
+layout (constant_id = 1) const float FAR_PLANE = 256.0f;
+
+float linearDepth(float depth)
+{
+ float z = depth * 2.0f - 1.0f;
+ return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
+}
+
+void main()
+{
+ outPosition = vec4(inWorldPos, 1.0);
+
+ vec3 N = normalize(inNormal);
+ N.y = -N.y;
+ outNormal = vec4(N, 1.0);
+
+ outAlbedo.rgb = inColor;
+
+ // Store linearized depth in alpha component
+ outPosition.a = linearDepth(gl_FragCoord.z);
+
+ // Write color attachments to avoid undefined behaviour (validation error)
+ outColor = vec4(0.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/subpasses/gbuffer.vert b/tests/glsl/sascha-willems/subpasses/gbuffer.vert
new file mode 100644
index 000000000..c57d04e6d
--- /dev/null
+++ b/tests/glsl/sascha-willems/subpasses/gbuffer.vert
@@ -0,0 +1,43 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outWorldPos;
+layout (location = 3) out vec3 outTangent;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ gl_Position = ubo.projection * ubo.view * ubo.model * inPos;
+
+ // Vertex position in world space
+ outWorldPos = vec3(ubo.model * inPos);
+ // GL to Vulkan coord space
+ outWorldPos.y = -outWorldPos.y;
+
+ // Normal in world space
+ mat3 mNormal = transpose(inverse(mat3(ubo.model)));
+ outNormal = mNormal * normalize(inNormal);
+
+ // Currently just vertex color
+ outColor = inColor;
+}
diff --git a/tests/glsl/sascha-willems/subpasses/transparent.frag b/tests/glsl/sascha-willems/subpasses/transparent.frag
new file mode 100644
index 000000000..f293f2b8c
--- /dev/null
+++ b/tests/glsl/sascha-willems/subpasses/transparent.frag
@@ -0,0 +1,34 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerPositionDepth;
+layout (binding = 2) uniform sampler2D samplerTexture;
+
+layout (location = 0) in vec3 inColor;
+layout (location = 1) in vec2 inUV;
+
+layout (location = 0) out vec4 outColor;
+
+layout (constant_id = 0) const float NEAR_PLANE = 0.1f;
+layout (constant_id = 1) const float FAR_PLANE = 256.0f;
+
+float linearDepth(float depth)
+{
+ float z = depth * 2.0f - 1.0f;
+ return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
+}
+
+void main ()
+{
+ // Sample depth from deferred depth buffer and discard if obscured
+ float depth = subpassLoad(samplerPositionDepth).a;
+ if ((depth != 0.0) && (linearDepth(gl_FragCoord.z) > depth))
+ {
+ discard;
+ };
+
+ outColor = texture(samplerTexture, inUV);
+}
diff --git a/tests/glsl/sascha-willems/subpasses/transparent.vert b/tests/glsl/sascha-willems/subpasses/transparent.vert
new file mode 100644
index 000000000..8d667b820
--- /dev/null
+++ b/tests/glsl/sascha-willems/subpasses/transparent.vert
@@ -0,0 +1,28 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+layout (location = 1) out vec2 outUV;
+
+void main ()
+{
+ outColor = inColor;
+ outUV = inUV;
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/terraintessellation/skysphere.frag b/tests/glsl/sascha-willems/terraintessellation/skysphere.frag
new file mode 100644
index 000000000..7d87b21cd
--- /dev/null
+++ b/tests/glsl/sascha-willems/terraintessellation/skysphere.frag
@@ -0,0 +1,14 @@
+//TEST:COMPARE_GLSL:
+#version 450 core
+
+layout (location = 0) in vec2 inUV;
+
+layout (set = 0, binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main(void)
+{
+ vec4 color = texture(samplerColorMap, inUV);
+ outFragColor = vec4(color.rgb, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/terraintessellation/skysphere.vert b/tests/glsl/sascha-willems/terraintessellation/skysphere.vert
new file mode 100644
index 000000000..74dd7ad3b
--- /dev/null
+++ b/tests/glsl/sascha-willems/terraintessellation/skysphere.vert
@@ -0,0 +1,24 @@
+//TEST:COMPARE_GLSL:
+#version 450 core
+
+layout (location = 0) in vec3 inPos;
+layout (location = 2) in vec2 inUV;
+
+layout (location = 0) out vec2 outUV;
+
+layout (set = 0, binding = 0) uniform UBO
+{
+ mat4 mvp;
+} ubo;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main(void)
+{
+ gl_Position = ubo.mvp * vec4(inPos, 1.0);
+ outUV = inUV;
+ outUV.t = 1.0 - outUV.t;
+}
diff --git a/tests/glsl/sascha-willems/terraintessellation/terrain.frag b/tests/glsl/sascha-willems/terraintessellation/terrain.frag
new file mode 100644
index 000000000..fcd8612ae
--- /dev/null
+++ b/tests/glsl/sascha-willems/terraintessellation/terrain.frag
@@ -0,0 +1,65 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (set = 0, binding = 1) uniform sampler2D samplerHeight;
+layout (set = 0, binding = 2) uniform sampler2DArray samplerLayers;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+layout (location = 4) in vec3 inEyePos;
+layout (location = 5) in vec3 inWorldPos;
+
+layout (location = 0) out vec4 outFragColor;
+
+vec3 sampleTerrainLayer()
+{
+ // Define some layer ranges for sampling depending on terrain height
+ vec2 layers[6];
+ layers[0] = vec2(-10.0, 10.0);
+ layers[1] = vec2(5.0, 45.0);
+ layers[2] = vec2(45.0, 80.0);
+ layers[3] = vec2(75.0, 100.0);
+ layers[4] = vec2(95.0, 140.0);
+ layers[5] = vec2(140.0, 190.0);
+
+ vec3 color = vec3(0.0);
+
+ // Get height from displacement map
+ float height = textureLod(samplerHeight, inUV, 0.0).r * 255.0;
+
+ for (int i = 0; i < 6; i++)
+ {
+ float range = layers[i].y - layers[i].x;
+ float weight = (range - abs(height - layers[i].y)) / range;
+ weight = max(0.0, weight);
+ color += weight * texture(samplerLayers, vec3(inUV * 16.0, i)).rgb;
+ }
+
+ return color;
+}
+
+float fog(float density)
+{
+ const float LOG2 = -1.442695;
+ float dist = gl_FragCoord.z / gl_FragCoord.w * 0.1;
+ float d = density * dist;
+ return 1.0 - clamp(exp2(d * d * LOG2), 0.0, 1.0);
+}
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 ambient = vec3(0.5);
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
+
+ vec4 color = vec4((ambient + diffuse) * sampleTerrainLayer(), 1.0);
+
+ const vec4 fogColor = vec4(0.47, 0.5, 0.67, 0.0);
+ outFragColor = mix(color, fogColor, fog(0.25));
+}
diff --git a/tests/glsl/sascha-willems/terraintessellation/terrain.tesc b/tests/glsl/sascha-willems/terraintessellation/terrain.tesc
new file mode 100644
index 000000000..133e44ea7
--- /dev/null
+++ b/tests/glsl/sascha-willems/terraintessellation/terrain.tesc
@@ -0,0 +1,120 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout(set = 0, binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 lightPos;
+ vec4 frustumPlanes[6];
+ float displacementFactor;
+ float tessellationFactor;
+ vec2 viewportDim;
+ float tessellatedEdgeSize;
+} ubo;
+
+layout(set = 0, binding = 1) uniform sampler2D samplerHeight;
+
+layout (vertices = 4) out;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec2 inUV[];
+
+layout (location = 0) out vec3 outNormal[4];
+layout (location = 1) out vec2 outUV[4];
+
+// Calculate the tessellation factor based on screen space
+// dimensions of the edge
+float screenSpaceTessFactor(vec4 p0, vec4 p1)
+{
+ // Calculate edge mid point
+ vec4 midPoint = 0.5 * (p0 + p1);
+ // Sphere radius as distance between the control points
+ float radius = distance(p0, p1) / 2.0;
+
+ // View space
+ vec4 v0 = ubo.modelview * midPoint;
+
+ // Project into clip space
+ vec4 clip0 = (ubo.projection * (v0 - vec4(radius, vec3(0.0))));
+ vec4 clip1 = (ubo.projection * (v0 + vec4(radius, vec3(0.0))));
+
+ // Get normalized device coordinates
+ clip0 /= clip0.w;
+ clip1 /= clip1.w;
+
+ // Convert to viewport coordinates
+ clip0.xy *= ubo.viewportDim;
+ clip1.xy *= ubo.viewportDim;
+
+ // Return the tessellation factor based on the screen size
+ // given by the distance of the two edge control points in screen space
+ // and a reference (min.) tessellation size for the edge set by the application
+ return clamp(distance(clip0, clip1) / ubo.tessellatedEdgeSize * ubo.tessellationFactor, 1.0, 64.0);
+}
+
+// Checks the current's patch visibility against the frustum using a sphere check
+// Sphere radius is given by the patch size
+bool frustumCheck()
+{
+ // Fixed radius (increase if patch size is increased in example)
+ const float radius = 8.0f;
+ vec4 pos = gl_in[gl_InvocationID].gl_Position;
+ pos.y -= textureLod(samplerHeight, inUV[0], 0.0).r * ubo.displacementFactor;
+
+ // Check sphere against frustum planes
+ for (int i = 0; i < 6; i++) {
+ if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void main()
+{
+ if (gl_InvocationID == 0)
+ {
+ if (!frustumCheck())
+ {
+ gl_TessLevelInner[0] = 0.0;
+ gl_TessLevelInner[1] = 0.0;
+ gl_TessLevelOuter[0] = 0.0;
+ gl_TessLevelOuter[1] = 0.0;
+ gl_TessLevelOuter[2] = 0.0;
+ gl_TessLevelOuter[3] = 0.0;
+ }
+ else
+ {
+ if (ubo.tessellationFactor > 0.0)
+ {
+ gl_TessLevelOuter[0] = screenSpaceTessFactor(gl_in[3].gl_Position, gl_in[0].gl_Position);
+ gl_TessLevelOuter[1] = screenSpaceTessFactor(gl_in[0].gl_Position, gl_in[1].gl_Position);
+ gl_TessLevelOuter[2] = screenSpaceTessFactor(gl_in[1].gl_Position, gl_in[2].gl_Position);
+ gl_TessLevelOuter[3] = screenSpaceTessFactor(gl_in[2].gl_Position, gl_in[3].gl_Position);
+ gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5);
+ gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5);
+ }
+ else
+ {
+ // Tessellation factor can be set to zero by example
+ // to demonstrate a simple passthrough
+ gl_TessLevelInner[0] = 1.0;
+ gl_TessLevelInner[1] = 1.0;
+ gl_TessLevelOuter[0] = 1.0;
+ gl_TessLevelOuter[1] = 1.0;
+ gl_TessLevelOuter[2] = 1.0;
+ gl_TessLevelOuter[3] = 1.0;
+ }
+ }
+
+ }
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ outNormal[gl_InvocationID] = inNormal[gl_InvocationID];
+ outUV[gl_InvocationID] = inUV[gl_InvocationID];
+}
diff --git a/tests/glsl/sascha-willems/terraintessellation/terrain.tese b/tests/glsl/sascha-willems/terraintessellation/terrain.tese
new file mode 100644
index 000000000..1a74ac377
--- /dev/null
+++ b/tests/glsl/sascha-willems/terraintessellation/terrain.tese
@@ -0,0 +1,58 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (set = 0, binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 modelview;
+ vec4 lightPos;
+ vec4 frustumPlanes[6];
+ float displacementFactor;
+ float tessellationFactor;
+ vec2 viewportDim;
+ float tessellatedEdgeSize;
+} ubo;
+
+layout (set = 0, binding = 1) uniform sampler2D displacementMap;
+
+layout(quads, equal_spacing, cw) in;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec2 inUV[];
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+layout (location = 4) out vec3 outEyePos;
+layout (location = 5) out vec3 outWorldPos;
+
+void main()
+{
+ // Interpolate UV coordinates
+ vec2 uv1 = mix(inUV[0], inUV[1], gl_TessCoord.x);
+ vec2 uv2 = mix(inUV[3], inUV[2], gl_TessCoord.x);
+ outUV = mix(uv1, uv2, gl_TessCoord.y);
+
+ vec3 n1 = mix(inNormal[0], inNormal[1], gl_TessCoord.x);
+ vec3 n2 = mix(inNormal[3], inNormal[2], gl_TessCoord.x);
+ outNormal = mix(n1, n2, gl_TessCoord.y);
+
+ // Interpolate positions
+ vec4 pos1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);
+ vec4 pos2 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);
+ vec4 pos = mix(pos1, pos2, gl_TessCoord.y);
+ // Displace
+ pos.y -= textureLod(displacementMap, outUV, 0.0).r * ubo.displacementFactor;
+ // Perspective projection
+ gl_Position = ubo.projection * ubo.modelview * pos;
+
+ // Calculate vectors for lighting based on tessellated position
+ outViewVec = -pos.xyz;
+ outLightVec = normalize(ubo.lightPos.xyz + outViewVec);
+ outWorldPos = pos.xyz;
+ outEyePos = vec3(ubo.modelview * pos);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/terraintessellation/terrain.vert b/tests/glsl/sascha-willems/terraintessellation/terrain.vert
new file mode 100644
index 000000000..4a7c6ec66
--- /dev/null
+++ b/tests/glsl/sascha-willems/terraintessellation/terrain.vert
@@ -0,0 +1,24 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main(void)
+{
+ gl_Position = vec4(inPos.xyz, 1.0);
+ outUV = inUV;
+ outNormal = inNormal;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/tessellation/base.frag b/tests/glsl/sascha-willems/tessellation/base.frag
new file mode 100644
index 000000000..3bdd8b954
--- /dev/null
+++ b/tests/glsl/sascha-willems/tessellation/base.frag
@@ -0,0 +1,22 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 2) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(vec3(0.0, -4.0, 4.0));
+
+ vec4 color = texture(samplerColorMap, inUV);
+
+ outFragColor.rgb = vec3(clamp(max(dot(N,L), 0.0), 0.2, 1.0)) * color.rgb * 1.5;
+}
diff --git a/tests/glsl/sascha-willems/tessellation/base.vert b/tests/glsl/sascha-willems/tessellation/base.vert
new file mode 100644
index 000000000..0bce97d99
--- /dev/null
+++ b/tests/glsl/sascha-willems/tessellation/base.vert
@@ -0,0 +1,24 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main(void)
+{
+ gl_Position = vec4(inPos.xyz, 1.0);
+ outNormal = inNormal;
+ outUV = inUV;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/tessellation/passthrough.tesc b/tests/glsl/sascha-willems/tessellation/passthrough.tesc
new file mode 100644
index 000000000..348bb43d7
--- /dev/null
+++ b/tests/glsl/sascha-willems/tessellation/passthrough.tesc
@@ -0,0 +1,28 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (vertices = 3) out;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec2 inUV[];
+
+layout (location = 0) out vec3 outNormal[3];
+layout (location = 1) out vec2 outUV[3];
+
+void main(void)
+{
+ if (gl_InvocationID == 0)
+ {
+ gl_TessLevelInner[0] = 1.0;
+ gl_TessLevelOuter[0] = 1.0;
+ gl_TessLevelOuter[1] = 1.0;
+ gl_TessLevelOuter[2] = 1.0;
+ }
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ outNormal[gl_InvocationID] = inNormal[gl_InvocationID];
+ outUV[gl_InvocationID] = inUV[gl_InvocationID];
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/tessellation/passthrough.tese b/tests/glsl/sascha-willems/tessellation/passthrough.tese
new file mode 100644
index 000000000..42dc5c562
--- /dev/null
+++ b/tests/glsl/sascha-willems/tessellation/passthrough.tese
@@ -0,0 +1,31 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (triangles) in;
+
+layout (binding = 1) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ float tessAlpha;
+} ubo;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec2 inUV[];
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+
+void main(void)
+{
+ gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +
+ (gl_TessCoord.y * gl_in[1].gl_Position) +
+ (gl_TessCoord.z * gl_in[2].gl_Position);
+ gl_Position = ubo.projection * ubo.model * gl_Position;
+
+ outNormal = gl_TessCoord.x*inNormal[0] + gl_TessCoord.y*inNormal[1] + gl_TessCoord.z*inNormal[2];
+ outUV = gl_TessCoord.x*inUV[0] + gl_TessCoord.y*inUV[1] + gl_TessCoord.z*inUV[2];
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/tessellation/pntriangles.tesc b/tests/glsl/sascha-willems/tessellation/pntriangles.tesc
new file mode 100644
index 000000000..90755153c
--- /dev/null
+++ b/tests/glsl/sascha-willems/tessellation/pntriangles.tesc
@@ -0,0 +1,87 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+// PN patch data
+struct PnPatch
+{
+ float b210;
+ float b120;
+ float b021;
+ float b012;
+ float b102;
+ float b201;
+ float b111;
+ float n110;
+ float n011;
+ float n101;
+};
+
+// tessellation levels
+layout (binding = 0) uniform UBO
+{
+ float tessLevel;
+} ubo;
+
+layout(vertices=3) out;
+
+layout(location = 0) in vec3 inNormal[];
+layout(location = 1) in vec2 inUV[];
+
+layout(location = 0) out vec3 outNormal[3];
+layout(location = 3) out vec2 outUV[3];
+layout(location = 6) out PnPatch outPatch[3];
+
+float wij(int i, int j)
+{
+ return dot(gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz, inNormal[i]);
+}
+
+float vij(int i, int j)
+{
+ vec3 Pj_minus_Pi = gl_in[j].gl_Position.xyz
+ - gl_in[i].gl_Position.xyz;
+ vec3 Ni_plus_Nj = inNormal[i]+inNormal[j];
+ return 2.0*dot(Pj_minus_Pi, Ni_plus_Nj)/dot(Pj_minus_Pi, Pj_minus_Pi);
+}
+
+void main()
+{
+ // get data
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ outNormal[gl_InvocationID] = inNormal[gl_InvocationID];
+ outUV[gl_InvocationID] = inUV[gl_InvocationID];
+
+ // set base
+ float P0 = gl_in[0].gl_Position[gl_InvocationID];
+ float P1 = gl_in[1].gl_Position[gl_InvocationID];
+ float P2 = gl_in[2].gl_Position[gl_InvocationID];
+ float N0 = inNormal[0][gl_InvocationID];
+ float N1 = inNormal[1][gl_InvocationID];
+ float N2 = inNormal[2][gl_InvocationID];
+
+ // compute control points
+ outPatch[gl_InvocationID].b210 = (2.0*P0 + P1 - wij(0,1)*N0)/3.0;
+ outPatch[gl_InvocationID].b120 = (2.0*P1 + P0 - wij(1,0)*N1)/3.0;
+ outPatch[gl_InvocationID].b021 = (2.0*P1 + P2 - wij(1,2)*N1)/3.0;
+ outPatch[gl_InvocationID].b012 = (2.0*P2 + P1 - wij(2,1)*N2)/3.0;
+ outPatch[gl_InvocationID].b102 = (2.0*P2 + P0 - wij(2,0)*N2)/3.0;
+ outPatch[gl_InvocationID].b201 = (2.0*P0 + P2 - wij(0,2)*N0)/3.0;
+ float E = ( outPatch[gl_InvocationID].b210
+ + outPatch[gl_InvocationID].b120
+ + outPatch[gl_InvocationID].b021
+ + outPatch[gl_InvocationID].b012
+ + outPatch[gl_InvocationID].b102
+ + outPatch[gl_InvocationID].b201 ) / 6.0;
+ float V = (P0 + P1 + P2)/3.0;
+ outPatch[gl_InvocationID].b111 = E + (E - V)*0.5;
+ outPatch[gl_InvocationID].n110 = N0+N1-vij(0,1)*(P1-P0);
+ outPatch[gl_InvocationID].n011 = N1+N2-vij(1,2)*(P2-P1);
+ outPatch[gl_InvocationID].n101 = N2+N0-vij(2,0)*(P0-P2);
+
+ // set tess levels
+ gl_TessLevelOuter[gl_InvocationID] = ubo.tessLevel;
+ gl_TessLevelInner[0] = ubo.tessLevel;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/tessellation/pntriangles.tese b/tests/glsl/sascha-willems/tessellation/pntriangles.tese
new file mode 100644
index 000000000..0187ad781
--- /dev/null
+++ b/tests/glsl/sascha-willems/tessellation/pntriangles.tese
@@ -0,0 +1,92 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+// PN patch data
+struct PnPatch
+{
+ float b210;
+ float b120;
+ float b021;
+ float b012;
+ float b102;
+ float b201;
+ float b111;
+ float n110;
+ float n011;
+ float n101;
+};
+
+layout (binding = 1) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ float tessAlpha;
+} ubo;
+
+layout(triangles, fractional_odd_spacing, ccw) in;
+
+layout(location = 0) in vec3 iNormal[];
+layout(location = 3) in vec2 iTexCoord[];
+layout(location = 6) in PnPatch iPnPatch[];
+
+layout(location = 0) out vec3 oNormal;
+layout(location = 1) out vec2 oTexCoord;
+
+#define uvw gl_TessCoord
+
+void main()
+{
+ vec3 uvwSquared = uvw * uvw;
+ vec3 uvwCubed = uvwSquared * uvw;
+
+ // extract control points
+ vec3 b210 = vec3(iPnPatch[0].b210, iPnPatch[1].b210, iPnPatch[2].b210);
+ vec3 b120 = vec3(iPnPatch[0].b120, iPnPatch[1].b120, iPnPatch[2].b120);
+ vec3 b021 = vec3(iPnPatch[0].b021, iPnPatch[1].b021, iPnPatch[2].b021);
+ vec3 b012 = vec3(iPnPatch[0].b012, iPnPatch[1].b012, iPnPatch[2].b012);
+ vec3 b102 = vec3(iPnPatch[0].b102, iPnPatch[1].b102, iPnPatch[2].b102);
+ vec3 b201 = vec3(iPnPatch[0].b201, iPnPatch[1].b201, iPnPatch[2].b201);
+ vec3 b111 = vec3(iPnPatch[0].b111, iPnPatch[1].b111, iPnPatch[2].b111);
+
+ // extract control normals
+ vec3 n110 = normalize(vec3(iPnPatch[0].n110, iPnPatch[1].n110, iPnPatch[2].n110));
+ vec3 n011 = normalize(vec3(iPnPatch[0].n011, iPnPatch[1].n011, iPnPatch[2].n011));
+ vec3 n101 = normalize(vec3(iPnPatch[0].n101, iPnPatch[1].n101, iPnPatch[2].n101));
+
+ // compute texcoords
+ oTexCoord = gl_TessCoord[2]*iTexCoord[0] + gl_TessCoord[0]*iTexCoord[1] + gl_TessCoord[1]*iTexCoord[2];
+
+ // normal
+ // Barycentric normal
+ vec3 barNormal = gl_TessCoord[2]*iNormal[0] + gl_TessCoord[0]*iNormal[1] + gl_TessCoord[1]*iNormal[2];
+ vec3 pnNormal = iNormal[0]*uvwSquared[2] + iNormal[1]*uvwSquared[0] + iNormal[2]*uvwSquared[1]
+ + n110*uvw[2]*uvw[0] + n011*uvw[0]*uvw[1]+ n101*uvw[2]*uvw[1];
+ oNormal = ubo.tessAlpha*pnNormal + (1.0-ubo.tessAlpha) * barNormal;
+
+ // compute interpolated pos
+ vec3 barPos = gl_TessCoord[2]*gl_in[0].gl_Position.xyz
+ + gl_TessCoord[0]*gl_in[1].gl_Position.xyz
+ + gl_TessCoord[1]*gl_in[2].gl_Position.xyz;
+
+ // save some computations
+ uvwSquared *= 3.0;
+
+ // compute PN position
+ vec3 pnPos = gl_in[0].gl_Position.xyz*uvwCubed[2]
+ + gl_in[1].gl_Position.xyz*uvwCubed[0]
+ + gl_in[2].gl_Position.xyz*uvwCubed[1]
+ + b210*uvwSquared[2]*uvw[0]
+ + b120*uvwSquared[0]*uvw[2]
+ + b201*uvwSquared[2]*uvw[1]
+ + b021*uvwSquared[0]*uvw[1]
+ + b102*uvwSquared[1]*uvw[2]
+ + b012*uvwSquared[1]*uvw[0]
+ + b111*6.0*uvw[0]*uvw[1]*uvw[2];
+
+ // final position and normal
+ vec3 finalPos = (1.0-ubo.tessAlpha)*barPos + ubo.tessAlpha*pnPos;
+ gl_Position = ubo.projection * ubo.model * vec4(finalPos,1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/textoverlay/background.frag b/tests/glsl/sascha-willems/textoverlay/background.frag
new file mode 100644
index 000000000..00ac6416b
--- /dev/null
+++ b/tests/glsl/sascha-willems/textoverlay/background.frag
@@ -0,0 +1,16 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec2 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerColorMap, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/textoverlay/background.vert b/tests/glsl/sascha-willems/textoverlay/background.vert
new file mode 100644
index 000000000..476834f38
--- /dev/null
+++ b/tests/glsl/sascha-willems/textoverlay/background.vert
@@ -0,0 +1,18 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+ gl_Position = vec4(outUV * vec2(2.0f, 2.0f) + vec2(-1.0f, -1.0f), 0.0f, 1.0f);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/textoverlay/mesh.frag b/tests/glsl/sascha-willems/textoverlay/mesh.frag
new file mode 100644
index 000000000..696914ded
--- /dev/null
+++ b/tests/glsl/sascha-willems/textoverlay/mesh.frag
@@ -0,0 +1,27 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColorMap;
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColorMap, inUV);
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * color.rgb;
+ vec3 specular = pow(max(dot(R, V), 0.0), 1.0) * vec3(color.a);
+ outFragColor = vec4(diffuse + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/textoverlay/mesh.vert b/tests/glsl/sascha-willems/textoverlay/mesh.vert
new file mode 100644
index 000000000..dde3bf92d
--- /dev/null
+++ b/tests/glsl/sascha-willems/textoverlay/mesh.vert
@@ -0,0 +1,39 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outNormal = inNormal;
+ outUV = inUV;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(transpose(inverse(ubo.model))) * normalize(inNormal);
+ vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = -pos.xyz;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/textoverlay/text.frag b/tests/glsl/sascha-willems/textoverlay/text.frag
new file mode 100644
index 000000000..42414689f
--- /dev/null
+++ b/tests/glsl/sascha-willems/textoverlay/text.frag
@@ -0,0 +1,14 @@
+//TEST:COMPARE_GLSL:
+#version 450 core
+
+layout (location = 0) in vec2 inUV;
+
+layout (binding = 0) uniform sampler2D samplerFont;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main(void)
+{
+ float color = texture(samplerFont, inUV).r;
+ outFragColor = vec4(vec3(color), 1.0);
+}
diff --git a/tests/glsl/sascha-willems/textoverlay/text.vert b/tests/glsl/sascha-willems/textoverlay/text.vert
new file mode 100644
index 000000000..a9877dd0e
--- /dev/null
+++ b/tests/glsl/sascha-willems/textoverlay/text.vert
@@ -0,0 +1,18 @@
+//TEST:COMPARE_GLSL:
+#version 450 core
+
+layout (location = 0) in vec2 inPos;
+layout (location = 1) in vec2 inUV;
+
+layout (location = 0) out vec2 outUV;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main(void)
+{
+ gl_Position = vec4(inPos, 0.0, 1.0);
+ outUV = inUV;
+}
diff --git a/tests/glsl/sascha-willems/texture/texture.frag b/tests/glsl/sascha-willems/texture/texture.frag
new file mode 100644
index 000000000..508f7f69c
--- /dev/null
+++ b/tests/glsl/sascha-willems/texture/texture.frag
@@ -0,0 +1,29 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in float inLodBias;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColor, inUV, inLodBias);
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
+ float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a;
+
+ outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/texture/texture.vert b/tests/glsl/sascha-willems/texture/texture.vert
new file mode 100644
index 000000000..9cd64b831
--- /dev/null
+++ b/tests/glsl/sascha-willems/texture/texture.vert
@@ -0,0 +1,45 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 viewPos;
+ float lodBias;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out float outLodBias;
+layout (location = 2) out vec3 outNormal;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ outLodBias = ubo.lodBias;
+
+ vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0));
+
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(inverse(transpose(ubo.model))) * inNormal;
+ vec3 lightPos = vec3(0.0);
+ vec3 lPos = mat3(ubo.model) * lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = ubo.viewPos.xyz - pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/texture3d/texture3d.frag b/tests/glsl/sascha-willems/texture3d/texture3d.frag
new file mode 100644
index 000000000..d9464a233
--- /dev/null
+++ b/tests/glsl/sascha-willems/texture3d/texture3d.frag
@@ -0,0 +1,29 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler3D samplerColor;
+
+layout (location = 0) in vec3 inUV;
+layout (location = 1) in float inLodBias;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(samplerColor, inUV);
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
+ float specular = pow(max(dot(R, V), 0.0), 16.0) * color.r;
+
+ outFragColor = vec4(diffuse * color.r + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/texture3d/texture3d.vert b/tests/glsl/sascha-willems/texture3d/texture3d.vert
new file mode 100644
index 000000000..1aca0195b
--- /dev/null
+++ b/tests/glsl/sascha-willems/texture3d/texture3d.vert
@@ -0,0 +1,44 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 viewPos;
+ float depth;
+} ubo;
+
+layout (location = 0) out vec3 outUV;
+layout (location = 1) out float outLodBias;
+layout (location = 2) out vec3 outNormal;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = vec3(inUV, ubo.depth);
+
+ vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0));
+
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec4 pos = ubo.model * vec4(inPos, 1.0);
+ outNormal = mat3(inverse(transpose(ubo.model))) * inNormal;
+ vec3 lightPos = vec3(0.0);
+ vec3 lPos = mat3(ubo.model) * lightPos.xyz;
+ outLightVec = lPos - pos.xyz;
+ outViewVec = ubo.viewPos.xyz - pos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/texturearray/instancing.frag b/tests/glsl/sascha-willems/texturearray/instancing.frag
new file mode 100644
index 000000000..b0e293e34
--- /dev/null
+++ b/tests/glsl/sascha-willems/texturearray/instancing.frag
@@ -0,0 +1,16 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform sampler2DArray samplerArray;
+
+layout (location = 0) in vec3 inUV;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerArray, inUV);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/texturearray/instancing.vert b/tests/glsl/sascha-willems/texturearray/instancing.vert
new file mode 100644
index 000000000..ad738a59b
--- /dev/null
+++ b/tests/glsl/sascha-willems/texturearray/instancing.vert
@@ -0,0 +1,30 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec2 inUV;
+
+struct Instance
+{
+ mat4 model;
+ vec4 arrayIndex;
+};
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ Instance instance[8];
+} ubo;
+
+layout (location = 0) out vec3 outUV;
+
+void main()
+{
+ outUV = vec3(inUV, ubo.instance[gl_InstanceIndex].arrayIndex.x);
+ mat4 modelView = ubo.view * ubo.instance[gl_InstanceIndex].model;
+ gl_Position = ubo.projection * modelView * inPos;
+}
diff --git a/tests/glsl/sascha-willems/texturemipmapgen/texture.frag b/tests/glsl/sascha-willems/texturemipmapgen/texture.frag
new file mode 100644
index 000000000..037ed4e30
--- /dev/null
+++ b/tests/glsl/sascha-willems/texturemipmapgen/texture.frag
@@ -0,0 +1,30 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (set = 0, binding = 1) uniform texture2D textureColor;
+layout (set = 0, binding = 2) uniform sampler samplers[3];
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in float inLodBias;
+layout (location = 2) flat in int inSamplerIndex;
+layout (location = 3) in vec3 inNormal;
+layout (location = 4) in vec3 inViewVec;
+layout (location = 5) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = texture(sampler2D(textureColor, samplers[inSamplerIndex]), inUV, inLodBias);
+
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(L, N);
+ vec3 diffuse = max(dot(N, L), 0.65) * vec3(1.0);
+ float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a;
+ outFragColor = vec4(diffuse * color.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/texturemipmapgen/texture.vert b/tests/glsl/sascha-willems/texturemipmapgen/texture.vert
new file mode 100644
index 000000000..ed98fc24e
--- /dev/null
+++ b/tests/glsl/sascha-willems/texturemipmapgen/texture.vert
@@ -0,0 +1,47 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inNormal;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 view;
+ mat4 model;
+ vec4 viewPos;
+ float lodBias;
+ int samplerIndex;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out float outLodBias;
+layout (location = 2) flat out int outSamplerIndex;
+layout (location = 3) out vec3 outNormal;
+layout (location = 4) out vec3 outViewVec;
+layout (location = 5) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV * vec2(2.0, 1.0);
+ outLodBias = ubo.lodBias;
+ outSamplerIndex = ubo.samplerIndex;
+
+ vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0));
+
+ gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0);
+
+ outNormal = mat3(inverse(transpose(ubo.model))) * inNormal;
+ vec3 lightPos = vec3(-30.0, 0.0, 0.0);
+ outLightVec = worldPos - lightPos;
+ outViewVec = ubo.viewPos.xyz - worldPos;
+}
diff --git a/tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.frag b/tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.frag
new file mode 100644
index 000000000..c82b621e4
--- /dev/null
+++ b/tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.frag
@@ -0,0 +1,48 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_sparse_texture2 : enable
+#extension GL_ARB_sparse_texture_clamp : enable
+
+layout (binding = 1) uniform sampler2D samplerColor;
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in float inLodBias;
+layout (location = 2) in vec3 inNormal;
+layout (location = 3) in vec3 inViewVec;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec4 color = vec4(0.0);
+
+ // Get residency code for current texel
+ int residencyCode = sparseTextureARB(samplerColor, inUV, color, inLodBias);
+
+ // Fetch sparse until we get a valid texel
+ float minLod = 1.0;
+ while (!sparseTexelsResidentARB(residencyCode))
+ {
+ residencyCode = sparseTextureClampARB(samplerColor, inUV, minLod, color);
+ minLod += 1.0f;
+ }
+
+ // Check if texel is resident
+ bool texelResident = sparseTexelsResidentARB(residencyCode);
+
+ if (!texelResident)
+ {
+ color = vec4(1.0, 0.0, 0.0, 0.0);
+ }
+
+ vec3 N = normalize(inNormal);
+
+ N = normalize((inNormal - 0.5) * 2.0);
+
+ vec3 L = normalize(inLightVec);
+ vec3 R = reflect(-L, N);
+ vec3 diffuse = max(dot(N, L), 0.25) * color.rgb;
+ outFragColor = vec4(diffuse, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.vert b/tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.vert
new file mode 100644
index 000000000..f29db5b5b
--- /dev/null
+++ b/tests/glsl/sascha-willems/texturesparseresidency/sparseresidency.vert
@@ -0,0 +1,43 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ vec4 viewPos;
+ float lodBias;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out float outLodBias;
+layout (location = 2) out vec3 outNormal;
+layout (location = 3) out vec3 outViewVec;
+layout (location = 4) out vec3 outLightVec;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outUV = inUV;
+ outLodBias = ubo.lodBias;
+ outNormal = inNormal;
+
+ vec3 worldPos = vec3(ubo.model * vec4(inPos, 1.0));
+
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+
+ vec3 lightPos = vec3(0.0, 50.0f, 0.0f);
+ outLightVec = lightPos - inPos.xyz;
+ outViewVec = ubo.viewPos.xyz - worldPos.xyz;
+}
diff --git a/tests/glsl/sascha-willems/triangle/triangle.frag b/tests/glsl/sascha-willems/triangle/triangle.frag
new file mode 100644
index 000000000..70ee9fc53
--- /dev/null
+++ b/tests/glsl/sascha-willems/triangle/triangle.frag
@@ -0,0 +1,14 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = vec4(inColor, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/triangle/triangle.vert b/tests/glsl/sascha-willems/triangle/triangle.vert
new file mode 100644
index 000000000..b14410d80
--- /dev/null
+++ b/tests/glsl/sascha-willems/triangle/triangle.vert
@@ -0,0 +1,29 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projectionMatrix;
+ mat4 modelMatrix;
+ mat4 viewMatrix;
+} ubo;
+
+layout (location = 0) out vec3 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+
+void main()
+{
+ outColor = inColor;
+ gl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/viewportarray/multiview.geom b/tests/glsl/sascha-willems/viewportarray/multiview.geom
new file mode 100644
index 000000000..39303fb33
--- /dev/null
+++ b/tests/glsl/sascha-willems/viewportarray/multiview.geom
@@ -0,0 +1,46 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_viewport_array : enable
+
+layout (triangles, invocations = 2) in;
+layout (triangle_strip, max_vertices = 3) out;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection[2];
+ mat4 modelview[2];
+ vec4 lightPos;
+} ubo;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec3 inColor[];
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+layout (location = 2) out vec3 outViewVec;
+layout (location = 3) out vec3 outLightVec;
+
+void main(void)
+{
+ for(int i = 0; i < gl_in.length(); i++)
+ {
+ outNormal = mat3(ubo.modelview[gl_InvocationID]) * inNormal[i];
+ outColor = inColor[i];
+
+ vec4 pos = gl_in[i].gl_Position;
+ vec4 worldPos = (ubo.modelview[gl_InvocationID] * pos);
+
+ vec3 lPos = vec3(ubo.modelview[gl_InvocationID] * ubo.lightPos);
+ outLightVec = lPos - worldPos.xyz;
+ outViewVec = -worldPos.xyz;
+
+ gl_Position = ubo.projection[gl_InvocationID] * worldPos;
+
+ // Set the viewport index that the vertex will be emitted to
+ gl_ViewportIndex = gl_InvocationID;
+
+ EmitVertex();
+ }
+ EndPrimitive();
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/viewportarray/scene.frag b/tests/glsl/sascha-willems/viewportarray/scene.frag
new file mode 100644
index 000000000..1ecd7fdb3
--- /dev/null
+++ b/tests/glsl/sascha-willems/viewportarray/scene.frag
@@ -0,0 +1,21 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (location = 0) in vec3 inNormal;
+layout (location = 1) in vec3 inColor;
+layout (location = 2) in vec3 inViewVec;
+layout (location = 3) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outColor;
+
+void main()
+{
+ vec3 N = normalize(inNormal);
+ vec3 L = normalize(inLightVec);
+ vec3 V = normalize(inViewVec);
+ vec3 R = reflect(-L, N);
+ vec3 ambient = vec3(0.1);
+ vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
+ vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75);
+ outColor = vec4((ambient + diffuse) * inColor.rgb + specular, 1.0);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/viewportarray/scene.vert b/tests/glsl/sascha-willems/viewportarray/scene.vert
new file mode 100644
index 000000000..28e1c3d8b
--- /dev/null
+++ b/tests/glsl/sascha-willems/viewportarray/scene.vert
@@ -0,0 +1,21 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec3 outColor;
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+};
+
+void main()
+{
+ outColor = inColor;
+ outNormal = inNormal;
+ gl_Position = vec4(inPos.xyz, 1.0);
+}
diff --git a/tests/glsl/sascha-willems/vulkanscene/logo.frag b/tests/glsl/sascha-willems/vulkanscene/logo.frag
new file mode 100644
index 000000000..aa42773b4
--- /dev/null
+++ b/tests/glsl/sascha-willems/vulkanscene/logo.frag
@@ -0,0 +1,23 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inEyePos;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ vec3 Eye = normalize(-inEyePos);
+ vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
+
+ vec4 diff = vec4(inColor, 1.0) * max(dot(inNormal, inLightVec), 0.0);
+ float shininess = 0.0;
+ vec4 spec = vec4(1.0, 1.0, 1.0, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.5) * shininess;
+
+ outFragColor = diff + spec;
+ outFragColor.a = 1.0;
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/vulkanscene/logo.vert b/tests/glsl/sascha-willems/vulkanscene/logo.vert
new file mode 100644
index 000000000..2887245a7
--- /dev/null
+++ b/tests/glsl/sascha-willems/vulkanscene/logo.vert
@@ -0,0 +1,38 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inTexCoord;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 normal;
+ mat4 view;
+ vec3 lightpos;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out vec3 outColor;
+layout (location = 3) out vec3 outEyePos;
+layout (location = 4) out vec3 outLightVec;
+
+void main()
+{
+ mat4 modelView = ubo.view * ubo.model;
+ vec4 pos = modelView * inPos;
+ outUV = inTexCoord.st;
+ outNormal = normalize(mat3(ubo.normal) * inNormal);
+ outColor = inColor;
+ gl_Position = ubo.projection * pos;
+ outEyePos = vec3(modelView * pos);
+ vec4 lightPos = vec4(1.0, 2.0, 0.0, 1.0) * modelView;
+ outLightVec = normalize(lightPos.xyz - outEyePos);
+}
diff --git a/tests/glsl/sascha-willems/vulkanscene/mesh.frag b/tests/glsl/sascha-willems/vulkanscene/mesh.frag
new file mode 100644
index 000000000..5afa294ed
--- /dev/null
+++ b/tests/glsl/sascha-willems/vulkanscene/mesh.frag
@@ -0,0 +1,45 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+layout (binding = 1) uniform sampler2D tex;
+
+layout (location = 0) in vec2 inUV;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec3 inColor;
+layout (location = 3) in vec3 inEyePos;
+layout (location = 4) in vec3 inLightVec;
+
+layout (location = 0) out vec4 outFragColor;
+
+float specpart(vec3 L, vec3 N, vec3 H)
+{
+ if (dot(N, L) > 0.0)
+ {
+ return pow(clamp(dot(H, N), 0.0, 1.0), 64.0);
+ }
+ return 0.0;
+}
+
+void main()
+{
+ vec3 Eye = normalize(-inEyePos);
+ vec3 Reflected = normalize(reflect(-inLightVec, inNormal));
+
+ vec3 halfVec = normalize(inLightVec + inEyePos);
+ float diff = clamp(dot(inLightVec, inNormal), 0.0, 1.0);
+ float spec = specpart(inLightVec, inNormal, halfVec);
+ float intensity = 0.1 + diff + spec;
+
+ vec4 IAmbient = vec4(0.2, 0.2, 0.2, 1.0);
+ vec4 IDiffuse = vec4(0.5, 0.5, 0.5, 0.5) * max(dot(inNormal, inLightVec), 0.0);
+ float shininess = 0.75;
+ vec4 ISpecular = vec4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 2.0) * shininess;
+
+ outFragColor = vec4((IAmbient + IDiffuse) * vec4(inColor, 1.0) + ISpecular);
+
+ // Some manual saturation
+ if (intensity > 0.95)
+ outFragColor *= 2.25;
+ if (intensity < 0.15)
+ outFragColor = vec4(0.1);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/vulkanscene/mesh.vert b/tests/glsl/sascha-willems/vulkanscene/mesh.vert
new file mode 100644
index 000000000..ca7e5b06d
--- /dev/null
+++ b/tests/glsl/sascha-willems/vulkanscene/mesh.vert
@@ -0,0 +1,38 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec4 inPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inTexCoord;
+layout (location = 3) in vec3 inColor;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+ mat4 normal;
+ mat4 view;
+ vec3 lightpos;
+} ubo;
+
+layout (location = 0) out vec2 outUV;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out vec3 outColor;
+layout (location = 3) out vec3 outEyePos;
+layout (location = 4) out vec3 outLightVec;
+
+void main()
+{
+ outUV = inTexCoord.st;
+ outNormal = normalize(mat3(ubo.normal) * inNormal);
+ outColor = inColor;
+ mat4 modelView = ubo.view * ubo.model;
+ vec4 pos = modelView * inPos;
+ gl_Position = ubo.projection * pos;
+ outEyePos = vec3(modelView * pos);
+ vec4 lightPos = vec4(ubo.lightpos, 1.0) * modelView;
+ outLightVec = normalize(lightPos.xyz - outEyePos);
+}
diff --git a/tests/glsl/sascha-willems/vulkanscene/skybox.frag b/tests/glsl/sascha-willems/vulkanscene/skybox.frag
new file mode 100644
index 000000000..8cf1d0b8b
--- /dev/null
+++ b/tests/glsl/sascha-willems/vulkanscene/skybox.frag
@@ -0,0 +1,16 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (binding = 1) uniform samplerCube samplerCubeMap;
+
+layout (location = 0) in vec3 inUVW;
+
+layout (location = 0) out vec4 outFragColor;
+
+void main()
+{
+ outFragColor = texture(samplerCubeMap, inUVW);
+} \ No newline at end of file
diff --git a/tests/glsl/sascha-willems/vulkanscene/skybox.vert b/tests/glsl/sascha-willems/vulkanscene/skybox.vert
new file mode 100644
index 000000000..81c2941dc
--- /dev/null
+++ b/tests/glsl/sascha-willems/vulkanscene/skybox.vert
@@ -0,0 +1,21 @@
+//TEST:COMPARE_GLSL:
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (binding = 0) uniform UBO
+{
+ mat4 projection;
+ mat4 model;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+
+void main()
+{
+ outUVW = inPos;
+ gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);
+}