opengl create a depth_stencil texture for reading
Asked Answered
K

2

6

I'm using defered rendering in my application and i'm trying to create a texture that will contain both the depth and the stencil.

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0,
???, GL_FLOAT, 0);

Now what format enum does opengl want for this particular texture. I tried a couple and got error for all of them

Also, what is the correct glsl syntax to access the depth and stencil part of the texture. I understand that depth texture are usually uniform sampler2Dshadow. But do I do

float depth = texture(depthstenciltex,uv).r;// <- first bit ? all 32 bit ? 24 bit ?
float stencil = texture(depthstenciltex,uv).a;
Kutchins answered 17/12, 2014 at 22:5 Comment(0)
N
15

Now what format enum does opengl want for this particular texture.

The problem you are running into is that Depth+Stencil is a totally oddball combination of data. The first 24-bits (depth) are fixed-point and the remaining 8-bits (stencil) are unsigned integer. This requires a special packed data type: GL_UNSIGNED_INT_24_8

Also, what is the correct glsl syntax to access the depth and stencil part of the texture. I understand that depth texture are usually uniform sampler2Dshadow.

You will actually never be able to sample both of those things using the same sampler uniform and here is why:

OpenGL Shading Language 4.50 Specification  -  8.9 Texture Functions  -  p. 158

For depth/stencil textures, the sampler type should match the component being accessed as set through the OpenGL API. When the depth/stencil texture mode is set to GL_DEPTH_COMPONENT, a floating-point sampler type should be used. When the depth/stencil texture mode is set to GL_STENCIL_INDEX, an unsigned integer sampler type should be used. Doing a texture lookup with an unsupported combination will return undefined values.

This means if you want to use both the depth and stencil in a shader you are going to have to use texture views (OpenGL 4.2+) and bind those texture to two different Texture Image Units (each view have a different state for GL_DEPTH_STENCIL_TEXTURE_MODE). Both of these things together mean you are going to need at least an OpenGL 4.4 implementation.

Fragment shader that samples depth and stencil:

#version 440
// Sampling the stencil index of a depth+stencil texture became core in OpenGL 4.4

layout (binding=0) uniform sampler2D  depth_tex;
layout (binding=1) uniform usampler2D stencil_tex;

in vec2 uv;

void main (void) {
  float depth   = texture (depth_tex,   uv);
  uint  stencil = texture (stencil_tex, uv);
}

Create a stencil view texture:

// Alternate view of the image data in `depth_stencil_texture`
GLuint stencil_view;
glGenTextures (&stencil_view, 1);
glTextureView (stencil_view, GL_TEXTURE_2D, depth_stencil_tex,
               GL_DEPTH24_STENCIL8, 0, 1, 0, 1);

// ^^^ This requires `depth_stencil_tex` be allocated using `glTexStorage2D (...)`
//       to satisfy `GL_TEXTURE_IMMUTABLE_FORMAT` == `GL_TRUE`

OpenGL state setup for this shader:

// Texture Image Unit 0 will treat it as a depth texture
glActiveTexture (GL_TEXTURE0);
glBindTexture   (GL_TEXTURE_2D, depth_stencil_tex);
glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);

// Texture Image Unit 1 will treat the stencil view of depth_stencil_tex accordingly
glActiveTexture (GL_TEXTURE1);
glBindTexture   (GL_TEXTURE_2D, stencil_view);
glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
Necker answered 17/12, 2014 at 22:38 Comment(6)
Probably a workaround is creating a texture view of the original texture, and set a different GL_DEPTH_TEXTURE_STENCIL_MODE for the view.Dekker
@peppe: Thank you for your suggestion. I had that thought too but then I foolishly thought that wouldn't work because GL_DEPTH24_STENCIL8 is not a member of GL_VIEW_CLASS_32_BITS. However, since the internal formats of both textures exactly match that does not matter. I have updated my answer.Necker
@AndonM.Coleman This is an old topic, but may be you could help me? In case I don't want to access stencil values in shader, but use stencil regularly as a mask, how should I work with stencil attachment? Here is what I tried - #43504528. Will appreciate any comment, thanksPlagio
I guess you included it just for clarity, but the line glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_STENCIL_MODE, GL_DEPTH_COMPONENT); can be omitted, since the initial value of GL_DEPTH_TEXTURE_STENCIL_MODE is GL_DEPTH_COMPONENT.Descent
this shader code won't compile in later versions. In #version 460, calling texture() on a sampler2D always returns a vec4, for a usampler2D it will return uvec4. I don't know what to do now....Jillion
@Jillion I made a complete guess at it in my code, since it doesn't seem to be documented anywhere, but uint stencilBits = texture(texture0, coord).r; does seem to pull out the actual stencil byte (assuming texture0 is a usampler2D that contains the depth/stencil texture, and GL_STENCIL_INDEX is enabled.) For what it's worth, the .g and .b properties seem to both consistently be 0, while .a seems to consistently be 255. I don't know if I'd trust those last values to be consistent across hardware, but .r seems to be the answer.Uriisa
K
2

nvm found it

glTexImage2D(gl.TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w,h,0,GL_DEPTH_STENCIL,
GL_UNSIGNED_INT_24_8, 0);

uint24_8 was my problem.

usage in glsl (330):

sampler2D depthstenciltex;
...
float depth = texture(depthstenciltex,uv).r;//access the 24 first bit, 
//transformed between [0-1]
Kutchins answered 17/12, 2014 at 22:36 Comment(1)
Actually, only the first 24 bits are available for you, the other (stencil) bits are undefined. The initial value of GL_DEPTH_TEXTURE_STENCIL_MODE property of a texture is GL_DEPTH_COMPONENT, so you can sample the depth component of your combined depth/stencil texture without changing any parameter of your texture object. If you would want to sample the stencil index of your combined depth/stencil texture, then you could set the texture's GL_DEPTH_TEXTURE_STENCIL_MODE to GL_STENCIL_INDEX just like @Andon showed you in his answer.Descent

© 2022 - 2024 — McMap. All rights reserved.