示例#1
0
文件: r_mesh.c 项目: raynorpat/cake
void RMesh_MakeVertexBuffers (model_t *mod)
{
	// because the buffers may have been used by a previous model
	if (mod->meshvbo) glDeleteBuffers (1, &mod->meshvbo);
	if (mod->texcoordvbo) glDeleteBuffers (1, &mod->texcoordvbo);
	if (mod->indexbuffer) glDeleteBuffers (1, &mod->indexbuffer);
	if (mod->meshvao) glDeleteVertexArrays (1, &mod->meshvao);

	RMesh_CreateFrames (mod, (dmdl_t *) mod->extradata);
	RMesh_CreateTexCoords (mod, (dmdl_t *) mod->extradata);
	RMesh_CreateIndexes (mod, (dmdl_t *) mod->extradata);

	glGenVertexArrays (1, &mod->meshvao);

	glEnableVertexArrayAttribEXT (mod->meshvao, 0);
	glVertexArrayVertexAttribOffsetEXT (mod->meshvao, mod->meshvbo, 0, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (posevert_t), 0);

	glEnableVertexArrayAttribEXT (mod->meshvao, 1);
	glVertexArrayVertexAttribOffsetEXT (mod->meshvao, mod->meshvbo, 1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (posevert_t), 0);

	glEnableVertexArrayAttribEXT (mod->meshvao, 2);
	glVertexArrayVertexAttribOffsetEXT (mod->meshvao, mod->texcoordvbo, 2, 2, GL_FLOAT, GL_FALSE, 0, 0);

	mod->lastcurrframe = 0;
	mod->lastlastframe = 0;

	GL_BindVertexArray (mod->meshvao);
	glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mod->indexbuffer);
}
bool initVertexArray()
{
	glGenVertexArrays(1, &VertexArrayName);
	glVertexArrayVertexAttribOffsetEXT(VertexArrayName, BufferName[buffer::VERTEX], glf::semantic::attr::POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(glf::vertex_v2fv2f), 0);
	glVertexArrayVertexAttribOffsetEXT(VertexArrayName, BufferName[buffer::VERTEX], glf::semantic::attr::TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(glf::vertex_v2fv2f), sizeof(glm::vec2));
	glEnableVertexArrayAttribEXT(VertexArrayName, glf::semantic::attr::POSITION);
	glEnableVertexArrayAttribEXT(VertexArrayName, glf::semantic::attr::TEXCOORD);

	return glf::checkError("initVertexArray");
}
示例#3
0
	void OGLRenderLayout::BindVertexStreams(ShaderObjectPtr const & so, GLuint vao) const
	{
		OGLShaderObjectPtr const & ogl_so = checked_pointer_cast<OGLShaderObject>(so);

		RenderEngine& re = Context::Instance().RenderFactoryInstance().RenderEngineInstance();
		uint32_t max_vertex_streams = re.DeviceCaps().max_vertex_streams;

		std::vector<char> used_streams(max_vertex_streams, 0);
		for (uint32_t i = 0; i < this->NumVertexStreams(); ++ i)
		{
			OGLGraphicsBuffer& stream(*checked_pointer_cast<OGLGraphicsBuffer>(this->GetVertexStream(i)));
			uint32_t const size = this->VertexSize(i);
			auto const & vertex_stream_fmt = this->VertexStreamFormat(i);

			if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
			{
				glVertexArrayVertexBuffer(vao, i, stream.GLvbo(), this->StartVertexLocation() * size, size);
			}

			uint32_t elem_offset = 0;
			for (auto const & vs_elem : vertex_stream_fmt)
			{
				GLint attr = ogl_so->GetAttribLocation(vs_elem.usage, vs_elem.usage_index);
				if (attr != -1)
				{
					GLintptr offset = elem_offset + this->StartVertexLocation() * size;
					GLint const num_components = static_cast<GLint>(NumComponents(vs_elem.format));
					GLenum type;
					GLboolean normalized;
					OGLMapping::MappingVertexFormat(type, normalized, vs_elem.format);
					normalized = (((VEU_Diffuse == vs_elem.usage) || (VEU_Specular == vs_elem.usage)) && !IsFloatFormat(vs_elem.format)) ? GL_TRUE : normalized;

					BOOST_ASSERT(GL_ARRAY_BUFFER == stream.GLType());
					stream.Active(true);
					if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
					{
						glVertexArrayAttribFormat(vao, attr, num_components, type, normalized, elem_offset);
						glVertexArrayAttribBinding(vao, attr, i);
						glEnableVertexArrayAttrib(vao, attr);
					}
					else if (glloader_GL_EXT_direct_state_access())
					{
						glVertexArrayVertexAttribOffsetEXT(vao, stream.GLvbo(), attr, num_components, type,
							normalized, size, offset);
						glEnableVertexArrayAttribEXT(vao, attr);
					}
					else
					{
						glVertexAttribPointer(attr, num_components, type, normalized, size, reinterpret_cast<GLvoid*>(offset));
						glEnableVertexAttribArray(attr);
					}

					used_streams[attr] = 1;
				}

				elem_offset += vs_elem.element_size();
			}
		}

		if (this->InstanceStream())
		{
			OGLGraphicsBuffer& stream(*checked_pointer_cast<OGLGraphicsBuffer>(this->InstanceStream()));

			uint32_t const instance_size = this->InstanceSize();
			BOOST_ASSERT(this->NumInstances() * instance_size <= stream.Size());

			if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
			{
				glVertexArrayVertexBuffer(vao, this->NumVertexStreams(), stream.GLvbo(),
					this->StartInstanceLocation() * instance_size, instance_size);
				glVertexArrayBindingDivisor(vao, this->NumVertexStreams(), 1);
			}

			size_t const inst_format_size = this->InstanceStreamFormat().size();
			uint32_t elem_offset = 0;
			for (size_t i = 0; i < inst_format_size; ++ i)
			{
				VertexElement const & vs_elem = this->InstanceStreamFormat()[i];

				GLint attr = ogl_so->GetAttribLocation(vs_elem.usage, vs_elem.usage_index);
				if (attr != -1)
				{
					GLint const num_components = static_cast<GLint>(NumComponents(vs_elem.format));
					GLenum type;
					GLboolean normalized;
					OGLMapping::MappingVertexFormat(type, normalized, vs_elem.format);
					normalized = (((VEU_Diffuse == vs_elem.usage) || (VEU_Specular == vs_elem.usage)) && !IsFloatFormat(vs_elem.format)) ? GL_TRUE : normalized;
					GLintptr offset = elem_offset + this->StartInstanceLocation() * instance_size;

					BOOST_ASSERT(GL_ARRAY_BUFFER == stream.GLType());
					stream.Active(true);
					if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
					{
						glVertexArrayAttribFormat(vao, attr, num_components, type, normalized, elem_offset);
						glVertexArrayAttribBinding(vao, attr, this->NumVertexStreams());
						glEnableVertexArrayAttrib(vao, attr);
					}
					else if (glloader_GL_EXT_direct_state_access())
					{
						glVertexArrayVertexAttribOffsetEXT(vao, stream.GLvbo(), attr, num_components, type,
							normalized, instance_size, offset);
						glEnableVertexArrayAttribEXT(vao, attr);
						glVertexAttribDivisor(attr, 1);
					}
					else
					{
						glVertexAttribPointer(attr, num_components, type, normalized, instance_size,
							reinterpret_cast<GLvoid*>(offset));
						glEnableVertexAttribArray(attr);
						glVertexAttribDivisor(attr, 1);
					}

					used_streams[attr] = 1;
				}

				elem_offset += vs_elem.element_size();
			}
		}

		for (GLuint i = 0; i < max_vertex_streams; ++ i)
		{
			if (!used_streams[i])
			{
				if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
				{
					glDisableVertexArrayAttrib(vao, i);
				}
				else if (glloader_GL_EXT_direct_state_access())
				{
					glDisableVertexArrayAttribEXT(vao, i);
				}
				else
				{
					glDisableVertexAttribArray(i);
				}
			}
		}
	}
示例#4
0
	//[-------------------------------------------------------]
	//[ Public methods                                        ]
	//[-------------------------------------------------------]
	VertexArrayVaoDsa::VertexArrayVaoDsa(OpenGLRenderer &openGLRenderer, const Renderer::VertexAttributes& vertexAttributes, uint32_t numberOfVertexBuffers, const Renderer::VertexArrayVertexBuffer *vertexBuffers, IndexBuffer *indexBuffer) :
		VertexArrayVao(openGLRenderer, numberOfVertexBuffers, vertexBuffers, indexBuffer)
	{
		// Vertex buffer reference handling is done within the base class "VertexArrayVao"
		const bool isARB_DSA = openGLRenderer.getExtensions().isGL_ARB_direct_state_access();
		if (isARB_DSA)
		{
			// Create the OpenGL vertex array
			glCreateVertexArrays(1, &mOpenGLVertexArray);
		}
		else
		{
			// Create the OpenGL vertex array
			glGenVertexArrays(1, &mOpenGLVertexArray);
		}

		// Loop through all attributes
		// -> We're using "glBindAttribLocationARB()" when linking the program so we have known attribute locations (the vertex array can't know about the program)
		GLuint attributeLocation = 0;
		const Renderer::VertexAttribute *attributeEnd = vertexAttributes.attributes + vertexAttributes.numberOfAttributes;
		for (const Renderer::VertexAttribute *attribute = vertexAttributes.attributes; attribute < attributeEnd; ++attribute, ++attributeLocation)
		{
			// Set the OpenGL vertex attribute pointer
			// TODO(co) Add security check: Is the given resource one of the currently used renderer?
			const Renderer::VertexArrayVertexBuffer& vertexArrayVertexBuffer = vertexBuffers[attribute->inputSlot];

			if (isARB_DSA)
			{
				// Enable attribute
				glEnableVertexArrayAttrib(mOpenGLVertexArray, attributeLocation);

				// Set up the format for my attribute
				glVertexArrayAttribFormat(mOpenGLVertexArray, attributeLocation, Mapping::getOpenGLSize(attribute->vertexAttributeFormat), Mapping::getOpenGLType(attribute->vertexAttributeFormat), static_cast<GLboolean>(Mapping::isOpenGLVertexAttributeFormatNormalized(attribute->vertexAttributeFormat)), static_cast<GLuint>(attribute->alignedByteOffset));

				// Bind vertex buffer to buffer point
				glVertexArrayVertexBuffer(mOpenGLVertexArray,
										  attributeLocation,
										  static_cast<VertexBuffer*>(vertexArrayVertexBuffer.vertexBuffer)->getOpenGLArrayBuffer(),
										  0,	// No offset to the first element of the buffer
										  static_cast<GLsizei>(vertexArrayVertexBuffer.strideInBytes));

				// Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays"
				if (attribute->instancesPerElement > 0 && openGLRenderer.getExtensions().isGL_ARB_instanced_arrays())
				{
					glVertexArrayBindingDivisor(mOpenGLVertexArray, attributeLocation, attribute->instancesPerElement);
				}
			}
			else
			{
				glVertexArrayVertexAttribOffsetEXT(mOpenGLVertexArray,
												  static_cast<VertexBuffer*>(vertexArrayVertexBuffer.vertexBuffer)->getOpenGLArrayBuffer(),
												  attributeLocation, Mapping::getOpenGLSize(attribute->vertexAttributeFormat),
												  Mapping::getOpenGLType(attribute->vertexAttributeFormat),
												  static_cast<GLboolean>(Mapping::isOpenGLVertexAttributeFormatNormalized(attribute->vertexAttributeFormat)),
												  static_cast<GLsizei>(vertexArrayVertexBuffer.strideInBytes),
												  static_cast<GLintptr>(attribute->alignedByteOffset));

				// Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays"
				if (attribute->instancesPerElement > 0 && openGLRenderer.getExtensions().isGL_ARB_instanced_arrays())
				{
					// Sadly, DSA has no support for "GL_ARB_instanced_arrays", so, we have to use the bind way
					// -> Keep the bind-horror as local as possible

					#ifndef OPENGLRENDERER_NO_STATE_CLEANUP
						// Backup the currently bound OpenGL vertex array
						GLint openGLVertexArrayBackup = 0;
						glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &openGLVertexArrayBackup);
					#endif

					// Bind this OpenGL vertex array
					glBindVertexArray(mOpenGLVertexArray);

					// Set divisor
					glVertexAttribDivisorARB(attributeLocation, attribute->instancesPerElement);

					#ifndef OPENGLRENDERER_NO_STATE_CLEANUP
						// Be polite and restore the previous bound OpenGL vertex array
						glBindVertexArray(static_cast<GLuint>(openGLVertexArrayBackup));
					#endif
				}

				// Enable OpenGL vertex attribute array
				glEnableVertexArrayAttribEXT(mOpenGLVertexArray, attributeLocation);
			}
		}

		// Check the used index buffer
		// -> In case of no index buffer we don't bind buffer 0, there's not really a point in it
		if (nullptr != indexBuffer)
		{
			if (isARB_DSA)
			{
				// Bind the index buffer
				glVertexArrayElementBuffer(mOpenGLVertexArray, indexBuffer->getOpenGLElementArrayBuffer());
			}
			else
			{
				// Sadly, EXT DSA has no support for element array buffer, so, we have to use the bind way
				// -> Keep the bind-horror as local as possible

				#ifndef OPENGLRENDERER_NO_STATE_CLEANUP
					// Backup the currently bound OpenGL vertex array
					GLint openGLVertexArrayBackup = 0;
					glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &openGLVertexArrayBackup);

					// Backup the currently bound OpenGL element array buffer
					GLint openGLElementArrayBufferBackup = 0;
					glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &openGLElementArrayBufferBackup);
				#endif

				// Bind this OpenGL vertex array
				glBindVertexArray(mOpenGLVertexArray);

				// Bind OpenGL element array buffer
				glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffer->getOpenGLElementArrayBuffer());

				#ifndef OPENGLRENDERER_NO_STATE_CLEANUP
					// Be polite and restore the previous bound OpenGL vertex array
					glBindVertexArray(static_cast<GLuint>(openGLVertexArrayBackup));

					// Be polite and restore the previous bound OpenGL element array buffer
					glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, static_cast<GLuint>(openGLElementArrayBufferBackup));
				#endif
			}
		}
	}
