<p>This is possible with only a single framebuffer and a single texture (with mips).</p>
<p>To select the mip level to <em>render to</em>, you can use <code>glFramebufferTexture2D</code>, as in the example you gave. Be sure to also set glViewport to the width/height of the mip you are rendering to.</p>
<pre><code>glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmaplevelToRenderTo);
glViewport(0, 0, mipWidth, mipHeight);
</code></pre>
<p>Then, to limit the mip level that you're sampling from, the safest<sup>1</sup> way is to use the <code>GL_TEXTURE_BASE_LEVEL</code> and <code>GL_TEXTURE_MAX_LEVEL</code> texture parameters.</p>
<pre><code>glBindTexture(GL_TEXTURE_2D, textureID);
int mipToSampleFrom = mipmaplevelToRenderTo - 1;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, mipToSampleFrom);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipToSampleFrom);
</code></pre>
<p>This will allow you to use <code>texture(sampler, uv)</code> (or similar) in your shader as normal, and it will only sample from the one mip level you specified. Note that <code>GL_TEXTURE_BASE_LEVEL</code> also changes the meaning of GLSL functions like <code>textureSize()</code>, which takes a <em>lod</em> parameter: if you've modified <code>GL_TEXTURE_BASE_LEVEL</code>, then <em>lod</em> will be relative to the base level, meaning that <code>textureSize(sampler, 0)</code> will conveniently return the size of the currently configured base mip level.</p>
<p>To reset, just set those params to their default OpenGL values:</p>
<pre><code>glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);
</code></pre>
<hr />
<p><sup>1</sup> Whenever a texture is sampled from while also being rendered to, you can run the risk of hitting undefined behavior. The OpenGL spec is fairly conservative about what can constitute undefined behavior, even if the shader wouldn't <em>actually</em> ever sample from the same texel that it's writing to, so one way to avoid the issue is to make it <em>impossible</em> by using the <code>GL_TEXTURE_BASE_LEVEL</code> and <code>GL_TEXTURE_MAX_LEVEL</code> params. See the spec for details: <a href="https://registry.khronos.org/OpenGL/specs/es/3.0/es_spec_3.0.pdf#page=224" rel="nofollow noreferrer">https://registry.khronos.org/OpenGL/specs/es/3.0/es_spec_3.0.pdf#page=224</a></p>

CC BY-SA 4.0
2022-12-27T21:44:52.153Z
2022-12-27T21:44:52.153Z
voithos
<p>I am trying to generate mipmaps, which are based on depthbuffer values. To generate the next mipmap level, I am trying to read in the 4 pixels of the upper mipmap level per pixel. Unlike the usual mipmap generation. I am checking the depth values, and only averaging those of the 4 pixels which are in depth range.
To do so, I need to read in the next larger mipmap level than the current one I am suppose to render to.
I know, that reading from the same texture than rendering to is not allowed. but I found this post on stackoverflow: <a href="https://stackoverflow.com/questions/44349792/is-it-possible-to-render-to-textures-mipmap-level-1-while-sampling-from-level-0">https://stackoverflow.com/questions/44349792/is-it-possible-to-render-to-textures-mipmap-level-1-while-sampling-from-level-0</a>
Here in the comments one person is talking about &quot;texture mipmap range specifiers&quot;. Does that mean, that I don't need to use two framebuffers (one for reading and one for writing and for each mipmap level switching between these both framebuffers?) with two textures to do what I am trying? If so. How can I specify which mipmap should be read from the shader?
I am using</p>
<pre><code>  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmaplevelToRenderTo);
</code></pre>
<p>command to render into a specific mipmap level. And I only want to read pixels from level &quot;mipmaplevelToRenderTo - 1&quot;</p>

CC BY-SA 4.0
2021-12-21T20:01:14.323Z
If I correctly understand the wiki article referenced in the comments to the linked question, setting the filtering mode to one that doesn't use mipmaps should be sufficient.
lisyarus
<opengl><mipmap>
OpenGL: read texture mipmap level 0 and render to same texture mipmap level 1
Thomas
# OpenGL: read texture mipmap level 0 and render to same texture mipmap level 1

(Asked by: username_0 on 2021-12-21)

I am trying to generate mipmaps, which are based on depthbuffer values. To generate the next mipmap level, I am trying to read in the 4 pixels of the upper mipmap level per pixel. Unlike the usual mipmap generation. I am checking the depth values, and only averaging those of the 4 pixels which are in depth range.
To do so, I need to read in the next larger mipmap level than the current one I am suppose to render to.
I know, that reading from the same texture than rendering to is not allowed. but I found this post on stackoverflow: <https://stackoverflow.com/questions/44349792/is-it-possible-to-render-to-textures-mipmap-level-1-while-sampling-from-level-0>
Here in the comments one person is talking about "texture mipmap range specifiers". Does that mean, that I don't need to use two framebuffers (one for reading and one for writing and for each mipmap level switching between these both framebuffers?) with two textures to do what I am trying? If so. How can I specify which mipmap should be read from the shader?
I am using

```
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmaplevelToRenderTo);

```

command to render into a specific mipmap level. And I only want to read pixels from level "mipmaplevelToRenderTo - 1"

**Tags:** opengl, mipmap

> **Comments:**
> **username_1**: If I correctly understand the wiki article referenced in the comments to the linked question, setting the filtering mode to one that doesn't use mipmaps should be sufficient.  

---

## 1 answers

### Answer by username_2 on 2022-12-27. Score: 4 | Accepted answer

This is possible with only a single framebuffer and a single texture (with mips).

To select the mip level to *render to*, you can use `glFramebufferTexture2D`, as in the example you gave. Be sure to also set glViewport to the width/height of the mip you are rendering to.

```
glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmaplevelToRenderTo);
glViewport(0, 0, mipWidth, mipHeight);

```

Then, to limit the mip level that you're sampling from, the safest1 way is to use the `GL_TEXTURE_BASE_LEVEL` and `GL_TEXTURE_MAX_LEVEL` texture parameters.

```
glBindTexture(GL_TEXTURE_2D, textureID);
int mipToSampleFrom = mipmaplevelToRenderTo - 1;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, mipToSampleFrom);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipToSampleFrom);

```

This will allow you to use `texture(sampler, uv)` (or similar) in your shader as normal, and it will only sample from the one mip level you specified. Note that `GL_TEXTURE_BASE_LEVEL` also changes the meaning of GLSL functions like `textureSize()`, which takes a *lod* parameter: if you've modified `GL_TEXTURE_BASE_LEVEL`, then *lod* will be relative to the base level, meaning that `textureSize(sampler, 0)` will conveniently return the size of the currently configured base mip level.

To reset, just set those params to their default OpenGL values:

```
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);

```

---

1 Whenever a texture is sampled from while also being rendered to, you can run the risk of hitting undefined behavior. The OpenGL spec is fairly conservative about what can constitute undefined behavior, even if the shader wouldn't *actually* ever sample from the same texel that it's writing to, so one way to avoid the issue is to make it *impossible* by using the `GL_TEXTURE_BASE_LEVEL` and `GL_TEXTURE_MAX_LEVEL` params. See the spec for details: <https://registry.khronos.org/OpenGL/specs/es/3.0/es_spec_3.0.pdf#page=224>


---

