Jump to content
  • Advertisement
Sign in to follow this  
andrew111

OpenGL glBindSampler weirdness

This topic is 2827 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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);
}








Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!