示例#5
0
文件: r_mesh.c 项目: raynorpat/cake
/*
=============
GL_DrawAliasFrameLerp

interpolates between two frames and origins
FIXME: batch lerp all vertexes
=============
*/
void GL_DrawAliasFrameLerp (entity_t *e, dmdl_t *hdr, float backlerp)
{
	int		i;
	float	frontlerp;
	float	alpha;
	vec3_t	delta, vectors[3];

	daliasframe_t *currframe = (daliasframe_t *) ((byte *) hdr + hdr->ofs_frames + e->currframe * hdr->framesize);
	daliasframe_t *lastframe = (daliasframe_t *) ((byte *) hdr + hdr->ofs_frames + e->lastframe * hdr->framesize);

	meshubo_t *meshubo = NULL;
	GLbitfield access;

	if (e->flags & RF_TRANSLUCENT)
		alpha = e->alpha;
	else alpha = 1.0;

	frontlerp = 1.0 - backlerp;

	// move should be the delta back to the previous frame * backlerp
	VectorSubtract (e->lastorigin, e->currorigin, delta);
	AngleVectors (e->angles, vectors[0], vectors[1], vectors[2]);

	gl_meshuboupdate.move[0] = lastframe->translate[0] + DotProduct (delta, vectors[0]);	// forward
	gl_meshuboupdate.move[1] = lastframe->translate[1] - DotProduct (delta, vectors[1]);	// left
	gl_meshuboupdate.move[2] = lastframe->translate[2] + DotProduct (delta, vectors[2]);	// up

	for (i = 0; i < 3; i++)
	{
		gl_meshuboupdate.move[i] = backlerp * gl_meshuboupdate.move[i] + frontlerp * currframe->translate[i];
		gl_meshuboupdate.frontv[i] = frontlerp * currframe->scale[i];
		gl_meshuboupdate.backv[i] = backlerp * lastframe->scale[i];
	}

	if (!(e->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE)))
	{
		if (gl_monolightmap->value)
		{
			float ntsc[] = {0.3f, 0.59f, 0.11f};
			float gs = DotProduct (gl_meshuboupdate.shadelight, ntsc);

			gl_meshuboupdate.shadelight[0] = gl_meshuboupdate.shadelight[1] = gl_meshuboupdate.shadelight[2] = gs;
		}

		gl_meshuboupdate.shadelight[0] *= r_lightscale->value * 2.0f;
		gl_meshuboupdate.shadelight[1] *= r_lightscale->value * 2.0f;
		gl_meshuboupdate.shadelight[2] *= r_lightscale->value * 2.0f;

		gl_meshuboupdate.powersuitscale = 0.0f;
		gl_meshuboupdate.shellmix = 0.0f;
	}
	else
	{
		float scale = (e->flags & RF_WEAPONMODEL) ? WEAPONSHELL_SCALE : POWERSUIT_SCALE;

		gl_meshuboupdate.powersuitscale = scale;
		gl_meshuboupdate.shellmix = 1.0f;
	}

	gl_meshuboupdate.shadelight[3] = alpha;
	gl_meshuboupdate.lerpfrac = backlerp;

	if (e->model->lastcurrframe != e->currframe)
	{
		glVertexArrayVertexAttribOffsetEXT (e->model->meshvao, e->model->meshvbo, 0, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (posevert_t), VERTOFFSET (e->currframe));
		e->model->lastcurrframe = e->currframe;
	}

	if (e->model->lastlastframe != e->lastframe)
	{
		glVertexArrayVertexAttribOffsetEXT (e->model->meshvao, e->model->meshvbo, 1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (posevert_t), VERTOFFSET (e->lastframe));
		e->model->lastlastframe = e->lastframe;
	}

	GL_BindVertexArray (e->model->meshvao);
	GL_Enable (DEPTHTEST_BIT | ((e->flags & RF_TRANSLUCENT) ? BLEND_BIT : DEPTHWRITE_BIT) | (gl_cull->value ? CULLFACE_BIT : 0));
	GL_UseProgram (gl_meshprog);

	if (gl_meshubonumblocks + 1 >= MESH_UBO_MAX_BLOCKS)
	{
		access = BUFFER_DISCARD;
		gl_meshubonumblocks = 0;
	}
	else access = BUFFER_NO_OVERWRITE;

	if ((meshubo = glMapNamedBufferRangeEXT (gl_meshubo, gl_meshubonumblocks * gl_meshuboblocksize, sizeof (meshubo_t), access)) != NULL)
	{
		memcpy (meshubo, &gl_meshuboupdate, sizeof (meshubo_t));

		glUnmapNamedBufferEXT (gl_meshubo);
		glBindBufferRange (GL_UNIFORM_BUFFER, gl_meshubobinding, gl_meshubo, gl_meshubonumblocks * gl_meshuboblocksize, sizeof (meshubo_t));

		glDrawElements (GL_TRIANGLES, e->model->numindexes, GL_UNSIGNED_SHORT, NULL);
		gl_meshubonumblocks++;
	}
}