diff --git a/test/Graphics/RenderWindow.test.cpp b/test/Graphics/RenderWindow.test.cpp index 441c996c..1bf285f2 100644 --- a/test/Graphics/RenderWindow.test.cpp +++ b/test/Graphics/RenderWindow.test.cpp @@ -1,8 +1,53 @@ #include +// Other 1st party headers +#include +#include +#include +#include + +#include + +#include #include static_assert(!std::is_copy_constructible_v); static_assert(!std::is_copy_assignable_v); static_assert(!std::is_nothrow_move_constructible_v); static_assert(!std::is_nothrow_move_assignable_v); + +TEST_CASE("[Graphics] sf::RenderWindow" * doctest::skip(skipDisplayTests)) +{ + SUBCASE("Construction") + { + const sf::RenderWindow window(sf::VideoMode(sf::Vector2u(256, 256), 24), + "Window Title", + sf::Style::Default, + sf::ContextSettings()); + CHECK(window.getSize() == sf::Vector2u(256, 256)); + } + + SUBCASE("Clear") + { + sf::RenderWindow window(sf::VideoMode(sf::Vector2u(256, 256), 24), + "Window Title", + sf::Style::Default, + sf::ContextSettings()); + REQUIRE(window.getSize() == sf::Vector2u(256, 256)); + + sf::Texture texture; + REQUIRE(texture.create(window.getSize())); + + window.clear(sf::Color::Red); + texture.update(window); + CHECK(texture.copyToImage().getPixel(sf::Vector2u(64, 64)) == sf::Color::Red); + + window.clear(sf::Color::Green); + texture.update(window); + CHECK(texture.copyToImage().getPixel(sf::Vector2u(128, 128)) == sf::Color::Green); + + window.clear(sf::Color::Blue); + texture.update(window); + CHECK(texture.copyToImage().getPixel(sf::Vector2u(196, 196)) == sf::Color::Blue); + } +} diff --git a/test/Graphics/Shader.test.cpp b/test/Graphics/Shader.test.cpp index 64f101d5..72514a25 100644 --- a/test/Graphics/Shader.test.cpp +++ b/test/Graphics/Shader.test.cpp @@ -1,8 +1,156 @@ #include +#include + #include static_assert(!std::is_copy_constructible_v); static_assert(!std::is_copy_assignable_v); static_assert(std::is_nothrow_move_constructible_v); static_assert(std::is_nothrow_move_assignable_v); + +namespace +{ +constexpr auto vertexSource = R"( +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; +} +)"; + +constexpr auto geometrySource = R"( +#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() +{ + // Caculate 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(); + } +} +)"; + +constexpr auto fragmentSource = R"( +uniform sampler2D texture; +uniform float blink_alpha; + +void main() +{ + vec4 pixel = gl_Color; + pixel.a = blink_alpha; + gl_FragColor = pixel; +} +)"; + +#ifdef SFML_RUN_DISPLAY_TESTS +#ifdef SFML_OPENGL_ES +constexpr bool skipShaderDummyTest = false; +constexpr bool skipShaderFullTest = true; +#else +constexpr bool skipShaderDummyTest = true; +constexpr bool skipShaderFullTest = false; +#endif +#else +constexpr bool skipShaderDummyTest = true; +constexpr bool skipShaderFullTest = true; +#endif + +} // namespace + +TEST_CASE("[Graphics] sf::Shader (Dummy Implementation)" * doctest::skip(skipShaderDummyTest)) +{ + SUBCASE("Available") + { + CHECK_FALSE(sf::Shader::isAvailable()); + CHECK_FALSE(sf::Shader::isGeometryAvailable()); + } + + SUBCASE("Load") + { + sf::Shader shader; + CHECK_FALSE(shader.loadFromMemory(vertexSource, sf::Shader::Type::Vertex)); + CHECK_FALSE(shader.loadFromMemory(geometrySource, sf::Shader::Type::Geometry)); + CHECK_FALSE(shader.loadFromMemory(fragmentSource, sf::Shader::Type::Fragment)); + CHECK_FALSE(shader.loadFromMemory(vertexSource, fragmentSource)); + CHECK_FALSE(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource)); + } +} + +TEST_CASE("[Graphics] sf::Shader" * doctest::skip(skipShaderFullTest)) +{ + if (!sf::Shader::isAvailable()) + return; + + SUBCASE("Load") + { + sf::Shader shader; + CHECK(shader.loadFromMemory(vertexSource, sf::Shader::Type::Vertex)); + 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); + } +} diff --git a/test/Window/Window.test.cpp b/test/Window/Window.test.cpp index e778c569..13c5815e 100644 --- a/test/Window/Window.test.cpp +++ b/test/Window/Window.test.cpp @@ -1,8 +1,24 @@ #include +// Other 1st party headers +#include +#include + +#include + +#include #include static_assert(!std::is_copy_constructible_v); static_assert(!std::is_copy_assignable_v); static_assert(!std::is_nothrow_move_constructible_v); static_assert(!std::is_nothrow_move_assignable_v); + +TEST_CASE("[Window] sf::Window" * doctest::skip(skipDisplayTests)) +{ + SUBCASE("Construction") + { + sf::Window window(sf::VideoMode(sf::Vector2u(256, 256), 32), "Window Title", sf::Style::Default, sf::ContextSettings()); + CHECK(window.getSize() == sf::Vector2u(256, 256)); + } +}