Remove default empty state of sf::Shader

This commit is contained in:
Chris Thrasher 2024-05-18 19:53:07 -06:00
parent 504b850f03
commit 7234fc149b
5 changed files with 201 additions and 199 deletions

View File

@ -96,8 +96,7 @@ int main()
// Create all of our graphics resources
sf::Text hudText(font);
sf::Text statusText(font);
sf::Shader terrainShader;
const sf::RenderStates terrainStates(&terrainShader);
std::optional<sf::Shader> terrainShader;
sf::VertexBuffer terrain(sf::PrimitiveType::Triangles, sf::VertexBuffer::Usage::Static);
// Set up our text drawables
@ -115,18 +114,13 @@ int main()
// Staging buffer for our terrain data that we will upload to our VertexBuffer
std::vector<sf::Vertex> terrainStagingBuffer;
// Check whether the prerequisites are supported
bool prerequisitesSupported = sf::VertexBuffer::isAvailable() && sf::Shader::isAvailable();
// Set up our graphics resources and set the status text accordingly
if (!prerequisitesSupported)
if (!sf::VertexBuffer::isAvailable() || !sf::Shader::isAvailable())
{
statusText.setString("Shaders and/or Vertex Buffers Unsupported");
}
else if (!terrainShader.loadFromFile("resources/terrain.vert", "resources/terrain.frag"))
else if (!(terrainShader = sf::Shader::loadFromFile("resources/terrain.vert", "resources/terrain.frag")))
{
prerequisitesSupported = false;
statusText.setString("Failed to load shader program");
}
else
@ -188,7 +182,7 @@ int main()
}
// Arrow key pressed:
if (prerequisitesSupported && event.is<sf::Event::KeyPressed>())
if (terrainShader.has_value() && event.is<sf::Event::KeyPressed>())
{
switch (event.getIf<sf::Event::KeyPressed>()->code)
{
@ -218,7 +212,7 @@ int main()
window.draw(statusText);
if (prerequisitesSupported)
if (terrainShader.has_value())
{
{
const std::lock_guard lock(workQueueMutex);
@ -238,8 +232,8 @@ int main()
bufferUploadPending = false;
}
terrainShader.setUniform("lightFactor", lightFactor);
window.draw(terrain, terrainStates);
terrainShader->setUniform("lightFactor", lightFactor);
window.draw(terrain, sf::RenderStates(&*terrainShader));
}
}

View File

@ -38,9 +38,6 @@ public:
return false;
m_sprite.emplace(m_texture);
// Load the shader
if (!m_shader.loadFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment))
return false;
m_shader.setUniform("texture", sf::Shader::CurrentTexture);
return true;
@ -60,7 +57,7 @@ public:
private:
sf::Texture m_texture;
std::optional<sf::Sprite> m_sprite;
sf::Shader m_shader;
sf::Shader m_shader{sf::Shader::loadFromFile("resources/pixelate.frag", sf::Shader::Type::Fragment).value()};
};
@ -99,8 +96,7 @@ public:
m_text.setCharacterSize(22);
m_text.setPosition({30.f, 20.f});
// Load the shader
return m_shader.loadFromFile("resources/wave.vert", "resources/blur.frag");
return true;
}
void onUpdate(float time, float x, float y) override
@ -118,7 +114,7 @@ public:
private:
sf::Text m_text;
sf::Shader m_shader;
sf::Shader m_shader{sf::Shader::loadFromFile("resources/wave.vert", "resources/blur.frag").value()};
};
@ -150,8 +146,7 @@ public:
m_points.append({{x, y}, {r, g, b}});
}
// Load the shader
return m_shader.loadFromFile("resources/storm.vert", "resources/blink.frag");
return true;
}
void onUpdate(float time, float x, float y) override
@ -171,7 +166,7 @@ public:
private:
sf::VertexArray m_points;
sf::Shader m_shader;
sf::Shader m_shader{sf::Shader::loadFromFile("resources/storm.vert", "resources/blink.frag").value()};
};
@ -211,9 +206,7 @@ public:
m_entities.push_back(entity);
}
// Load the shader
if (!m_shader.loadFromFile("resources/edge.frag", sf::Shader::Type::Fragment))
return false;
// Set the shader uniform
m_shader.setUniform("texture", sf::Shader::CurrentTexture);
return true;
@ -254,7 +247,7 @@ private:
sf::Texture m_entityTexture;
std::optional<sf::Sprite> m_backgroundSprite;
std::vector<sf::Sprite> m_entities;
sf::Shader m_shader;
sf::Shader m_shader{sf::Shader::loadFromFile("resources/edge.frag", sf::Shader::Type::Fragment).value()};
};
@ -287,9 +280,6 @@ public:
if (!m_logoTexture.loadFromFile("resources/logo.png"))
return false;
// Load the shader
if (!m_shader.loadFromFile("resources/billboard.vert", "resources/billboard.geom", "resources/billboard.frag"))
return false;
m_shader.setUniform("texture", sf::Shader::CurrentTexture);
// Set the render resolution (used for proper scaling)
@ -328,7 +318,8 @@ public:
private:
sf::Texture m_logoTexture;
sf::Transform m_transform;
sf::Shader m_shader;
sf::Shader m_shader{
sf::Shader::loadFromFile("resources/billboard.vert", "resources/billboard.geom", "resources/billboard.frag").value()};
sf::VertexArray m_pointCloud;
};

