Skip to content

Instantly share code, notes, and snippets.

@hamsham
Created February 4, 2016 06:04
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save hamsham/f05bf25ddaa0bde6588e to your computer and use it in GitHub Desktop.
Test to retrieve GLSL outputs from a fragment shader.
/**
* 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;
}
@hamsham
Copy link
Author

hamsham commented Feb 4, 2016

Sample output:


FRAGMENT SHADER OUTPUT ATTRIB
        NAME:       test_1
        TYPE:       int
        LOCATION:   0
        COMPONENTS: 1
FRAGMENT SHADER OUTPUT ATTRIB
        NAME:       test_2
        TYPE:       vec4
        LOCATION:   1
        COMPONENTS: 1
FRAGMENT SHADER OUTPUT ATTRIB
        NAME:       test_3
        TYPE:       vec4
        LOCATION:   3
        COMPONENTS: 5
FRAGMENT SHADER OUTPUT ATTRIB
        NAME:       test_4
        TYPE:       int
        LOCATION:   0
        COMPONENTS: 1
FRAGMENT SHADER OUTPUT ATTRIB
        NAME:       test_5
        TYPE:       float
        LOCATION:   0
        COMPONENTS: 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment