From 751aceadf808a760d44a78667c4181470c1b970b Mon Sep 17 00:00:00 2001 From: Chris Thrasher Date: Fri, 4 Aug 2023 19:42:59 -0600 Subject: [PATCH] Add tests for `sf::Shader::loadFromFile` Plus a few cleanups while I was in there --- test/Graphics/Shader.test.cpp | 56 +++++++++++++++++++++++++++++------ test/Graphics/shader.frag | 9 ++++++ test/Graphics/shader.geom | 56 +++++++++++++++++++++++++++++++++++ test/Graphics/shader.vert | 19 ++++++++++++ 4 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 test/Graphics/shader.frag create mode 100644 test/Graphics/shader.geom create mode 100644 test/Graphics/shader.vert diff --git a/test/Graphics/Shader.test.cpp b/test/Graphics/Shader.test.cpp index 2efc2b55e..f6f70d9d4 100644 --- a/test/Graphics/Shader.test.cpp +++ b/test/Graphics/Shader.test.cpp @@ -142,7 +142,7 @@ TEST_CASE("[Graphics] sf::Shader (Dummy Implementation)", skipShaderDummyTests() CHECK_FALSE(sf::Shader::isGeometryAvailable()); } - SECTION("Load") + SECTION("loadFromMemory()") { sf::Shader shader; CHECK_FALSE(shader.loadFromMemory(vertexSource, sf::Shader::Type::Vertex)); @@ -163,17 +163,55 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests()) STATIC_CHECK(std::is_nothrow_move_assignable_v); } - if (!sf::Shader::isAvailable()) - return; + SECTION("Construction") + { + const sf::Shader shader; + CHECK(shader.getNativeHandle() == 0); + } - SECTION("Load") + SECTION("loadFromFile()") + { + SECTION("One shader") + { + sf::Shader shader; + CHECK(!shader.loadFromFile("does-not-exist.vert", sf::Shader::Type::Vertex)); + + CHECK(shader.loadFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex) == sf::Shader::isAvailable()); + CHECK(static_cast(shader.getNativeHandle()) == sf::Shader::isAvailable()); + + CHECK(shader.loadFromFile("Graphics/shader.frag", sf::Shader::Type::Fragment) == sf::Shader::isAvailable()); + CHECK(static_cast(shader.getNativeHandle()) == sf::Shader::isAvailable()); + } + + SECTION("Two shaders") + { + sf::Shader shader; + CHECK(!shader.loadFromFile("does-not-exist.vert", "Graphics/shader.frag")); + CHECK(!shader.loadFromFile("Graphics/shader.vert", "does-not-exist.frag")); + CHECK(shader.loadFromFile("Graphics/shader.vert", "Graphics/shader.frag") == sf::Shader::isAvailable()); + CHECK(static_cast(shader.getNativeHandle()) == sf::Shader::isAvailable()); + } + + SECTION("Three shaders") + { + sf::Shader shader; + CHECK(!shader.loadFromFile("does-not-exist.vert", "Graphics/shader.geom", "Graphics/shader.frag")); + CHECK(!shader.loadFromFile("Graphics/shader.vert", "does-not-exist.geom", "Graphics/shader.frag")); + CHECK(!shader.loadFromFile("Graphics/shader.vert", "Graphics/shader.geom", "does-not-exist.frag")); + CHECK(shader.loadFromFile("Graphics/shader.vert", "Graphics/shader.geom", "Graphics/shader.frag") == + sf::Shader::isGeometryAvailable()); + CHECK(static_cast(shader.getNativeHandle()) == sf::Shader::isGeometryAvailable()); + } + } + + SECTION("loadFromMemory()") { sf::Shader shader; - CHECK(shader.loadFromMemory(vertexSource, sf::Shader::Type::Vertex)); + CHECK(shader.loadFromMemory(vertexSource, sf::Shader::Type::Vertex) == sf::Shader::isAvailable()); CHECK_FALSE(shader.loadFromMemory(geometrySource, sf::Shader::Type::Geometry)); - CHECK(shader.loadFromMemory(fragmentSource, sf::Shader::Type::Fragment)); - CHECK(shader.loadFromMemory(vertexSource, fragmentSource)); - CHECK(sf::Shader::isGeometryAvailable() == shader.loadFromMemory(vertexSource, geometrySource, fragmentSource)); - CHECK(shader.getNativeHandle() != 0); + CHECK(shader.loadFromMemory(fragmentSource, sf::Shader::Type::Fragment) == sf::Shader::isAvailable()); + CHECK(shader.loadFromMemory(vertexSource, fragmentSource) == sf::Shader::isAvailable()); + CHECK(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource) == sf::Shader::isGeometryAvailable()); + CHECK(static_cast(shader.getNativeHandle()) == sf::Shader::isAvailable()); } } diff --git a/test/Graphics/shader.frag b/test/Graphics/shader.frag new file mode 100644 index 000000000..50a04a510 --- /dev/null +++ b/test/Graphics/shader.frag @@ -0,0 +1,9 @@ +uniform sampler2D texture; +uniform float blink_alpha; + +void main() +{ + vec4 pixel = gl_Color; + pixel.a = blink_alpha; + gl_FragColor = pixel; +} diff --git a/test/Graphics/shader.geom b/test/Graphics/shader.geom new file mode 100644 index 000000000..dc3037afd --- /dev/null +++ b/test/Graphics/shader.geom @@ -0,0 +1,56 @@ +#version 150 + +// The render target's resolution (used for scaling) +uniform vec2 resolution; + +// The billboards' size +uniform vec2 size; + +// Input is the passed point cloud +layout (points) in; + +// The output will consist of triangle strips with four vertices each +layout (triangle_strip, max_vertices = 4) out; + +// Output texture coordinates +out vec2 tex_coord; + +// Main entry point +void main() +{ + // Calculate the half width/height of the billboards + vec2 half_size = size / 2.f; + + // Scale the size based on resolution (1 would be full width/height) + half_size /= resolution; + + // Iterate over all vertices + for (int i = 0; i < gl_in.length(); ++i) + { + // Retrieve the passed vertex position + vec2 pos = gl_in[i].gl_Position.xy; + + // Bottom left vertex + gl_Position = vec4(pos - half_size, 0.f, 1.f); + tex_coord = vec2(1.f, 1.f); + EmitVertex(); + + // Bottom right vertex + gl_Position = vec4(pos.x + half_size.x, pos.y - half_size.y, 0.f, 1.f); + tex_coord = vec2(0.f, 1.f); + EmitVertex(); + + // Top left vertex + gl_Position = vec4(pos.x - half_size.x, pos.y + half_size.y, 0.f, 1.f); + tex_coord = vec2(1.f, 0.f); + EmitVertex(); + + // Top right vertex + gl_Position = vec4(pos + half_size, 0.f, 1.f); + tex_coord = vec2(0.f, 0.f); + EmitVertex(); + + // And finalize the primitive + EndPrimitive(); + } +} diff --git a/test/Graphics/shader.vert b/test/Graphics/shader.vert new file mode 100644 index 000000000..fab9da41b --- /dev/null +++ b/test/Graphics/shader.vert @@ -0,0 +1,19 @@ +uniform vec2 storm_position; +uniform float storm_total_radius; +uniform float storm_inner_radius; + +void main() +{ + vec4 vertex = gl_ModelViewMatrix * gl_Vertex; + vec2 offset = vertex.xy - storm_position; + float len = length(offset); + if (len < storm_total_radius) + { + float push_distance = storm_inner_radius + len / storm_total_radius * (storm_total_radius - storm_inner_radius); + vertex.xy = storm_position + normalize(offset) * push_distance; + } + + gl_Position = gl_ProjectionMatrix * vertex; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +}