My goal is to "multiplicate" two OSG::Textures, where one is a Light-Distribution (RGBA picture) the other a black and white filter Image/Texture, that I generate myself. For now both Textures have the same size, even though it would be nice, if its possible that they don't. You can imagine, that I'm trying to remove the black areas on the filter texture from the light texture.
Currently my code works as far as making the whole screen one color, no matter what. I think that something around the gl_MultiTexCoord0
or gl_TexCoord[0]
is not correct. I had a look at multiple online sources, but could not get anything else to work.
Sadly I have to use an old version of glew (2.1.0) [-> ? OpenGL #version 120
] and OSG (3.0.1) due to framework restrictions.
Because nothing is working correctly, I'll try for now just to show the filterTexture (because if I show the lightTexture, everything is black)... Inside init and update I have multiple "checkError" in place, to see whats going on, but atm there are no errors. Here are my shaders:
// vertex shader
const char* shader_combine_vertex = "\n\
#version 120 \n\
\n\
void main() \n\
{ \n\
// homogeneous vertex position \n\
gl_Position = ftransform(); \n\
//Texture coordinate of texture unit 0 and 1\n\
gl_TexCoord[0] = gl_MultiTexCoord0; \n\
gl_TexCoord[1] = gl_MultiTexCoord1; \n\
} \n";
// fragment shader
const char* shader_combine_fragment = " \n\
#version 120 \n\
// input \n\
uniform sampler2D lightTexture; \n\
uniform sampler2D filterTexture; \n\
//varying vec2 lightTexCoord; \n\
//varying vec2 filterTexCoord; \n\
\n\
void main() \n\
{ \n\
gl_FragColor = texture2D(filterTexture, gl_TexCoord[1].st); \n\
\n\
// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); //works and shows red \n\
\n\
// gl_FragColor = texture2D(filterTexture, filterTexCoord); \n\
\n\
// vec4 texel = texture2D(lightTexture, gl_TexCoord[0].st); \n\
// gl_FragColor = texel * texture2D(filterTexture, gl_TexCoord[1].st); \n\
}\n";
And the global Variables and the init and update functions with valid OpenGL context:
/** textures for each lightSourceID **/
std::map<int, GLuint> vp_ShaderCombine;
std::map<int, GLuint> fp_ShaderCombine;
/** Program linking shaders **/
std::map<int, GLhandleARB> combineProgram;
// TODO: maybe generate all texture IDs at once, but works for now
std::map<int, unsigned int> g_uiSceneTex[2]; // for every sensor - 2 texture IDs (Light | Filter)
---------
bool initShaders(int id, int width, int height, char* texture)
{
// Shaders compilation
vp_ShaderCombine.insert(std::pair<int, GLuint>(id, glCreateShaderObjectARB(GL_VERTEX_SHADER)));
fp_ShaderCombine.insert(std::pair<int, GLuint>(id, glCreateShaderObjectARB(GL_FRAGMENT_SHADER)));
glShaderSource(vp_ShaderCombine.at(id), 1, &shader_combine_vertex, NULL);
glShaderSource(fp_ShaderCombine.at(id), 1, &shader_combine_fragment, NULL);
glCompileShader(vp_ShaderCombine.at(id));
checkShaderCompileError(vp_ShaderCombine.at(id), "vertex");
glCompileShader(fp_ShaderCombine.at(id));
checkShaderCompileError(fp_ShaderCombine.at(id), "fragment");
combineProgram[id] = glCreateProgram();
glAttachShader(combineProgram[id], vp_ShaderCombine[id]);
glAttachShader(combineProgram[id], fp_ShaderCombine[id]);
glLinkProgram(combineProgram.at(id));
glValidateProgram(combineProgram.at(id));
// Check result and display errors if any
...
return ...;
}
void update()
{
for (... every light source id ...)
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
// ------------ NECESSARY? ----------------
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
// ----------- LIGHT----------------
// mainly the same as filter just on g_uiSceneTex[id][0]
// ----------- FILTER ----------------
glUseProgramObjectARB(combineProgram[id]); // call before each glActiveTexture (according to some SO post)
glActiveTexture(GL_TEXTURE0 + 1);
// TODO: maybe generate all texture IDs at once, but works for now
glGenTextures(1, &g_uiSceneTex[id][1]); // generate texture names
glBindTexture(GL_TEXTURE_2D, g_uiSceneTex[id][1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, itSHM->myOsgImg->s(), itSHM->myOsgImg->t(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, itSHM->myOsgImg);
GLint filterTexUnitLoc = glGetUniformLocation(combineProgram[id], "filterTexture");
glUniform1i(filterTexUnitLoc, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
// render
// draw QUAD
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0, 1, -1);
glTexCoord2f(0, ScreenHeight);
glVertex3f(0, 0, -1);
glTexCoord2f(ScreenWidth, ScreenHeight);
glVertex3f(1, 0, -1);
glTexCoord2f(ScreenWidth, 0);
glVertex3f(1, 1, -1);
glEnd();
// Disable Shaders
glUseProgramObjectARB(0);
glDisable(GL_TEXTURE_2D);
// NECESSARY?
myShmImages[0].myOsgImg->dirty();
myPhotometries[0].myOSGTexture->dirtyTextureObject();
}
}
Now arise multiple Questions on my side:
You are not supplying gl_Multitexcoord1
at all:
glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(0, 1, -1); [...] glEnd();
This code only supplies data for gl_MultiTexCoord0
. If you really need different texcoords for each texture, then you need to provide them per vertex via glMultiTexCoord
:
glBegin(GL_QUADS); glMultiTexCoord2f(GL_TEXTURE0, 0, 0); glMultiTexCoord2f(GL_TEXTURE1, ..., ...); glVertex3f(0, 1, -1); [...] glEnd();
However, you can also use a single set of texture coords for both textures, if you don't really need different values (which is not clear from your question).
Note that your code is horribly outdated, and deprecated in the GL since 2008. Even if you are limited to GL2.x (as your shaders target), you should never use the builtin attributes like gl_MultiTexCoord*
etc. Use generic vertex attributes, and supply your data as vertex arrays in vertex buffer objects.