Моя цель - «умножить» два OSG :: Textures, где один - Light-Distribution (изображение RGBA), другой - черно-белый фильтр Image / Texture, который я генерирую сам. На данный момент оба Текстуры имеют одинаковый размер, хотя было бы неплохо, если бы это было возможно, что они этого не делают. Вы можете себе представить, что я пытаюсь удалить черные области на текстуре фильтра из светлой текстуры.
В настоящее время мой код работает так, чтобы весь экран был одним цветом, несмотря ни на что. Я думаю, что что-то вокруг gl_MultiTexCoord0
или gl_TexCoord[0]
не правильно. Я просмотрел несколько онлайн-источников, но не смог заставить работать что-либо еще.
К сожалению, мне приходится использовать старую версию glew (2.1.0) [->? OpenGL #version 120
] и OSG (3.0.1) из-за ограничений фреймворка.
Поскольку ничего не работает правильно, я пока попробую просто показать filterTexture (потому что, если я покажу lightTexture, все будет черный) ... Внутри init и update у меня есть несколько "checkError", чтобы увидеть, что происходит, но нет ошибок. Вот мои шейдеры:
// 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";
И глобальные переменные и функции init и update с действительным контекстом 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 для создания шейдера? Есть ли ограничения или возможна моя настройка? Это "проще"? Какое-нибудь хорошее чтение по этой теме c, я не нашел ни одного?
- Код обновления выглядит очень длинным и ненужным, нужно ли мне генерировать / создавать текстуру каждый раз при обновлении, или я могу только инициировать ее? один раз?
- В настоящее время текстура отображается в полноэкранном режиме, но я хочу отобразить ее в позиции Light в дереве OSG. У меня есть видимость распределения света, поэтому я думаю, что мне просто нужно «отобразить» новую отфильтрованную текстуру, используя этот вид / камеру / усеченный ...