View File

@ -34,6 +34,7 @@
#include <SFML/Window/GlResource.hpp>
#include <filesystem>
#include <optional>
#include <string>
#include <unordered_map>
@ -83,14 +84,6 @@ public:
// NOLINTNEXTLINE(readability-identifier-naming)
static inline CurrentTextureType CurrentTexture;
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates an invalid shader.
///
////////////////////////////////////////////////////////////
Shader() = default;
////////////////////////////////////////////////////////////
/// \brief Destructor
///
@ -136,12 +129,12 @@ public:
/// \param filename Path of the vertex, geometry or fragment shader file to load
/// \param type Type of shader (vertex, geometry or fragment)
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromMemory, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename, Type type);
[[nodiscard]] static std::optional<Shader> loadFromFile(const std::filesystem::path& filename, Type type);
////////////////////////////////////////////////////////////
/// \brief Load both the vertex and fragment shaders from files
@ -157,12 +150,12 @@ public:
/// \param vertexShaderFilename Path of the vertex shader file to load
/// \param fragmentShaderFilename Path of the fragment shader file to load
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromMemory, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(const std::filesystem::path& vertexShaderFilename,
[[nodiscard]] static std::optional<Shader> loadFromFile(const std::filesystem::path& vertexShaderFilename,
const std::filesystem::path& fragmentShaderFilename);
////////////////////////////////////////////////////////////
@ -180,12 +173,12 @@ public:
/// \param geometryShaderFilename Path of the geometry shader file to load
/// \param fragmentShaderFilename Path of the fragment shader file to load
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromMemory, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(const std::filesystem::path& vertexShaderFilename,
[[nodiscard]] static std::optional<Shader> loadFromFile(const std::filesystem::path& vertexShaderFilename,
const std::filesystem::path& geometryShaderFilename,
const std::filesystem::path& fragmentShaderFilename);
@ -202,12 +195,12 @@ public:
/// \param shader String containing the source code of the shader
/// \param type Type of shader (vertex, geometry or fragment)
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(const std::string& shader, Type type);
[[nodiscard]] static std::optional<Shader> loadFromMemory(const std::string& shader, Type type);
////////////////////////////////////////////////////////////
/// \brief Load both the vertex and fragment shaders from source codes in memory
@ -223,12 +216,13 @@ public:
/// \param vertexShader String containing the source code of the vertex shader
/// \param fragmentShader String containing the source code of the fragment shader
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader);
[[nodiscard]] static std::optional<Shader> loadFromMemory(const std::string& vertexShader,
const std::string& fragmentShader);
////////////////////////////////////////////////////////////
/// \brief Load the vertex, geometry and fragment shaders from source codes in memory
@ -245,12 +239,12 @@ public:
/// \param geometryShader String containing the source code of the geometry shader
/// \param fragmentShader String containing the source code of the fragment shader
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(const std::string& vertexShader,
[[nodiscard]] static std::optional<Shader> loadFromMemory(const std::string& vertexShader,
const std::string& geometryShader,
const std::string& fragmentShader);
@ -267,12 +261,12 @@ public:
/// \param stream Source stream to read from
/// \param type Type of shader (vertex, geometry or fragment)
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromMemory
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& stream, Type type);
[[nodiscard]] static std::optional<Shader> loadFromStream(InputStream& stream, Type type);
////////////////////////////////////////////////////////////
/// \brief Load both the vertex and fragment shaders from custom streams
@ -288,12 +282,13 @@ public:
/// \param vertexShaderStream Source stream to read the vertex shader from
/// \param fragmentShaderStream Source stream to read the fragment shader from
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromMemory
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream);
[[nodiscard]] static std::optional<Shader> loadFromStream(InputStream& vertexShaderStream,
InputStream& fragmentShaderStream);
////////////////////////////////////////////////////////////
/// \brief Load the vertex, geometry and fragment shaders from custom streams
@ -310,12 +305,12 @@ public:
/// \param geometryShaderStream Source stream to read the geometry shader from
/// \param fragmentShaderStream Source stream to read the fragment shader from
///
/// \return True if loading succeeded, false if it failed
/// \return Shader if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromMemory
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& vertexShaderStream,
[[nodiscard]] static std::optional<Shader> loadFromStream(InputStream& vertexShaderStream,
InputStream& geometryShaderStream,
InputStream& fragmentShaderStream);
@ -650,6 +645,12 @@ public:
static bool isGeometryAvailable();
private:
////////////////////////////////////////////////////////////
/// \brief Construct from shader program
///
////////////////////////////////////////////////////////////
explicit Shader(unsigned int shaderProgram);
////////////////////////////////////////////////////////////
/// \brief Compile the shader(s) and create the program
///
@ -660,10 +661,12 @@ private:
/// \param geometryShaderCode Source code of the geometry shader
/// \param fragmentShaderCode Source code of the fragment shader
///
/// \return True on success, false if any error happened
/// \return Shader on success, `std::nullopt` if any error happened
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode);
[[nodiscard]] static std::optional<Shader> compile(const char* vertexShaderCode,
const char* geometryShaderCode,
const char* fragmentShaderCode);
////////////////////////////////////////////////////////////
/// \brief Bind all the textures used by the shader

View File

@ -269,14 +269,14 @@ Shader& Shader::operator=(Shader&& right) noexcept
}
////////////////////////////////////////////////////////////
bool Shader::loadFromFile(const std::filesystem::path& filename, Type type)
std::optional<Shader> Shader::loadFromFile(const std::filesystem::path& filename, Type type)
{
// Read the file
std::vector<char> shader;
if (!getFileContents(filename, shader))
{
err() << "Failed to open shader file\n" << formatDebugPathInfo(filename) << std::endl;
return false;
return std::nullopt;
}
// Compile the shader program
@ -290,7 +290,7 @@ bool Shader::loadFromFile(const std::filesystem::path& filename, Type type)
////////////////////////////////////////////////////////////
bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
std::optional<Shader> Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
const std::filesystem::path& fragmentShaderFilename)
{
// Read the vertex shader file
@ -298,7 +298,7 @@ bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
if (!getFileContents(vertexShaderFilename, vertexShader))
{
err() << "Failed to open vertex shader file\n" << formatDebugPathInfo(vertexShaderFilename) << std::endl;
return false;
return std::nullopt;
}
// Read the fragment shader file
@ -306,7 +306,7 @@ bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
if (!getFileContents(fragmentShaderFilename, fragmentShader))
{
err() << "Failed to open fragment shader file\n" << formatDebugPathInfo(fragmentShaderFilename) << std::endl;
return false;
return std::nullopt;
}
// Compile the shader program
@ -315,7 +315,7 @@ bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
////////////////////////////////////////////////////////////
bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
std::optional<Shader> Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
const std::filesystem::path& geometryShaderFilename,
const std::filesystem::path& fragmentShaderFilename)
{
@ -324,7 +324,7 @@ bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
if (!getFileContents(vertexShaderFilename, vertexShader))
{
err() << "Failed to open vertex shader file\n" << formatDebugPathInfo(vertexShaderFilename) << std::endl;
return false;
return std::nullopt;
}
// Read the geometry shader file
@ -332,7 +332,7 @@ bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
if (!getFileContents(geometryShaderFilename, geometryShader))
{
err() << "Failed to open geometry shader file\n" << formatDebugPathInfo(geometryShaderFilename) << std::endl;
return false;
return std::nullopt;
}
// Read the fragment shader file
@ -340,7 +340,7 @@ bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
if (!getFileContents(fragmentShaderFilename, fragmentShader))
{
err() << "Failed to open fragment shader file\n" << formatDebugPathInfo(fragmentShaderFilename) << std::endl;
return false;
return std::nullopt;
}
// Compile the shader program
@ -349,7 +349,7 @@ bool Shader::loadFromFile(const std::filesystem::path& vertexShaderFilename,
////////////////////////////////////////////////////////////
bool Shader::loadFromMemory(const std::string& shader, Type type)
std::optional<Shader> Shader::loadFromMemory(const std::string& shader, Type type)
{
// Compile the shader program
if (type == Type::Vertex)
@ -362,7 +362,7 @@ bool Shader::loadFromMemory(const std::string& shader, Type type)
////////////////////////////////////////////////////////////
bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader)
std::optional<Shader> Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader)
{
// Compile the shader program
return compile(vertexShader.c_str(), nullptr, fragmentShader.c_str());
@ -370,7 +370,9 @@ bool Shader::loadFromMemory(const std::string& vertexShader, const std::string&
////////////////////////////////////////////////////////////
bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& geometryShader, const std::string& fragmentShader)
std::optional<Shader> Shader::loadFromMemory(const std::string& vertexShader,
const std::string& geometryShader,
const std::string& fragmentShader)
{
// Compile the shader program
return compile(vertexShader.c_str(), geometryShader.c_str(), fragmentShader.c_str());
@ -378,14 +380,14 @@ bool Shader::loadFromMemory(const std::string& vertexShader, const std::string&
////////////////////////////////////////////////////////////
bool Shader::loadFromStream(InputStream& stream, Type type)
std::optional<Shader> Shader::loadFromStream(InputStream& stream, Type type)
{
// Read the shader code from the stream
std::vector<char> shader;
if (!getStreamContents(stream, shader))
{
err() << "Failed to read shader from stream" << std::endl;
return false;
return std::nullopt;
}
// Compile the shader program
@ -399,14 +401,14 @@ bool Shader::loadFromStream(InputStream& stream, Type type)
////////////////////////////////////////////////////////////
bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream)
std::optional<Shader> Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream)
{
// Read the vertex shader code from the stream
std::vector<char> vertexShader;
if (!getStreamContents(vertexShaderStream, vertexShader))
{
err() << "Failed to read vertex shader from stream" << std::endl;
return false;
return std::nullopt;
}
// Read the fragment shader code from the stream
@ -414,7 +416,7 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragme
if (!getStreamContents(fragmentShaderStream, fragmentShader))
{
err() << "Failed to read fragment shader from stream" << std::endl;
return false;
return std::nullopt;
}
// Compile the shader program
@ -423,14 +425,16 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragme
////////////////////////////////////////////////////////////
bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream)
std::optional<Shader> Shader::loadFromStream(InputStream& vertexShaderStream,
InputStream& geometryShaderStream,
InputStream& fragmentShaderStream)
{
// Read the vertex shader code from the stream
std::vector<char> vertexShader;
if (!getStreamContents(vertexShaderStream, vertexShader))
{
err() << "Failed to read vertex shader from stream" << std::endl;
return false;
return std::nullopt;
}
// Read the geometry shader code from the stream
@ -438,7 +442,7 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geomet
if (!getStreamContents(geometryShaderStream, geometryShader))
{
err() << "Failed to read geometry shader from stream" << std::endl;
return false;
return std::nullopt;
}
// Read the fragment shader code from the stream
@ -446,7 +450,7 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geomet
if (!getStreamContents(fragmentShaderStream, fragmentShader))
{
err() << "Failed to read fragment shader from stream" << std::endl;
return false;
return std::nullopt;
}
// Compile the shader program
@ -768,7 +772,13 @@ bool Shader::isGeometryAvailable()
////////////////////////////////////////////////////////////
bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
Shader::Shader(unsigned int shaderProgram) : m_shaderProgram(shaderProgram)
{
}
////////////////////////////////////////////////////////////
std::optional<Shader> Shader::compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
{
const TransientContextLock lock;
@ -777,7 +787,7 @@ bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCod
{
err() << "Failed to create a shader: your system doesn't support shaders "
<< "(you should test Shader::isAvailable() before trying to use the Shader class)" << std::endl;
return false;
return std::nullopt;
}
// Make sure we can use geometry shaders
@ -785,21 +795,9 @@ bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCod
{
err() << "Failed to create a shader: your system doesn't support geometry shaders "
<< "(you should test Shader::isGeometryAvailable() before trying to use geometry shaders)" << std::endl;
return false;
return std::nullopt;
}
// Destroy the shader if it was already created
if (m_shaderProgram)
{
glCheck(GLEXT_glDeleteObject(castToGlHandle(m_shaderProgram)));
m_shaderProgram = 0;
}
// Reset the internal state
m_currentTexture = -1;
m_textures.clear();
m_uniforms.clear();
// Create the program
GLEXT_GLhandle shaderProgram{};
glCheck(shaderProgram = GLEXT_glCreateProgramObject());
@ -823,7 +821,7 @@ bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCod
err() << "Failed to compile vertex shader:" << '\n' << log << std::endl;
glCheck(GLEXT_glDeleteObject(vertexShader));
glCheck(GLEXT_glDeleteObject(shaderProgram));
return false;
return std::nullopt;
}
// Attach the shader to the program, and delete it (not needed anymore)
@ -849,7 +847,7 @@ bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCod
err() << "Failed to compile geometry shader:" << '\n' << log << std::endl;
glCheck(GLEXT_glDeleteObject(geometryShader));
glCheck(GLEXT_glDeleteObject(shaderProgram));
return false;
return std::nullopt;
}
// Attach the shader to the program, and delete it (not needed anymore)
@ -876,7 +874,7 @@ bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCod
err() << "Failed to compile fragment shader:" << '\n' << log << std::endl;
glCheck(GLEXT_glDeleteObject(fragmentShader));
glCheck(GLEXT_glDeleteObject(shaderProgram));
return false;
return std::nullopt;
}
// Attach the shader to the program, and delete it (not needed anymore)
@ -896,16 +894,14 @@ bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCod
glCheck(GLEXT_glGetInfoLog(shaderProgram, sizeof(log), nullptr, log));
err() << "Failed to link shader:" << '\n' << log << std::endl;
glCheck(GLEXT_glDeleteObject(shaderProgram));
return false;
return std::nullopt;
}
m_shaderProgram = castFromGlHandle(shaderProgram);
// Force an OpenGL flush, so that the shader will appear updated
// in all contexts immediately (solves problems in multi-threaded apps)
glCheck(glFlush());
return true;
return Shader(castFromGlHandle(shaderProgram));
}
@ -970,72 +966,72 @@ Shader& Shader::operator=(Shader&& right) noexcept = default;
////////////////////////////////////////////////////////////
bool Shader::loadFromFile(const std::filesystem::path& /* filename */, Type /* type */)
std::optional<Shader> Shader::loadFromFile(const std::filesystem::path& /* filename */, Type /* type */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */,
std::optional<Shader> Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */,
const std::filesystem::path& /* fragmentShaderFilename */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */,
std::optional<Shader> Shader::loadFromFile(const std::filesystem::path& /* vertexShaderFilename */,
const std::filesystem::path& /* geometryShaderFilename */,
const std::filesystem::path& /* fragmentShaderFilename */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromMemory(const std::string& /* shader */, Type /* type */)
std::optional<Shader> Shader::loadFromMemory(const std::string& /* shader */, Type /* type */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromMemory(const std::string& /* vertexShader */, const std::string& /* fragmentShader */)
std::optional<Shader> Shader::loadFromMemory(const std::string& /* vertexShader */, const std::string& /* fragmentShader */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromMemory(const std::string& /* vertexShader */,
std::optional<Shader> Shader::loadFromMemory(const std::string& /* vertexShader */,
const std::string& /* geometryShader */,
const std::string& /* fragmentShader */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromStream(InputStream& /* stream */, Type /* type */)
std::optional<Shader> Shader::loadFromStream(InputStream& /* stream */, Type /* type */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromStream(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */)
std::optional<Shader> Shader::loadFromStream(InputStream& /* vertexShaderStream */, InputStream& /* fragmentShaderStream */)
{
return false;
return std::nullopt;
}
////////////////////////////////////////////////////////////
bool Shader::loadFromStream(InputStream& /* vertexShaderStream */,
std::optional<Shader> Shader::loadFromStream(InputStream& /* vertexShaderStream */,
InputStream& /* geometryShaderStream */,
InputStream& /* fragmentShaderStream */)
{
return false;
return std::nullopt;
}
@ -1199,9 +1195,17 @@ bool Shader::isGeometryAvailable()
////////////////////////////////////////////////////////////
bool Shader::compile(const char* /* vertexShaderCode */, const char* /* geometryShaderCode */, const char* /* fragmentShaderCode */)
Shader::Shader(unsigned int shaderProgram) : m_shaderProgram(shaderProgram)
{
return false;
}
////////////////////////////////////////////////////////////
std::optional<Shader> Shader::compile(const char* /* vertexShaderCode */,
const char* /* geometryShaderCode */,
const char* /* fragmentShaderCode */)
{
return std::nullopt;
}

View File

@ -147,12 +147,11 @@ TEST_CASE("[Graphics] sf::Shader (Dummy Implementation)", skipShaderDummyTests()
SECTION("loadFromMemory()")
{
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));
CHECK_FALSE(sf::Shader::loadFromMemory(vertexSource, sf::Shader::Type::Vertex).has_value());
CHECK_FALSE(sf::Shader::loadFromMemory(geometrySource, sf::Shader::Type::Geometry).has_value());
CHECK_FALSE(sf::Shader::loadFromMemory(fragmentSource, sf::Shader::Type::Fragment).has_value());
CHECK_FALSE(sf::Shader::loadFromMemory(vertexSource, fragmentSource).has_value());
CHECK_FALSE(sf::Shader::loadFromMemory(vertexSource, geometrySource, fragmentSource).has_value());
}
}
@ -160,84 +159,90 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
{
SECTION("Type traits")
{
STATIC_CHECK(!std::is_default_constructible_v<sf::Shader>);
STATIC_CHECK(!std::is_copy_constructible_v<sf::Shader>);
STATIC_CHECK(!std::is_copy_assignable_v<sf::Shader>);
STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::Shader>);
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Shader>);
}
SECTION("Construction")
{
const sf::Shader shader;
CHECK(shader.getNativeHandle() == 0);
}
SECTION("Move semantics")
{
SECTION("Construction")
{
sf::Shader movedShader;
sf::Shader movedShader = sf::Shader::loadFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex).value();
const sf::Shader shader = std::move(movedShader);
CHECK(shader.getNativeHandle() == 0);
CHECK(shader.getNativeHandle() != 0);
}
SECTION("Assignment")
{
sf::Shader movedShader;
sf::Shader shader;
sf::Shader movedShader = sf::Shader::loadFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex).value();
sf::Shader shader = sf::Shader::loadFromFile("Graphics/shader.frag", sf::Shader::Type::Fragment).value();
shader = std::move(movedShader);
CHECK(shader.getNativeHandle() == 0);
CHECK(shader.getNativeHandle() != 0);
}
}
SECTION("loadFromFile()")
{
sf::Shader shader;
SECTION("One shader")
{
CHECK(!shader.loadFromFile("does-not-exist.vert", sf::Shader::Type::Vertex));
CHECK(!sf::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<bool>(shader.getNativeHandle()) == sf::Shader::isAvailable());
const auto vertexShader = sf::Shader::loadFromFile("Graphics/shader.vert", sf::Shader::Type::Vertex);
CHECK(vertexShader.has_value() == sf::Shader::isAvailable());
if (vertexShader)
CHECK(static_cast<bool>(vertexShader->getNativeHandle()) == sf::Shader::isAvailable());
CHECK(shader.loadFromFile("Graphics/shader.frag", sf::Shader::Type::Fragment) == sf::Shader::isAvailable());
CHECK(static_cast<bool>(shader.getNativeHandle()) == sf::Shader::isAvailable());
const auto fragmentShader = sf::Shader::loadFromFile("Graphics/shader.frag", sf::Shader::Type::Fragment);
CHECK(fragmentShader.has_value() == sf::Shader::isAvailable());
if (fragmentShader)
CHECK(static_cast<bool>(fragmentShader->getNativeHandle()) == sf::Shader::isAvailable());
}
SECTION("Two shaders")
{
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<bool>(shader.getNativeHandle()) == sf::Shader::isAvailable());
CHECK(!sf::Shader::loadFromFile("does-not-exist.vert", "Graphics/shader.frag"));
CHECK(!sf::Shader::loadFromFile("Graphics/shader.vert", "does-not-exist.frag"));
const auto shader = sf::Shader::loadFromFile("Graphics/shader.vert", "Graphics/shader.frag");
CHECK(shader.has_value() == sf::Shader::isAvailable());
if (shader)
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isAvailable());
}
SECTION("Three shaders")
{
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<bool>(shader.getNativeHandle()) == sf::Shader::isGeometryAvailable());
CHECK(!sf::Shader::loadFromFile("does-not-exist.vert", "Graphics/shader.geom", "Graphics/shader.frag"));
CHECK(!sf::Shader::loadFromFile("Graphics/shader.vert", "does-not-exist.geom", "Graphics/shader.frag"));
CHECK(!sf::Shader::loadFromFile("Graphics/shader.vert", "Graphics/shader.geom", "does-not-exist.frag"));
const auto shader = sf::Shader::loadFromFile("Graphics/shader.vert",
"Graphics/shader.geom",
"Graphics/shader.frag");
CHECK(shader.has_value() == sf::Shader::isGeometryAvailable());
if (shader)
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isGeometryAvailable());
}
}
SECTION("loadFromMemory()")
{
sf::Shader shader;
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) == sf::Shader::isAvailable());
CHECK(shader.loadFromMemory(vertexSource, fragmentSource) == sf::Shader::isAvailable());
CHECK(shader.loadFromMemory(vertexSource, geometrySource, fragmentSource) == sf::Shader::isGeometryAvailable());
CHECK(static_cast<bool>(shader.getNativeHandle()) == sf::Shader::isAvailable());
CHECK(sf::Shader::loadFromMemory(vertexSource, sf::Shader::Type::Vertex).has_value() == sf::Shader::isAvailable());
CHECK(!sf::Shader::loadFromMemory(geometrySource, sf::Shader::Type::Geometry));
CHECK(sf::Shader::loadFromMemory(fragmentSource, sf::Shader::Type::Fragment).has_value() ==
sf::Shader::isAvailable());
CHECK(sf::Shader::loadFromMemory(vertexSource, fragmentSource).has_value() == sf::Shader::isAvailable());
const auto shader = sf::Shader::loadFromMemory(vertexSource, geometrySource, fragmentSource);
CHECK(shader.has_value() == sf::Shader::isGeometryAvailable());
if (shader)
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isAvailable());
}
SECTION("loadFromStream()")
{
sf::Shader shader;
sf::FileInputStream vertexShaderStream;
REQUIRE(vertexShaderStream.open("Graphics/shader.vert"));
@ -251,26 +256,31 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
SECTION("One shader")
{
REQUIRE(!shader.loadFromStream(emptyStream, sf::Shader::Type::Vertex));
REQUIRE(shader.loadFromStream(vertexShaderStream, sf::Shader::Type::Vertex) == sf::Shader::isAvailable());
REQUIRE(shader.loadFromStream(fragmentShaderStream, sf::Shader::Type::Fragment) == sf::Shader::isAvailable());
CHECK(!sf::Shader::loadFromStream(emptyStream, sf::Shader::Type::Vertex));
CHECK(sf::Shader::loadFromStream(vertexShaderStream, sf::Shader::Type::Vertex).has_value() ==
sf::Shader::isAvailable());
CHECK(sf::Shader::loadFromStream(fragmentShaderStream, sf::Shader::Type::Fragment).has_value() ==
sf::Shader::isAvailable());
}
SECTION("Two shaders")
{
REQUIRE(!shader.loadFromStream(emptyStream, fragmentShaderStream));
REQUIRE(!shader.loadFromStream(vertexShaderStream, emptyStream));
REQUIRE(shader.loadFromStream(vertexShaderStream, fragmentShaderStream) == sf::Shader::isAvailable());
CHECK(!sf::Shader::loadFromStream(emptyStream, fragmentShaderStream));
CHECK(!sf::Shader::loadFromStream(vertexShaderStream, emptyStream));
CHECK(sf::Shader::loadFromStream(vertexShaderStream, fragmentShaderStream).has_value() ==
sf::Shader::isAvailable());
}
SECTION("Three shaders")
{
REQUIRE(!shader.loadFromStream(emptyStream, geometryShaderStream, fragmentShaderStream));
REQUIRE(!shader.loadFromStream(vertexShaderStream, emptyStream, fragmentShaderStream));
REQUIRE(!shader.loadFromStream(vertexShaderStream, geometryShaderStream, emptyStream));
REQUIRE(shader.loadFromStream(vertexShaderStream, geometryShaderStream, fragmentShaderStream) ==
sf::Shader::isGeometryAvailable());
CHECK(static_cast<bool>(shader.getNativeHandle()) == sf::Shader::isGeometryAvailable());
CHECK(!sf::Shader::loadFromStream(emptyStream, geometryShaderStream, fragmentShaderStream));
CHECK(!sf::Shader::loadFromStream(vertexShaderStream, emptyStream, fragmentShaderStream));
CHECK(!sf::Shader::loadFromStream(vertexShaderStream, geometryShaderStream, emptyStream));
const auto shader = sf::Shader::loadFromStream(vertexShaderStream, geometryShaderStream, fragmentShaderStream);
CHECK(shader.has_value() == sf::Shader::isGeometryAvailable());
if (shader)
CHECK(static_cast<bool>(shader->getNativeHandle()) == sf::Shader::isGeometryAvailable());
}
}
}