<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:discourse="http://www.discourse.org/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>OpenGL - Khronos Forums</title>
    <link>https://community.khronos.org/c/opengl-general/34</link>
    <description>Topics in the &#39;OpenGL&#39; category General OpenGL questions that do not fit into any of the other categories</description>
    
      <lastBuildDate>Thu, 28 May 2026 08:39:01 +0000</lastBuildDate>
      <atom:link href="https://community.khronos.org/c/opengl-general/34.rss" rel="self" type="application/rss+xml" />
        <item>
          <title>Is it possible to render HDR in OpenGL 4.1 on macOS or iPadOS</title>
          <dc:creator><![CDATA[markc]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>I am trying to get my macOS app to render in HDR with an HDR texture. It is rendering but not in HDR. The app uses SDL3. I set {RED,GREEN,BLUE}_SIZE to 16 before creating the SDL window and the GL context. The app is rendering a textured quad using a GL_RGBA16F format texture. Is there something else I need to do? Is it even possible?</p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/is-it-possible-to-render-hdr-in-opengl-4-1-on-macos-or-ipados/112551">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/is-it-possible-to-render-hdr-in-opengl-4-1-on-macos-or-ipados/112551</link>
          <pubDate>Thu, 28 May 2026 08:39:01 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112551</guid>
          <source url="https://community.khronos.org/t/is-it-possible-to-render-hdr-in-opengl-4-1-on-macos-or-ipados/112551.rss">Is it possible to render HDR in OpenGL 4.1 on macOS or iPadOS</source>
        </item>
        <item>
          <title>Error in loading fragment shader from frag.glsl</title>
          <dc:creator><![CDATA[ArunSharma-2]]></dc:creator>
          <category>OpenGL: Basic Coding</category>
          <description><![CDATA[
            <p>this is my fragment shader from shader/frag.glsl</p>
<p><span class="hashtag-raw">#version</span> 330 core<br>
out vec4 aColor;<br>
void main(){<br>
aColor = vec4(1.0, 0.0, 0.0, 1.0);<br>
}</p>
<p>there are no errors in program compiling but on running the “app.exe” i am getting this error</p>
<p>ERROR::SHADER::COMPILATION_FAILED<br>
ERROR: 0:1: ‘’ : illegal character (0x1)<br>
ERROR: 0:1: ‘’ : illegal non-ASCII character (0xb6)<br>
ERROR: 0:1: ‘’ : illegal non-ASCII character (0xc4)<br>
ERROR: 0:1: ‘’ : illegal character (0x2)<br>
WARNING: 0:1: ‘’ :  <span class="hashtag-raw">#version</span> directive missing<br>
ERROR: 0:1: ‘PZ’ : syntax error syntax error</p>
<p>This is my loadShader program:</p>
<p>std::string loadShader(const std::string&amp; path){</p>
<pre><code>std::string result;

std::string line;

std::ifstream myFile(path.c_str());

if (myFile.is_open()) {

    while (std::getline(myFile, line)) {

        result += line + "\\n";

    }

    myFile.close();

} else {

    std::cerr &lt;&lt; "Could not read file " &lt;&lt; path &lt;&lt; ". File does not exist.\\n";

}

return result;
</code></pre>
<p>};</p>
<p>this is working fine for vert.glsl .</p>
<p>i also tried to load vert.glsl from file and fragemt shader using</p>
<p>“<span class="hashtag-raw">#version</span> 330 core\n”</p>
<pre><code>    "out vec4 aColor;\\n"

    "void main()\\n"

    "{\\n"

    "    aColor = vec4(1.0f, 0.0, 0.0, 1.0);\\n"

    "}\\0";
</code></pre>
<p>this combo is working file .</p>
<p>help me where i am wrong in loading fragment shader from frag.glsl .</p>
            <p><small>4 posts - 4 participants</small></p>
            <p><a href="https://community.khronos.org/t/error-in-loading-fragment-shader-from-frag-glsl/112549">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/error-in-loading-fragment-shader-from-frag-glsl/112549</link>
          <pubDate>Thu, 28 May 2026 07:55:58 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112549</guid>
          <source url="https://community.khronos.org/t/error-in-loading-fragment-shader-from-frag-glsl/112549.rss">Error in loading fragment shader from frag.glsl</source>
        </item>
        <item>
          <title>How to set opengl up on linux manuelly (no ide) with clang?</title>
          <dc:creator><![CDATA[elevatedCluelessness]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>Hi,</p>
<p>I have installed opengl with arch linus’s packages via AUR and pacman repos but still get linker errors trying to compile some examples like below:</p>
<pre><code class="lang-auto">$ clang -v dials.c 
clang version 22.1.2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/15.2.1
Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1
Selected GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
Found HIP installation: /opt/rocm, version 7.2.53211
 "/usr/bin/clang-22" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dials.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/alek/Downloads/examples/examples -v -fcoverage-compilation-dir=/home/alek/Downloads/examples/examples -resource-dir /usr/lib/clang/22 -internal-isystem /usr/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../x86_64-pc-linux-gnu/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fmessage-length=190 -stack-protector 2 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -faddrsig -fdwarf2-cfi-asm -o /tmp/dials-08e501.o -x c dials.c
clang -cc1 version 22.1.2 based upon LLVM 22.1.2 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../x86_64-pc-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include &lt;...&gt; search starts here:
 /usr/lib/clang/22/include
 /usr/local/include
 /usr/include
End of search list.
 "/usr/bin/ld" --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -pie -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../lib64/Scrt1.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../lib64/crti.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/crtbeginS.o -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1 -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../lib64 -L/lib/../lib64 -L/usr/lib64 -L/lib -L/usr/lib /tmp/dials-08e501.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/crtendS.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../lib64/crtn.o
/usr/bin/ld: /tmp/dials-08e501.o: in function `drawCircle':
dials.c:(.text+0x15): undefined reference to `glPushMatrix'
/usr/bin/ld: dials.c:(.text+0x27): undefined reference to `glTranslatef'
/usr/bin/ld: dials.c:(.text+0x31): undefined reference to `glBegin'
/usr/bin/ld: dials.c:(.text+0x3c): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0x72): undefined reference to `cos'
/usr/bin/ld: dials.c:(.text+0x9f): undefined reference to `sin'
/usr/bin/ld: dials.c:(.text+0xb9): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0xe1): undefined reference to `glEnd'
/usr/bin/ld: dials.c:(.text+0xf4): undefined reference to `glColor3f'
/usr/bin/ld: dials.c:(.text+0xfe): undefined reference to `glBegin'
/usr/bin/ld: dials.c:(.text+0x109): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0x135): undefined reference to `cos'
/usr/bin/ld: dials.c:(.text+0x176): undefined reference to `sin'
/usr/bin/ld: dials.c:(.text+0x190): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0x195): undefined reference to `glEnd'
/usr/bin/ld: dials.c:(.text+0x19a): undefined reference to `glPopMatrix'
/usr/bin/ld: /tmp/dials-08e501.o: in function `displayDials':
dials.c:(.text+0x1be): undefined reference to `glClear'
/usr/bin/ld: dials.c:(.text+0x1e3): undefined reference to `glColor3f'
/usr/bin/ld: dials.c:(.text+0x232): undefined reference to `glutSwapBuffers'
/usr/bin/ld: /tmp/dials-08e501.o: in function `displayButtons':
dials.c:(.text+0x24e): undefined reference to `glClear'
/usr/bin/ld: dials.c:(.text+0x258): undefined reference to `glBegin'
/usr/bin/ld: dials.c:(.text+0x2bd): undefined reference to `glColor3f'
/usr/bin/ld: dials.c:(.text+0x2d2): undefined reference to `glColor3f'
/usr/bin/ld: dials.c:(.text+0x301): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0x330): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0x35f): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0x38e): undefined reference to `glVertex2f'
/usr/bin/ld: dials.c:(.text+0x3aa): undefined reference to `glEnd'
/usr/bin/ld: dials.c:(.text+0x3af): undefined reference to `glutSwapBuffers'
/usr/bin/ld: /tmp/dials-08e501.o: in function `reshape':
dials.c:(.text+0x3d9): undefined reference to `glViewport'
/usr/bin/ld: dials.c:(.text+0x3e3): undefined reference to `glMatrixMode'
/usr/bin/ld: dials.c:(.text+0x3e8): undefined reference to `glLoadIdentity'
/usr/bin/ld: dials.c:(.text+0x3fd): undefined reference to `gluOrtho2D'
/usr/bin/ld: dials.c:(.text+0x402): undefined reference to `glutGetWindow'
/usr/bin/ld: dials.c:(.text+0x422): undefined reference to `glScalef'
/usr/bin/ld: dials.c:(.text+0x436): undefined reference to `glTranslatef'
/usr/bin/ld: dials.c:(.text+0x440): undefined reference to `glMatrixMode'
/usr/bin/ld: /tmp/dials-08e501.o: in function `dodial':
dials.c:(.text+0x483): undefined reference to `glutSetWindow'
/usr/bin/ld: dials.c:(.text+0x488): undefined reference to `glutPostRedisplay'
/usr/bin/ld: /tmp/dials-08e501.o: in function `dobutton':
dials.c:(.text+0x4df): undefined reference to `glutSetWindow'
/usr/bin/ld: dials.c:(.text+0x4e4): undefined reference to `glutPostRedisplay'
/usr/bin/ld: /tmp/dials-08e501.o: in function `main':
dials.c:(.text+0x51c): undefined reference to `glutInit'
/usr/bin/ld: dials.c:(.text+0x526): undefined reference to `glutDeviceGet'
/usr/bin/ld: dials.c:(.text+0x561): undefined reference to `glutDeviceGet'
/usr/bin/ld: dials.c:(.text+0x5a4): undefined reference to `glutInitDisplayMode'
/usr/bin/ld: dials.c:(.text+0x5cb): undefined reference to `glutInitWindowSize'
/usr/bin/ld: dials.c:(.text+0x5d7): undefined reference to `glutCreateWindow'
/usr/bin/ld: dials.c:(.text+0x602): undefined reference to `glClearColor'
/usr/bin/ld: dials.c:(.text+0x60f): undefined reference to `glLineWidth'
/usr/bin/ld: dials.c:(.text+0x61f): undefined reference to `glutDialsFunc'
/usr/bin/ld: dials.c:(.text+0x62f): undefined reference to `glutButtonBoxFunc'
/usr/bin/ld: dials.c:(.text+0x63b): undefined reference to `glutDisplayFunc'
/usr/bin/ld: dials.c:(.text+0x64b): undefined reference to `glutReshapeFunc'
/usr/bin/ld: dials.c:(.text+0x657): undefined reference to `glutInitWindowSize'
/usr/bin/ld: dials.c:(.text+0x663): undefined reference to `glutCreateWindow'
/usr/bin/ld: dials.c:(.text+0x67e): undefined reference to `glClearColor'
/usr/bin/ld: dials.c:(.text+0x68a): undefined reference to `glutDisplayFunc'
/usr/bin/ld: dials.c:(.text+0x693): undefined reference to `glutReshapeFunc'
/usr/bin/ld: dials.c:(.text+0x69c): undefined reference to `glutDialsFunc'
/usr/bin/ld: dials.c:(.text+0x6a5): undefined reference to `glutButtonBoxFunc'
/usr/bin/ld: dials.c:(.text+0x6aa): undefined reference to `glutMainLoop'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
</code></pre>
            <p><small>4 posts - 3 participants</small></p>
            <p><a href="https://community.khronos.org/t/how-to-set-opengl-up-on-linux-manuelly-no-ide-with-clang/112519">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/how-to-set-opengl-up-on-linux-manuelly-no-ide-with-clang/112519</link>
          <pubDate>Sat, 25 Apr 2026 19:41:12 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112519</guid>
          <source url="https://community.khronos.org/t/how-to-set-opengl-up-on-linux-manuelly-no-ide-with-clang/112519.rss">How to set opengl up on linux manuelly (no ide) with clang?</source>
        </item>
        <item>
          <title>Looking for old version of glslangvalidater</title>
          <dc:creator><![CDATA[JoshKlint]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>I am looking for an old version of the glslangvalidater tool, as newer versions are focused on Vulkan. I want the best version for support of OpenGL 4.5. The ones on Khronos Github are all too new.<br>
I have a really old copy of it, but OpenGL 4.5 support is listed as “experimental”.</p>
<pre><code class="lang-auto">Usage: glslangValidator [option]... [file]...

Where: each 'file' ends in
    .conf to provide an optional config file that replaces the default configuration
          (see -c option below for generating a template)
    .vert for a vertex shader
    .tesc for a tessellation control shader
    .tese for a tessellation evaluation shader
    .geom for a geometry shader
    .frag for a fragment shader
    .comp for a compute shader

Compilation warnings and errors will be printed to stdout.

To get other information, use one of the following options:
(Each option must be specified separately, but can go anywhere in the command line.)
  -c  configuration dump; use to create default configuration file (redirect to a .conf file)
  -i  intermediate tree (glslang AST) is printed out
  -l  link validation of all input files
  -m  memory leak mode
  -q  dump reflection query database
  -r  relaxed semantic error-checking mode
  -s  silent mode
  -t  multi-threaded mode
  -v  print version strings
  -w  suppress warnings (except as required by #extension : warn)
</code></pre>
            <p><small>3 posts - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/looking-for-old-version-of-glslangvalidater/112509">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/looking-for-old-version-of-glslangvalidater/112509</link>
          <pubDate>Sat, 18 Apr 2026 02:00:34 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112509</guid>
          <source url="https://community.khronos.org/t/looking-for-old-version-of-glslangvalidater/112509.rss">Looking for old version of glslangvalidater</source>
        </item>
        <item>
          <title>OpenGL not displaying rectangle</title>
          <dc:creator><![CDATA[Leondagreatest]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>I have checked the entire codebase and have not been able to recognize the problem.</p>
<p>Here’s the main part where I hypothesize it lies:</p>
<pre><code>unsigned int vertexShader;

if(compileVertexShader(&amp;vertexShader, vertexShaderSource) == FAIL)
{
    return FAIL;
}

unsigned int fragmentShader;

if(compileFragmentShader(&amp;fragmentShader, fragmentShaderSource) == FAIL)
{
    return FAIL;
}

unsigned int shaderProgram;
shaderProgram = glCreateProgram();

glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

if(checkShaderProgramSuccess(shaderProgram) == FAIL)
{
    return FAIL;
}

glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

unsigned int VBO;
unsigned int VAO;
unsigned int EBO;

glGenVertexArrays(1, &amp;VAO);
glGenBuffers(1, &amp;VBO);
glGenBuffers(1, &amp;EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle.vertices), rectangle.vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(rectangle.indices), rectangle.indices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

while(!glfwWindowShouldClose(window))
{
    windowRender(window, shaderProgram, VBO, EBO);

    glfwPollEvents();
}

printf("Program closing due to user input. The program ran successfully without error.\n");

cleanup();

return SUCCESS;
</code></pre>
<p>And here’s the entire codebase</p>
<p>main.c</p>
<pre><code class="lang-auto">#include "main.h"

#include "window.h"
#include "display.h"
#include "shaders.h"

// gcc Assets/Code/main.c Assets/Code/window.c Assets/Code/display.c Assets/Code/shaders.c -lGLEW -lGL -lglfw -o "Game" -Wall

const char* vertexShaderSource = "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0";

const char* fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\0";

GLFWwindow* window;

float test_rectangle_vertices[] = {
        0.5f,  0.5f, 0.0f,  // top right
        0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left
    };

unsigned int test_rectangle_indices[] = {
    0, 1, 3,
    1, 2, 3
};

void cleanup()
{
    if(window)
    {
        glfwDestroyWindow(window);
    }

    glfwTerminate();
}

void print_glfw_error()
{
    const char* error_ptr;
    glfwGetError(&amp;error_ptr);

    printf("%s\n", error_ptr);
}

void print_glew_error(GLenum error)
{
    printf("%s\n", glewGetErrorString(error));
}

bool initialize_glew()
{
    // GLAD is not very glad, GLEW is what makes me glad

    GLenum glewinit_return_value = glewInit();

    if(glewinit_return_value != GLEW_OK)
    {
        print_glew_error(glewinit_return_value);
        handle_error(true, true); // clean up, and the error was fatal

        return FAIL;
    }

    return SUCCESS;
}

void handle_error(bool is_cleanup, bool is_fatal)
{
    if(is_fatal)
    {
        printf("Fatal error. Program aborted.\n");
    }

    if(is_cleanup)
    {
        cleanup();
    }
}

void createShape(Shape* rectangle, float* shape_vertices, unsigned int*  shape_indices)
{
    printf("Creating shape...\n");

    rectangle-&gt;vertices = shape_vertices;
    rectangle-&gt;indices = shape_indices;

    printf("Shape created.\n");
}

int main()
{
    if(!glfwInit())
    {
        print_glfw_error();
        handle_error(false, true); // do not clean up, and the error was fatal
        return FAIL;
    }

    window = createWindow();

    if(window == NULL)
    {
        return FAIL;
    }

    if(initialize_glew() == FAIL)
    {
        return FAIL;
    }

    glViewport(0, 0, 1920, 1080);

    Shape rectangle;

    createShape(&amp;rectangle, test_rectangle_vertices, test_rectangle_indices);

    unsigned int vertexShader;

    if(compileVertexShader(&amp;vertexShader, vertexShaderSource) == FAIL)
    {
        return FAIL;
    }

    unsigned int fragmentShader;

    if(compileFragmentShader(&amp;fragmentShader, fragmentShaderSource) == FAIL)
    {
        return FAIL;
    }

    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();

    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    if(checkShaderProgramSuccess(shaderProgram) == FAIL)
    {
        return FAIL;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    unsigned int VBO;
    unsigned int VAO;
    unsigned int EBO;

    glGenVertexArrays(1, &amp;VAO);
    glGenBuffers(1, &amp;VBO);
    glGenBuffers(1, &amp;EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle.vertices), rectangle.vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(rectangle.indices), rectangle.indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    while(!glfwWindowShouldClose(window))
    {
        windowRender(window, shaderProgram, VBO, EBO);

        glfwPollEvents();
    }

    printf("Program closing due to user input. The program ran successfully without error.\n");

    cleanup();

    return SUCCESS;
}
</code></pre>
<p>display.c</p>
<pre><code class="lang-auto">#include "main.h"

// Rectangle's gone. This is depressing.

void windowRender(GLFWwindow* window, unsigned int shaderProgram, unsigned int VAO, unsigned int EBO)
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    glfwSwapBuffers(window);
}
</code></pre>
<pre><code class="lang-auto">#include "main.h"

// Please stop

bool compileVertexShader(unsigned int* vertexShaderInput, const char* vertexShaderSourceInput)
{
    *vertexShaderInput = glCreateShader(GL_VERTEX_SHADER);

    glShaderSource(*vertexShaderInput, 1, &amp;vertexShaderSourceInput, NULL);
    glCompileShader(*vertexShaderInput);

    int is_successful;
    char infoLog[512];

    glGetShaderiv(*vertexShaderInput, GL_COMPILE_STATUS, &amp;is_successful);

    if(!is_successful)
    {
        glGetShaderInfoLog(*vertexShaderInput, 512, NULL, infoLog);
        printf("Vertex shader compilation failed. Error log is as follows:\n%s", infoLog);

        handle_error(true, true); // clean up, and the error was fatal

        return FAIL;
    }

    return SUCCESS;
}

bool compileFragmentShader(unsigned int* fragmentShaderInput, const char* fragmentShaderSourceInput)
{
    *fragmentShaderInput = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(*fragmentShaderInput, 1, &amp;fragmentShaderSourceInput, NULL);
    glCompileShader(*fragmentShaderInput);

    int is_successful;
    char infoLog[512];

    glGetShaderiv(*fragmentShaderInput, GL_COMPILE_STATUS, &amp;is_successful);

    if(!is_successful)
    {
        glGetShaderInfoLog(*fragmentShaderInput, 512, NULL, infoLog);
        printf("Fragment shader compilation failed. Error log is as follows:\n%s", infoLog);

        handle_error(true, true); // clean up, and the error was fatal

        return FAIL;
    }

    return SUCCESS;
}

bool checkShaderProgramSuccess(unsigned int shaderProgram)
{
    int is_successful;
    char infoLog[512];

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &amp;is_successful);

    if(!is_successful)
    {
        glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
        printf("Shader program compilation failed. Error log is as follows:\n%s", infoLog);

        handle_error(true, true); // clean up, and the error was fatal

        return FAIL;
    }

    return SUCCESS;
}
</code></pre>
<p>window.c</p>
<pre><code class="lang-auto">#include "main.h"

// Hours that the rectangle has been gone. It's just black. Darkness.

GLFWwindow* createWindow()
{
    GLFWwindow* window = glfwCreateWindow(1920, 1080, "Badpa", NULL, NULL);

    if(!window)
    {
        print_glfw_error();
        handle_error(true, true); // clean up, and the error was fatal

        return NULL;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    glfwMakeContextCurrent(window);

    return window;
}
</code></pre>
<p>main.h</p>
<pre><code class="lang-auto">#pragma once

#include &lt;stdio.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;stdlib.h&gt;

#include &lt;GL/glew.h&gt;
#include &lt;GLFW/glfw3.h&gt;

#define SUCCESS 0
#define FAIL 1

void cleanup();
void handle_error(bool is_cleanup, bool is_fatal);
void print_glfw_error();
void print_glew_error(GLenum error);
bool initialize_glew();

typedef struct{
    float* vertices;
    unsigned int* indices;
} Shape;
</code></pre>
<p>window.h</p>
<pre><code class="lang-auto">#pragma once

GLFWwindow* createWindow();
</code></pre>
<p>shaders.h</p>
<pre><code class="lang-auto">#pragma once

bool compileVertexShader(unsigned int* vertexShaderInput, const char* vertexShaderSourceInput);
bool compileFragmentShader(unsigned int* fragmentShaderInput, const char* fragmentShaderSourceInput);
bool checkShaderProgramSuccess(unsigned int shaderProgram);
</code></pre>
<p>display.h</p>
<pre><code class="lang-auto">#pragma once

bool windowRender(GLFWwindow* window, unsigned int shaderProgram, unsigned int VAO, unsigned int EBO);
</code></pre>
            <p><small>2 posts - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/opengl-not-displaying-rectangle/112504">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/opengl-not-displaying-rectangle/112504</link>
          <pubDate>Wed, 15 Apr 2026 09:51:14 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112504</guid>
          <source url="https://community.khronos.org/t/opengl-not-displaying-rectangle/112504.rss">OpenGL not displaying rectangle</source>
        </item>
        <item>
          <title>How to use SDL2/GLES2 to test if the window is occluded?</title>
          <dc:creator><![CDATA[SwuduSusuwu]]></dc:creator>
          <category>OpenGL: User Software</category>
          <description><![CDATA[
            <p><a href="https://poe.com/s/n2ngvfKEQ1slS0mIPmvG" rel="noopener nofollow ugc">This discussion with <em>Solar-Pro-2</em> lists some platform-specific solutions</a>, but the software is supposed to function portable across all popular platforms (such as <em>Windows</em> or <em>Unix</em> derivatives).<br>
Wish to know how to use portable (<em>SDL2</em>/<em>GLES2</em>) functions to test if the <code>java</code> window is occluded (does not require maximized forefront window, just requires that the whole <code>java</code> window is occluded, which suggests compositors have improved), so that the physics loop is more course (less granular) when the contents are not shown.<br>
What prompted this was: noticed that <code>top</code> shows <code>xwayland</code> + <code>gnome-shell</code> <strong>CPU</strong> usage drops to ~0% when the <code>java</code> window is occluded, plus <code>java</code>’s <strong>CPU</strong> usage drops from 22% to 6% when occluded: the goal is that if the contents are not shown, to have 4x less physics steps, but 4x larger physics steps, which should lower <code>java</code> <strong>CPU</strong> usage down to 2%.<br>
Since <em>Linux</em> does this, guess <em>Windows</em> does too, so wish to know the most portable functions to use.</p>
<p>Source code for the <code>java</code> software is at <a href="https://community.khronos.org/t/susujava-floss-java-sim-now-uses-khronos-gles2-includes-jni-for-sdl2/112496/2" class="inline-onebox">SusuJava (FLOSS Java sim) now uses Khronos' GLES2 (includes JNI for SDL2) - #2 by SwuduSusuwu</a> , but guess this “occlusion mode” is not <code>java</code>-specific</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/how-to-use-sdl2-gles2-to-test-if-the-window-is-occluded/112501">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/how-to-use-sdl2-gles2-to-test-if-the-window-is-occluded/112501</link>
          <pubDate>Fri, 10 Apr 2026 01:58:58 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112501</guid>
          <source url="https://community.khronos.org/t/how-to-use-sdl2-gles2-to-test-if-the-window-is-occluded/112501.rss">How to use SDL2/GLES2 to test if the window is occluded?</source>
        </item>
        <item>
          <title>Resolving a multisample stencil texture</title>
          <dc:creator><![CDATA[JoshKlint]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>A “resolved” multisample depth texture is not particularly useful, but the stencil component of a Depth24/Stencil8 texture could be, if the resolve step includes all bit values of each subpixel.</p>
<p>For example, a 4x multisample pixel with stencil values like this could be resolved into a single value 1|2|4.</p>
<pre><code class="lang-auto">1|2  4
 0   1
</code></pre>
<p>Is this a supported feature?</p>
            <p><small>2 posts - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/resolving-a-multisample-stencil-texture/112485">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/resolving-a-multisample-stencil-texture/112485</link>
          <pubDate>Sun, 22 Mar 2026 07:36:05 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112485</guid>
          <source url="https://community.khronos.org/t/resolving-a-multisample-stencil-texture/112485.rss">Resolving a multisample stencil texture</source>
        </item>
        <item>
          <title>Using the stencil buffer for the first time</title>
          <dc:creator><![CDATA[JoshKlint]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>I want to use the stencil buffer to mask out my background in a deferred renderer, so the full-screen directional light pass only draws to pixels that have had something drawn to them, and for other things. So far it is not working in a predictable way.</p>
<p>The stencil buffer is cleared like this:</p>
<pre><code class="lang-auto">glStencilMask(0xFF);
glClearNamedFramebufferfi(fbo, GL_DEPTH_STENCIL, 0, 1.0f, 0);
glStencilMask(0x1);
</code></pre>
<p>I prepare to draw objects like this:</p>
<pre><code class="lang-auto">glEnable(GL_STENCIL_TEST);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0x1);
</code></pre>
<p>Now I get ready to draw the full-screen pass for directional lights:</p>
<pre><code class="lang-auto">glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 0, 0xFF);// Background pixels get drawn to
//glStencilFunc(GL_EQUAL, 1, 0xFF);// Nothing gets drawn
glStencilMask(0);
</code></pre>
<p>If I use glStencilFunc(GL_EQUAL, 0, 0xFF) then the full-screen pass draws to the background pixels (where nothing has been drawn).<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/6/6a5f29a654fcb57a1b7bdbb85b5b2395c23d4e2a.jpeg" data-download-href="https://community.khronos.org/uploads/default/6a5f29a654fcb57a1b7bdbb85b5b2395c23d4e2a" title="image"><img src="https://community.khronos.org/uploads/default/optimized/2X/6/6a5f29a654fcb57a1b7bdbb85b5b2395c23d4e2a_2_690x404.jpeg" alt="image" data-base62-sha1="fb0uOsXFd8s5wCv1tPCr2ndyLr4" width="690" height="404" srcset="https://community.khronos.org/uploads/default/optimized/2X/6/6a5f29a654fcb57a1b7bdbb85b5b2395c23d4e2a_2_690x404.jpeg, https://community.khronos.org/uploads/default/optimized/2X/6/6a5f29a654fcb57a1b7bdbb85b5b2395c23d4e2a_2_1035x606.jpeg 1.5x, https://community.khronos.org/uploads/default/original/2X/6/6a5f29a654fcb57a1b7bdbb85b5b2395c23d4e2a.jpeg 2x" data-dominant-color="4F5C68"></a></div><p></p>
<p>This indicates that the FBO is correctly set up with an active stencil buffer attached.</p>
<p>However, calling glStencilFunc(GL_EQUAL, 1, 0xFF) does not draw lighting on my foreground pixels (where objects have been drawn). I just get a black screen instead.<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/6/6b760630efb91c88648deb9efe1ef2975c5ddc2a.png" data-download-href="https://community.khronos.org/uploads/default/6b760630efb91c88648deb9efe1ef2975c5ddc2a" title="image"><img src="https://community.khronos.org/uploads/default/optimized/2X/6/6b760630efb91c88648deb9efe1ef2975c5ddc2a_2_690x404.png" alt="image" data-base62-sha1="fkDXcY1DcX41L6vcww1KYJWXoDM" width="690" height="404" srcset="https://community.khronos.org/uploads/default/optimized/2X/6/6b760630efb91c88648deb9efe1ef2975c5ddc2a_2_690x404.png, https://community.khronos.org/uploads/default/optimized/2X/6/6b760630efb91c88648deb9efe1ef2975c5ddc2a_2_1035x606.png 1.5x, https://community.khronos.org/uploads/default/original/2X/6/6b760630efb91c88648deb9efe1ef2975c5ddc2a.png 2x" data-dominant-color="080808"></a></div><p></p>
<p>What am I doing wrong?</p>
            <p><small>7 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/using-the-stencil-buffer-for-the-first-time/112484">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/using-the-stencil-buffer-for-the-first-time/112484</link>
          <pubDate>Sat, 21 Mar 2026 22:50:35 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112484</guid>
          <source url="https://community.khronos.org/t/using-the-stencil-buffer-for-the-first-time/112484.rss">Using the stencil buffer for the first time</source>
        </item>
        <item>
          <title>Reverse Z Depth Buffer</title>
          <dc:creator><![CDATA[SpiderPig]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>Hello,</p>
<p>I am trying to get Reverse Z working for my application but am not quite getting there.  I managed to get the scene rendering again (except the skybox but I think that’s just a shader issue) but all my models are inside out and the front objects are being rendered behind the back objects.  My setup is +Z forward and matrices should be column major.</p>
<p>I can’t quite figure it out!</p>
<p>I wonder if anyone would be kind enough to take a glance at some of my matrices?  And setup?</p>
<p>I change the OpenGL stuff like this at app startup.</p>
<pre><code class="lang-auto">glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GREATER);
glClearDepth(0.0f);
glDepthRange(1.0, 0.0);
</code></pre>
<p>And then my perspective matrix is changed to this.</p>
<pre><code class="lang-auto">void dMat4::SetIdentity() {
    for (int i = 0; i &lt; 16; i++) {
        data[i] = (i % 5 == 0) ? 1.0 : 0.0;
    }
}

void dMat4::SetPerspective(double fov, double aspect, double near, double far) {

    auto tanHalfFov = std::tan(fov * 0.5);

    SetIdentity();

    data[0] = 1.0 / (aspect * tanHalfFov);
    data[5] = 1.0 / tanHalfFov;

    data[10] = 0.0;
    data[11] = 1.0;

    data[14] = near;
    data[15] = 0.0;
}
</code></pre>
<p>I also have an GL_DEPTH_COMPONENT32 depth buffer.</p>
<p>Does my perspective matrix look okay?  Thanks for any insight you might have.  <img src="https://community.khronos.org/images/emoji/twitter/slight_smile.png?v=14" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
            <p><small>10 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/reverse-z-depth-buffer/112483">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/reverse-z-depth-buffer/112483</link>
          <pubDate>Sat, 21 Mar 2026 19:46:23 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112483</guid>
          <source url="https://community.khronos.org/t/reverse-z-depth-buffer/112483.rss">Reverse Z Depth Buffer</source>
        </item>
        <item>
          <title>Code that approximates the GGX lookup table?</title>
          <dc:creator><![CDATA[JoshKlint]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>Does anyone have a GLSL function that will approximate the contents of this image?</p><aside class="onebox githubblob" data-onebox-src="https://github.com/KhronosGroup/glTF-Sample-Renderer/blob/main/assets/images/lut_ggx.png">
  <header class="source">

      <a href="https://github.com/KhronosGroup/glTF-Sample-Renderer/blob/main/assets/images/lut_ggx.png" target="_blank" rel="noopener nofollow ugc">github.com/KhronosGroup/glTF-Sample-Renderer</a>
  </header>

  <article class="onebox-body">
    <h4><a href="https://github.com/KhronosGroup/glTF-Sample-Renderer/blob/main/assets/images/lut_ggx.png" target="_blank" rel="noopener nofollow ugc">assets/images/lut_ggx.png</a></h4>

<div class="git-blob-info">
  <a href="https://github.com/KhronosGroup/glTF-Sample-Renderer/blob/main/assets/images/lut_ggx.png" rel="noopener nofollow ugc"><code>main</code></a>
</div>


  This file is binary. <a href="https://github.com/KhronosGroup/glTF-Sample-Renderer/blob/main/assets/images/lut_ggx.png" target="_blank" rel="noopener nofollow ugc">show original</a>


  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>I feel like having a texture lookup that uses texcoords resulting from another texture lookup is something to be avoided when possible.</p>
<p>I think it might come from here?</p><aside class="onebox githubblob" data-onebox-src="https://github.com/KhronosGroup/glTF-IBL-Sampler/blob/08fa12250f6f5f5969c1846aaa266e6eea887731/lib/source/shaders/filter.frag#L385">
  <header class="source">

      <a href="https://github.com/KhronosGroup/glTF-IBL-Sampler/blob/08fa12250f6f5f5969c1846aaa266e6eea887731/lib/source/shaders/filter.frag#L385" target="_blank" rel="noopener nofollow ugc">github.com/KhronosGroup/glTF-IBL-Sampler</a>
  </header>

  <article class="onebox-body">
    <h4><a href="https://github.com/KhronosGroup/glTF-IBL-Sampler/blob/08fa12250f6f5f5969c1846aaa266e6eea887731/lib/source/shaders/filter.frag#L385" target="_blank" rel="noopener nofollow ugc">lib/source/shaders/filter.frag</a></h4>

<div class="git-blob-info">
  <a href="https://github.com/KhronosGroup/glTF-IBL-Sampler/blob/08fa12250f6f5f5969c1846aaa266e6eea887731/lib/source/shaders/filter.frag#L385" rel="noopener nofollow ugc"><code>08fa12250</code></a>
</div>



    <pre class="onebox"><code class="lang-frag">
      <ol class="start lines" start="375" style="counter-reset: li-counter 374 ;">
          <li>}</li>
          <li></li>
          <li>// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L136</li>
          <li>float V_Ashikhmin(float NdotL, float NdotV)</li>
          <li>{</li>
          <li>    return clamp(1.0 / (4.0 * (NdotL + NdotV - NdotL * NdotV)), 0.0, 1.0);</li>
          <li>}</li>
          <li></li>
          <li>// Compute LUT for GGX distribution.</li>
          <li>// See https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf</li>
          <li class="selected">vec3 LUT(float NdotV, float roughness)</li>
          <li>{</li>
          <li>    // Compute spherical view vector: (sin(phi), 0, cos(phi))</li>
          <li>    vec3 V = vec3(sqrt(1.0 - NdotV * NdotV), 0.0, NdotV);</li>
          <li></li>
          <li>    // The macro surface normal just points up.</li>
          <li>    vec3 N = vec3(0.0, 0.0, 1.0);</li>
          <li></li>
          <li>    // To make the LUT independant from the material's F0, which is part of the Fresnel term</li>
          <li>    // when substituted by Schlick's approximation, we factor it out of the integral,</li>
          <li>    // yielding to the form: F0 * I1 + I2</li>
      </ol>
    </code></pre>



  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

            <p><small>6 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/code-that-approximates-the-ggx-lookup-table/112464">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/code-that-approximates-the-ggx-lookup-table/112464</link>
          <pubDate>Sun, 08 Mar 2026 19:28:10 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112464</guid>
          <source url="https://community.khronos.org/t/code-that-approximates-the-ggx-lookup-table/112464.rss">Code that approximates the GGX lookup table?</source>
        </item>
        <item>
          <title>1x Multisample Texture reports two samples in a shader?</title>
          <dc:creator><![CDATA[JoshKlint]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>I have determined that a texture that uses 1 for the sample count when glTextureStorage2DMultisample is called will produce a texture that reports the sample count is 2 in a shader. Card is an Nvidia GEForce 1080.</p>
<p>This code produces a green screen:</p>
<pre><code class="lang-auto">if (textureSamples(ColorBuffer) == 2) outColor = vec4(0,1,0,1);
</code></pre>
<p>Is this “1x” texture consuming the same memory and bandwidth as a 2x multisample texture? The spec makes it sounds as if 1x is supported:</p>
<blockquote>
<p>samples specifies the number of samples to be used for the texture and must be greater than zero and less than or equal to the value of GL_MAX_SAMPLES.<br>
<a href="https://registry.khronos.org/OpenGL-Refpages/gl4/html/glTexStorage2DMultisample.xhtml" class="inline-onebox">glTexStorage2DMultisample - OpenGL 4 Reference Pages</a></p>
</blockquote>
            <p><small>4 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/1x-multisample-texture-reports-two-samples-in-a-shader/112463">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/1x-multisample-texture-reports-two-samples-in-a-shader/112463</link>
          <pubDate>Sun, 08 Mar 2026 18:41:24 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112463</guid>
          <source url="https://community.khronos.org/t/1x-multisample-texture-reports-two-samples-in-a-shader/112463.rss">1x Multisample Texture reports two samples in a shader?</source>
        </item>
        <item>
          <title>Issues using Conservative Depth to stop the fragment shader runnig</title>
          <dc:creator><![CDATA[DuncanHopkinsFoundry]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>Hi,<br>
I would like to use the conservative depth options on the fragment shader.</p>
<p>Ideally I want to depth cull the fragments to stop the fragment shader doing the work. The issue is I also need to use <code>discard</code> and other operations (like <code>image[Load|Store]()</code>) in the the fragment shader. I have added <code>layout (depth_unchanged) out float gl_FragDepth;</code> to the GLSL and never write to <code>gl_FragDepth</code>. But I can see that the fragment shader is still being run when it should be depth culled.</p>
<p>Do I need to set anything else to enable conservative depth?</p>
<p>Is there other operations that will disable the conservative depth that I need to be aware of?<br>
I did fine a Vulkan reference to <code>if the shader also writes to storage resources</code>!</p>
<p>I have been testing this code against both Windows AMD and nVidia GPUs. Both showing the same behaviour. So I assume I have missed something.</p>
<p>Thanks.</p>
            <p><small>5 posts - 3 participants</small></p>
            <p><a href="https://community.khronos.org/t/issues-using-conservative-depth-to-stop-the-fragment-shader-runnig/112458">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/issues-using-conservative-depth-to-stop-the-fragment-shader-runnig/112458</link>
          <pubDate>Thu, 26 Feb 2026 14:37:35 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112458</guid>
          <source url="https://community.khronos.org/t/issues-using-conservative-depth-to-stop-the-fragment-shader-runnig/112458.rss">Issues using Conservative Depth to stop the fragment shader runnig</source>
        </item>
        <item>
          <title>Pixel-path performance warning: Pixel transfer is synchronized with 3D rendering</title>
          <dc:creator><![CDATA[Aks]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>Hi,</p>
<p>I’m working on a tiled GPU-based map reprojection pipeline in OpenGL (on NVIDIA). The driver frequently reports:</p>
<blockquote>
<p>Pixel-path performance warning: Pixel transfer is synchronized with 3D rendering.</p>
</blockquote>
<p>My pipeline streams and processes imagery in tiles. At a high level:</p>
<ul>
<li>Upload tile data into a texture (currently PBO + glTexSubImage2D).</li>
<li>Reproject by rendering a quad into an FBO (color attachment is an GL_RGBA8 texture).</li>
<li>Read back the FBO result and save it as JPEG.</li>
</ul>
<p>The tiles that are produced and written to disk are 1024×1024. I use a ring of buffers and glFenceSync/polling so that uploads/readbacks are queued and later harvested without intentional blocking (map/copy + JPEG encode runs on a worker thread).</p>
<p>The warning appears in runs where the time is dominated by pixel transfers: both texture uploads and readbacks. I don’t want to assume it is only a readback issue; it seems plausible that either glTexSubImage2D (upload) or glReadPixels (readback), or their interaction/ordering, can trigger synchronization with 3D rendering. The warning always occurs on one of those calls, or on both. I see ~3,263 warnings for 3,072 output tiles (each output tile may require loading 0 to 64 input tiles). So the warning does not occur every time, and I can observe it either on glTexSubImage2D or on glReadPixels.</p>
<p>I also tried an alternative readback path (compute shader copies the FBO texture into a persistently mapped SSBO, then fence + memcpy + JPEG), but it did not show a clear performance improvement in quick tests (even a slight performance regression).</p>
<p>Question: what is the recommended NVIDIA/OpenGL approach to avoid or minimize these pixel-path synchronizations in a streaming pipeline that performs both frequent texture uploads and readbacks? Are there known best practices for buffer usage, formats/packing, synchronization/barriers, or pipeline structure that typically help prevent the driver from synchronizing pixel transfers with rendering?</p>
<p>Thank you in advance!</p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/pixel-path-performance-warning-pixel-transfer-is-synchronized-with-3d-rendering/112455">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/pixel-path-performance-warning-pixel-transfer-is-synchronized-with-3d-rendering/112455</link>
          <pubDate>Fri, 20 Feb 2026 15:36:50 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112455</guid>
          <source url="https://community.khronos.org/t/pixel-path-performance-warning-pixel-transfer-is-synchronized-with-3d-rendering/112455.rss">Pixel-path performance warning: Pixel transfer is synchronized with 3D rendering</source>
        </item>
        <item>
          <title>Bindless textures functions throw seg fault [SOLVED]</title>
          <dc:creator><![CDATA[CoolFede97]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>What’s up.<br>
I’ve got a new laptop and I was installing arch linux on it so that it is exactly as my pc. Now I cloned my opengl project where I use bindless textures and when I try to run it it throws a seg fault in the line of this function:</p>
<pre><code class="lang-auto">glGetTextureHandleARB()
</code></pre>
<p>This one is the first arb function that appears in the program lifetime.<br>
I’ve been trying to solve this problem since yesterday and I made sure that:<br>
My opengl context is set properly,<br>
Glew is initialized properly,<br>
Before calling that function, the pointer to that function is valid,<br>
It seems like I have bindless textures available:</p>
<pre><code class="lang-auto">[coolfede97@coolfede97 ~]$ glxinfo | grep -i "GL_ARB_bindless_texture"

    GL_ARB_bindless_texture, GL_ARB_blend_func_extended, 
    GL_ARB_bindless_texture, GL_ARB_blend_func_extended, 
</code></pre>
<p>The texture I pass as argument to that function is valid</p>
<p>I’ve got a intel gpu:</p>
<pre><code class="lang-auto">[coolfede97@coolfede97 ~]$ lspci | grep -i --color 'vga\|3d\|2d'   
00:02.0 VGA compatible controller: Intel Corporation Iris Plus Graphics G1 (Ice Lake) (rev 07)
</code></pre>
<p>and I use mesa:</p>
<pre><code class="lang-auto">[coolfede97@coolfede97 ~]$ pacman -Q mesa
mesa 1:25.3.3-2
</code></pre>
<p>I tried debugging with gdb, and it seems like the seg fault occurs when a function with an invalid pointer is called (which is strange since</p>
<pre><code class="lang-auto"> if (glGexTexutreHandleARB == nullptr) 
</code></pre>
<p>returns false).</p>
<p>Here is the gdb output:</p>
<pre><code class="lang-auto">[New Thread 0x7fffcffff6c0 (LWP 9743)]
[New Thread 0x7fffcf7fe6c0 (LWP 9744)]
Buffer of textures 2D: 1
Texture2D at path: /home/coolfede97/coding/RuamEngine/RuamEngine/assets/sprites/defaultSprite.png was loaded succesfully
About to call glGetTextureHandleARB

Thread 1 "RuamEngine" received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x00007fffe1339ed1 in ?? () from /usr/lib/libgallium-25.3.3-arch1.2.so
#2  0x000055555558b35f in RuamEngine::Renderer::RegisterTexture (
    texture=std::shared_ptr&lt;RuamEngine::Texture&gt; (use count 2, weak count 0) = {...})
    at /home/coolfede97/coding/RuamEngine/RuamEngine/RuamCore/Rendering/Renderer.cpp:224
#3  0x0000555555593d5e in RuamEngine::ResourceManager::RegisterTextureInRenderer (
    texture=std::shared_ptr&lt;RuamEngine::Texture&gt; (use count 2, weak count 0) = {...})
    at /home/coolfede97/coding/RuamEngine/RuamEngine/RuamCore/Rendering/ResourceManager.cpp:161
#4  RuamEngine::ResourceManager::LoadTexture&lt;RuamEngine::Texture2D&gt; (relativePath="assets/sprites/defaultSprite.png")
    at /home/coolfede97/coding/RuamEngine/RuamEngine/RuamCore/Rendering/ResourceManager.h:35
#5  0x0000555555590dde in RuamEngine::ResourceManager::Init () at /usr/include/c++/15.2.1/bits/basic_string.tcc:248
#6  0x000055555558c6a5 in RuamEngine::Renderer::Init ()
    at /home/coolfede97/coding/RuamEngine/RuamEngine/RuamCore/Rendering/Renderer.cpp:72
</code></pre>
            <p><small>3 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/bindless-textures-functions-throw-seg-fault-solved/112453">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/bindless-textures-functions-throw-seg-fault-solved/112453</link>
          <pubDate>Sun, 15 Feb 2026 19:39:35 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112453</guid>
          <source url="https://community.khronos.org/t/bindless-textures-functions-throw-seg-fault-solved/112453.rss">Bindless textures functions throw seg fault [SOLVED]</source>
        </item>
        <item>
          <title>Compression of triangles mesh</title>
          <dc:creator><![CDATA[The_Little_Body]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>Hi,</p>
<p>I work actually about a triangle mesh compressor that give only a little more than 6 bits per triangle<br>
(only the topologic part, not already the geometric part)</p>
<p>Think you than this style of triangle compression can efficicently to be used for to speed the input of larges triangles meshes<br>
(this give very superiors results than BELR that use about 20+ bits per triangle and seem to approch the level of Zipper that uses about 5 bpt on average, at about 6 bpt with my scheme)</p>
<pre><code class="lang-auto">#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;sstream&gt;
#include &lt;vector&gt;
#include &lt;map&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
#include &lt;bitset&gt;
#include &lt;cstddef&gt;

// Fonction pour lire un fichier .obj et extraire les faces
void readObjFile(const std::string &amp;filename, std::vector&lt;std::vector&lt;int&gt;&gt; &amp;faces) {
    std::ifstream file(filename);
    std::string line;

    while (std::getline(file, line)) {
        if (line.substr(0, 2) == "f ") {
            std::istringstream iss(line.substr(2));
            std::vector&lt;int&gt; face;
            int vertex;
            while (iss &gt;&gt; vertex) {
                face.push_back(vertex - 1); // Convertir en indice 0-based
            }
            faces.push_back(face);
        }
    }
}

// Fonction pour générer les tables L et R
void generateTables(const std::vector&lt;std::vector&lt;int&gt;&gt; &amp;faces, std::vector&lt;int&gt; &amp;L, std::vector&lt;int&gt; &amp;R) {
    int num_corners = faces.size() * 3;
    L.resize(num_corners, -1);
    R.resize(num_corners, -1);

    std::map&lt;std::pair&lt;int, int&gt;, std::pair&lt;int, int&gt;&gt; edge_to_corners;

    // Initialiser edge_to_corners
    for (int i = 0; i &lt; faces.size(); ++i) {
        for (int j = 0; j &lt; 3; ++j) {
            int v1 = faces[i][j];
            int v2 = faces[i][(j + 1) % 3];
            edge_to_corners[{v1, v2}] = {i * 3 + j, i * 3 + ((j + 1) % 3)};
            edge_to_corners[{v2, v1}] = {i * 3 + ((j + 1) % 3), i * 3 + j};
        }
    }

    // Remplir la table R (cycle autour du sommet)
    for (int i = 0; i &lt; faces.size(); ++i) {
        for (int j = 0; j &lt; 3; ++j) {
            int corner_index = i * 3 + j;
            int next_corner_index = i * 3 + ((j + 1) % 3);
            R[corner_index] = next_corner_index;
        }
    }

    // Remplir la table L (corner opposé)
    for (int i = 0; i &lt; faces.size(); ++i) {
        for (int j = 0; j &lt; 3; ++j) {
            int v1 = faces[i][j];
            int v2 = faces[i][(j + 1) % 3];
            int corner_index = i * 3 + j;
            auto it = edge_to_corners.find({v2, v1});
            if (it != edge_to_corners.end() &amp;&amp; it-&gt;second.first != corner_index) {
                L[corner_index] = it-&gt;second.first; // Corner opposé
            }
        }
    }
}

// Fonction pour compter les occurrences des incréments
std::map&lt;int, int&gt; countIncrementOccurrences(const std::vector&lt;int&gt; &amp;L, const std::vector&lt;int&gt; &amp;R) {
    std::map&lt;int, int&gt; totalCount;

    for (int i = 0; i &lt; L.size(); ++i) {
        int incrementL = L[i] - i;
        totalCount[incrementL]++;

        int incrementR = R[i] - i;
        totalCount[incrementR]++;
    }

    return totalCount;
}

// Fonction pour créer un codage sur 2 bits pour les incréments fréquents
void create2BitEncoding(const std::map&lt;int, int&gt; &amp;totalCount, std::map&lt;int, std::string&gt; &amp;compactEncoding, std::vector&lt;int&gt; &amp;frequentIncrements) {
    // Convertir les occurrences en un vecteur de paires pour le tri
    std::vector&lt;std::pair&lt;int, int&gt;&gt; sortedIncrements(totalCount.begin(), totalCount.end());
    std::sort(sortedIncrements.begin(), sortedIncrements.end(), [](const std::pair&lt;int, int&gt; &amp;a, const std::pair&lt;int, int&gt; &amp;b) { return a.second &gt; b.second; });

    // Attribuer les codes sur 2 bits aux 3 incréments les plus fréquents
    compactEncoding[sortedIncrements[0].first] = "00";  // Le plus fréquent
    compactEncoding[sortedIncrements[1].first] = "01";  // Deuxième plus fréquent
    compactEncoding[sortedIncrements[2].first] = "10";  // Troisième plus fréquent
    frequentIncrements.push_back(sortedIncrements[0].first);
    frequentIncrements.push_back(sortedIncrements[1].first);
    frequentIncrements.push_back(sortedIncrements[2].first);
}

// Fonction pour encoder un tableau avec codage sur 2 bits
std::string encodeTable2Bit(const std::vector&lt;int&gt; &amp;table, const std::map&lt;int, std::string&gt; &amp;compactEncoding, std::vector&lt;int&gt; &amp;exceptionIndices, std::vector&lt;int&gt; &amp;exceptions) {
    std::string encoded;
    std::map&lt;int, int&gt; exceptionIndexMap;
    int currentExceptionIndex = 0;

    for (int i = 0; i &lt; table.size(); ++i) {
        int increment = table[i] - i;
        if (compactEncoding.find(increment) != compactEncoding.end()) {
            encoded += compactEncoding.at(increment);
        } else {
            // Ajouter l'incrément à la liste des exceptions s'il n'y est pas déjà
            if (exceptionIndexMap.find(increment) == exceptionIndexMap.end()) {
                exceptionIndexMap[increment] = currentExceptionIndex++;
                exceptions.push_back(increment);
            }
            // Utiliser un code spécial pour indiquer une exception (par exemple, "11")
            encoded += "11";
            exceptionIndices.push_back(exceptionIndexMap[increment]);
        }
    }
    return encoded;
}

// Fonction pour décoder une chaîne binaire avec codage sur 2 bits
std::vector&lt;int&gt; decodeTable2Bit(const std::string &amp;encoded, const std::map&lt;std::string, int&gt; &amp;compactDecoding, const std::vector&lt;int&gt; &amp;exceptionIndices, const std::vector&lt;int&gt; &amp;exceptions) {
    std::vector&lt;int&gt; decoded;
    int currentIndex = 0;
    int exceptionPos = 0;

    for (size_t pos = 0; pos &lt; encoded.size(); pos += 2) {
        if (pos + 2 &gt; encoded.size()) {
            break; // Éviter de dépasser la taille de la chaîne
        }
        std::string code = encoded.substr(pos, 2);
        if (code == "11") {
            // Cas exceptionnel : utiliser l'index de l'exception
            if (exceptionPos &lt; exceptionIndices.size() &amp;&amp; exceptionIndices[exceptionPos] &lt; exceptions.size()) {
                int increment = exceptions[exceptionIndices[exceptionPos]];
                decoded.push_back(currentIndex + increment);
                exceptionPos++;
            } else {
                std::cerr &lt;&lt; "Erreur: Index d'exception hors limites" &lt;&lt; std::endl;
            }
        } else {
            // Cas normal : utiliser le dictionnaire de décodage
            if (compactDecoding.find(code) != compactDecoding.end()) {
                int increment = compactDecoding.at(code);
                decoded.push_back(currentIndex + increment);
            } else {
                std::cerr &lt;&lt; "Erreur: Code non reconnu: " &lt;&lt; code &lt;&lt; std::endl;
            }
        }
        currentIndex++;
    }
    return decoded;
}

// Fonction pour afficher les détails du codage
void printEncodingDetails(const std::vector&lt;int&gt; &amp;table, const std::map&lt;int, std::string&gt; &amp;compactEncoding, const std::vector&lt;int&gt; &amp;exceptionIndices, const std::vector&lt;int&gt; &amp;exceptions, const std::string &amp;tableName) {
    std::cout &lt;&lt; "\nDétails du codage sur 2 bits pour " &lt;&lt; tableName &lt;&lt; " : " &lt;&lt; std::endl;
    int exceptionPos = 0;
    for (int i = 0; i &lt; table.size(); ++i) {
        int increment = table[i] - i;
        if (compactEncoding.find(increment) != compactEncoding.end()) {
            std::cout &lt;&lt; "Indice " &lt;&lt; i &lt;&lt; " : c" &lt;&lt; table[i] &lt;&lt; " (c" &lt;&lt; (increment &gt;= 0 ? "+" : "") &lt;&lt; increment &lt;&lt; ") -&gt; "
                      &lt;&lt; compactEncoding.at(increment) &lt;&lt; std::endl;
        } else {
            if (exceptionPos &lt; exceptionIndices.size()) {
                std::cout &lt;&lt; "Indice " &lt;&lt; i &lt;&lt; " : c" &lt;&lt; table[i] &lt;&lt; " (c" &lt;&lt; (increment &gt;= 0 ? "+" : "") &lt;&lt; increment &lt;&lt; ") -&gt; "
                          &lt;&lt; "11 (exception index: " &lt;&lt; exceptionIndices[exceptionPos] &lt;&lt; ")" &lt;&lt; std::endl;
                exceptionPos++;
            } else {
                std::cerr &lt;&lt; "Erreur: Pas assez d'indices d'exceptions" &lt;&lt; std::endl;
            }
        }
    }
}

// Fonction pour afficher les statistiques de compression
void printCompressionStats(const std::string &amp;encoded, const std::vector&lt;int&gt; &amp;table, const std::string &amp;tableName) {
    int originalSizeBits = table.size() * 32; // Chaque int occupe 32 bits
    float compressionRate = (float)encoded.size() / originalSizeBits * 100;

    std::cout &lt;&lt; "\nChaîne binaire encodée pour " &lt;&lt; tableName &lt;&lt; " : " &lt;&lt; encoded &lt;&lt; std::endl;
    std::cout &lt;&lt; "Longueur de la chaîne binaire : " &lt;&lt; encoded.size() &lt;&lt; " bits (au lieu de " &lt;&lt; originalSizeBits &lt;&lt; " bits)" &lt;&lt; std::endl;
    std::cout &lt;&lt; "Taux de compression par rapport aux indices non compressés : " &lt;&lt; compressionRate &lt;&lt; "%" &lt;&lt; std::endl;
}

// Fonction pour afficher la table des exceptions
void printExceptionTable(const std::vector&lt;int&gt; &amp;exceptions) {
    std::cout &lt;&lt; "\nTable des exceptions : " &lt;&lt; std::endl;
    for (size_t i = 0; i &lt; exceptions.size(); ++i) {
        std::cout &lt;&lt; "Index " &lt;&lt; i &lt;&lt; " : c" &lt;&lt; (exceptions[i] &gt;= 0 ? "+" : "") &lt;&lt; exceptions[i] &lt;&lt; std::endl;
    }
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr &lt;&lt; "Usage: " &lt;&lt; argv[0] &lt;&lt; " &lt;fichier.obj&gt;" &lt;&lt; std::endl;
        return 1;
    }

    std::string filename = argv[1];
    std::vector&lt;std::vector&lt;int&gt;&gt; faces;
    readObjFile(filename, faces);

    std::vector&lt;int&gt; L, R;
    generateTables(faces, L, R);

    // Compter les occurrences des incréments
    std::map&lt;int, int&gt; totalCount = countIncrementOccurrences(L, R);

    // Afficher les occurrences des incréments
    std::cout &lt;&lt; "Occurrences des incréments (trié par fréquence) :" &lt;&lt; std::endl;
    std::vector&lt;std::pair&lt;int, int&gt;&gt; sortedIncrements(totalCount.begin(), totalCount.end());
    std::sort(sortedIncrements.begin(), sortedIncrements.end(), [](const std::pair&lt;int, int&gt; &amp;a, const std::pair&lt;int, int&gt; &amp;b) { return a.second &gt; b.second; });
    for (const auto &amp;entry : sortedIncrements) {
        std::cout &lt;&lt; "c" &lt;&lt; (entry.first &gt;= 0 ? "+" : "") &lt;&lt; entry.first &lt;&lt; " : " &lt;&lt; entry.second &lt;&lt; " fois" &lt;&lt; std::endl;
    }

    // Créer un codage sur 2 bits pour les incréments fréquents
    std::map&lt;int, std::string&gt; compactEncoding;
    std::vector&lt;int&gt; frequentIncrements;
    create2BitEncoding(totalCount, compactEncoding, frequentIncrements);

    // Affichage du dictionnaire de codage sur 2 bits
    std::cout &lt;&lt; "\nDictionnaire de codage sur 2 bits : " &lt;&lt; std::endl;
    for (const auto &amp;entry : compactEncoding) {
        std::cout &lt;&lt; "c" &lt;&lt; (entry.first &gt;= 0 ? "+" : "") &lt;&lt; entry.first &lt;&lt; " -&gt; " &lt;&lt; entry.second &lt;&lt; std::endl;
    }

    // Encodage et affichage des détails pour L[]
    std::vector&lt;int&gt; exceptionIndicesL, exceptionsL;
    std::string encodedL = encodeTable2Bit(L, compactEncoding, exceptionIndicesL, exceptionsL);
    printEncodingDetails(L, compactEncoding, exceptionIndicesL, exceptionsL, "L[]");
    printCompressionStats(encodedL, L, "L[]");

    // Encodage et affichage des détails pour R[]
    std::vector&lt;int&gt; exceptionIndicesR, exceptionsR;
    std::string encodedR = encodeTable2Bit(R, compactEncoding, exceptionIndicesR, exceptionsR);
    printEncodingDetails(R, compactEncoding, exceptionIndicesR, exceptionsR, "R[]");
    printCompressionStats(encodedR, R, "R[]");

    // Fusionner les exceptions de L[] et R[]
    std::vector&lt;int&gt; allExceptions = exceptionsL;
    for (int exception : exceptionsR) {
        if (std::find(allExceptions.begin(), allExceptions.end(), exception) == allExceptions.end()) {
            allExceptions.push_back(exception);
        }
    }

    // Afficher la table des exceptions unifiée
    printExceptionTable(allExceptions);

    // Taux de compression global
    int totalEncodedBits = encodedL.size() + encodedR.size();
    int totalOriginalBits = L.size() * 32 + R.size() * 32; // 32 bits par int
    float globalCompressionRate = (float)totalEncodedBits / totalOriginalBits * 100;

    std::cout &lt;&lt; "\nCompression globale : " &lt;&lt; totalEncodedBits &lt;&lt; " bits (au lieu de " &lt;&lt; totalOriginalBits &lt;&lt; " bits)" &lt;&lt; std::endl;
    std::cout &lt;&lt; "Taux de compression global par rapport aux indices non compressés : " &lt;&lt; globalCompressionRate &lt;&lt; "%" &lt;&lt; std::endl;

    // Comparaison avec une représentation naïve (3 ints × nombre de triangles)
    int naiveSizeBits = (L.size() / 3) * 96; // 3 ints × 32 bits × nombre de triangles
    float naiveCompressionRate = (float)totalEncodedBits / naiveSizeBits * 100;

    std::cout &lt;&lt; "\nComparaison avec une représentation naïve (3 ints × nombre de triangles) : " &lt;&lt; std::endl;
    std::cout &lt;&lt; "Taille naïve : " &lt;&lt; naiveSizeBits &lt;&lt; " bits" &lt;&lt; std::endl;
    std::cout &lt;&lt; "Taux de compression par rapport à la représentation naïve : " &lt;&lt; naiveCompressionRate &lt;&lt; "%" &lt;&lt; std::endl;

    // Créer les dictionnaires de décodage
    std::map&lt;std::string, int&gt; compactDecoding;
    for (const auto &amp;entry : compactEncoding) {
        compactDecoding[entry.second] = entry.first;
    }

    // Décodage pour vérifier la cohérence
    std::vector&lt;int&gt; decodedL = decodeTable2Bit(encodedL, compactDecoding, exceptionIndicesL, allExceptions);
    std::vector&lt;int&gt; decodedR = decodeTable2Bit(encodedR, compactDecoding, exceptionIndicesR, allExceptions);

    // Vérification que les tableaux décodés correspondent aux originaux
    bool correctL = (L == decodedL);
    bool correctR = (R == decodedR);
    std::cout &lt;&lt; "\nVérification du décodage : " &lt;&lt; (correctL &amp;&amp; correctR ? "Succès ✅" : "Échec ❌") &lt;&lt; std::endl;

    return 0;
}</code></pre>
<p>This give this for a basic cube for example</p>
<pre><code class="lang-auto">annoo@yannoo-ThinkCentre-M710q:~/Dev/LR2$ ./lr2 cube.obj
Occurrences des incréments (trié par fréquence) :
c+1 : 45 fois
c-2 : 15 fois
c+10 : 4 fois
c+18 : 2 fois
c+13 : 1 fois
c+14 : 1 fois
c+15 : 1 fois
c+21 : 1 fois
c+23 : 1 fois
c+26 : 1 fois

Dictionnaire de codage sur 2 bits : 
c-2 -&gt; 01
c+1 -&gt; 00
c+10 -&gt; 10

Détails du codage sur 2 bits pour L[] : 
Indice 0 : c13 (c+13) -&gt; 11 (exception index: 0)
Indice 1 : c19 (c+18) -&gt; 11 (exception index: 1)
Indice 2 : c3 (c+1) -&gt; 00
Indice 3 : c4 (c+1) -&gt; 00
Indice 4 : c25 (c+21) -&gt; 11 (exception index: 2)
Indice 5 : c31 (c+26) -&gt; 11 (exception index: 3)
Indice 6 : c16 (c+10) -&gt; 10
Indice 7 : c22 (c+15) -&gt; 11 (exception index: 4)
Indice 8 : c9 (c+1) -&gt; 00
Indice 9 : c10 (c+1) -&gt; 00
Indice 10 : c28 (c+18) -&gt; 11 (exception index: 1)
Indice 11 : c34 (c+23) -&gt; 11 (exception index: 5)
Indice 12 : c13 (c+1) -&gt; 00
Indice 13 : c23 (c+10) -&gt; 10
Indice 14 : c15 (c+1) -&gt; 00
Indice 15 : c16 (c+1) -&gt; 00
Indice 16 : c17 (c+1) -&gt; 00
Indice 17 : c31 (c+14) -&gt; 11 (exception index: 6)
Indice 18 : c19 (c+1) -&gt; 00
Indice 19 : c29 (c+10) -&gt; 10
Indice 20 : c21 (c+1) -&gt; 00
Indice 21 : c22 (c+1) -&gt; 00
Indice 22 : c23 (c+1) -&gt; 00
Indice 23 : c21 (c-2) -&gt; 01
Indice 24 : c25 (c+1) -&gt; 00
Indice 25 : c35 (c+10) -&gt; 10
Indice 26 : c27 (c+1) -&gt; 00
Indice 27 : c28 (c+1) -&gt; 00
Indice 28 : c29 (c+1) -&gt; 00
Indice 29 : c27 (c-2) -&gt; 01
Indice 30 : c31 (c+1) -&gt; 00
Indice 31 : c32 (c+1) -&gt; 00
Indice 32 : c33 (c+1) -&gt; 00
Indice 33 : c34 (c+1) -&gt; 00
Indice 34 : c35 (c+1) -&gt; 00
Indice 35 : c33 (c-2) -&gt; 01

Chaîne binaire encodée pour L[] : 111100001111101100001111001000000011001000000001001000000001000000000001
Longueur de la chaîne binaire : 72 bits (au lieu de 1152 bits)
Taux de compression par rapport aux indices non compressés : 6.25%

Détails du codage sur 2 bits pour R[] : 
Indice 0 : c1 (c+1) -&gt; 00
Indice 1 : c2 (c+1) -&gt; 00
Indice 2 : c0 (c-2) -&gt; 01
Indice 3 : c4 (c+1) -&gt; 00
Indice 4 : c5 (c+1) -&gt; 00
Indice 5 : c3 (c-2) -&gt; 01
Indice 6 : c7 (c+1) -&gt; 00
Indice 7 : c8 (c+1) -&gt; 00
Indice 8 : c6 (c-2) -&gt; 01
Indice 9 : c10 (c+1) -&gt; 00
Indice 10 : c11 (c+1) -&gt; 00
Indice 11 : c9 (c-2) -&gt; 01
Indice 12 : c13 (c+1) -&gt; 00
Indice 13 : c14 (c+1) -&gt; 00
Indice 14 : c12 (c-2) -&gt; 01
Indice 15 : c16 (c+1) -&gt; 00
Indice 16 : c17 (c+1) -&gt; 00
Indice 17 : c15 (c-2) -&gt; 01
Indice 18 : c19 (c+1) -&gt; 00
Indice 19 : c20 (c+1) -&gt; 00
Indice 20 : c18 (c-2) -&gt; 01
Indice 21 : c22 (c+1) -&gt; 00
Indice 22 : c23 (c+1) -&gt; 00
Indice 23 : c21 (c-2) -&gt; 01
Indice 24 : c25 (c+1) -&gt; 00
Indice 25 : c26 (c+1) -&gt; 00
Indice 26 : c24 (c-2) -&gt; 01
Indice 27 : c28 (c+1) -&gt; 00
Indice 28 : c29 (c+1) -&gt; 00
Indice 29 : c27 (c-2) -&gt; 01
Indice 30 : c31 (c+1) -&gt; 00
Indice 31 : c32 (c+1) -&gt; 00
Indice 32 : c30 (c-2) -&gt; 01
Indice 33 : c34 (c+1) -&gt; 00
Indice 34 : c35 (c+1) -&gt; 00
Indice 35 : c33 (c-2) -&gt; 01

Chaîne binaire encodée pour R[] : 000001000001000001000001000001000001000001000001000001000001000001000001
Longueur de la chaîne binaire : 72 bits (au lieu de 1152 bits)
Taux de compression par rapport aux indices non compressés : 6.25%

Table des exceptions : 
Index 0 : c+13
Index 1 : c+18
Index 2 : c+21
Index 3 : c+26
Index 4 : c+15
Index 5 : c+23
Index 6 : c+14

Compression globale : 144 bits (au lieu de 2304 bits)
Taux de compression global par rapport aux indices non compressés : 6.25%

Comparaison avec une représentation naïve (3 ints × nombre de triangles) : 
Taille naïve : 1152 bits
Taux de compression par rapport à la représentation naïve : 12.5%

Vérification du décodage : Succès ✅</code></pre>
<p>Here, the file Cube.obj used</p>
<pre><code class="lang-auto">v -1.0 -1.0 -1.0
v  1.0 -1.0 -1.0
v  1.0  1.0 -1.0
v -1.0  1.0 -1.0
v -1.0 -1.0  1.0
v  1.0 -1.0  1.0
v  1.0  1.0  1.0
v -1.0  1.0  1.0

f 1 2 3
f 1 3 4
f 5 6 7
f 5 7 8
f 1 2 6
f 1 6 5
f 2 3 7
f 2 7 6
f 3 4 8
f 3 8 7
f 4 1 5
f 4 5 8</code></pre>
            <p><small>3 posts - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/compression-of-triangles-mesh/112440">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/compression-of-triangles-mesh/112440</link>
          <pubDate>Tue, 03 Feb 2026 21:14:31 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112440</guid>
          <source url="https://community.khronos.org/t/compression-of-triangles-mesh/112440.rss">Compression of triangles mesh</source>
        </item>
        <item>
          <title>I think my objects are rendering without depth</title>
          <dc:creator><![CDATA[GameGuy]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/7/77bccd7e7eb2fc743320bd684c7f7023f493f0d1.png" data-download-href="https://community.khronos.org/uploads/default/77bccd7e7eb2fc743320bd684c7f7023f493f0d1" title="Screenshots-20260128145452"><img src="https://community.khronos.org/uploads/default/original/2X/7/77bccd7e7eb2fc743320bd684c7f7023f493f0d1.png" alt="Screenshots-20260128145452" data-base62-sha1="h5fkgHS6iVAwlPWsZ8ZGd4Y4mxr" width="364" height="324"></a></div><p></p>
<p>This image is supposed to be a tv on a stand.</p>
<p>What I am doing is both bloom and shadows, so I need 3 framebuffers to do this. I haven’t got the shadow maps to work yet but I want to get my objects to show up properly first. I have a point light in a room, so I guess cube maps are used for this.</p>
<p>this is the setup for the framebuffers:</p>
<pre><code class="lang-auto">	GLuint hdrFBO;
	glGenFramebuffers(1, &amp;hdrFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);

	// Color buffers (HDR + Bright)
	GLuint colorBuffers[2];
	glGenTextures(2, colorBuffers);

	for (int i = 0; i &lt; 2; ++i)
	{
		glBindTexture(GL_TEXTURE_2D, colorBuffers[i]);
		glTexImage2D(
			GL_TEXTURE_2D,
			0,
			GL_RGBA16F,
			gWindowWidth,
			gWindowHeight,
			0,
			GL_RGBA,
			GL_FLOAT,
			nullptr
		);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		glFramebufferTexture2D(
			GL_FRAMEBUFFER,
			GL_COLOR_ATTACHMENT0 + i,
			GL_TEXTURE_2D,
			colorBuffers[i],
			0
		);
	}

	// Depth buffer
	GLuint rboDepth;
	glGenRenderbuffers(1, &amp;rboDepth);
	glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
	glRenderbufferStorage(
		GL_RENDERBUFFER,
		GL_DEPTH_COMPONENT24,
		gWindowWidth,
		gWindowHeight
	);
	glFramebufferRenderbuffer(
		GL_FRAMEBUFFER,
		GL_DEPTH_ATTACHMENT,
		GL_RENDERBUFFER,
		rboDepth
	);

	// Tell OpenGL we have two color outputs
	GLuint attachments[2] = {
		GL_COLOR_ATTACHMENT0,
		GL_COLOR_ATTACHMENT1
	};
	glDrawBuffers(2, attachments);

	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
		std::cout &lt;&lt; "HDR FBO broken\n";
	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	// Sanity check
	



	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	
	// ------------------------------------------------------------
// PING-PONG FRAMEBUFFERS (bloom blur)
// ------------------------------------------------------------
	GLuint pingpongFBO[2];
	GLuint pingpongColorBuffers[2];
	glGenFramebuffers(2, pingpongFBO);
	glGenTextures(2, pingpongColorBuffers);

	for (int i = 0; i &lt; 2; ++i)
	{
		glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]);

		glBindTexture(GL_TEXTURE_2D, pingpongColorBuffers[i]);
		glTexImage2D(
			GL_TEXTURE_2D,
			0,
			GL_RGBA16F,
			gWindowWidth,
			gWindowHeight,
			0,
			GL_RGBA,
			GL_FLOAT,
			nullptr
		);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		glFramebufferTexture2D(
			GL_FRAMEBUFFER,
			GL_COLOR_ATTACHMENT0,
			GL_TEXTURE_2D,
			pingpongColorBuffers[i],
			0
		);

		if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
			std::cout &lt;&lt; "Pingpong FBO broken\n";
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	
	// ------------------------------------------------------------
// DEPTH CUBEMAP (point light shadows)
// ------------------------------------------------------------
	const unsigned int SHADOW_WIDTH = 1024;
	const unsigned int SHADOW_HEIGHT = 1024;

	// Depth cubemap texture
	GLuint depthCubemap;
	glGenTextures(1, &amp;depthCubemap);
	glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap);

	for (unsigned int i = 0; i &lt; 6; ++i)
	{
		glTexImage2D(
			GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
			0,
			GL_DEPTH_COMPONENT,
			SHADOW_WIDTH,
			SHADOW_HEIGHT,
			0,
			GL_DEPTH_COMPONENT,
			GL_FLOAT,
			nullptr
		);
	}

	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

	// Shadow FBO
	GLuint depthCubemapFBO;
	glGenFramebuffers(1, &amp;depthCubemapFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, depthCubemapFBO);
	glFramebufferTexture(
		GL_FRAMEBUFFER,
		GL_DEPTH_ATTACHMENT,
		depthCubemap,
		0
	);

	glDrawBuffer(GL_NONE);
	glReadBuffer(GL_NONE);

	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
		std::cout &lt;&lt; "Depth cubemap FBO broken\n";

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
</code></pre>
<p>This is the rendering code up to when I redraw my objects:</p>
<pre><code class="lang-auto">glBindFramebuffer(GL_FRAMEBUFFER, depthCubemapFBO);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glClearDepth(1.0);
glClear(GL_DEPTH_BUFFER_BIT);

sceneShader.use();

for (int i = 0; i &lt; 6; i++)
{
	sceneShader.setUniform(
		"shadowMatrices[" + std::to_string(i) + "]",
		shadowTransforms[i]
	);
}

sceneShader.setUniform("lightPos", lightPos);
sceneShader.setUniform("farPlane", wid);			
sceneShader.setUniformI("isFan", 0);

model = glm::translate(glm::mat4(1), glm::vec3(-5.894, 1.123, 5.775)) * glm::rotate(glm::mat4(1), glm::radians(135.0f), glm::vec3(0, 1, 0)) * glm::rotate(glm::mat4(1), glm::radians(270.0f), glm::vec3(1, 0, 0));
sceneShader.setUniform("model", model);

// then I render my objects with this shader

//glBindFramebuffer(GL_FRAMEBUFFER, 0);

glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
glViewport(0, 0, gWindowWidth, gWindowHeight);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap);

model = glm::rotate(glm::mat4(1), glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::rotate(glm::mat4(1), glm::radians(270.0f), glm::vec3(1, 0, 0)) * glm::scale(glm::mat4(1), glm::vec3(1.5, 1.5, 1.5));

glm::mat4 vp1 = MyCam.getVP();

glm::vec3 viewPos = MyCam.campos;		

roomShader.use();
roomShader.setUniform("vp", vp1);
roomShader.setUniform("model", model);
roomShader.setUniform("lightPos", lightPos);
roomShader.setUniform("viewPos", viewPos);
roomShader.setUniform("farPlane", wid);
roomShader.setUniformSampler("Texture1", 0);
roomShader.setUniformSampler("Texture2", 1);
roomShader.setUniformSampler("depthCubemap", 2);

carpetTex.bind(1);
sceneTex.bind(0);
room.Draw();
carpetTex.unbind(1);
sceneTex.unbind(0);

glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
</code></pre>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/i-think-my-objects-are-rendering-without-depth/112436">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/i-think-my-objects-are-rendering-without-depth/112436</link>
          <pubDate>Wed, 28 Jan 2026 23:49:23 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112436</guid>
          <source url="https://community.khronos.org/t/i-think-my-objects-are-rendering-without-depth/112436.rss">I think my objects are rendering without depth</source>
        </item>
        <item>
          <title>Draw a tetrahedron on OpenGL with only one call</title>
          <dc:creator><![CDATA[The_Little_Body]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>Hi,</p>
<p>I want to display tetrahedrons volumes with OpenGL</p>
<p>I think use this function for to implement it</p>
<pre><code class="lang-auto">void glTetra3fv( float *v0, float *v1, float *v2, float *v3 ) 
{
    glBegin(GL_TRIANGLES);

        glVertex3fv(v0);   // face A (face entry)
        glVertex3fv(v1);
        glVertex3fv(v2);
 
        glVertex3fv(v3);   // face B
        glVertex3fv(v0);
        glVertex3fv(v1);

        glVertex3fv(v3);   // face C
        glVertex3fv(v1);
        glVertex3fv(v2);
 
        glVertex3fv(v3);   // face D
        glVertex3fv(v2);
        glVertex3fv(v0);

    glEnd();
}</code></pre>
<p>Think you that it is better to use the glBegin() / glEnd() calls inside or outside this function ?</p>
<p>This is for to call this fonction something like this :<br>
(4  tetrahedrons =  three tetrahedrons glued to one first)</p>
<pre><code class="lang-auto">// glBegin(GL_TRIANGLES);

    glTetra3fv( &amp;v1 , &amp;v2 , &amp;v3 , &amp;v4 );
    glTetra3fv( &amp;v1 , &amp;v2 , &amp;v4 , &amp;v5 );
    glTetra3fv( &amp;v2 , &amp;v3 , &amp;v4 , &amp;v6 );
    glTetra3fv( &amp;v3 , &amp;v1 , &amp;v4 , &amp;v7 );

// glEnd();</code></pre>
<p>or a very little more complex code like this for other example :<br>
(one internal black tetrahedron glued by red, green, blue and gray tetrahedrons on his faces)</p>
<pre><code class="lang-auto">// glBegin(GL_TRIANGLES);

    // a black tetrahedron in the interior
    glColor3fv( 0.0f, 0.0f, 0.0f );
    glTetra3fv( &amp;v1 , &amp;v2 , &amp;v3 , &amp;v4 );

    // a red tetrahedron glued to the 1th extern face of this tetrahedron
    glColor3fv(1.0f,0.0f,0.0f);
    glTetra3fv( &amp;v1 , &amp;v2 , &amp;v4 , &amp;v5 );

    // a green tetrahedron glued to the 2th extern face of this tetrahedron
    glColor3fv(0.0f,1.0f,0.0f);
    glTetra3fv( &amp;v2 , &amp;v3 , &amp;v4 , &amp;v6 );

    // a blue tetrahedron glued to the 3th extern face of this tetrahedron
    glColor3fv(0.0f,0.0f,1.0f);
    glTetra3fv( &amp;v3 , &amp;v1 , &amp;v4 , &amp;v7 );

    // a gray tetrahedron glued to the entry face of this tetrahedron
    glColor3fv( 0.5f, 0.5f, 0.5f );
    glTetra3fv( &amp;v1 , &amp;v2 , &amp;v3 , &amp;v8 );

// glEnd();</code></pre>
            <p><small>2 posts - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/draw-a-tetrahedron-on-opengl-with-only-one-call/112426">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/draw-a-tetrahedron-on-opengl-with-only-one-call/112426</link>
          <pubDate>Thu, 15 Jan 2026 22:02:42 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112426</guid>
          <source url="https://community.khronos.org/t/draw-a-tetrahedron-on-opengl-with-only-one-call/112426.rss">Draw a tetrahedron on OpenGL with only one call</source>
        </item>
        <item>
          <title>Can someone please help me with light attenuation values?</title>
          <dc:creator><![CDATA[GameGuy]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/d/dda2559aaf1ac19fa15ed9625f8aed61a7c3909f.png" data-download-href="https://community.khronos.org/uploads/default/dda2559aaf1ac19fa15ed9625f8aed61a7c3909f" title="capture_251221_163151"><img src="https://community.khronos.org/uploads/default/optimized/2X/d/dda2559aaf1ac19fa15ed9625f8aed61a7c3909f_2_313x500.png" alt="capture_251221_163151" data-base62-sha1="vCFjT9p0kpMOlLR0H8KJJdhnlsb" width="313" height="500" srcset="https://community.khronos.org/uploads/default/optimized/2X/d/dda2559aaf1ac19fa15ed9625f8aed61a7c3909f_2_313x500.png, https://community.khronos.org/uploads/default/original/2X/d/dda2559aaf1ac19fa15ed9625f8aed61a7c3909f.png 1.5x, https://community.khronos.org/uploads/default/original/2X/d/dda2559aaf1ac19fa15ed9625f8aed61a7c3909f.png 2x" data-dominant-color="1F271B"></a></div><p></p>
<p>This is a Christmas tree that I am trying to render. It is 4.9 units high it has 1008 Christmas lights and the star to illuminate it. I am just trying to use these lights to make the tree look like it is lit up by them and not anything else.</p>
<p>This is the fragment shader that i am using to render it.</p>
<pre><code class="lang-auto">#version 430 core

layout(std430, binding = 0) buffer Centers {
    vec3 centers[];
};

uniform vec3 viewPos;
uniform vec3 starCent;

flat in uint mNum;
in vec3 Pos;
in vec3 Norm;

out vec4 FragColor;

vec3 CalcPointLight(vec3 lightPos, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightColor = vec3(1, 1, 1);

    float constant = .75;
    float linear = 5.2;
    float quadratic = 10.1;

    vec3 lightDir = normalize(lightPos - fragPos);

    // Diffuse
    float diff = max(dot(normal, lightDir), 0.0);

    // Specular
    vec3 halfwayDir = normalize(lightDir + viewDir);
    float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0);

    // Distance attenuation
    float distance = length(lightPos - fragPos);
    float attenuation = 1.0 / (
        constant +
        linear * distance +
        quadratic * distance * distance
    );

    vec3 ambient  = 0.05 * lightColor;
    vec3 diffuse  = diff * lightColor * 2;
    vec3 specular = spec * lightColor;

    return (ambient + diffuse) * attenuation * .4;
}

vec3 CalcPointLight1(vec3 lightPos, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightColor = vec3(1, 1, 0);

    float constant = .75;
    float linear = 2;
    float quadratic = 2;

    vec3 lightDir = normalize(lightPos - fragPos);

    // Diffuse
    float diff = max(dot(normal, lightDir), 0.0);

    // Specular
    vec3 halfwayDir = normalize(lightDir + viewDir);
    float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0);

    // Distance attenuation
    float distance = length(lightPos - fragPos);
    float attenuation = 1.0 / (
        constant +
        linear * distance +
        quadratic * distance * distance
    );

    vec3 ambient  = 0.05 * lightColor;
    vec3 diffuse  = diff * lightColor;
    vec3 specular = spec * lightColor;

    return (ambient + diffuse) * attenuation * 6;
}

void main(){
	vec3 norm = normalize(Norm);
    vec3 viewDir = normalize(viewPos - Pos);
    vec3 result = vec3(0.0);

	for (int i=0;i&lt;1008;i++){
		vec3 center = centers[i];    
        result += CalcPointLight(center, norm, Pos, viewDir);
    }

    result += CalcPointLight1(starCent, norm, Pos, viewDir);

    vec3 albedo; 
	if (mNum == 0){
		albedo = vec3(0.18039215686274509803921568627451, 0.11764705882352941176470588235294, 0.05882352941176470588235294117647);
	}else{
		albedo = vec3(0.09411764705882352941176470588235, 0.21960784313725490196078431372549, 0.12549019607843137254901960784314);
	}
    FragColor = vec4(result * albedo, 1.0);
}
</code></pre>
            <p><small>5 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/can-someone-please-help-me-with-light-attenuation-values/112411">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/can-someone-please-help-me-with-light-attenuation-values/112411</link>
          <pubDate>Mon, 22 Dec 2025 00:44:03 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112411</guid>
          <source url="https://community.khronos.org/t/can-someone-please-help-me-with-light-attenuation-values/112411.rss">Can someone please help me with light attenuation values?</source>
        </item>
        <item>
          <title>Why won&#39;t my bloom material work?</title>
          <dc:creator><![CDATA[GameGuy]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>I am trying to model Christmas lights. The models render but I do not see the bloom effect. I have even made a temporary change to the blend shader so that it outputs the image that is supposed to be blended, and everything is black.</p>
<p>This is my code:</p>
<pre><code class="lang-auto">unsigned int hdrFBO;
glGenFramebuffers(1, &amp;hdrFBO);
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
unsigned int colorBuffers[2];
glGenTextures(2, colorBuffers);
for (unsigned int i = 0; i &lt; 2; i++)
{
	glBindTexture(GL_TEXTURE_2D, colorBuffers[i]);
	glTexImage2D(
		GL_TEXTURE_2D, 0, GL_RGBA16F, gWindowWidth, gWindowHeight, 0, GL_RGBA, GL_FLOAT, NULL
	);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	// attach texture to framebuffer
	glFramebufferTexture2D(
		GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, colorBuffers[i], 0
	);
}
GLuint rboDepth;
glGenRenderbuffers(1, &amp;rboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,
	gWindowWidth, gWindowHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
	GL_RENDERBUFFER, rboDepth);

unsigned int attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, attachments);

unsigned int pingpongFBO[2];
unsigned int pingpongBuffer[2];
glGenFramebuffers(2, pingpongFBO);
glGenTextures(2, pingpongBuffer);
for (unsigned int i = 0; i &lt; 2; i++)
{
	glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]);
	glBindTexture(GL_TEXTURE_2D, pingpongBuffer[i]);
	glTexImage2D(
		GL_TEXTURE_2D, 0, GL_RGBA16F, gWindowWidth, gWindowHeight, 0, GL_RGBA, GL_FLOAT, NULL
	);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glFramebufferTexture2D(
		GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongBuffer[i], 0
	);
}

glm::mat4 projection = glm::perspective(glm::radians(45.0f), 1.7777777777f, 0.5f, 200.0f);

double lastTime = glfwGetTime();
double deltaTime;

while (!glfwWindowShouldClose(gWindow))
{
	double currentTime = glfwGetTime();
	deltaTime = currentTime - lastTime;
	lastTime = currentTime;

	glfwPollEvents();
	update(deltaTime);

	glm::mat4 view = MyCam.getViewMatrix();
	glm::mat4 model = glm::rotate(glm::mat4(1), glm::radians(270.0f), glm::vec3(1, 0, 0));

	glm::mat4 mvp = projection * view * model;

	glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
	glViewport(0, 0, gWindowWidth, gWindowHeight);

	glClearColor(0, 0, 0, 1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	

	treeShader.use();
	treeShader.setUniform("mvp", mvp);
	
	//tree.Draw();

	lightShader.use();
	lightShader.setUniform("mvp", mvp);

	lights.Draw();

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	bool horizontal = true;
	bool first_iteration = true;
	int amount = 10;

	shaderBlur.use();

	for (int i = 0; i &lt; amount; i++)
	{
		glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]);

		shaderBlur.setUniformI("horizontal", horizontal);

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(
			GL_TEXTURE_2D,
			first_iteration ? colorBuffers[1] : pingpongBuffer[!horizontal]
		);
		shaderBlur.setUniformSampler("image", 0);

		glBindVertexArray(lVAO);
		glDrawArrays(GL_TRIANGLES, 0, 6);

		horizontal = !horizontal;
		if (first_iteration)
			first_iteration = false;
	}

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	blendShader.use();

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, colorBuffers[0]); // scene

	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, pingpongBuffer[!horizontal]); // bloom

	blendShader.setUniformSampler("scene", 0);
	blendShader.setUniformSampler("bloomBlur", 1);

	glBindVertexArray(lVAO);
	glDrawArrays(GL_TRIANGLES, 0, 6);
	glBindVertexArray(0);

	glfwSwapBuffers(gWindow);
</code></pre>
<p>These are my fragment shaders:</p>
<pre><code class="lang-auto">#version 430 core //lights

layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 BrightColor;

void main()
{
    vec3 emissiveColor = vec3(1, 1, 1);
    float emissiveStrength = .75;

    vec3 color = vec3(20, 20, 20);

    vec3 emissive = emissiveColor * emissiveStrength;
    color += emissive;

    FragColor = vec4(color, 1.0);

    float brightness = dot(emissive, vec3(0.2126, 0.7152, 0.0722));
    if (brightness &gt; 1.0)
        BrightColor = vec4(emissive, 1.0);
    else
        BrightColor = vec4(0.0);
}

</code></pre>
<pre><code class="lang-auto">#version 430 core //blur
out vec4 FragColor;
  
in vec2 TexCoords;

uniform sampler2D image;
  
uniform bool horizontal;
uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);

void main()
{             
    vec2 tex_offset = 1.0 / textureSize(image, 0); // gets size of single texel
    vec3 result = texture(image, TexCoords).rgb * weight[0]; // current fragment's contribution
    if(horizontal)
    {
        for(int i = 1; i &lt; 5; ++i)
        {
            result += texture(image, TexCoords + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
            result += texture(image, TexCoords - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
        }
    }
    else
    {
        for(int i = 1; i &lt; 5; ++i)
        {
            result += texture(image, TexCoords + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
            result += texture(image, TexCoords - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
        }
    }
    FragColor = vec4(result, 1.0);
}
</code></pre>
<pre><code class="lang-auto">#version 430 core //blend
out vec4 FragColor;
  
in vec2 TexCoords;

uniform sampler2D scene;
uniform sampler2D bloomBlur;

void main()
{   
    float exposure = .5;
    const float gamma = 2.2;
    vec3 hdrColor = texture(scene, TexCoords).rgb;      
    vec3 bloomColor = texture(bloomBlur, TexCoords).rgb;
    hdrColor += bloomColor; // additive blending
    // tone mapping
    vec3 result = vec3(1.0) - exp(-hdrColor * exposure);
    // also gamma correct while we're at it       
    result = pow(result, vec3(1.0 / gamma));
    //FragColor = vec4(result, 1.0);
    FragColor = vec4(bloomColor, 1);
}  
</code></pre>
            <p><small>2 posts - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/why-wont-my-bloom-material-work/112406">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/why-wont-my-bloom-material-work/112406</link>
          <pubDate>Fri, 19 Dec 2025 21:59:20 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112406</guid>
          <source url="https://community.khronos.org/t/why-wont-my-bloom-material-work/112406.rss">Why won&#39;t my bloom material work?</source>
        </item>
        <item>
          <title>PBR shader look okay?</title>
          <dc:creator><![CDATA[SpiderPig]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>Hey everyone,</p>
<p>I’ve been working on a PBR shader the last few months and have gotten a good ways with it I think.  I’m just not sure if I have actually got a robust solution, and I’m getting PBR working with my terrain system and feel like the screenshot below is just a little to “blue” from IBL.  You can see the left of the terrain has a blue tint compared to the right.  I tend to believe that the camera is facing the directional light there…  I don’t know.  It just feels washed out to me, but might be correct.</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/8/8dcefff13f4f1169bbdc00d6f102f402ee38de7a.jpeg" data-download-href="https://community.khronos.org/uploads/default/8dcefff13f4f1169bbdc00d6f102f402ee38de7a" title="Terrain_PBR_Lighting_003"><img src="https://community.khronos.org/uploads/default/optimized/2X/8/8dcefff13f4f1169bbdc00d6f102f402ee38de7a_2_690x432.jpeg" alt="Terrain_PBR_Lighting_003" data-base62-sha1="keuOJz99YVAmUsdZ1f47NM9H9GO" width="690" height="432" srcset="https://community.khronos.org/uploads/default/optimized/2X/8/8dcefff13f4f1169bbdc00d6f102f402ee38de7a_2_690x432.jpeg, https://community.khronos.org/uploads/default/optimized/2X/8/8dcefff13f4f1169bbdc00d6f102f402ee38de7a_2_1035x648.jpeg 1.5x, https://community.khronos.org/uploads/default/optimized/2X/8/8dcefff13f4f1169bbdc00d6f102f402ee38de7a_2_1380x864.jpeg 2x" data-dominant-color="A8A58E"></a></div><p></p>
<p>Here’s the same PBR lighting on the helmet model (different shader code but same lighting functions)</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/9/90a0ff9696fb488580ca8038a80b272b4534e95f.jpeg" data-download-href="https://community.khronos.org/uploads/default/90a0ff9696fb488580ca8038a80b272b4534e95f" title="PBRLighting_003"><img src="https://community.khronos.org/uploads/default/optimized/2X/9/90a0ff9696fb488580ca8038a80b272b4534e95f_2_690x432.jpeg" alt="PBRLighting_003" data-base62-sha1="kDrGYGOOIKurD4XpRUheexLsN8X" width="690" height="432" srcset="https://community.khronos.org/uploads/default/optimized/2X/9/90a0ff9696fb488580ca8038a80b272b4534e95f_2_690x432.jpeg, https://community.khronos.org/uploads/default/optimized/2X/9/90a0ff9696fb488580ca8038a80b272b4534e95f_2_1035x648.jpeg 1.5x, https://community.khronos.org/uploads/default/optimized/2X/9/90a0ff9696fb488580ca8038a80b272b4534e95f_2_1380x864.jpeg 2x" data-dominant-color="959285"></a></div><p></p>
<p>Hoping some of you guys might have some tips or may see something not right in the code.</p>
<p>Here’s the full vert and frag code for the terrain.</p>
<pre><code class="lang-auto">//Vertex Shader
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shader_draw_parameters : enable
#extension GL_ARB_bindless_texture : enable


#define BUFFER_BINDING_CAMERA_SSBO 0
#define BUFFER_BINDING_ENTITY_SSBO 1
#define BUFFER_BINDING_MESH_SSBO 2
#define BUFFER_BINDING_MATERIAL_SSBO 3
#define BUFFER_BINDING_FRAMEBUFFER_SSBO 4
#define BUFFER_BINDING_LIGHTS_SSBO 5
#define BUFFER_BINDING_INSTANCE_SSBO 6
#define BUFFER_BINDING_VOXEL_OBJECT_SSBO 7
#define BUFFER_BINDING_PROBE_SSBO 8

//Shader master starts from 8.  This needs to be manually changed if more enigne values are added here.

layout(location = 0) uniform int CameraID;
#ifdef DOUBLE_FLOAT
//layout(location = 1) uniform dvec3 WorldOffset;
#endif

struct Camera {
    mat4 view;
	mat4 projection;
};

layout(std430, binding = BUFFER_BINDING_CAMERA_SSBO) buffer CameraBuffer {
    Camera cameras[];
};

mat4 CameraMatrix;
mat4 CameraInverseMatrix;

vec3 ExtractCameraPosition(in int CameraID) {
	Camera cam = cameras[CameraID];
	CameraInverseMatrix = inverse(cam.view);
	return CameraInverseMatrix[3].xyz;
}
vec3 CameraPosition = ExtractCameraPosition(CameraID);


//Shoud only be used in a vertex shader due to : uint id = gl_BaseInstanceARB + gl_InstanceID;

struct Mesh {
	uint entityID;
	uint materialID;
};

layout(std430, binding = BUFFER_BINDING_MESH_SSBO) readonly buffer MeshBuffer {
    Mesh instanceInfo[];
};

uint EntityID;
uint MaterialID;

uint ExtractInstanceInfo() {
	uint id = gl_BaseInstanceARB + gl_InstanceID;
	EntityID = instanceInfo[id].entityID;
	MaterialID = instanceInfo[id].materialID;
	
	return id;
}
uint MeshID = ExtractInstanceInfo();

//Entities
//Structs are auto padded to 16 bytes
struct Entity {
	mat4 matrix;
	mat4 normal_matrix;
	vec4 color;
};

layout(std430, binding = BUFFER_BINDING_ENTITY_SSBO) readonly buffer EntityBuffer {
    Entity entities[];
};
layout(location = 0) in vec3 in_vPosition;
layout(location = 1) in vec3 in_vNormal;
layout(location = 2) in vec3 in_vTangent;
layout(location = 3) in vec3 in_vBitangent;
layout(location = 4) in vec4 in_vCoords;
layout(location = 5) in vec3 in_vColor;
#define TEXTURE_DIFFUSE 0
#define TEXTURE_NORMAL 1
#define TEXTURE_TANGENT 2
#define TEXTURE_BITANGENT 3
#define TEXTURE_AO 4
#define TEXTURE_SLOT_ALBEDO 0
#define TEXTURE_SLOT_NORMAL 1
#define TEXTURE_SLOT_METALLIC_ROUGHNESS_AO 2
#define TEXTURE_SLOT_EMISSIVE 3
#define TEXTURE_SLOT_DISPLACMENT 4

struct Material {
	vec4 diffuseColor;
	float roughness;
	float metallic;
	float displacment_strength;
	uvec2 textureHandle[16];
};

layout(std430, binding = 3) readonly buffer MaterialBlock { Material materials[]; };

layout(location = 0) out vec3 out_vNormal;
layout(location = 1) out vec4 out_vCoords;
layout(location = 2) out vec4 out_vColor;
layout(location = 3) flat out uint out_MaterialIndex;
layout(location = 4) flat out uint out_EntityIndex;
layout(location = 5) flat out uint out_MeshIndex;
layout(location = 6) out vec3 out_WorldPosition;
layout(location = 7) out vec3 out_CameraPosition;
layout(location = 8) out mat3 out_TBN;


void main() {
	Entity entity = entities[EntityID];
	Material material = materials[MaterialID];
	
	vec3 vertex_position = in_vPosition;
	
	//mat4 model_matrix = entity.matrix;
	
	Camera camera = cameras[CameraID];
	mat4 proj_matrix = camera.projection;
	mat4 view_matrix = camera.view;
	
	//Can we calculate the normal_matrix once per model?
	//-mat3 normal_matrix = transpose(inverse(mat3(entity.matrix)));
	mat3 normal_matrix = mat3(entity.matrix);
	vec3 T = normalize(vec3(normal_matrix * vec3(1,0,0)));
	vec3 B = normalize(vec3(normal_matrix * vec3(0,0,1)));
	vec3 N = normalize(vec3(normal_matrix * vec3(0,1,0)));
	out_TBN = mat3(T, B, N);
	
	out_CameraPosition = inverse(view_matrix)[3].xyz;
	out_WorldPosition = vec3(entity.matrix * vec4(vertex_position, 1.0f));
	out_EntityIndex = EntityID;
	//out_EntityColor = entity.color;
	out_MeshIndex = MeshID;
	out_MaterialIndex = MaterialID;
	out_vNormal = N;
	out_vColor = vec4(in_vColor, 1.0f);
	out_vCoords = in_vCoords;
    gl_Position = proj_matrix * view_matrix * vec4(out_WorldPosition, 1.0f);
}
</code></pre>
<pre><code class="lang-auto">//Fragment Shader
#version 460
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_bindless_texture : enable

layout(location = 0) in vec3 in_vNormal;
layout(location = 1) in vec4 in_vCoords;
layout(location = 2) in vec4 in_vColor;
layout(location = 3) flat in uint in_MaterialIndex;
layout(location = 4) flat in uint in_EntityIndex;
layout(location = 5) flat in uint in_MeshIndex;
layout(location = 6) in vec3 in_WorldPosition;
layout(location = 7) in vec3 in_CameraPosition;
layout(location = 8) in mat3 in_TBN;

#define TEXTURE_DIFFUSE 0
#define TEXTURE_NORMAL 1
#define TEXTURE_TANGENT 2
#define TEXTURE_BITANGENT 3
#define TEXTURE_AO 4
#define TEXTURE_SLOT_ALBEDO 0
#define TEXTURE_SLOT_NORMAL 1
#define TEXTURE_SLOT_METALLIC_ROUGHNESS_AO 2
#define TEXTURE_SLOT_EMISSIVE 3
#define TEXTURE_SLOT_DISPLACMENT 4


struct Material {
	vec4 diffuseColor;
	float roughness;
	float metallic;
	float displacment_strength;
	uvec2 textureHandle[16];
};

layout(std430, binding = 3) readonly buffer MaterialBlock { Material materials[]; };

struct VoxelTerrainLayer {
	uint material_index;
	float min_height;
	float max_height;
	float min_slope;
	float max_slope;
	float min_angle;
	float max_angle;
	float transition;
};




float MacroVariation( in Material material , in int texture_slot , in vec2 coords , in float strength ) {
	return mix( ( 1.0f - strength ) , 1.0f , ( ( texture( sampler2D( material.textureHandle[ texture_slot ] ) , ( coords * 0.2134f ) ).x + 0.5f ) * ( ( texture( sampler2D( material.textureHandle[ texture_slot ] ) , ( coords * 0.05341f ) ).x + 0.5f ) * ( texture( sampler2D( material.textureHandle[ texture_slot ] ) , ( coords * 0.002f ) ).x + 0.5f ) ) ) );
}




vec4 SampleDiffuse( Material material , in vec2 coords ) {
	return ( material.diffuseColor * ( texture( sampler2D( material.textureHandle[ 0 ] ) , coords ) * MacroVariation( material , 0 , coords , 1.0f ) ) );
}




vec3 SampleNormal( in Material material , in vec2 coords ) {
	vec4 node22_pixel = texture( sampler2D( material.textureHandle[ 1 ] ) , coords );
	return vec3( ( ( node22_pixel.x * 2.0f ) - 1.0f ) , ( ( node22_pixel.z * 2.0f ) - 1.0f ) , ( ( node22_pixel.y * 2.0f ) - 1.0f ) );
}




void SampleLayer( in VoxelTerrainLayer layer , in vec2 coords , in float slope , out vec3 normal , out vec4 color , out float blend ) {
	normal = SampleNormal(materials[ layer.material_index ] , coords);
	blend = smoothstep( ( layer.max_slope + 0.001f ) , layer.min_slope , slope );
	if ( blend &gt; 0.0f ) {
		color = ( materials[ layer.material_index ].diffuseColor * SampleDiffuse(materials[ layer.material_index ] , coords) );
		
	}
}


#define BUFFER_BINDING_CAMERA_SSBO 0
#define BUFFER_BINDING_ENTITY_SSBO 1
#define BUFFER_BINDING_MESH_SSBO 2
#define BUFFER_BINDING_MATERIAL_SSBO 3
#define BUFFER_BINDING_FRAMEBUFFER_SSBO 4
#define BUFFER_BINDING_LIGHTS_SSBO 5
#define BUFFER_BINDING_INSTANCE_SSBO 6
#define BUFFER_BINDING_VOXEL_OBJECT_SSBO 7
#define BUFFER_BINDING_PROBE_SSBO 8

//Shader master starts from 8.  This needs to be manually changed if more enigne values are added here.


layout(location = 0) uniform int CameraID;
#ifdef DOUBLE_FLOAT
layout(location = 1) uniform dvec3 WorldOffset;
#endif


struct Camera {
    mat4 view;
	mat4 projection;
};

layout(std430, binding = BUFFER_BINDING_CAMERA_SSBO) buffer CameraBuffer {
    Camera cameras[];
};

mat4 CameraMatrix;
mat4 CameraInverseMatrix;

vec3 ExtractCameraPosition(in int CameraID) {
	Camera cam = cameras[CameraID];
	CameraInverseMatrix = inverse(cam.view);
	return CameraInverseMatrix[3].xyz;
}
vec3 CameraPosition = ExtractCameraPosition(CameraID);


vec2 DistanceCoords( in vec2 coords , in vec3 world_position , in float uv_scale , in float step_size ) {
	return ( coords / ( uv_scale * ( floor( ( distance(world_position, CameraPosition) / step_size ) ) + 1.0f ) ) );
}



uniform float object_size = 1.0f;
uniform int total_material_layers = 0;

void VoxelTerrainInput( out float size , out float height , out float detail , out float noise , out float ao , out vec3 normal , out vec3 tangent , out vec3 bi_tangent , out vec2 object_uv , out vec2 tile_uv , out int layer_count , out uint layers ) {
	size = object_size;
	vec4 node23_tex_sample = texture( sampler2D( materials[ in_MaterialIndex ].textureHandle[ TEXTURE_DIFFUSE ] ) , ( in_WorldPosition.xz / object_size ) );
	height = node23_tex_sample.x;
	detail = node23_tex_sample.y;
	noise = node23_tex_sample.z;
	ao = node23_tex_sample.w;
	normal = SampleNormal(materials[ in_MaterialIndex ] , ( in_WorldPosition.xz / object_size ));
	tangent = texture( sampler2D( materials[ in_MaterialIndex ].textureHandle[ TEXTURE_TANGENT ] ) , ( in_WorldPosition.xz / object_size ) ).xyz;
	bi_tangent = texture( sampler2D( materials[ in_MaterialIndex ].textureHandle[ TEXTURE_BITANGENT ] ) , ( in_WorldPosition.xz / object_size ) ).xyz;
	object_uv = ( in_WorldPosition.xz / object_size );
	tile_uv = in_WorldPosition.xz;
	layer_count = total_material_layers;
}



float GetSlope( in vec3 normal , in vec3 up ) {
	return clamp(dot( normal , up ), 0.0f, 1.0f);
}



const int node38_array_size = 32;
layout(std140, binding = 8) uniform material_layers_block {
	VoxelTerrainLayer material_layers[32];
};
out vec4 FragColor;

void main() {
	float node29_size;
	float node29_height;
	float node29_detail;
	float node29_noise;
	float node29_ao;
	vec3 node29_normal;
	vec3 node29_tangent;
	vec3 node29_bi_tangent;
	vec2 node29_object_uv;
	vec2 node29_tile_uv;
	int node29_layer_count;
	uint node29_layers;
	VoxelTerrainInput( node29_size , node29_height , node29_detail , node29_noise , node29_ao , node29_normal , node29_tangent , node29_bi_tangent , node29_object_uv , node29_tile_uv , node29_layer_count , node29_layers );
	vec4 node13_variable = vec4( 1.0f, 1.0f, 1.0f, 0.0f );
	
	vec3 node6_normal;
	vec4 node6_color;
	float node6_blend;
	
	for( int node35_index = 0; node35_index &lt; node29_layer_count; node35_index++ ) {
		SampleLayer( material_layers[node35_index] , DistanceCoords( node29_tile_uv , in_WorldPosition , 1.0f , 32.0f ) , GetSlope(node29_normal , vec3( 0.0f, 1.0f, 0.0f )) , node6_normal , node6_color , node6_blend );
		if ( node35_index == 0 ) {
			node6_blend = 1.0f;
			
		}
		node13_variable = mix( node13_variable , node6_color , node6_blend );
	}
	
	FragColor = node13_variable;
}
</code></pre>
            <p><small>4 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/pbr-shader-look-okay/112397">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/pbr-shader-look-okay/112397</link>
          <pubDate>Tue, 09 Dec 2025 20:09:38 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112397</guid>
          <source url="https://community.khronos.org/t/pbr-shader-look-okay/112397.rss">PBR shader look okay?</source>
        </item>
        <item>
          <title>How to batch-drawCall for many shader-clip textured quad?</title>
          <dc:creator><![CDATA[gpu22]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>how to batch-drawCall for many shader-clip textured quad?<br>
eg. there are many textured-circle, each one is drawn as this:</p>
<ol>
<li>draw quad with texture</li>
<li>clip quad to circle with shader and scissor state<br>
as clip break the batching-drawCall, when there are many this textured circle, there are many drawCall.<br>
is there any way to batching all of these drawCall?<br>
Thanks!</li>
</ol>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/how-to-batch-drawcall-for-many-shader-clip-textured-quad/112396">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/how-to-batch-drawcall-for-many-shader-clip-textured-quad/112396</link>
          <pubDate>Tue, 09 Dec 2025 13:39:58 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112396</guid>
          <source url="https://community.khronos.org/t/how-to-batch-drawcall-for-many-shader-clip-textured-quad/112396.rss">How to batch-drawCall for many shader-clip textured quad?</source>
        </item>
        <item>
          <title>I’m trying to render a textured rectangle, but regardless of my texture setup, the rectangle shows a color gradient instead of the actual texture</title>
          <dc:creator><![CDATA[PancakeFlipper11]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>I am learning OpenGL, and I am trying to draw a rectangle with a texture on it. However, it instead renders a gradient from red in the corners to black at the center. At first, I thought it was like when you specify a color at the vertices of a shape, and it interpolates the color between them. However, there is no vertex at the middle, where is fades to black. My line that sets the color is the only place I can possibly think if that could give a bug like this, but I don’t see any problems with it. The line is “fragColor = texture(ourTexture, texCoord);”. I have confirmed that the texture coordinates are correct, and that the texture file is also correct. Does anybody have any ideas why a bug like this might happen?</p>
            <p><small>7 posts - 3 participants</small></p>
            <p><a href="https://community.khronos.org/t/i-m-trying-to-render-a-textured-rectangle-but-regardless-of-my-texture-setup-the-rectangle-shows-a-color-gradient-instead-of-the-actual-texture/112312">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/i-m-trying-to-render-a-textured-rectangle-but-regardless-of-my-texture-setup-the-rectangle-shows-a-color-gradient-instead-of-the-actual-texture/112312</link>
          <pubDate>Thu, 27 Nov 2025 00:03:25 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>Yes</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112312</guid>
          <source url="https://community.khronos.org/t/i-m-trying-to-render-a-textured-rectangle-but-regardless-of-my-texture-setup-the-rectangle-shows-a-color-gradient-instead-of-the-actual-texture/112312.rss">I’m trying to render a textured rectangle, but regardless of my texture setup, the rectangle shows a color gradient instead of the actual texture</source>
        </item>
        <item>
          <title>Semitransparent blending with maximum alpha</title>
          <dc:creator><![CDATA[Shtille]]></dc:creator>
          <category>OpenGL: Advanced Coding</category>
          <description><![CDATA[
            <p>Hi! I try to implement blending of several semitransparent screen space quads with case that I take maximum alpha value from current framebuffer alpha and fragment alpha and that value is used in traditional transparent blending calculation:</p>
<pre><code class="lang-auto">glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
</code></pre>
<p>So in result I need something like:</p>
<pre><code class="lang-auto">glBlendFunc(GL_MAX_ALPHA, GL_ONE_MINUS_MAX_ALPHA);
</code></pre>
<p>As far as I understand this can be done with framebuffer ping-pong in shaders and manual color calculation. But in my case there might be many screen space objects, so it will affect performance.<br>
Any advices?</p>
            <p><small>1 post - 1 participant</small></p>
            <p><a href="https://community.khronos.org/t/semitransparent-blending-with-maximum-alpha/112159">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/semitransparent-blending-with-maximum-alpha/112159</link>
          <pubDate>Mon, 10 Nov 2025 16:46:01 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>No</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112159</guid>
          <source url="https://community.khronos.org/t/semitransparent-blending-with-maximum-alpha/112159.rss">Semitransparent blending with maximum alpha</source>
        </item>
        <item>
          <title>Capping nested entities with a color by entity</title>
          <dc:creator><![CDATA[Fede]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>Hi everyone,</p>
<p>I’m clipping some entities in the scene by setting <a href="https://registry.khronos.org/OpenGL-Refpages/gl4/html/gl_ClipDistance.xhtml">gl_ClipDistance</a>, I have some doubts about giving caps to entities and I hope you can give me good hints about that: thank you all in advance! <img src="https://community.khronos.org/images/emoji/twitter/slight_smile.png?v=14" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p><strong>CONTEXT</strong><br>
I used what I think to be the standard approach to create single coloured cappings:</p>
<pre><code class="lang-auto">1. Draw all the entities only in stencil with front face clipping, increasing stencil
2. Draw all the entities only in stencil with back face clipping, decreasing stencil
3. Draw a mesh (color mask on, depth test on [GL_LESS]) representing the clipping plane: the stencil allows only the cap to be drawn
</code></pre>
<p>I wanted to take a step further, by giving each entities its own capping color;<br>
my main issue is that entities in my scene can be nested, and I could just came up with the following approach:</p>
<pre><code class="lang-auto">1. for each entity in scene
2.     Draw the given entity only in stencil with front face clipping, increasing stencil
3.     Draw the given entity only in stencil with back face clipping, decreasing stencil
4.     Draw the clipping plane (color mask on, depth test on [GL_LESS]) using the entity color 
5.     Next
</code></pre>
<p>This approach works (at least, I’m getting the expected results), but I was wondering if something better could be achieved; namely, I change face clipping twice on a per entity basis, as well as stencil operation and depth testing, whilst in the single colour approach I could change all the settings on a per scene draw basis.<br>
I tried some depth-based approaches, but I couldn’t manage to produce a proper result.</p>
<p><strong>SIMPLE USE CASE</strong><br>
A simple situation that I tried to analize is the following, where my attempts with depth failed due to the face pointed at by the green arrow<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/d/d6849fcfdf7c0e04b938786d59937b5f8a3605e8.png" data-download-href="https://community.khronos.org/uploads/default/d6849fcfdf7c0e04b938786d59937b5f8a3605e8" title="image"><img src="https://community.khronos.org/uploads/default/original/2X/d/d6849fcfdf7c0e04b938786d59937b5f8a3605e8.png" alt="image" data-base62-sha1="uBIk8JZ822lL1ekqdoYqWmWgcwo" width="514" height="316"></a></div><p></p>
<p><strong>EXPECTED RESULT</strong><br>
This is the expected result, that I can get with the previously described approach<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/d/d9eff7d2229f6f35b40041d4aeab3375dcf45742.png" data-download-href="https://community.khronos.org/uploads/default/d9eff7d2229f6f35b40041d4aeab3375dcf45742" title="image"><img src="https://community.khronos.org/uploads/default/original/2X/d/d9eff7d2229f6f35b40041d4aeab3375dcf45742.png" alt="image" data-base62-sha1="v5XJTzAerP13iNUTu3AsKDVHIjw" width="428" height="332"></a></div><p></p>
<p><strong>QUESTION</strong><br>
Is performing two stencil passes and a color draw call for each entity a good enough approach, or is there a better algorithm to achieve the wanted result?<br>
Thank anyone who can share their thoughts on this matter!</p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/capping-nested-entities-with-a-color-by-entity/112157">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/capping-nested-entities-with-a-color-by-entity/112157</link>
          <pubDate>Mon, 10 Nov 2025 11:27:25 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>Yes</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112157</guid>
          <source url="https://community.khronos.org/t/capping-nested-entities-with-a-color-by-entity/112157.rss">Capping nested entities with a color by entity</source>
        </item>
        <item>
          <title>Why are my textures glitching?</title>
          <dc:creator><![CDATA[Ditsapat]]></dc:creator>
          <category>OpenGL</category>
          <description><![CDATA[
            <p>i use batching method for this but somehow the textures are glitching to others’ textures. I have no depth test enable. I don’t know why this happen. Anyone has any idea to fix it?<br>
</p><div class="lightbox-wrapper"><a class="lightbox" href="https://community.khronos.org/uploads/default/original/2X/9/9cb5b4d14d3acd581e4ca443d4fb57eaf12a593d.png" data-download-href="https://community.khronos.org/uploads/default/9cb5b4d14d3acd581e4ca443d4fb57eaf12a593d" title="Screenshot 2025-10-25 002709"><img src="https://community.khronos.org/uploads/default/optimized/2X/9/9cb5b4d14d3acd581e4ca443d4fb57eaf12a593d_2_690x387.png" alt="Screenshot 2025-10-25 002709" data-base62-sha1="mmjMWnVvdOTBhRurh7KWWdmvYsZ" width="690" height="387" srcset="https://community.khronos.org/uploads/default/optimized/2X/9/9cb5b4d14d3acd581e4ca443d4fb57eaf12a593d_2_690x387.png, https://community.khronos.org/uploads/default/optimized/2X/9/9cb5b4d14d3acd581e4ca443d4fb57eaf12a593d_2_1035x580.png 1.5x, https://community.khronos.org/uploads/default/optimized/2X/9/9cb5b4d14d3acd581e4ca443d4fb57eaf12a593d_2_1380x774.png 2x" data-dominant-color="6ED5E7"></a></div><p></p>
<p>You can see that the second texture is on the first (black) texture and it’s only happen when I use texture and not color to draw and sometimes they appear sometimes don’t.</p>
<p>my shaders:</p>
<pre><code class="lang-auto">#shader vertex
#version 330 core
uniform mat4 u_view;
uniform mat4 u_model;
uniform mat4 u_proj;
layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
layout (location = 2) in float texID;
layout (location = 3) in vec2 texCoord;

out float v_texID;
out vec2 v_texCoord;
out vec4 v_color;
  void main()
  {
      mat4 mat = u_proj*u_view*u_model;
      gl_Position = mat*position;
      v_color = color;
      v_texID = texID;
      v_texCoord = texCoord;
  }
  
  #shader fragment
  uniform sampler2D u_textures[8];
  in float v_texID;
  in vec2 v_texCoord;
  in vec4 v_color;
  out vec4 FragColor;
  
  void main()
  {
      vec4 color = v_color;
      if (v_texID&gt;=0.0) FragColor =  texture2D(u_textures[int(v_texID)], v_texCoord)*color;
      else FragColor = color;
  }
</code></pre>
<p>my vertex datas :</p>
<pre><code>    Vertex2D v[] = {
        0.f,0.f,0.f, 1.f,1.f,1.f,1.f, 0.f, 0.f,0.f,
        100.f,0.f,0.f, 1.f,1.f,1.f,1.f, 0.f, 1.f,0.f,
        0.f,100.f,0.f, 1.f,1.f,1.f,1.f, 0.f, 0.f,1.f,
        100.f,100.f,0.f, 1.f,1.f,1.f,1.f, 0.f, 1.f,1.f,

        150.f,0.f,0.f, 1.f,1.f,1.f,1.f, 1.f, 0.f,0.f,
        250.f,0.f,0.f, 1.f,1.f,1.f,1.f, 1.f, 1.f,0.f,
        150.f,100.f,0.f, 1.f,1.f,1.f,1.f, 1.f, 0.f,1.f,
        250.f,100.f,0.f, 1.f,1.f,1.f,1.f, 1.f, 1.f,1.f
    };
    unsigned i[] = {0,1,2,1,2,3, 4,5,6,5,6,7};
</code></pre>
<p>texID is just for texture slot.</p>
            <p><small>2 posts - 2 participants</small></p>
            <p><a href="https://community.khronos.org/t/why-are-my-textures-glitching/112140">Read full topic</a></p>
          ]]></description>
          <link>https://community.khronos.org/t/why-are-my-textures-glitching/112140</link>
          <pubDate>Fri, 24 Oct 2025 17:46:54 +0000</pubDate>
          <discourse:topicPinned>No</discourse:topicPinned>
          <discourse:topicClosed>Yes</discourse:topicClosed>
          <discourse:topicArchived>No</discourse:topicArchived>
          <guid isPermaLink="false">community.khronos.org-topic-112140</guid>
          <source url="https://community.khronos.org/t/why-are-my-textures-glitching/112140.rss">Why are my textures glitching?</source>
        </item>
  </channel>
</rss>
