glBindSampler weirdness

Started by
4 comments, last by andrew111 13 years, 3 months ago
Hi, I've a really strange problem with glBindSampler, using opengl 3.1.

In my shader I have a '2d uniform sampler' set to 'texture unit' 2, with a corresponding '2d texture' correctly bound to GL_TEXTURE2. So when I call glBindSampler(2, sampler), there is no effect on my texture(ie GL_TEXTURE_WRAP_S being set to GL_CLAMP_TO_EDGE, instead of using the default GL_REPEAT). But if I call glBindSampler(0, sampler), then the sampler works and is used by the texture.

glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, texture);glBindSampler(2, sampler);


Things I am sure arn't the problem are:
- uniform sampler (is set correctly to 2, and is correctly defined in shader)
- sampler (is correctly initialised)
- other textures, samplers (no others are being used)

Also if anyone has some working sample code of using samplers on a texture unit other than 0, that I can test on my computer, that would be really helpful.

Thanks.
Advertisement
http://www.opengl.org/sdk/docs/man3/xhtml/glBindSampler.xml

"glBindSampler is available only if the GL version is 3.3 or higher."

Aside from that, check if GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS actually returns 3 or something higher.
Ok I changed my context to "3.3.10317 Compatibility Profile Context", using the context attribs:

int attribs[] =	{	WGL_CONTEXT_MAJOR_VERSION_ARB, 3,	WGL_CONTEXT_MINOR_VERSION_ARB, 3,	WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,	0};

