Я пытаюсь отобразить pointprites в Opengl по определенному пути. Я определяю спрайт как двумерную текстуру и устанавливаю ее для использования GL_NEAREST в качестве фильтра mag/min. Я также определяю 1D текстуру, содержащую несколько 2D-координат (так что мне нужно только 1 float для спрайта, чтобы определить их расположение в пространстве экрана), которые я установил в GL_LINEAR.Использование нескольких текстур + фильтров в GLSL
Однако, когда я запускаю свою программу на своем ноутбуке, он всегда использует метод фильтра mag для спрайта-текстуры и игнорирует настройку на текстуре пути. Мой ноутбук работает под управлением Linux + mesa 9.2.1 + Opengl 3.0 на Intel Iris Pro 5200. Все работает так, как ожидалось, на моем рабочем столе, который работает под управлением Linux, и использует собственный драйвер Nvidia с opengl 4.2.
Соответствующий код
//A path "t -> (x,y)" along which we will place our sprites
v2f path[] = {{-0.5,0.5},
{-0.5,-0.5},
{0.5,-0.5},
{0.5,0.5}};
glActiveTexture(GL_TEXTURE0);
if(glGetError() != GL_NO_ERROR)
report(FAIL, "Couldn't activate texture!");
GLuint pathTex;
glGenTextures(1, &pathTex); //create a new texture
glBindTexture(GL_TEXTURE_1D, pathTex); //start using it as a 1D texture
//store the coordinates of path in the texture so that we can interpolate our path in the shader.
glTexImage1D(GL_TEXTURE_1D,0,GL_RG32F, sizeof(path)/sizeof(v2f),0,GL_RG,GL_FLOAT,path);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_BASE_LEVEL, 0);//We need these two lines
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);//because we don't have mipmaps.
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//We want the path to be linearly filtered
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//Set the min filter just to be safe.
if(glGetError() != GL_NO_ERROR)
report(FAIL, "Something went wrong setting up pathTex");
GLint uniformLoc = glGetUniformLocation(shaderProgram, "pathTexture"); //locate the uniform
uniformLoc >= 0?glUniform1i(uniformLoc, 0):report(FAIL, "found uniform spriteTexture at %d", uniformLoc); //and set it to "0" because we're using GL_TEXTURE0
if(glGetError() != GL_NO_ERROR)
report(FAIL, "Couldn't set uniform!");
report(PASS, "Setup texture for path");
//create and set second texture
rgba sprite[] = {{1.0,0,0,1},{0,1.0,0,1},{0,0,1.0,1},{1,1,0,1}}; //our sprite, a simple "red,green,blue,yellow" square.
glActiveTexture(GL_TEXTURE0+1); //use texUnit 1 now.
if(glGetError() != GL_NO_ERROR)
report(FAIL, "Couldn't activate texture!");
GLuint spriteTex;
glGenTextures(1, &spriteTex); //create a new texture
glBindTexture(GL_TEXTURE_2D, spriteTex); //start using it as a 2D texture
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, 2,2,0,GL_RGBA,GL_FLOAT,sprite); //load the data again. 2x2 sprite.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);//We need these two lines
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);//because we don't have mipmaps.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//We want our sprites to be filtered to
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);//the nearest pixel, not interpolated.
if(glGetError() != GL_NO_ERROR)
report(FAIL, "Something went wrong setting up pathTex");
uniformLoc = glGetUniformLocation(shaderProgram, "spriteTexture"); //locates and set the second sampler.
uniformLoc >= 0?glUniform1i(uniformLoc, 1):report(FAIL, "found uniform spriteTexture at %d", uniformLoc);
if(glGetError() != GL_NO_ERROR)
report(FAIL, "Couldn't set uniform!");
report(PASS, "Setup texture for sprite");
И моя вершина затенения
#version 130
uniform sampler1D pathTexture;
in float t;
void main(){
gl_Position = texture(pathTexture, t);
}
и мой фрагмент затенения
#version 130
uniform sampler2D spriteTexture;
out vec4 outputColor;
void main()
{
outputColor = texture(spriteTexture, gl_PointCoord);
}
Весь код (один подал) я приклеила here , и here - скриншоты того, что я вижу на Nvidia и Inte л соответственно.
Редактировать: Я получаю те же результаты на Nvidia с контекстом 3.0.
Что может быть причиной этого?
Если вы используете OpenGL 4.x, вы можете использовать Sampler Objects для хранения состояния фильтра/обертки. Вы можете привязать пробник к текстурному блоку 0, который использует ближайшую фильтрацию, а один - к текстурной единице 1, которая использует билинейную. Затем вместо использования объекта фильтра для текстуры вы можете привязать любую текстуру, которую вы хотите к единице, и вместо этого будет использовать фильтр сэмплера. Это действительно намного более элегантное решение, поскольку оно в основном превращает объекты текстуры в хранилища изображений и разделяет некоторые из состояний, которые на самом деле никогда не принадлежали им; это хорошая идея, что D3D проделал это в течение 10 лет :) –
Спасибо за совет:), но я тоже пробовал его с использованием объектов сэмплера, однако я получаю те же результаты. –
Теперь, когда я понимаю, что вы на самом деле пытаетесь сделать здесь, я чувствую себя обязанным указать, что выборки вершинной текстуры очень ограничены по сравнению с фрагментом. Некоторые аппаратные средства поддерживают только несколько форматов изображений на этапе вершины, линейная фильтрация не всегда аппаратно ускорена, анизотропная фильтрация ** никогда не работает в вершинном шейдере (для этого требуется знание градиентной/частичной производной, которая действительно не имеет смысла в контекст выборки по вершинам) и mipmapping тоже. У меня такое чувство, что это либо ограничение Mesa, либо аппаратное обеспечение Iris, либо, возможно, и то, и другое. –