Author Topic: Carousel  (Read 4840 times)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Carousel
« on: February 26, 2018, 11:43:16 pm »
Billboard in action (it works only in fixed pipeline mode  ???)

Food for thought...
« Last Edit: February 26, 2018, 11:55:13 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Carousel
« Reply #1 on: February 27, 2018, 02:41:38 am »
Hmm...

1. It seems like a classical case when #alphatocoverage should be global, don't you think? Nonetheless it's an obvious bug somewhere in my code or a side effect of immediate mode OpenGL deprecation. Thanks for spotting it.

2. Looks as if the OpenGL stack wouldn't pop and restore the A2C or multisample enabled state after it's been explicitly glDisable()'d. (switch on the FPS counter and see A2C stop working in OR_VBO but not in OR_VBA)

[UPD] Much to my surprise, as per the OpenGL help manual, GL_ENABLE_BIT stack pushing/popping should work for both the GL_MULTISAMPLE and GL_SAMPLE_ALPHA_TO_COVERAGE flags but in fact it doesn't work for either of them, at least not in our OpenGL v4.4 drivers!  >:(

I'll be looking more into it tomorrow.

:-\
« Last Edit: February 27, 2018, 03:34:20 am by Michael Lobko-Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Carousel
« Reply #2 on: February 27, 2018, 10:11:56 am »
The problem seems to be related to the use of billboard rather than A2C.

PS: I am restoring the rotation widget on the LS panel. (i need to have it from the LS panel while in full screen mode).
« Last Edit: February 27, 2018, 12:11:19 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Carousel
« Reply #3 on: February 27, 2018, 08:46:17 pm »
There's nothing wrong with the billboard code per se; gnm_BlinnPhongShader binding occured in the wrong place respective to the billboard code call. Two fixes in mobj.h follow below.

