Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Getting GL_STENCIL_BITS returns 0

  1. #1
    Junior Member Newbie
    Join Date
    Mar 2017
    Posts
    28

    Getting GL_STENCIL_BITS returns 0

    I wanted to know the value of GL_STENCIL_BITS on my computer, but I tried glGetIntegerv() with it, I got 0. I don't think it should be 0 though. Has anyone had this result before, and found a way to get a reasonable number?

    I made a bare minimum code file to show what I tried with glGetIntegerv. The stencil get code is before the while loop. I initialized the variable `stencil_bits` to 0 because when I didn't, I'd get a value of 1 on a 64-bit build of GLEW and GLFW or a value like 1400537549 in a 32-bit build. 1 seems too small, and 1400537549 seems way too big.

    Code :
    #include <iostream>
    #define GLEW_STATIC
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
     
    int main()
    {
    	// Initialize GLFW
    	glfwInit();
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    	GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
    	glfwMakeContextCurrent(window);
     
    	// Initialize GLEW
    	glewExperimental = GL_TRUE;
    	glewInit();
     
    	// Setup viewport
    	int width, height;
    	glfwGetFramebufferSize(window, &width, &height);
    	glViewport(0, 0, width, height);
     
    	// Enable stencil test, and get stencil bits
    	glEnable(GL_STENCIL_TEST);
    	int stencil_bits = 0;
    	glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
    	std::cout << stencil_bits;
     
    	// window loop
    	while (!glfwWindowShouldClose(window)) {
    		glfwPollEvents();
    		glfwSwapBuffers(window);
    	}
     
    	return 0;
    }

    Someone in an OpenGL post a long time ago said something about `glutDisplayMode(....|GL_STENCIL_BUFFER)`, but I don't know how to do that in GLFW. If this could fix the problem, does anyone know the equivalent function in GLFW?

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,402
    GL_STENCIL_BITS isn't a valid enumerant for glGetIntegerv() in OpenGL 3.3 core profile. You're supposed to use glGetFramebufferAttachmentParameteriv() with GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE instead.

    The GLFW equivalent of glutDisplayMode() is glfwWindowHint(), but the default is 8 stencil bits.

  3. #3
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,123
    See this link. Search for "stencil".

  4. #4
    Junior Member Newbie
    Join Date
    Mar 2017
    Posts
    28
    I tried glGetFramebufferAttachmentParameteriv() like GClements recommended:

    Code :
    glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER,
    	GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);

    `std::cout << stencil_bits` still gave me 0 though. Oddly, the .exe I built returns 8 on a university computer and my friend's computer, as expected, for both `glGetIntegerv()` and `glGetFramebufferAttachmentParameteriv()`. Could there be a bug in my drivers or something that I could report?

    Anyways, thanks for the glfw function and the link.

  5. #5
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,683
    This can be hardware-dependent. If your graphics hardware does not support a stencil buffer, then no amount of asking for one will give you one. It's always useful if you say what your hardware is.

    I suggest that you run the OpenGL Extensions Viewer then in the left-pane select "Display Modes & Pixel Formats", and in the bottom "Pixel Formats" section use the numeric up-down control to scroll through the available formats on your PC, looking for anything with 8 stencil bits.

  6. #6
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,123
    Possibly related:
    * https://www.monkey-x.com/Community/p...hp?topic=10454

    If you want a stencil buffer, you should request it. For instance:
    glfwWindowHint( GLFW_STENCIL_BITS, 8 );
    glfwWindowHint( GLFW_DEPTH_BITS , 24 );

  7. #7
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    418
    Quote Originally Posted by Dark Photon View Post
    Possibly related:
    * https://www.monkey-x.com/Community/p...hp?topic=10454

    If you want a stencil buffer, you should request it. For instance:
    glfwWindowHint( GLFW_STENCIL_BITS, 8 );
    glfwWindowHint( GLFW_DEPTH_BITS , 24 );
    That would therefore be against the glfw documentation (as also stated by GClements). In this case, this is probably a bug whether in their documentation or their code... Because if the default hint stencil is set to be 8 but is not honored, and then an explicit user call to set the stencil hint will work, there is something wrong somewhere...

  8. #8
    Junior Member Newbie
    Join Date
    Mar 2017
    Posts
    28
    I tried those two `glfwWindowHint` calls before trying to get the stencil size, but I'm still getting 0 bits.

    I'm pretty sure I have a stencil buffer. I was able to run the Stencil Testing tutorial on Learn OpenGL. Functions like `glStencilOp`, `glStencilFunc`, and `glStencilMask` work as expected.

    I tried OpenGL Extensions Viewer, and I was able to find my stencil bits. WGL_STENCIL_BITS_ARB = 8, which I'm happy to know now. It was in Pixel Format 3, if that means anything. Pixel Format 1 and 2 gives 0 for that value. It's weird to me how I can't get a gl function to return something like 8 bits. Does anyone think it's still possible?

    Here's my laptop's hardware settings I got from the extensions viewer, as requested, if it helps.
    System Info.
    Renderer: Intel(R) HD Graphics 4000
    Adapter RAM: 2048 MB
    Monitor: Generic PnP Monitor
    Display: 1600 x 900 x 32 bpp (60 Hz)
    Operating System: Microsoft Windows 8.1
    Processor: Intel(R) Core(TM) i7-3632QM CPU @ 2.20GHz, Ivy Bridge, Family 6h, Model: 3ah, Stepping: 9h

    OpenGL
    Version: 4.0
    Driver version: 12.104.0.0 (28-Mar-13)

  9. #9
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,683
    The Intel HD 4000 does have stencil support, and it's possible to create a context with a 24/8 depth/stencil buffer using either native WGL (I don't know about GL on other platforms) or D3D, so this seems a bug in GLFW's context creation if anything.

    I do recall that with some older Intels you will be given a 16/0 depth/stencil buffer if you request anything that's not supported in hardware, but I haven't seen this behaviour in at least 5 years.

    Does GLFW allow you to enumerate the pixel formats and explicitly select one? Because unfortunately GL context creation can be loosely-specified and can be allowed give you a "best" approximation to what you ask for rather than an exact match (with a failure and meaningful error if it can't), and it seems you're falling into that hole.

  10. #10
    Member Regular Contributor
    Join Date
    May 2016
    Posts
    416
    one way to the around this problem is to use your own framebuffer, it also has some advantages that the defalt framebuffer hasnt, you can use texture attachments and read from those later in a fragment shader (if you want, for example to post-process the frame)

    try this code: (it gives me 24 bits depth + 8 bits stencil)
    ("me" means intel core i5 4430 + NVIDIA GT640)
    Code :
    #include <iostream>
    #define GLEW_STATIC
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
     
     
     using namespace std;
     
     
     void CheckForGLError()
    {
        for (GLenum error; (error = glGetError()) != GL_NO_ERROR;)
        {
            cout << "OpenGL Error:  \t";
            if (error == GL_INVALID_ENUM)
                cout << "GL_INVALID_ENUM";
            if (error == GL_INVALID_VALUE)
                cout << "GL_INVALID_VALUE";
            if (error == GL_INVALID_OPERATION)
                cout << "GL_INVALID_OPERATION";
            if (error == GL_STACK_OVERFLOW)
                cout << "GL_STACK_OVERFLOW";
            if (error == GL_STACK_UNDERFLOW)
                cout << "GL_STACK_UNDERFLOW";
            if (error == GL_OUT_OF_MEMORY)
                cout << "GL_OUT_OF_MEMORY";
            if (error == GL_INVALID_FRAMEBUFFER_OPERATION)
                cout << "GL_INVALID_FRAMEBUFFER_OPERATION";
            if (error == GL_CONTEXT_LOST)
                cout << "GL_CONTEXT_LOST";
            cout << (char)7 << endl;        /*play sound*/
            cin.get();
        }
    }
     
     
    void glfw_error_callback(int error, const char* description)
    {
        cout << "GLFW ERROR: \t" << description << endl;
    }
     
     
    void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
        glViewport(0, 0, width, height);
    }
     
     
    void Render()
    {
        /* clear framebuffer */
        glClearColor(0, 1, 0, 0);
        glClearDepth(1);
        glClearStencil(0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
     
        /* render here */
     
        /* check for GL errors */
        CheckForGLError();
    }
     
     
    int main()
    {
    	// Initialize GLFW
    	if (!glfwInit())
            return -1;
     
        bool fullscreen = false;
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    	glfwWindowHint(GLFW_STENCIL_BITS, 8);
     
    	GLFWmonitor* monitor = NULL;
    	if (fullscreen)
            monitor = glfwGetPrimaryMonitor();
    	GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", monitor, nullptr);
    	if (!window)
        {
            glfwTerminate();
            return 1;
        }
     
    	glfwMakeContextCurrent(window);
    	glfwSetErrorCallback(glfw_error_callback);
    	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
     
     
    	// Initialize GLEW
    	glewExperimental = GL_TRUE;
    	if (glewInit() != GLEW_OK)
        {
            glfwTerminate();
            return 2;
        }
     
    	// Setup viewport
    	int width, height;
    	glfwGetFramebufferSize(window, &width, &height);
    	glViewport(0, 0, width, height);
     
    	/**
    	If the specified framebuffer is a framebuffer object, attachment must be one of
            GL_DEPTH_ATTACHMENT,
            GL_STENCIL_ATTACHMENT,
            GL_DEPTH_STENCIL_ATTACHMENT,
            or GL_COLOR_ATTACHMENTi, where i is between zero and the value of GL_MAX_COLOR_ATTACHMENTS minus one.
     
        If the specified framebuffer is a default framebuffer, target, attachment must be one of
            GL_FRONT_LEFT,
            GL_FRONT_RIGHT,
            GL_BACK_LEFT,
            GL_BACK_RIGHT,
            GL_DEPTH
            or GL_STENCIL, identifying the corresponding buffer.
    	**/
    	GLint depth_bits = 0, stencil_bits = 0;
    	glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits);
    	glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
    	cout << "depth bits: " << depth_bits << endl;
    	cout << "stencil bits: " << stencil_bits << endl;
     
    	// window loop
    	while (!glfwWindowShouldClose(window)) {
            Render();
    		glfwPollEvents();
    		glfwSwapBuffers(window);
    	}
     
    	return 0;
    }

    its important to check for errors (GL errors or others, like glfw errors), otherwise you dont know whats wrong with your code
    Last edited by john_connor; 04-22-2017 at 12:37 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •