Skip to content

Instantly share code, notes, and snippets.

@wwylele
Created April 24, 2018 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wwylele/b3c5a0f0bf881f7078d161b517e29d9f to your computer and use it in GitHub Desktop.
Save wwylele/b3c5a0f0bf881f7078d161b517e29d9f to your computer and use it in GitHub Desktop.
sample shader
////////////////////////////////////////////////////////////////
/// Programmable Vertex Shader
#version 330 core
#extension GL_ARB_separate_shader_objects : enable // only presents for separable shader
struct pica_uniforms {
bool b[16];
uvec4 i[4];
vec4 f[96];
};
bool exec_shader();
#define uniforms vs_uniforms
layout (std140) uniform vs_config {
pica_uniforms uniforms;
}
// unused registers wouldn't be declared here
layout(location = 0) in vec4 vs_in_reg0;
layout(location = 1) in vec4 vs_in_reg1;
layout(location = 2) in vec4 vs_in_reg2;
...
layout(location = 15) in vec4 vs_in_reg15;
// N = BitCount(regs.vs.output_mask)
// "layout(location = X)" only presents for separable shader
layout(location = 0) out vec4 vs_out_attr0;
layout(location = 1) out vec4 vs_out_attr1;
layout(location = 2) out vec4 vs_out_attr2;
...
layout(location = (N-1)) out vec4 vs_out_attr(N-1);
void main() {
// initialize all output registers
vs_out_attr0 = vec4(0.0, 0.0, 0.0, 1.0);
vs_out_attr1 = vec4(0.0, 0.0, 0.0, 1.0);
vs_out_attr2 = vec4(0.0, 0.0, 0.0, 1.0);
...
vs_out_attrN = vec4(0.0, 0.0, 0.0, 1.0);
exec_shader();
}
// below are generated by decompiler
bool exec_shader() {
...
// inputreg[I] is translated to vs_in_regI
// outputreg[I] is translated to vs_out_attrK, where K = config.state.output_map[I]
// i.e. the I-th bit in regs.vs.output_mask is the K-th set bit.
// assigment operation is omitted if outputreg[I] has no mapping
}
////////////////////////////////////////////////////////////////
/// Fixed Geometry Shader
#version 330 core
#extension GL_ARB_separate_shader_objects : enable // only presents for separable shader
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
// "layout(location = X)" only presents for separable shader
layout (location = 1) out vec4 primary_color;
layout (location = 2) out vec2 texcoord0;
layout (location = 3) out vec2 texcoord1;
layout (location = 4) out vec2 texcoord2;
layout (location = 5) out float texcoord0_w;
layout (location = 6) out vec4 normquat;
layout (location = 7) out vec3 view;
// only presents for separable shader
out gl_PerVertex {
vec4 gl_Position;
float gl_ClipDistance[2];
};
layout (std140) uniform shader_data {
...
}
// same layout as in vertex shader output
layout(location = 0) in vec4 vs_out_attr0;
layout(location = 1) in vec4 vs_out_attr1;
layout(location = 2) in vec4 vs_out_attr2;
...
layout(location = (N-1)) in vec4 vs_out_attr(N-1);
#define uniforms gs_uniforms
layout (std140) uniform gs_config {
pica_uniforms uniforms;
};
struct Vertex {
vec4 attributes[N]; // N is the same as the N in input layout
};
vec4 GetVertexQuaternion(Vertex vtx) {
return vec4(vtx.attributes[?].?...);
}
void EmitVtx(Vertex vtx, bool quats_opposite) {
vec4 vtx_pos = vec4(vtx.attributes[?].?...);
gl_Position = vtx_pos;
gl_ClipDistance[0] = -vtx_pos.z;
gl_ClipDistance[1] = dot(clip_coef, vtx_pos);
vec4 vtx_quat = GetVertexQuaternion(vtx);
normquat = mix(vtx_quat, -vtx_quat, bvec4(quats_opposite));'
vec4 vtx_color = vec4(vtx.attributes[?].?...);
primary_color = min(abs(vtx_color), vec4(1.0));
texcoord0 = vec2(vtx.attributes[?].?...);
texcoord1 = vec2(vtx.attributes[?].?...);
texcoord0_w = vtx.attributes[?].?;
texcoord2 = vec2(vtx.attributes[?].?...);
texcoord3 = vec3(vtx.attributes[?].?...);
EmitVertex();
}
bool AreQuaternionsOpposite(vec4 qa, vec4 qb) {
return (dot(qa, qb) < 0.0);
}
void EmitPrim(Vertex vtx0, Vertex vtx1, Vertex vtx2) {
EmitVtx(vtx0, false);
EmitVtx(vtx1, AreQuaternionsOpposite(GetVertexQuaternion(vtx0), GetVertexQuaternion(vtx1)));
EmitVtx(vtx2, AreQuaternionsOpposite(GetVertexQuaternion(vtx0), GetVertexQuaternion(vtx2)));
EndPrimitive();
}
void main() {
Vertex prim_buffer[3];
prim_buffer[0].attributes = attributes[N](vs_out_attr0[0], vs_out_attr1[0], ... vs_out_attr(N-1)[0]);
prim_buffer[1].attributes = attributes[N](vs_out_attr0[1], vs_out_attr1[1], ... vs_out_attr(N-1)[1]);
prim_buffer[2].attributes = attributes[N](vs_out_attr0[2], vs_out_attr1[2], ... vs_out_attr(N-1)[2]);
EmitPrim(prim_buffer[0], prim_buffer[1], prim_buffer[2]);
}
////////////////////////////////////////////////////////////////
/// Programmable Geometry Shader
#version 330 core
#extension GL_ARB_separate_shader_objects : enable // only presents for separable shader
layout(XXX) in; // XXX depends on input register
layout(triangle_strip, max_vertices = 30) out;
// "layout(location = X)" only presents for separable shader
layout (location = 1) out vec4 primary_color;
layout (location = 2) out vec2 texcoord0;
layout (location = 3) out vec2 texcoord1;
layout (location = 4) out vec2 texcoord2;
layout (location = 5) out float texcoord0_w;
layout (location = 6) out vec4 normquat;
layout (location = 7) out vec3 view;
// only presents for separable shader
out gl_PerVertex {
vec4 gl_Position;
float gl_ClipDistance[2];
};
layout (std140) uniform shader_data {
...
}
// same layout as in vertex shader output
layout(location = 0) in vec4 vs_out_attr0;
layout(location = 1) in vec4 vs_out_attr1;
layout(location = 2) in vec4 vs_out_attr2;
...
layout(location = (N-1)) in vec4 vs_out_attr(N-1);
#define uniforms gs_uniforms
layout (std140) uniform gs_config {
pica_uniforms uniforms;
};
struct Vertex {
vec4 attributes[M]; // M is BitCount(regs.gs.output_mask)
};
vec4 GetVertexQuaternion(Vertex vtx) {
return vec4(vtx.attributes[?].?...);
}
void EmitVtx(Vertex vtx, bool quats_opposite) {
vec4 vtx_pos = vec4(vtx.attributes[?].?...);
gl_Position = vtx_pos;
gl_ClipDistance[0] = -vtx_pos.z;
gl_ClipDistance[1] = dot(clip_coef, vtx_pos);
vec4 vtx_quat = GetVertexQuaternion(vtx);
normquat = mix(vtx_quat, -vtx_quat, bvec4(quats_opposite));'
vec4 vtx_color = vec4(vtx.attributes[?].?...);
primary_color = min(abs(vtx_color), vec4(1.0));
texcoord0 = vec2(vtx.attributes[?].?...);
texcoord1 = vec2(vtx.attributes[?].?...);
texcoord0_w = vtx.attributes[?].?;
texcoord2 = vec2(vtx.attributes[?].?...);
texcoord3 = vec3(vtx.attributes[?].?...);
EmitVertex();
}
bool AreQuaternionsOpposite(vec4 qa, vec4 qb) {
return (dot(qa, qb) < 0.0);
}
void EmitPrim(Vertex vtx0, Vertex vtx1, Vertex vtx2) {
EmitVtx(vtx0, false);
EmitVtx(vtx1, AreQuaternionsOpposite(GetVertexQuaternion(vtx0), GetVertexQuaternion(vtx1)));
EmitVtx(vtx2, AreQuaternionsOpposite(GetVertexQuaternion(vtx0), GetVertexQuaternion(vtx2)));
EndPrimitive();
}
Vertex output_buffer;
Vertex prim_buffer[3];
uint vertex_id = 0u;
bool prim_emit = false;
bool winding = false;
void setemit(uint vertex_id_, bool prim_emit_, bool winding_) {
vertex_id = vertex_id_;
prim_emit = prim_emit_;
winding = winding_;
}
void emit() {
prim_buffer[vertex_id] = output_buffer;
if (prim_emit) {
if (winding) {
EmitPrim(prim_buffer[1], prim_buffer[0], prim_buffer[2]);
winding = false;
} else {
EmitPrim(prim_buffer[0], prim_buffer[1], prim_buffer[2]);
}
}
}
void main() {
// initialize all output registers
output_buffer.attributes[0] = vec4(0.0, 0.0, 0.0, 1.0);
output_buffer.attributes[1] = vec4(0.0, 0.0, 0.0, 1.0);
...
output_buffer.attributes[N-1] = vec4(0.0, 0.0, 0.0, 1.0);
exec_shader();
}
// below are generated by decompiler
bool exec_shader() {
...
// inputreg[I] is translated to vs_out_attrA[B], where
// A = C % N'
// B = C / N'
// N' is attributes per vertex input (usually equals to N, attributes per vertex shader output)
// C = config.state.input_map[I], which is generated from regs.gs.input_attribute_to_register_map
// use vec4(0.0, 0.0, 0.0, 1.0) if inputreg[I] has no mapping
// outputreg[I] is translated to output_buffer.attribute[K], where K = config.state.output_map[I]
// i.e. the I-th bit in regs.gs.output_mask is the K-th set bit.
// assigment operation is omitted if outputreg[I] has no mapping
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment