mirror of
https://github.com/SFML/SFML.git
synced 2024-11-24 20:31:05 +08:00
Remove default empty state of sf::Shader
This commit is contained in:
parent
504b850f03
commit
7234fc149b
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user