//----------------------------------------------------------------------------- void GLES2RenderToVertexBuffer::bindVerticesOutput(Pass* pass) { VertexDeclaration* declaration = mVertexData->vertexDeclaration; size_t elemCount = declaration->getElementCount(); if (elemCount > 0) { GLuint linkProgramId = 0; // Have GLSL shaders, using varying attributes if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { GLSLESProgramPipeline* programPipeline = GLSLESProgramPipelineManager::getSingleton().getActiveProgramPipeline(); linkProgramId = programPipeline->getGLProgramPipelineHandle(); } else { GLSLESLinkProgram* linkProgram = GLSLESLinkProgramManager::getSingleton().getActiveLinkProgram(); linkProgramId = linkProgram->getGLProgramHandle(); } // Note: 64 is the minimum number of interleaved attributes allowed by GL_EXT_transform_feedback // So we are using it. Otherwise we could query during rendersystem initialisation and use a dynamic sized array. // But that would require C99. const GLchar *names[64]; for (unsigned short e = 0; e < elemCount; e++) { const VertexElement* element = declaration->getElement(e); String varyingName = getSemanticVaryingName(element->getSemantic(), element->getIndex()); names[e] = varyingName.c_str(); } OGRE_CHECK_GL_ERROR(glTransformFeedbackVaryings(linkProgramId, elemCount, names, GL_INTERLEAVED_ATTRIBS)); OGRE_CHECK_GL_ERROR(glLinkProgram(linkProgramId)); } }
//----------------------------------------------------------------------------- void GLRenderToVertexBuffer::bindVerticesOutput(Pass* pass) { VertexDeclaration* declaration = mVertexData->vertexDeclaration; bool useVaryingAttributes = false; //Check if we are FixedFunc/ASM shaders (Static attributes) or GLSL (Varying attributes) //We assume that there isn't a mix of GLSL and ASM as this is illegal GpuProgram* sampleProgram = 0; if (pass->hasVertexProgram()) { sampleProgram = pass->getVertexProgram().getPointer(); } else if (pass->hasGeometryProgram()) { sampleProgram = pass->getGeometryProgram().getPointer(); } if ((sampleProgram != 0) && (sampleProgram->getLanguage() == "glsl")) { useVaryingAttributes = true; } if (useVaryingAttributes) { //Have GLSL shaders, using varying attributes GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); GLhandleARB linkProgramId = linkProgram->getGLHandle(); vector<GLint>::type locations; for (unsigned short e=0; e < declaration->getElementCount(); e++) { const VertexElement* element =declaration->getElement(e); String varyingName = getSemanticVaryingName(element->getSemantic(), element->getIndex()); GLint location = glGetVaryingLocationNV(linkProgramId, varyingName.c_str()); if (location < 0) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "GLSL link program does not output " + varyingName + " so it cannot fill the requested vertex buffer", "OgreGLRenderToVertexBuffer::bindVerticesOutput"); } locations.push_back(location); } glTransformFeedbackVaryingsNV( linkProgramId, static_cast<GLsizei>(locations.size()), &locations[0], GL_INTERLEAVED_ATTRIBS_NV); } else { //Either fixed function or assembly (CG = assembly) shaders vector<GLint>::type attribs; for (unsigned short e=0; e < declaration->getElementCount(); e++) { const VertexElement* element = declaration->getElement(e); //Type attribs.push_back(getGLSemanticType(element->getSemantic())); //Number of components attribs.push_back(VertexElement::getTypeCount(element->getType())); //Index attribs.push_back(element->getIndex()); } glTransformFeedbackAttribsNV( static_cast<GLuint>(declaration->getElementCount()), &attribs[0], GL_INTERLEAVED_ATTRIBS_NV); } checkGLError(true, true, "GLRenderToVertexBuffer::bindVerticesOutput"); }
void GL3PlusRenderToVertexBuffer::bindVerticesOutput(Pass* pass) { VertexDeclaration* declaration = mVertexData->vertexDeclaration; size_t elemCount = declaration->getElementCount(); if (elemCount == 0) return; // Get program object ID. GLuint programId = 0; if (Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { GLSLSeparableProgram* separableProgram = GLSLSeparableProgramManager::getSingleton().getCurrentSeparableProgram(); GLSLShader* glslGpuProgram = 0; if ((glslGpuProgram = separableProgram->getGeometryShader())) programId = glslGpuProgram->getGLProgramHandle(); //TODO include tessellation stages else // vertex program programId = separableProgram->getVertexShader()->getGLProgramHandle(); } else { GLSLMonolithicProgram* monolithicProgram = GLSLMonolithicProgramManager::getSingleton().getActiveMonolithicProgram(); programId = monolithicProgram->getGLProgramHandle(); } // Store the output in a buffer. The buffer has the same // structure as the shader output vertex data. // Note: 64 is the minimum number of interleaved // attributes allowed by GL_EXT_transform_feedback so we // are using it. Otherwise we could query during // rendersystem initialisation and use a dynamic sized // array. But that would require C99. size_t sourceBufferIndex = mTargetBufferIndex == 0 ? 1 : 0; // Bind and fill vertex arrays + buffers. reallocateBuffer(sourceBufferIndex); reallocateBuffer(mTargetBufferIndex); // GL3PlusHardwareVertexBuffer* sourceVertexBuffer = static_cast<GL3PlusHardwareVertexBuffer*>(mVertexBuffers[mSourceBufferIndex].getPointer()); // GL3PlusHardwareVertexBuffer* targetVertexBuffer = static_cast<GL3PlusHardwareVertexBuffer*>(mVertexBuffers[mTargetBufferIndex].getPointer()); //TODO GL4+ glBindTransformFeedback // Dynamically determine shader output variable names. std::vector<String> nameStrings; std::vector<const GLchar*> names; for (uint e = 0; e < elemCount; e++) { const VertexElement* element = declaration->getElement(e); String name = getSemanticVaryingName(element->getSemantic(), element->getIndex()); nameStrings.push_back(name); } // Convert to const char * for GL for (uint e = 0; e < elemCount; e++) { names.push_back(nameStrings[e].c_str()); } //TODO replace glTransformFeedbackVaryings with in-shader specification (GL 4.4) OGRE_CHECK_GL_ERROR(glTransformFeedbackVaryings(programId, elemCount, &names[0], GL_INTERLEAVED_ATTRIBS)); if (Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { GLSLSeparableProgram* separableProgram = GLSLSeparableProgramManager::getSingleton().getCurrentSeparableProgram(); separableProgram->activate(); } else { OGRE_CHECK_GL_ERROR(glLinkProgram(programId)); } #if OGRE_DEBUG_MODE // Check if program linking was successful. GLint didLink = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(programId, GL_LINK_STATUS, &didLink)); logObjectInfo(String("RVB GLSL link result : "), programId); if (glIsProgram(programId)) { glValidateProgram(programId); } logObjectInfo(String("RVB GLSL validation result : "), programId); // Check if varyings were successfully set. GLchar Name[64]; GLsizei Length(0); GLsizei Size(0); GLenum Type(0); // bool Validated = false; for (size_t i = 0; i < elemCount; i++) { OGRE_CHECK_GL_ERROR(glGetTransformFeedbackVarying( programId, i, 64, &Length, &Size, &Type, Name )); std::cout << "Varying " << i << ": " << Name <<" "<< Length <<" "<< Size <<" "<< Type << std::endl; // Validated = (Size == 1) && (Type == GL_FLOAT_VEC3); // std::cout << Validated << " " << GL_FLOAT_VEC3 << std::endl; } #endif }