You may need a suitable fragment shader simply to prevent the vertex shader’s outputs from being considered unused.
That seems to help a bit. My logfile reports,
Index of tffInput: 0
alfter calling glGetAttribLocation and glEnableVertexAttribArray as also glVertexAttribPointer do not lead to error-messages anymore.
Unfortunatly, now it stucks at “glBeginTransformFeedback(GL_POINTS);”. After this glGetErrors reports GL_INVALID_OPERATION. I’m not sure, if the existence of a fragment-shader, leads to this?
However: i did not really looked at the code after glEnableVertexAttribArray. I’ll check it later.
For the case that someone also want to have a look at it: Here is my c-code…
Shader-compilation (the complete function except of the error-output. So it is prepared to compile all kind of shaders - even if i currently don’t use most of it). Here is the glTransformFeedbackVaryings-call (the upper-one is used, since i have a fragment-shader).
A short explanation:
- First, the sources are checked for changes (=> bool ch) and cut together of fragments (“uniformStr”). If there are none, the function returns.
- After this some temporary handles are requested.
- The regex is used to detect “void main () {…}”-expressions in the sources. If there is none, the shader is skipped.
- glTransformFeedbackVaryings is called, it the vertex-shader contains “cppReturn”. Here i also tested BindLocation.
- If the compilation is okay, the temporary handels are swapped with the active ones. Otherwise the active ones stay in use.
void clsControl::PrepareShader(wxString uniformStr) { if (!recompile) return; _ONCE_PER_FRAME();
bool ch = false;
if (SYS != shSrcStr[_sysShd ]) { SYS = shSrcStr[_sysShd ]; ch = true; }
if (GLB != shSrcStr[_glbShd ]) { GLB = shSrcStr[_glbShd ]; ch = true; }
if (CTR != uniformStr ) { CTR = uniformStr; ch = true; }
if (VS != shSrcStr[_vShd ]) { VS = shSrcStr[_vShd ]; ch = true; if (vShLnkC ) { delete vShLnkC; vShLnkC = NULL; } vShLnkC = _NEW_CHAR(SYS + CTR + GLB + VS); }
if (TCS != shSrcStr[_tcShd ]) { TCS = shSrcStr[_tcShd ]; ch = true; if (tcShLnkC) { delete tcShLnkC; tcShLnkC = NULL; } tcShLnkC = _NEW_CHAR( TCS ); }
if (TES != shSrcStr[_teShd ]) { TES = shSrcStr[_teShd ]; ch = true; if (teShLnkC) { delete teShLnkC; teShLnkC = NULL; } teShLnkC = _NEW_CHAR( TES ); }
if (GS != shSrcStr[_gShd ]) { GS = shSrcStr[_gShd ]; ch = true; if (gShLnkC ) { delete gShLnkC; gShLnkC = NULL; } gShLnkC = _NEW_CHAR(SYS + CTR + GS); }
if (FS != shSrcStr[_fShd ]) { FS = shSrcStr[_fShd ]; ch = true; if (fShLnkC ) { delete fShLnkC; fShLnkC = NULL; } fShLnkC = _NEW_CHAR(SYS + CTR + GLB + FS); }
if (CS != shSrcStr[_prstShd]) { CS = shSrcStr[_prstShd]; ch = true; if (cShLnkC ) { delete cShLnkC; cShLnkC = NULL; } cShLnkC = _NEW_CHAR( CTR + CS); }
if (!ch) return; Debug(3, "Compilig shader progeam");
CheckGL("Error left in cue");
vShNewHandle = glCreateShader (GL_VERTEX_SHADER);
tcShNewHandle = glCreateShader (GL_TESS_CONTROL_SHADER);
teShNewHandle = glCreateShader (GL_TESS_EVALUATION_SHADER);
gShNewHandle = glCreateShader (GL_GEOMETRY_SHADER);
fShNewHandle = glCreateShader (GL_FRAGMENT_SHADER);
cShNewHandle = glCreateShader (GL_COMPUTE_SHADER);
prgNewHandle = glCreateProgram ();
static wxRegEx hasCode ("[\
\\r][\ ]*void\\s*main\\s*\\(\\s*\\)\\s*\\{.*\\}"/*"[\
\\r][\ ]*void\\s*main\\s*\\("/*"[\
\\r][\ ]*\\w.*"*/, wxRE_ADVANCED);
if (hasCode.Matches(vShLnkC)) {
success = GL_FALSE; errHandle = vShNewHandle;
glShaderSource (vShNewHandle, 1, &vShLnkC, NULL); glCompileShader (vShNewHandle);
glGetShaderiv (vShNewHandle, GL_COMPILE_STATUS, &success); if (success != GL_TRUE) goto ex;
glAttachShader (prgNewHandle, vShNewHandle);
if (hasCode.Matches(fShLnkC)) {
if (hasCode.Matches(tcShLnkC) && hasCode.Matches(teShLnkC)) {
//if (shdShader->tcShSrc != "" && shdShader->teShSrc != "") {
success = GL_FALSE; errHandle = tcShNewHandle;
glShaderSource (tcShNewHandle, 1, &tcShLnkC, NULL); glCompileShader (tcShNewHandle);
glGetShaderiv (tcShNewHandle, GL_COMPILE_STATUS, &success); if (success != GL_TRUE) goto ex;
glAttachShader (prgNewHandle, tcShNewHandle); //glLinkProgram (prgNewHandle);
success = GL_FALSE; errHandle = teShNewHandle;
glShaderSource (teShNewHandle, 1, &teShLnkC, NULL); glCompileShader (teShNewHandle);
glGetShaderiv (teShNewHandle, GL_COMPILE_STATUS, &success); if (success != GL_TRUE) goto ex;
glAttachShader (prgNewHandle, teShNewHandle); //glLinkProgram (prgNewHandle);
}
if (hasCode.Matches(gShLnkC)) { //_wxMessageBox(shdShader->gShSrc);
//if (shdShader->gShSrc != "") {
success = GL_FALSE; errHandle = gShNewHandle;
glShaderSource (gShNewHandle, 1, &gShLnkC, NULL); glCompileShader (gShNewHandle);
glGetShaderiv (gShNewHandle, GL_COMPILE_STATUS, &success); if (success != GL_TRUE) goto ex;
glAttachShader (prgNewHandle, gShNewHandle); //glLinkProgram (prgNewHandle);
}
success = GL_FALSE; errHandle = fShNewHandle;
glShaderSource (fShNewHandle, 1, &fShLnkC, NULL); glCompileShader (fShNewHandle);
glGetShaderiv (fShNewHandle, GL_COMPILE_STATUS, &success); if (success != GL_TRUE) goto ex;
glAttachShader (prgNewHandle, fShNewHandle);
if (shSrcStr[_vShd ].Find("tffInput") != wxNOT_FOUND) {
const GLchar* feedbackVaryings[] = { "cppReturn" };
glEnable(GL_RASTERIZER_DISCARD);
// if (!feedbackVaryings) wxMessageBox("feedbackVaryings = 0");
glTransformFeedbackVaryings (prgNewHandle, 0, feedbackVaryings, GL_INTERLEAVED_ATTRIBS); //wxMessageBox("ENDLICH!!!");
glBindAttribLocation(prgNewHandle, 0, "tffInput"); CheckGL("glBindAttribLocation");
}
}
else { //_wxMessageBox(tostr(prgNewHandle));
const GLchar* feedbackVaryings[] = { "cppReturn" };
glEnable(GL_RASTERIZER_DISCARD);
// if (!feedbackVaryings) wxMessageBox("feedbackVaryings = 0");
glTransformFeedbackVaryings (prgNewHandle, 0, feedbackVaryings, GL_INTERLEAVED_ATTRIBS); //wxMessageBox("ENDLICH!!!");
glBindAttribLocation(prgNewHandle, 0, "tffInput"); CheckGL("glBindAttribLocation");
}
}
if (hasCode.Matches(cShLnkC)) { //_wxMessageBox(shdShader->gShSrc);
//if (shdShader->gShSrc != "") {
success = GL_FALSE; errHandle = cShNewHandle;
glShaderSource (cShNewHandle, 1, &cShLnkC, NULL); glCompileShader (cShNewHandle);
glGetShaderiv (cShNewHandle, GL_COMPILE_STATUS, &success); if (success != GL_TRUE) goto ex;
glAttachShader (prgNewHandle, cShNewHandle); //glLinkProgram (prgNewHandle);
}
success = GL_FALSE; errHandle = prgNewHandle;
glLinkProgram (prgNewHandle); glUseProgram (prgNewHandle);
glGetProgramiv (prgNewHandle, GL_LINK_STATUS, &success); if (success != GL_TRUE) goto ex;
GLuint tmpHandle;
tmpHandle = vShHandle; vShHandle = vShNewHandle; vShNewHandle = tmpHandle;
tmpHandle = tcShHandle; tcShHandle = tcShNewHandle; tcShNewHandle = tmpHandle;
tmpHandle = teShHandle; teShHandle = teShNewHandle; teShNewHandle = tmpHandle;
tmpHandle = gShHandle; gShHandle = gShNewHandle; gShNewHandle = tmpHandle;
tmpHandle = fShHandle; fShHandle = fShNewHandle; fShNewHandle = tmpHandle;
tmpHandle = cShHandle; cShHandle = cShNewHandle; cShNewHandle = tmpHandle;
tmpHandle = prgHandle; prgHandle = prgNewHandle; prgNewHandle = tmpHandle;
prgCanLink = true; recompile = false;
ex: OutStatus ();
glUseProgram (0);
glDeleteProgram (prgNewHandle);
glDeleteShader (vShNewHandle);
glDeleteShader (tcShNewHandle);
glDeleteShader (teShNewHandle);
glDeleteShader (gShNewHandle);
glDeleteShader (fShNewHandle);
glDeleteShader (cShNewHandle);
CheckGL();
}
Binding the program - “PrepareShader” is the upper function. Here i cut out everything, which is not relevant - normally here uniforms are implemented, but in this case, tere are none:
void clsControl::ApplyShader(clsLst &list) {
CheckGL("Error left in cue");
PrepareShader ("");
if (prgCanLink) { Debug(3, "Activate shader program " + tostr(prgHandle));
curPRG = prgHandle; glUseProgram ( prgHandle );
}
CheckGL();
}
The tff-function (this one and the previous function are called by my interpreter without anything in between):
void ParseDrawRenderTFF(clsControl *Control, clsLst &list) {
glDisable(GL_TEXTURE_2D); CheckGL("Error left in cue");
// theorie:
// ----------------
// Shader ist bereits aktiviert. Enthält:
// in float tffInput;
// out float cppReturn
//
// VAO erzeugen (noch nie gemacht - wofür?)
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao); CheckGL("VAO-Creation");
// Array von "list" erzeugen
GLfloat data[list.size];
for (int i=0; i < list.size; i++) data[i] = list[i][0];
// Aktiven Shader-Programm-Index ermitteln
GLint prg;
glGetIntegerv(GL_CURRENT_PROGRAM, &prg);
Print(tostr(prg) + " - " + tostr(curPRG));
// VBO von array" erzeugen
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); CheckGL("VBO-Creation");
// Übergabeadress für Attribut "inValue" ermitteln
// glBindAttribLocation(prg, 0, "tffInput"); CheckGL("glBindAttribLocation");
GLint tffInput = glGetAttribLocation(prg, "tffInput"); CheckGL("glGetAttribLocation");
//
Print ("Index of tffInput: " + tostr(tffInput));
glEnableVertexAttribArray(tffInput); CheckGL("glEnableVertexAttribArray");
glVertexAttribPointer(tffInput, 1, GL_FLOAT, GL_FALSE, 0, 0); CheckGL("glVertexAttribPointer");
// Gleich großen Zielbuffer erzeugen mit
GLuint tbo;
glGenBuffers(1, &tbo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), NULL, GL_STATIC_READ); CheckGL("TBO-Creation");
// PROZESS:
glEnable(GL_RASTERIZER_DISCARD); CheckGL("glEnable(GL_RASTERIZER_DISCARD)");
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo); CheckGL("glBindBufferBase");
glBeginTransformFeedback(GL_POINTS); CheckGL("glBeginTransformFeedback");
glDrawArrays(GL_POINTS, 0, list.size); CheckGL("glDrawArrays");
glEndTransformFeedback(); CheckGL("glEndTransformFeedback");
glFlush(); CheckGL("glFlush");
// Ergebnis auslesen:
GLfloat feedback[list.size];
glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(data), feedback);
Print(tostr(data[0]) + " - " + tostr(feedback[1]) + " - " + tostr(feedback[2]) + " - " + tostr(data[3]) + " - " + tostr(data[4]));
// Aufräumen:
// glDisable (GL_RASTERIZER_DISCARD); muss nicht - ist in ResetGL();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &tbo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
}
This is the shader-code, i use…
Vertex-shader (currently without “layout…”):
#version 330
//////////////////////////////////////////////////////////
// Vertex-shader
//////////////////////////////////////////////////////////
in float tffInput;
out float cppReturn;
void main() {
cppReturn = sqrt ( tffInput );
}
Fragment-shader:
in float cppReturn;
out vec4 color;
void main() {
color = vec4(cppReturn);
}
Thanks for your help!!
Best,
Frank