Fix for Mobj_DrawUsingProgrammablePipeline():
Code: [Select]
void Mobj_DrawUsingProgrammablePipeline(IN long nSpecularMode, IN long nUseTexture) { // MLL 02-08-2018: no more ListView
    MobjMesh* pMesh = 0;
    MobjMat* pMaterial = 0;

    long nI = 0, nCount = 0, nTexture = 0, nFlagBump = 0, nGlassIsUsed = 0, doSpherical = 0;
    long nFlagTextures = Mobj_enableTextures(0, 0); // ML: 11-24-2015

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    long nVertexSize = sizeof(MobjVertexT); // Mobj_getVertexSize();
    //long nMeshes = Mobj_getNumberOfMeshes();
    float rShine = 64.0f; // 128.0f;

    long nClockwise = Mobj_gl_cw(0, 0);
    long nLights = 3; // ML 02-01-2018: keep it a uniform for when number of lights becomes per-material :)
    long nLightFlags = gP.nLightFlags & 7; // ML 02-01-2018: another uniform with respective light on/off bitfield flags

    bool doRefresh = true; // ML 01-18-2018: need or not to refresh current MODELVIEW matrix
    long isBillboard = 0; // ML 01-18-2018: faster local cache (checked twice)

    for (nI = 0; nI < gnm_numberOfMeshes; ++nI) {
        // MLL 02-08-2018: !!! SLOW !!! There may be thousands of meshes like e.g. in the AmericanBeauty model!
        //if (IsWindow(hCheckList)) {
        //    nChecked = ListView_GetCheckState(hCheckList, nI);
        //}
        //if (nChecked) {
        pMesh = &gtm_meshes[nI];
        if (pMesh->isVisible) {
            pMaterial = pMesh->pMaterial;
            isBillboard = pMaterial->isBillboard; // ML 01-18-2018:

            // MLL 02-17-2018: !!! TEMPORARILY DISABLED !!!
            //if (!isSphereInFrustum(grm_frustum, pMesh->centerPoint, pMesh->meshRadius)) continue; // ML: 03-14-2016

            if (pMaterial->isA2C) { glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); } // PAT: 01-07-2018

            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pMaterial->ambient);
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pMaterial->diffuse);
            glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pMaterial->specular);
            glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, pMaterial->emissive); // ML 01-02-2018: glow
            glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * rShine);

            pMaterial->ambient[3] = pMaterial->alpha;
            pMaterial->diffuse[3] = pMaterial->alpha;
            pMaterial->specular[3] = pMaterial->alpha;
            pMaterial->emissive[3] = pMaterial->alpha; // ML 01-02-2018: glow

            nTexture = 0;
            doSpherical = 0; // ML: 11-26-2015
            if ((pMaterial->alpha < 1.0f) || (pMaterial->illum == 12)) { nGlassIsUsed = -1; } // 11-27-2015

            // 12-09-2015 ML: !!! can't do "Specular mode" in multishader !!!
            // ML 01-18-2018: diffuse only mapping for billboards for now
            if (!pMaterial->bumpMapID || nSpecularMode || isBillboard) {

                //// Per fragment Blinn-Phong code path. // MLL 02-27-2018: bypass billboard code below
                //glUseProgram(gnm_BlinnPhongShader);

                // Bind the color map texture.  // ML: 11-26-2015
                glActiveTexture(GL_TEXTURE0);
                glEnable(GL_TEXTURE_2D);
                if (nFlagTextures && !nSpecularMode) { // ML: 12-09-2015
                    if ((pMaterial->reflMapID) && (pMaterial->illum > 2)) { // 11-13-2015
                        doSpherical = 1;
                        if ((pMaterial->illum == 4) || (pMaterial->illum == 11)) { // global reflection
                            nTexture = nUseTexture;
                        } else {                     // individual reflection
                            nTexture = pMaterial->reflMapID;
                        }
                    } else if (pMaterial->illum == 11) {
                        doSpherical = 1;
                        nTexture = nUseTexture;
                    } else {
                        nTexture = pMaterial->colorMapID;
                        if (nTexture == 0) { nTexture = gnm_NullTexture; }
                    }
                } else {
                    if (nSpecularMode) {
                        doSpherical = 1;
                        if (nFlagTextures) {
                            if ((pMaterial->reflMapID) && (pMaterial->illum > 2)) {
                                nTexture = pMaterial->reflMapID;
                            } else {
                                nTexture = pMaterial->colorMapID;
                            }
                            if (nTexture == 0) { nTexture = nUseTexture; }
                        } else {
                            nTexture = nUseTexture;
                        }
                    } else {
                        nTexture = gnm_NullTexture;
                    }
                }
                //GL_BindTexture(GL_TEXTURE_2D, nTexture);
                glBindTexture(GL_TEXTURE_2D, nTexture);

                if (isBillboard) { // ML 01-18-2018: let it ride w/o shaders for the time being
                    glFrontFace(GL_CW);
                    billBoard(isBillboard, pMesh, &doRefresh);
                    if (!nClockwise) {
                        glFrontFace(GL_CCW);
                    }
                    goto doneBillboard;
                }

                // Per fragment Blinn-Phong code path.
                glUseProgram(gnm_BlinnPhongShader); // MLL 02-27-2018: bypass billboard code above

                // Update shader parameters.
                glUniform1i(glGetUniformLocation(gnm_BlinnPhongShader, "colorMap"), 0);
                glUniform1i(glGetUniformLocation(gnm_BlinnPhongShader, "nLights"), nLights); // ML: 12-11-2015
                glUniform1i(glGetUniformLocation(gnm_BlinnPhongShader, "nLightFlags"), nLightFlags); // ML 02-01-2018:
                glUniform1i(glGetUniformLocation(gnm_BlinnPhongShader, "doSpherical"), doSpherical); // ML: 11-26-2015
                glUniform1f(glGetUniformLocation(gnm_BlinnPhongShader, "materialAlpha"), pMaterial->alpha);

            } else {

                // Normal mapping code path.
                glUseProgram(gnm_NormalMappingShader);

                // Bind the specular map texture. // ML: 11-05-2015
                glActiveTexture(GL_TEXTURE2); nFlagBump = -1;
                glEnable(GL_TEXTURE_2D);
                glUniform1i(glGetUniformLocation(gnm_NormalMappingShader, "sSpecmap"), 2);
                if (nFlagTextures) { // ML: 11-24-2015
                    if (pMaterial->specMapID) {
                        nTexture = pMaterial->specMapID;
                    } else {
                        if (pMaterial->colorMapID) {
                            nTexture = pMaterial->colorMapID; // !!! ML: LEAVE IT BE !!!
                        } else {
                            nTexture = gnm_NullTexture;
                        }
                    }
                } else {
                    nTexture = gnm_NullTexture;
                }
                glBindTexture(GL_TEXTURE_2D, nTexture);

                // Bind the normal map texture. // ML: 11-05-2015
                glActiveTexture(GL_TEXTURE1); nFlagBump = -1;
                glEnable(GL_TEXTURE_2D);
                glUniform1i(glGetUniformLocation(gnm_NormalMappingShader, "sNormalmap"), 1);
                if (nFlagTextures) { // ML: 11-24-2015
                    if (pMaterial->bumpMapID) {
                        nTexture = pMaterial->bumpMapID;
                    } else {
                        nTexture = gnm_NullBump;
                    }
                } else {
                    nTexture = gnm_NullBump;
                }
                glBindTexture(GL_TEXTURE_2D, nTexture);

                // Bind the color map texture.
                glActiveTexture(GL_TEXTURE0);
                glEnable(GL_TEXTURE_2D);
                glUniform1i(glGetUniformLocation(gnm_NormalMappingShader, "sBasemap"), 0);
                if (nFlagTextures) { // ML: 11-24-2015
                    if (pMaterial->colorMapID) {
                        nTexture = pMaterial->colorMapID;
                    } else {
                        nTexture = gnm_NullTexture;
                    }
                } else {
                    nTexture = gnm_NullTexture;
                }
                glBindTexture(GL_TEXTURE_2D, nTexture);

                glUniform1i(glGetUniformLocation(gnm_NormalMappingShader, "nLights"), nLights); // ML: 12-11-2015
                glUniform1i(glGetUniformLocation(gnm_NormalMappingShader, "nLightFlags"), nLightFlags); // ML 02-01-2018:
                glUniform1f(glGetUniformLocation(gnm_NormalMappingShader, "materialAlpha"), pMaterial->alpha);
            }

            // MLL 02-08-2018: start using VBO's
            glBindBuffer(GL_ARRAY_BUFFER, gP.nVBO);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gP.nIBO);

            // Render mesh.
            glClientActiveTexture(GL_TEXTURE0);
            if (gnm_hasPositions) {
                glEnableClientState(GL_VERTEX_ARRAY);
                //glVertexPointer(3, GL_FLOAT, nVertexSize, Mobj_getVertexBufferPosition());
                glVertexPointer(3, GL_FLOAT, sizeof(MobjVertexT), (GLvoid*)0); // MLL 02-08-2018: 0 byte offset to 1st vertex pos
            }

            if (gnm_hasTextureCoords) {
                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
                //glTexCoordPointer(2, GL_FLOAT, nVertexSize, Mobj_getVertexBufferTexCoord());
                glTexCoordPointer(2, GL_FLOAT, sizeof(MobjVertexT), (GLvoid*)12); // MLL 02-08-2018: 12 byte offset to 1st tex coords
            }

            if (gnm_hasNormals) {
                glEnableClientState(GL_NORMAL_ARRAY);
                //glNormalPointer(GL_FLOAT, nVertexSize, Mobj_getVertexBufferNormal());
                glNormalPointer(GL_FLOAT, sizeof(MobjVertexT), (GLvoid*)20); // MLL 02-08-2018: 20 byte offset to 1st normal
            }

            if (gnm_hasTangents) {
                glClientActiveTexture(GL_TEXTURE1);
                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
                //glTexCoordPointer(4, GL_FLOAT, nVertexSize, Mobj_getVertexBufferTangent());
                // MLL 02-21-2018: 36 (?) byte offset to 1st tangent. I don't know why it is so;
                // should be 32 bytes. (buffer pack/unpack alignment?)
                glTexCoordPointer(4, GL_FLOAT, sizeof(MobjVertexT), (GLvoid*)(32 + 4));
            }

            if (nFlagBump) {
                // ML: 11-05-2015
                if (gnm_hasTextureCoords) {
                    glClientActiveTexture(GL_TEXTURE2);
                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
                    //glTexCoordPointer(2, GL_FLOAT, nVertexSize, Mobj_getVertexBufferTexCoord());
                    glTexCoordPointer(2, GL_FLOAT, sizeof(MobjVertexT), (GLvoid*)12); // MLL 02-08-2018: 12 byte offset to 1st tex coords
                }
            }

            nCount = pMesh->triangleCount * 3;
            //const GLvoid* indices = Mobj_getIndexBuffer() + pMesh->startIndex;
            const GLvoid* indices = (GLvoid*)(pMesh->startIndex * 4); // MLL 02-08-2018: byte offset to mesh 1st index

            if (nGlassIsUsed) {  // if we are using transparency then get rid of artefacts
                glEnable(GL_CULL_FACE);
                glFrontFace(nClockwise ? GL_CCW : GL_CW);
                glDrawElements(GL_TRIANGLES, nCount, GL_UNSIGNED_INT, indices);
                glFrontFace(nClockwise ? GL_CW : GL_CCW);
            }

            glDrawElements(GL_TRIANGLES, nCount, GL_UNSIGNED_INT, indices);

            if (nGlassIsUsed) { // 11-27-2015
                if (!Mobj_CullBackFace(0, 0)) { glDisable(GL_CULL_FACE); } // TODO: remove Mobj_() !!!
            }

            if (nFlagBump) { // ML: 11-05-2015
                glActiveTexture(GL_TEXTURE2);
                glBindTexture(GL_TEXTURE_2D, 0);
                glDisable(GL_TEXTURE_2D);
                if (gnm_hasTextureCoords) {
                    glClientActiveTexture(GL_TEXTURE2);
                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
                }
                nFlagBump = 0;
            } else { // ML 01-18-2018: else it's impossible to get rid of these shitty tex coords in immediate mode!
                if (doSpherical) {
                    glUniform1i(glGetUniformLocation(gnm_BlinnPhongShader, "doSpherical"), 0);
                }
            }

            glActiveTexture(GL_TEXTURE1);
            glBindTexture(GL_TEXTURE_2D, 0);
            glDisable(GL_TEXTURE_2D);

            if (gnm_hasTangents) {
                glClientActiveTexture(GL_TEXTURE1);
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            }

            // MLL 02-08-2018: unbind VBO's
            glBindBuffer(GL_ARRAY_BUFFER, 0);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

