//-----------------------------------------------------------------------------
	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");
	}
Exemple #3
0
    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;
	}