Ejemplo n.º 1
0
/*	TODO:
		- Firstly save each iteration of our water, so we can keep track of colour etc.
		- Recalc colour for different dynamic moving lights.
*/
void Warp_DrawWaterPoly(glpoly_t *p)
{
	VideoObject_t	*voWaterPoly;
	vec3_t			vWave,vLightColour;
	float			*v;
	int				i;

	voWaterPoly = malloc(p->numverts*sizeof(VideoObject_t));
	if(!voWaterPoly)
	{
		Sys_Error("Failed to allocate water poly!\n");
		return;
	}

	v = p->verts[0];

	for(i = 0; i < p->numverts; i++,v += VERTEXSIZE)
	{
		voWaterPoly[i].vTextureCoord[0][0]	= WARPCALC(v[3],v[4]);
		voWaterPoly[i].vTextureCoord[0][1]	= WARPCALC(v[4],v[3]);
		voWaterPoly[i].vColour[3] = Math_Clamp(0, r_wateralpha.value, 1.0f);

		Math_VectorCopy(v,vWave);

		// Shitty lit water, use dynamic light points in the future...
		{
			MathVector_t	mvLightColour;

			// Use vWave position BEFORE we move it, otherwise the water will flicker.
			mvLightColour = Light_GetSample(vWave);

			Math_MVToVector(mvLightColour,vLightColour);
			Math_VectorScale(vLightColour,1.0f/200.0f,vLightColour);
			Math_VectorDivide(vLightColour,0.2f,vLightColour);
		}

		Math_VectorCopy(vLightColour,voWaterPoly[i].vColour);

		// [20/1/2013] Added in subtle water bobbing, based on this code http://www.quake-1.com/docs/quakesrc.org/26.html ~hogsy
		vWave[2] =	v[2]+
					2.0f*(float)sin(v[0]*0.025f+cl.time)*(float)sin(v[2]*0.05f+cl.time)+
					2.0f*(float)sin(v[1]*0.025f+cl.time*2.0f)*(float)sin(v[2]*0.05f+cl.time);

		Math_VectorCopy(vWave,voWaterPoly[i].vVertex);
	}

	Video_DrawObject(voWaterPoly,VIDEO_PRIMITIVE_TRIANGLE_FAN,p->numverts);

	free(voWaterPoly);
}
Ejemplo n.º 2
0
/*	Each frame, update warping textures
*/
void R_UpdateWarpTextures (void)
{
	texture_t *tx;
	int i;
	float x, y, x2, warptess;

	if (r_oldwater.value || cl.bIsPaused || r_drawflat_cheatsafe || r_lightmap_cheatsafe)
		return;

	warptess = 128.0f / Math_Clamp(3.0f, floor(r_waterquality.value), 64.0f);

	for (i=0; i<cl.worldmodel->numtextures; i++)
	{
		tx = cl.worldmodel->textures[i];
		if(!tx)
			continue;

		if(!tx->update_warp)
			continue;

		//render warp
		GL_SetCanvas (CANVAS_WARPIMAGE);
		Video_SetTexture(tx->gltexture);
		for (x=0.0; x<128.0; x=x2)
		{
			x2 = x + warptess;
			glBegin (GL_TRIANGLE_STRIP);
			for (y=0.0; y<128.01; y+=warptess) // .01 for rounding errors
			{
				glTexCoord2f (WARPCALC(x,y), WARPCALC(y,x));
				glVertex2f (x,y);
				glTexCoord2f (WARPCALC(x2,y), WARPCALC(y,x2));
				glVertex2f (x2,y);
			}
			glEnd();
		}

		//copy to texture
		Video_SetTexture(tx->warpimage);
		glCopyTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, glx, gly+glheight-gl_warpimagesize, gl_warpimagesize, gl_warpimagesize);

		tx->update_warp = FALSE;
	}

	//if viewsize is less than 100, we need to redraw the frame around the viewport
	scr_tileclear_updates = 0;
}
Ejemplo n.º 3
0
void R_UpdateWarpTextures (void)
{
	texture_t *tx;
	int i;
	float x, y, x2, warptess;

	if (cl.paused || r_drawflat_cheatsafe || r_lightmap_cheatsafe)
		return;

	warptess = 128.0/CLAMP (3.0, floor(r_waterquality.value), 64.0);

	int num_textures = cl.worldmodel->numtextures;
	int num_warp_textures = 0;

	// Render warp to top mips
	for (i = 0; i < num_textures; ++i)
	{
		if (!(tx = cl.worldmodel->textures[i]))
			continue;

		if (!tx->update_warp)
			continue;

		VkRect2D render_area;
		render_area.offset.x = 0;
		render_area.offset.y = 0;
		render_area.extent.width = WARPIMAGESIZE;
		render_area.extent.height = WARPIMAGESIZE;

		VkRenderPassBeginInfo render_pass_begin_info;
		memset(&render_pass_begin_info, 0, sizeof(render_pass_begin_info));
		render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
		render_pass_begin_info.renderArea = render_area;
		render_pass_begin_info.renderPass = vulkan_globals.warp_render_pass;
		render_pass_begin_info.framebuffer = tx->warpimage->frame_buffer;

		vkCmdBeginRenderPass(vulkan_globals.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);

		//render warp
		GL_SetCanvas (CANVAS_WARPIMAGE);
		vkCmdBindPipeline(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.warp_pipeline);
		vkCmdBindDescriptorSets(vulkan_globals.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vulkan_globals.basic_pipeline_layout, 0, 1, &tx->gltexture->descriptor_set, 0, NULL);

		int num_verts = 0;
		for (y=0.0; y<128.01; y+=warptess) // .01 for rounding errors
			num_verts += 2;

		for (x=0.0; x<128.0; x=x2)
		{	
			VkBuffer buffer;
			VkDeviceSize buffer_offset;
			basicvertex_t * vertices = (basicvertex_t*)R_VertexAllocate(num_verts * sizeof(basicvertex_t), &buffer, &buffer_offset);

			int i = 0;
			x2 = x + warptess;
			for (y=0.0; y<128.01; y+=warptess) // .01 for rounding errors
			{
				vertices[i].position[0] = x;
				vertices[i].position[1] = y;
				vertices[i].position[2] = 0.0f;
				vertices[i].texcoord[0] = WARPCALC(x,y);
				vertices[i].texcoord[1] = WARPCALC(y,x);
				vertices[i].color[0] = 255;
				vertices[i].color[1] = 255;
				vertices[i].color[2] = 255;
				vertices[i].color[3] = 255;
				i += 1;
				vertices[i].position[0] = x2;
				vertices[i].position[1] = y;
				vertices[i].position[2] = 0.0f;
				vertices[i].texcoord[0] = WARPCALC(x2,y);
				vertices[i].texcoord[1] = WARPCALC(y,x2);
				vertices[i].color[0] = 255;
				vertices[i].color[1] = 255;
				vertices[i].color[2] = 255;
				vertices[i].color[3] = 255;
				i += 1;
			}

			vkCmdBindVertexBuffers(vulkan_globals.command_buffer, 0, 1, &buffer, &buffer_offset);
			vkCmdDraw(vulkan_globals.command_buffer, num_verts, 1, 0, 0);
		}

		vkCmdEndRenderPass(vulkan_globals.command_buffer);

		VkImageMemoryBarrier * image_barrier = &warp_image_barriers[num_warp_textures];
		image_barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
		image_barrier->pNext = NULL;
		image_barrier->srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
		image_barrier->dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
		image_barrier->oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
		image_barrier->newLayout = VK_IMAGE_LAYOUT_GENERAL;
		image_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
		image_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
		image_barrier->image = tx->warpimage->image;
		image_barrier->subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
		image_barrier->subresourceRange.baseMipLevel = 1;
		image_barrier->subresourceRange.levelCount = WARPIMAGEMIPS - 1;
		image_barrier->subresourceRange.baseArrayLayer = 0;
		image_barrier->subresourceRange.layerCount = 1;

		warp_textures[num_warp_textures] = tx;
		num_warp_textures += 1;
	}

	// Make sure that writes are done for top mips we just rendered to
	VkMemoryBarrier memory_barrier;
	memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
	memory_barrier.pNext = NULL;
	memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
	memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;

	// Transfer all other mips from UNDEFINED to GENERAL layout
	vkCmdPipelineBarrier(vulkan_globals.command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memory_barrier, 0, NULL, num_warp_textures, warp_image_barriers);

	// Generate mip chains
	for (int mip = 1; mip < WARPIMAGEMIPS; ++mip)
	{
		int srcSize = WARPIMAGESIZE >> (mip - 1);
		int dstSize = WARPIMAGESIZE >> mip;

		for (i = 0; i < num_warp_textures; ++i)
		{
			tx = warp_textures[i];

			VkImageBlit region;
			memset(&region, 0, sizeof(region));
			region.srcOffsets[1].x = srcSize;
			region.srcOffsets[1].y = srcSize;
			region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			region.srcSubresource.layerCount = 1;
			region.srcSubresource.mipLevel = (mip - 1);
			region.dstOffsets[1].x = dstSize;
			region.dstOffsets[1].y = dstSize;
			region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			region.dstSubresource.layerCount = 1;
			region.dstSubresource.mipLevel = mip;

			vkCmdBlitImage(vulkan_globals.command_buffer, tx->warpimage->image, VK_IMAGE_LAYOUT_GENERAL, tx->warpimage->image, VK_IMAGE_LAYOUT_GENERAL, 1, &region, VK_FILTER_LINEAR);
		}

		if (mip < (WARPIMAGEMIPS - 1))
		{
			memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
			memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
			vkCmdPipelineBarrier(vulkan_globals.command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memory_barrier, 0, NULL, 0, NULL);
		}
	}

	// Transfer all warp texture mips from GENERAL to SHADER_READ_ONLY_OPTIMAL
	for (i = 0; i < num_warp_textures; ++i)
	{
		tx = warp_textures[i];
		
		VkImageMemoryBarrier * image_barrier = &warp_image_barriers[i];
		image_barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
		image_barrier->pNext = NULL;
		image_barrier->srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
		image_barrier->dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
		image_barrier->oldLayout = VK_IMAGE_LAYOUT_GENERAL;
		image_barrier->newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
		image_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
		image_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
		image_barrier->image = tx->warpimage->image;
		image_barrier->subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
		image_barrier->subresourceRange.baseMipLevel = 0;
		image_barrier->subresourceRange.levelCount = WARPIMAGEMIPS;
		image_barrier->subresourceRange.baseArrayLayer = 0;
		image_barrier->subresourceRange.layerCount = 1;

		tx->update_warp = false;
	}

	vkCmdPipelineBarrier(vulkan_globals.command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, num_warp_textures, warp_image_barriers);

	//if warp render went down into sbar territory, we need to be sure to refresh it next frame
	if (WARPIMAGESIZE + sb_lines > glheight)
		Sbar_Changed ();

	//if viewsize is less than 100, we need to redraw the frame around the viewport
	scr_tileclear_updates = 0;
}