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);}