//----------------------------------------------------------------------------- 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 }
//Attribute map: //ATTR0 - POSITION0 //ATTR1 - POSITION1 //ATTR2 - NORMAL //ATTR3 - COLOR0 //ATTR4 - COLOR1 //ATTR5 - FOGCOORD //ATTR6 - //ATTR7 - //ATTR8 - TEXCOORD0 //ATTR9 - TEXCOORD1 //ATTR10 - TEXCOORD2 //ATTR11 - TEXCOORD3 //ATTR12 - TEXCOORD4 //ATTR13 - TEXCOORD5 //ATTR14 - TEXCOORD6 //ATTR15 - TEXCOORD7 bool VertexDataOpenGL::generateStreamInfo() { if (!mVertexArray) glGenVertexArrays(1, &mVertexArray); glBindVertexArray(mVertexArray); VertexDeclaration* decl = getDeclaration(); RavAssert(decl); ushort size = getStreamCount(); for (ushort stream = 0; stream < size; ++stream) { //TODO: dynamic_cast VertexBufferOpenGL* buffer = (VertexBufferOpenGL*)getStream(stream); RavAssert(buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer->getBufferID()); //TODO: Check reenabling already enabled states. unsigned offset = 0; unsigned stride = decl->getStreamVertexSize(stream); unsigned streamSize = decl->getElementsCount(stream); for (unsigned elementID = 0; elementID < streamSize; ++elementID) { VertexDeclaration::Element* element = decl->getElement(stream, elementID); GLint size = 0; GLenum type = 0; switch (element->type) { case VertexDeclaration::TYPE_BYTE3: size = 3; type = GL_BYTE; break; case VertexDeclaration::TYPE_BYTE4: size = 4; type = GL_BYTE; break; case VertexDeclaration::TYPE_REAL1: size = 1; type = GL_FLOAT; break; case VertexDeclaration::TYPE_REAL2: size = 2; type = GL_FLOAT; break; case VertexDeclaration::TYPE_REAL3: size = 3; type = GL_FLOAT; break; case VertexDeclaration::TYPE_REAL4: size = 4; type = GL_FLOAT; break; } switch (element->usage) { case VertexDeclaration::USAGE_POSITION: RavAssert(element->usageIndex <= 1); glEnableVertexAttribArray(element->usageIndex); glVertexAttribPointer(element->usageIndex, size, type, GL_FALSE, stride, (char*)0 + offset); break; case VertexDeclaration::USAGE_NORMAL: RavAssert(size == 3); glEnableVertexAttribArray(2); glVertexAttribPointer(2, size, type, GL_FALSE, stride, (char*)0 + offset); break; case VertexDeclaration::USAGE_COLOR: RavAssert(element->usageIndex <= 1); glEnableVertexAttribArray(3 + element->usageIndex); glVertexAttribPointer(3 + element->usageIndex, size, type, GL_FALSE, stride, (char*)0 + offset); break; case VertexDeclaration::USAGE_TEXCOORD: RavAssert(element->usageIndex <= 8); glEnableVertexAttribArray(8 + element->usageIndex); glVertexAttribPointer(8 + element->usageIndex, size, type, GL_FALSE, stride, (char*)0 + offset); break; } offset += decl->getTypeSize(element->type); } } glBindVertexArray(0); return true; }