(I'm using the compatible profile, because using the core profile causes my textures come up black)
But the same problem is still occurring.

and GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS returns 32.

Also I tried my program on another computer which has a different video card, and it still doesn't work (my video card is a radeon 4800 series, I'm not sure what the other computer has, I can't check at the moment).



Thanks.
Okay since no one seems to know what's wrong, I've created a short program reproducing the problem.

When the texture unit for the sampler is set to anything but 0, the sampler states aren't used.

So in my program I bind a texture and set the uniform sampler to a texture unit other than 0, and then bind the sampler to the same texture unit.

The sampler's WRAP_S is set to CLAMP_TO_EDGE. You can see the sampler not working when the image is tiling from left to right.

To see that the sampler only works when bound to texture unit 0, set the const 'textureUnitForSampler' to 0 while the uniform sampler and texture are bound to 2, and see the texture drawn clamped, even though by default it should be repeated(tiled).

I am using OpenGL 3.3 compatibility profile context.

The source code can be downloaded here in a vc++ 2010 project. The only library used is glew 1.5.7.

If someone else see if they get the same problem, that would be great.

Thanks.

Also here's the source code:
#include <windows.h>#include <gl/glew.h>#include <GL/wglew.h>#include <iostream>#include <fstream>#include <string>int screenWidth=0, screenHeight=0;GLuint program=0, texture=0, sampler=0;const int textureUnit = 2, textureUnitForSampler=2; //when the sampler is set to anything but 0, it doesn't work.bool compileAndAttachShaderFromFile(GLuint program, GLenum type, const std::string &fileName) {	//read file	std::ifstream inFile(fileName.c_str());	if(inFile.fail()) {		std::cout << "Could not read file: " << fileName << std::endl;		return false;	}	std::string source((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());	const char *sourceChars = source.c_str();	inFile.close();		//create and compile shader	GLuint shader = glCreateShader(type);	glShaderSource(shader, 1, &sourceChars, 0);	glCompileShader(shader);	//check compile status	int status;	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);	if(!status) {		GLsizei infoLen;		GLchar infoLog[1024];		glGetShaderInfoLog(shader, 1024, &infoLen, infoLog);		std::cout << "Error compiling shader from " << fileName << "\n" << infoLog << std::endl;		glDeleteShader(shader);		return false;	}		//attach shader to program	glAttachShader(program, shader);	glDeleteShader(shader);		//	return true;}bool init() {	//create program	{		program = glCreateProgram();		//attach shaders to program		if(!compileAndAttachShaderFromFile(program, GL_VERTEX_SHADER, "vertex.shader") ||			!compileAndAttachShaderFromFile(program, GL_FRAGMENT_SHADER, "fragment.shader")) {				return false;		}		//link program		glLinkProgram(program);		//check link status		GLint linkStatus;		glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);		if(!linkStatus) {			GLsizei infoLen;			GLchar infoLog[1024];			glGetProgramInfoLog(program, 1024, &infoLen, infoLog);			std::cout << "Linking program error:\n" << infoLog << std::endl;			glDeleteProgram(program);			program = 0;			return false;		}	}	//load texture	{		HBITMAP hBMP=(HBITMAP)LoadImage(GetModuleHandle(0), "bear.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );		if (!hBMP) {			std::cout << "Error loading texture\n";			return 0;		}		BITMAP bmp;		GetObject(hBMP, sizeof(bmp), &bmp);			glGenTextures(1, &texture);		glBindTexture(GL_TEXTURE_2D, texture);		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);		glTexImage2D(GL_TEXTURE_2D, 0, 3, bmp.bmWidth, bmp.bmHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, bmp.bmBits);		glGenerateMipmap(GL_TEXTURE_2D);		DeleteObject(hBMP);		glBindTexture(GL_TEXTURE_2D, 0); //clear texture binding (from unit 0)	}	//create sampler	{		glGenSamplers(1, &sampler);		glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S,  GL_CLAMP_TO_EDGE);			}	/*{		GLuint testSampler;		glGenSamplers(1, &testSampler);		glSamplerParameteri(testSampler, GL_TEXTURE_WRAP_T,  GL_CLAMP_TO_EDGE);		glBindSampler(0, testSampler);	}*/	return true;}void run() {	//code involving texture unit	glUseProgram(program);	glUniform1i(glGetUniformLocation(program, "colorMap"), textureUnit);	glBindSampler(textureUnitForSampler, sampler);	glActiveTexture(GL_TEXTURE0+textureUnit);	glBindTexture(GL_TEXTURE_2D, texture);	//	glViewport(0,0,screenWidth, screenHeight);	//clear screen	glClearColor(0.3f, 0.4f, 0.7f, 1.0f);	glClear(GL_COLOR_BUFFER_BIT);	//draw square	glBegin(GL_QUADS);	glTexCoord2f(0,0); glVertex2f(-1,-1);	glTexCoord2f(5,0); glVertex2f(1,-1);	glTexCoord2f(5,5); glVertex2f(1,1);	glTexCoord2f(0,5); glVertex2f(-1,1);	glEnd();}LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {	if(msg == WM_DESTROY) {		PostQuitMessage(0);		return 0;	} else if(msg == WM_SIZE) {		screenWidth = LOWORD(lParam);		screenHeight = HIWORD(lParam);	} else if((msg==WM_KEYDOWN) && (wParam==VK_ESCAPE)) {		PostQuitMessage(0);	}		return DefWindowProc(hWnd, msg, wParam, lParam);}void main() {	//create window	HINSTANCE hInstance = GetModuleHandle(0);	WNDCLASS wc = {CS_CLASSDC|CS_DBLCLKS, WndProc, 0, 0, hInstance, 0, LoadCursor(0, IDC_ARROW), (HBRUSH)COLOR_WINDOW, 0, "app"};	RegisterClass(&wc);	HWND window = CreateWindow(wc.lpszClassName, "app",  WS_OVERLAPPED|WS_MINIMIZEBOX|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, 		CW_USEDEFAULT,CW_USEDEFAULT , 800, 600, 0, 0, hInstance, 0);		//	HDC dc=GetDC(window);	//init opengl	HGLRC rc=0;		PIXELFORMATDESCRIPTOR pfd;	ZeroMemory( &pfd, sizeof(pfd));	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);	pfd.nVersion = 1;	pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;	pfd.iPixelType = PFD_TYPE_RGBA;	pfd.cColorBits = 32;	pfd.cDepthBits = 32;	pfd.iLayerType = PFD_MAIN_PLANE;		int nPixelFormat = ChoosePixelFormat(dc, &pfd);	if(nPixelFormat == 0) {		OutputDebugString("ChoosePixelFormat error\n");		return;	}	if(!SetPixelFormat (dc, nPixelFormat, &pfd)) {		OutputDebugString("SetPixelFormat error\n");		return;	}	HGLRC tempContext = wglCreateContext(dc);	wglMakeCurrent(dc, tempContext);	if (GLEW_OK != glewInit()) {		OutputDebugString("glewInit error\n");		return;	}	if(wglewIsSupported("WGL_ARB_create_context") == 1) {		wglMakeCurrent(0, 0);		wglDeleteContext(tempContext);		int attribs[] =	{			WGL_CONTEXT_MAJOR_VERSION_ARB, 3,			WGL_CONTEXT_MINOR_VERSION_ARB, 3,			//WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,			WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,			//WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,			0		};		rc = wglCreateContextAttribsARB(dc,0, attribs);		wglMakeCurrent(dc, rc);		wglSwapIntervalEXT(1);		std::cout << glGetString(GL_VERSION) << std::endl;	} else {		OutputDebugString("wglewIsSupported error\n");		return;	}		ShowWindow(window, SW_SHOW);	//	if(!init()) {		ShowWindow(window, SW_HIDE);		system("pause");		return;	}	//start message loop	MSG msg;	ZeroMemory(&msg, sizeof(MSG));		while(msg.message != WM_QUIT) {		if(IsIconic(window)) {// || GetForegroundWindow() != window			if(GetMessage(&msg, 0,0,0) > 0) {				TranslateMessage(&msg); 				DispatchMessage(&msg); 			}		} else if(PeekMessage(&msg, 0,0,0, PM_REMOVE)) {			TranslateMessage(&msg);			DispatchMessage(&msg);		} else {			run();			SwapBuffers(dc);						GLenum gerr = glGetError();						if(gerr != GL_NO_ERROR) {				std::cout << "glerror: " << gluErrorString(gerr) << std::endl;			}		}	}		}


Vertex shader:
varying vec2 t;void main() {	gl_Position = ftransform();	t = gl_MultiTexCoord0.st;}


Fragment shader:
uniform sampler2D colorMap;varying vec2 t;void main() {	gl_FragColor = texture2D(colorMap, t);}
I tested on my nVidia 8600 M with drivers I downloaded 1 month ago and it works fine. It does look like GL_CLAMP_TO_EDGE for the S component.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Thank you, then it must be the ati radeon 4800 drivers that is the problem, even with the latest drivers.

This topic is closed to new replies.

Advertisement