Test to retrieve GLSL outputs from a fragment shader.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Testing a parser to grab the outputs of a fragment shader | |
* | |
* g++ -std=c++11 -Wall -Werror -Wextra -pedantic -pedantic-errors glsl_regex.cpp -o glsl_regex | |
*/ | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include <regex> | |
constexpr char fragShader[] = u8R"***( | |
#precision mediump float | |
varying vec3 fragVertNormal; | |
varying vec3 fragEyeDirection; | |
uniform ivec4 meshColor; | |
layout (location = 0, index = 1) out int test_1; | |
layout (depth_greater, location = 1) out vec4 test_2; | |
layout (location = 3) out vec4 test_3[5]; | |
out int test_4; | |
out float test_5[4]; | |
layout (location = 2) out bvec4 fail_1; | |
layout (location = 4) out mat3 fail_2; | |
out bool fail_3; | |
vec4 convertRgbaToVec4(in ivec4 col) { | |
return vec4(float(col.r), float(col.g), float(col.b), float(col.a)) / 255.0; | |
} | |
float getDiffuseIntensity(in vec3 vertNorm, in vec3 lightDir) { | |
float brightness = dot(vertNorm, lightDir); | |
return 0.5 + (0.5 * brightness); | |
} | |
void main() { | |
float diffuseIntensity = getDiffuseIntensity(fragVertNormal, fragEyeDirection); | |
gl_FragColor = convertRgbaToVec4(meshColor); | |
gl_FragColor.rgb *= diffuseIntensity; | |
} | |
)***"; | |
enum frag_output_attrib_t : unsigned { | |
FRAG_OUT_LAYOUT = 1, | |
FRAG_OUT_TYPE = 2, | |
FRAG_OUT_NAME = 3, | |
FRAG_OUT_COMPONENTS = 4, | |
}; | |
struct FragOutAttrib { | |
unsigned layout; | |
unsigned components; | |
std::string name; | |
std::string type; | |
}; | |
void print_fragment_attrib(const FragOutAttrib& attrib) { | |
std::cout << "FRAGMENT SHADER OUTPUT ATTRIB" | |
<< "\n\tNAME: " << attrib.name | |
<< "\n\tTYPE: " << attrib.type | |
<< "\n\tLOCATION: " << attrib.layout | |
<< "\n\tCOMPONENTS: " << attrib.components | |
<< std::endl; | |
} | |
unsigned get_frag_attrib_layout(const std::smatch& fragMatches) { | |
const std::string& layout = fragMatches[frag_output_attrib_t::FRAG_OUT_LAYOUT]; | |
return layout.empty() ? 0 : (unsigned)std::stoi(layout); | |
} | |
unsigned get_frag_attrib_components(const std::smatch& fragMatches) { | |
const std::string& components = fragMatches[frag_output_attrib_t::FRAG_OUT_COMPONENTS]; | |
return components.empty() ? 1 : (unsigned)std::stoi(components); | |
} | |
inline std::string get_frag_attrib_name(const std::smatch& fragMatches) { | |
return fragMatches[frag_output_attrib_t::FRAG_OUT_NAME]; | |
} | |
inline std::string get_frag_attrib_type(const std::smatch& fragMatches) { | |
return fragMatches[frag_output_attrib_t::FRAG_OUT_TYPE]; | |
} | |
std::vector<FragOutAttrib> get_fragment_outputs(const std::string& shaderData) { | |
static constexpr char fragOutPattern[] = | |
u8R"***((?:location\s*\=\s*(\d+).*\))?\s*out\s+(int|uint|float|[iud]?vec[2-4]?)\s+([a-zA-Z_]\w*)\s*(?:\[(\d+)\]\s*)?;)***"; | |
std::vector<FragOutAttrib> outputs; | |
std::regex fragRegex{fragOutPattern, std::regex::ECMAScript}; | |
std::sregex_iterator iter{shaderData.begin(), shaderData.end(), fragRegex, std::regex_constants::match_any}; | |
const std::sregex_iterator end; | |
for (; iter != end; ++iter) { | |
FragOutAttrib attrib; | |
attrib.layout = get_frag_attrib_layout(*iter); | |
attrib.components = get_frag_attrib_components(*iter); | |
attrib.name = get_frag_attrib_name(*iter); | |
attrib.type = get_frag_attrib_type(*iter); | |
outputs.emplace_back(std::move(attrib)); | |
} | |
return outputs; | |
} | |
int main() { | |
const std::vector<FragOutAttrib> attribs = std::move(get_fragment_outputs(fragShader)); | |
for (const FragOutAttrib& attrib : attribs) { | |
print_fragment_attrib(attrib); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sample output: