void SCSChannelManagerFragmentProgram::merge() { GLuint vId = OpenGL::getARBVertexProgram(mergeVertexProgram, (sizeof(mergeVertexProgram) / sizeof(mergeVertexProgram[0])) - 1); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vId); glEnable(GL_VERTEX_PROGRAM_ARB); GLuint fId = isRectangularTexture() ? OpenGL::getARBFragmentProgram(mergeFragmentProgramRect, (sizeof(mergeFragmentProgramRect) / sizeof(mergeFragmentProgramRect[0])) - 1) : OpenGL::getARBFragmentProgram(mergeFragmentProgram2D, (sizeof(mergeFragmentProgram2D) / sizeof(mergeFragmentProgram2D[0])) - 1); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fId); glEnable(GL_FRAGMENT_PROGRAM_ARB); bool isFixedFunction = false; setupProjectiveTexture(isFixedFunction); glEnable(GL_ALPHA_TEST); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glAlphaFunc(GL_LESS, 1.0f / 255.0f); std::vector<Channel> channels; channels.push_back(AllChannels); for (std::vector<Channel>::const_iterator c = channels.begin(); c!=channels.end(); ++c) { scissor->recall(*c); scissor->enableScissor(); const std::vector<Primitive*> primitives = getPrimitives(*c); for (std::vector<Primitive*>::const_iterator j = primitives.begin(); j != primitives.end(); ++j) { glCullFace((*j)->getOperation() == Intersection ? GL_BACK : GL_FRONT); RenderData* primitiveData = getRenderData(*j); GLubyte * id = primitiveData->bufferId.vec(); glColor4ubv(id); (*j)->render(); } } scissor->disableScissor(); glDisable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glDepthFunc(GL_LEQUAL); glDisable(GL_FRAGMENT_PROGRAM_ARB); glDisable(GL_VERTEX_PROGRAM_ARB); resetProjectiveTexture(isFixedFunction); clear(); }
void cSceneManager::renderEntitySingleShader(cShader* shader, std_string const& technique, cEntityModel const* entity) { if (!shader) return ; if (!entity) return ; cRenderData* rd = getRenderData(entity->getRenderDataBuid()); if (!rd) return ; uint pass; shader->setTechnique(technique.c_str()); shader->begin(&pass); renderRdShader(shader, pass, rd); shader->end(); }
void SCSChannelManagerAlphaOnly::merge() { bool isFixedFunction = true; setupProjectiveTexture(isFixedFunction); glEnable(GL_ALPHA_TEST); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); std::vector<Channel> channels = occupied(); for (std::vector<Channel>::const_iterator c = channels.begin(); c!=channels.end(); ++c) { setupTexEnv(*c); scissor->recall(*c); scissor->enableScissor(); const std::vector<Primitive*> primitives = getPrimitives(*c); for (std::vector<Primitive*>::const_iterator j = primitives.begin(); j != primitives.end(); ++j) { glCullFace((*j)->getOperation() == Intersection ? GL_BACK : GL_FRONT); RenderData* primitiveData = getRenderData(*j); GLubyte id = primitiveData->bufferId.a; // Here is an interesting bug, which happened on an ATI HD4670, but actually // might happen on every hardware. I am not sure whether it can be solved // correctly. // Problem is that in optimized mode with some compilers (VC6, Visual Studio 2003 // in particular), when setting the alpha func as follows: // glAlphaFunc(GL_EQUAL, static_cast<float>(id) / 255.0f); // the division is optimized as multiplication with 1.0f/255.0f. // This is a fine and valid optimization. Unfortunately, the results // are not exactly the same as the direct division for some ids. // Which is apparently what the ATI driver is doing internally. // So with comparison with GL_EQUAL fails. // Fortunately the OpenGL standard enforces that the mapping of color byte // values to float fragment values be done by division. So if the // solution found below (just working at double precision) proves // to work once, it should work forever, such that a precompiling // lookup table containing the correct alpha reference values is // not required. However a bad feeling remains. // The SCSChannelManagerFragmentProgram path implemented below should fix this. double alpha = static_cast<double>(id) / 255.0; GLfloat fAlpha = static_cast<float>(alpha); glAlphaFunc(GL_EQUAL, fAlpha); (*j)->render(); } } scissor->disableScissor(); glDisable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glDepthFunc(GL_LEQUAL); resetProjectiveTexture(isFixedFunction); clear(); }