OpenGL OSG::Texture 乘法只显示一种颜色
OpenGL OSG::Texture multiplication only shows one color
我的目标是 "multiplicate" 两个 OSG::Textures,其中一个是光分布(RGBA 图片)另一个是我自己生成的黑白滤镜 Image/Texture。现在两个纹理具有相同的大小,即使它们可能不一样也很好。你可以想象,我正试图从光纹理中移除滤镜纹理上的黑色区域。
目前我的代码可以使整个屏幕都变成一种颜色,无论如何。我认为 gl_MultiTexCoord0
或 gl_TexCoord[0]
周围的内容不正确。我查看了多个在线资源,但找不到任何其他资源。
遗憾的是我必须使用旧版本的 glew (2.1.0) [-> ?由于框架限制,OpenGL #version 120
] 和 OSG (3.0.1)。
因为没有任何东西正常工作,我现在尝试只显示 filterTexture(因为如果我显示 lightTexture,一切都是黑色的)...
在 init 和 update 中,我有多个 "checkError",以查看发生了什么,但 atm 没有错误。
这是我的着色器:
// 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";
以及具有有效 OpenGL 上下文的全局变量以及初始化和更新函数:
/** 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();
}
}
我这边出现了多个问题:
- 着色器有什么问题,它们只显示一种颜色?我认为他们只评估一个像素。
- 使用这些 gl 函数与使用 OSG 原生函数创建着色器有什么区别?是否有限制,或者我的设置是否可行?是"easier"吗?我没有找到任何关于该主题的好读物?
- 更新代码看起来很长而且没有必要,我是否需要每次更新都生成/创建纹理,还是只初始化一次?
- 目前贴图是全屏显示,但我想在OSG树中的Light位置显示。我有光分布的视锥体,因此我认为,我只需要 "map" 使用 view/camera/frustum...
的新过滤纹理
您根本没有提供 gl_Multitexcoord1
:
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0, 1, -1);
[...]
glEnd();
此代码仅提供 gl_MultiTexCoord0
的数据。 如果你真的需要为每个纹理提供不同的纹理坐标,那么你需要通过glMultiTexCoord
:
为每个顶点提供它们
glBegin(GL_QUADS);
glMultiTexCoord2f(GL_TEXTURE0, 0, 0);
glMultiTexCoord2f(GL_TEXTURE1, ..., ...);
glVertex3f(0, 1, -1);
[...]
glEnd();
但是,如果您真的不需要不同的值(从您的问题中不清楚),您也可以对两个纹理使用一组纹理坐标。
请注意,您的代码非常过时,并且自 2008 年 以来在 GL 中已弃用。即使您仅限于 GL2.x(作为您的着色器目标),您也应该 永远不要 使用内置属性,例如 gl_MultiTexCoord*
等。使用通用顶点属性,并提供您的数据作为顶点缓冲区对象中的顶点数组。
我的目标是 "multiplicate" 两个 OSG::Textures,其中一个是光分布(RGBA 图片)另一个是我自己生成的黑白滤镜 Image/Texture。现在两个纹理具有相同的大小,即使它们可能不一样也很好。你可以想象,我正试图从光纹理中移除滤镜纹理上的黑色区域。
目前我的代码可以使整个屏幕都变成一种颜色,无论如何。我认为 gl_MultiTexCoord0
或 gl_TexCoord[0]
周围的内容不正确。我查看了多个在线资源,但找不到任何其他资源。
遗憾的是我必须使用旧版本的 glew (2.1.0) [-> ?由于框架限制,OpenGL #version 120
] 和 OSG (3.0.1)。
因为没有任何东西正常工作,我现在尝试只显示 filterTexture(因为如果我显示 lightTexture,一切都是黑色的)... 在 init 和 update 中,我有多个 "checkError",以查看发生了什么,但 atm 没有错误。 这是我的着色器:
// 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";
以及具有有效 OpenGL 上下文的全局变量以及初始化和更新函数:
/** 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();
}
}
我这边出现了多个问题:
- 着色器有什么问题,它们只显示一种颜色?我认为他们只评估一个像素。
- 使用这些 gl 函数与使用 OSG 原生函数创建着色器有什么区别?是否有限制,或者我的设置是否可行?是"easier"吗?我没有找到任何关于该主题的好读物?
- 更新代码看起来很长而且没有必要,我是否需要每次更新都生成/创建纹理,还是只初始化一次?
- 目前贴图是全屏显示,但我想在OSG树中的Light位置显示。我有光分布的视锥体,因此我认为,我只需要 "map" 使用 view/camera/frustum... 的新过滤纹理
您根本没有提供 gl_Multitexcoord1
:
glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(0, 1, -1); [...] glEnd();
此代码仅提供 gl_MultiTexCoord0
的数据。 如果你真的需要为每个纹理提供不同的纹理坐标,那么你需要通过glMultiTexCoord
:
glBegin(GL_QUADS); glMultiTexCoord2f(GL_TEXTURE0, 0, 0); glMultiTexCoord2f(GL_TEXTURE1, ..., ...); glVertex3f(0, 1, -1); [...] glEnd();
但是,如果您真的不需要不同的值(从您的问题中不清楚),您也可以对两个纹理使用一组纹理坐标。
请注意,您的代码非常过时,并且自 2008 年 以来在 GL 中已弃用。即使您仅限于 GL2.x(作为您的着色器目标),您也应该 永远不要 使用内置属性,例如 gl_MultiTexCoord*
等。使用通用顶点属性,并提供您的数据作为顶点缓冲区对象中的顶点数组。