ObjReader Community
WIP => WIP => Topic started by: Patrice Terrier on February 26, 2018, 11:43:16 pm
-
Billboard in action (it works only in fixed pipeline mode ???)
Food for thought...
-
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.
:-\
-
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).
-
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():
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 = >m_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():
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();
}
-
Seems to work fine now, thank you Michael!
I hope you feel better my friend.
-
Thanks Patrice!
(I do, more or less)