doneBillboard: // ML 01-21-2018: immediate mode for billboards is emulated by the OpenGL driver with an intrinsic shader,
               // so our billboard epilogue should also include disabling client states even though we didn't enable them.
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, 0);
            glClientActiveTexture(GL_TEXTURE0);

            if (gnm_hasNormals) { glDisableClientState(GL_NORMAL_ARRAY); }

            if (gnm_hasTextureCoords) { glDisableClientState(GL_TEXTURE_COORD_ARRAY); }

            if (gnm_hasPositions) { glDisableClientState(GL_VERTEX_ARRAY); }

            if (pMaterial->isA2C) { glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); } // PAT: 01-07-2018
        }
    }

    glUseProgram(0);
    //glDisable(GL_BLEND);
}


Fix for printFPS():
Code: [Select]
void printFPS(int x, char* str, int newFPS) {
    static bool fpsInited = false;
    char* s = str;
    int i, j, idx = 0;

    if (!fpsInited)
        fpsInit(&fpsInited);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glTranslatef(0.0f, gP.glHeight - 1.0f, 0.0f);
    glScalef(1.0f, -1.0f, 1.0f);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0.0, gP.glWidth, 0.0, gP.glHeight, -1.0, 1.0);
    glMatrixMode(GL_TEXTURE);
    glPushMatrix();
    glScalef(1.0f / float(g_digitW * 10), 1.0f / float(g_digitH), 1.0f);
    glMatrixMode(GL_MODELVIEW);

    glPushAttrib(GL_ENABLE_BIT);

    glEnable(GL_BLEND);
    glDisable(GL_LIGHTING);
    glDisable(GL_DEPTH_TEST);
    //glDisable(GL_MULTISAMPLE_ARB); // MLL 02-27-2018: doesn't get pushed on attrib stack!

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBindTexture(GL_TEXTURE_2D, gnm_fpsTexture);

    x += 1;
    while (*s) {
        i = x + g_digitW;
        idx = (*s++) - 48;
        j = idx * g_digitW;//(idx << 5) / 2;

        glBegin(GL_QUADS);
        glTexCoord2i(j, 0); glVertex2i(x, g_digitH);
        glTexCoord2i(j + g_digitW, 0); glVertex2i(i, g_digitH);
        glTexCoord2i(j + g_digitW, g_digitH); glVertex2i(i, 0);
        glTexCoord2i(j, g_digitH); glVertex2i(x, 0);
        glEnd();

        x += g_digitW;
    }

    glBindTexture(GL_TEXTURE_2D, 0);
    glPopAttrib();

    glMatrixMode(GL_TEXTURE);
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1983
    • zapsolution
Re: Carousel
« Reply #4 on: February 27, 2018, 09:03:38 pm »
Seems to work fine now, thank you Michael!

I hope you feel better my friend.
Patrice
(Always working with the latest Windows version available...)

Michael Lobko-Lobanovsky

  • Administrator
  • *****
  • Posts: 1481
Re: Carousel
« Reply #5 on: February 27, 2018, 09:57:49 pm »
Thanks Patrice!

(I do, more or less)
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)