⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameswf_render_handler_ogl.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// gameswf_render_handler_ogl.cpp	-- Willem Kokke <willem@mindparity.com> 2003// This source code has been donated to the Public Domain.  Do// whatever you want with it.// A gameswf::render_handler that uses SDL & OpenGL#include "gameswf.h"#include "gameswf_types.h"#include "base/image.h"#include "base/ogl.h"#include "base/utility.h"#include <string.h>	// for memset()// choose the resampling method:// 1 = hardware (experimental, should be fast, somewhat buggy)// 2 = fast software bilinear (default)// 3 = use image::resample(), slow software resampling#define RESAMPLE_METHOD 2// Determines whether to generate mipmaps for smoother rendering of// minified textures.  It actually tends to look OK to not use// mipmaps, though it is potentially a performance hit if you use big// textures.//// TODO: need to code mipmap LOD bias adjustment, to keep mipmaps from// looking too blurry.  (Also applies to text rendering.)#define GENERATE_MIPMAPS 0// bitmap_info_ogl declarationstruct bitmap_info_ogl : public gameswf::bitmap_info{	bitmap_info_ogl();	bitmap_info_ogl(int width, int height, Uint8* data);	bitmap_info_ogl(image::rgb* im);	bitmap_info_ogl(image::rgba* im);	~bitmap_info_ogl()	{		if (m_texture_id > 0)		{			glDeleteTextures(1, (GLuint*) &m_texture_id);		}	}};struct render_handler_ogl : public gameswf::render_handler{	// Some renderer state.	// Enable/disable antialiasing.	bool	m_enable_antialias;		// Output size.	float	m_display_width;	float	m_display_height;		gameswf::matrix	m_current_matrix;	gameswf::cxform	m_current_cxform;	void set_antialiased(bool enable)	{		m_enable_antialias = enable;	}	static void make_next_miplevel(int* width, int* height, Uint8* data)	// Utility.  Mutates *width, *height and *data to create the	// next mip level.	{		assert(width);		assert(height);		assert(data);		int	new_w = *width >> 1;		int	new_h = *height >> 1;		if (new_w < 1) new_w = 1;		if (new_h < 1) new_h = 1;				if (new_w * 2 != *width	 || new_h * 2 != *height)		{			// Image can't be shrunk along (at least) one			// of its dimensions, so don't bother			// resampling.	Technically we should, but			// it's pretty useless at this point.  Just			// change the image dimensions and leave the			// existing pixels.		}		else		{			// Resample.  Simple average 2x2 --> 1, in-place.			for (int j = 0; j < new_h; j++) {				Uint8*	out = ((Uint8*) data) + j * new_w;				Uint8*	in = ((Uint8*) data) + (j << 1) * *width;				for (int i = 0; i < new_w; i++) {					int	a;					a = (*(in + 0) + *(in + 1) + *(in + 0 + *width) + *(in + 1 + *width));					*(out) = a >> 2;					out++;					in += 2;				}			}		}		// Munge parameters to reflect the shrunken image.		*width = new_w;		*height = new_h;	}		struct fill_style	{		enum mode		{			INVALID,			COLOR,			BITMAP_WRAP,			BITMAP_CLAMP,			LINEAR_GRADIENT,			RADIAL_GRADIENT,		};		mode	m_mode;		gameswf::rgba	m_color;		const gameswf::bitmap_info*	m_bitmap_info;		gameswf::matrix	m_bitmap_matrix;		gameswf::cxform	m_bitmap_color_transform;		bool	m_has_nonzero_bitmap_additive_color;				fill_style()			:			m_mode(INVALID),			m_has_nonzero_bitmap_additive_color(false)		{		}		void	apply(/*const matrix& current_matrix*/) const		// Push our style into OpenGL.		{			assert(m_mode != INVALID);						if (m_mode == COLOR)			{				apply_color(m_color);				glDisable(GL_TEXTURE_2D);			}			else if (m_mode == BITMAP_WRAP				 || m_mode == BITMAP_CLAMP)			{				assert(m_bitmap_info != NULL);				apply_color(m_color);				if (m_bitmap_info == NULL)				{					glDisable(GL_TEXTURE_2D);				}				else				{					// Set up the texture for rendering.					{						// Do the modulate part of the color						// transform in the first pass.  The						// additive part, if any, needs to						// happen in a second pass.						glColor4f(m_bitmap_color_transform.m_[0][0],							  m_bitmap_color_transform.m_[1][0],							  m_bitmap_color_transform.m_[2][0],							  m_bitmap_color_transform.m_[3][0]							  );					}					glBindTexture(GL_TEXTURE_2D, m_bitmap_info->m_texture_id);					glEnable(GL_TEXTURE_2D);					glEnable(GL_TEXTURE_GEN_S);					glEnable(GL_TEXTURE_GEN_T);									if (m_mode == BITMAP_CLAMP)					{							glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);					}					else					{						assert(m_mode == BITMAP_WRAP);						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);					}					// Set up the bitmap matrix for texgen.					float	inv_width = 1.0f / m_bitmap_info->m_original_width;					float	inv_height = 1.0f / m_bitmap_info->m_original_height;					const gameswf::matrix&	m = m_bitmap_matrix;					glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);					float	p[4] = { 0, 0, 0, 0 };					p[0] = m.m_[0][0] * inv_width;					p[1] = m.m_[0][1] * inv_width;					p[3] = m.m_[0][2] * inv_width;					glTexGenfv(GL_S, GL_OBJECT_PLANE, p);					glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);					p[0] = m.m_[1][0] * inv_height;					p[1] = m.m_[1][1] * inv_height;					p[3] = m.m_[1][2] * inv_height;					glTexGenfv(GL_T, GL_OBJECT_PLANE, p);				}			}		}		bool	needs_second_pass() const		// Return true if we need to do a second pass to make		// a valid color.  This is for cxforms with additive		// parts; this is the simplest way (that we know of)		// to implement an additive color with stock OpenGL.		{			if (m_mode == BITMAP_WRAP			    || m_mode == BITMAP_CLAMP)			{				return m_has_nonzero_bitmap_additive_color;			}			else			{				return false;			}		}		void	apply_second_pass() const		// Set OpenGL state for a necessary second pass.		{			assert(needs_second_pass());			// The additive color also seems to be modulated by the texture. So,			// maybe we can fake this in one pass using using the mean value of 			// the colors: c0*t+c1*t = ((c0+c1)/2) * t*2			// I don't know what the alpha component of the color is for.			//glDisable(GL_TEXTURE_2D);			glColor4f(				m_bitmap_color_transform.m_[0][1] / 255.0f,				m_bitmap_color_transform.m_[1][1] / 255.0f,				m_bitmap_color_transform.m_[2][1] / 255.0f,				m_bitmap_color_transform.m_[3][1] / 255.0f				);			glBlendFunc(GL_ONE, GL_ONE);		}		void	cleanup_second_pass() const		{			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);		}		void	disable() { m_mode = INVALID; }		void	set_color(gameswf::rgba color) { m_mode = COLOR; m_color = color; }		void	set_bitmap(const gameswf::bitmap_info* bi, const gameswf::matrix& m, bitmap_wrap_mode wm, const gameswf::cxform& color_transform)		{			m_mode = (wm == WRAP_REPEAT) ? BITMAP_WRAP : BITMAP_CLAMP;			m_bitmap_info = bi;			m_bitmap_matrix = m;			m_bitmap_color_transform = color_transform;			m_bitmap_color_transform.clamp();			m_color = gameswf::rgba(				Uint8(m_bitmap_color_transform.m_[0][0] * 255.0f), 				Uint8(m_bitmap_color_transform.m_[1][0] * 255.0f), 				Uint8(m_bitmap_color_transform.m_[2][0] * 255.0f), 				Uint8(m_bitmap_color_transform.m_[3][0] * 255.0f));			if (m_bitmap_color_transform.m_[0][1] > 1.0f			    || m_bitmap_color_transform.m_[1][1] > 1.0f			    || m_bitmap_color_transform.m_[2][1] > 1.0f			    || m_bitmap_color_transform.m_[3][1] > 1.0f)			{				m_has_nonzero_bitmap_additive_color = true;			}			else			{				m_has_nonzero_bitmap_additive_color = false;			}		}		bool	is_valid() const { return m_mode != INVALID; }	};	// Style state.	enum style_index	{		LEFT_STYLE = 0,		RIGHT_STYLE,		LINE_STYLE,		STYLE_COUNT	};	fill_style	m_current_styles[STYLE_COUNT];	gameswf::bitmap_info*	create_bitmap_info_rgb(image::rgb* im)	// Given an image, returns a pointer to a bitmap_info struct	// that can later be passed to fill_styleX_bitmap(), to set a	// bitmap fill style.	{		return new bitmap_info_ogl(im);	}	gameswf::bitmap_info*	create_bitmap_info_rgba(image::rgba* im)	// Given an image, returns a pointer to a bitmap_info struct	// that can later be passed to fill_style_bitmap(), to set a	// bitmap fill style.	//	// This version takes an image with an alpha channel.	{		return new bitmap_info_ogl(im);	}	gameswf::bitmap_info*	create_bitmap_info_empty()	// Create a placeholder bitmap_info.  Used when	// DO_NOT_LOAD_BITMAPS is set; then later on the host program	// can use movie_definition::get_bitmap_info_count() and	// movie_definition::get_bitmap_info() to stuff precomputed	// textures into these bitmap infos.	{		return new bitmap_info_ogl;	}	gameswf::bitmap_info*	create_bitmap_info_alpha(int w, int h, Uint8* data)	// Create a bitmap_info so that it contains an alpha texture	// with the given data (1 byte per texel).	//	// Munges *data (in order to make mipmaps)!!	{		return new bitmap_info_ogl(w, h, data);	}	void	delete_bitmap_info(gameswf::bitmap_info* bi)	// Delete the given bitmap info struct.	{		delete bi;	}	~render_handler_ogl()	{	}	void	begin_display(		gameswf::rgba background_color,		int viewport_x0, int viewport_y0,		int viewport_width, int viewport_height,		float x0, float x1, float y0, float y1)	// Set up to render a full frame from a movie and fills the	// background.	Sets up necessary transforms, to scale the	// movie to fit within the given dimensions.  Call	// end_display() when you're done.	//	// The rectangle (viewport_x0, viewport_y0, viewport_x0 +	// viewport_width, viewport_y0 + viewport_height) defines the	// window coordinates taken up by the movie.	//	// The rectangle (x0, y0, x1, y1) defines the pixel	// coordinates of the movie that correspond to the viewport	// bounds.	{		m_display_width = fabsf(x1 - x0);		m_display_height = fabsf(y1 - y0);		glViewport(viewport_x0, viewport_y0, viewport_width, viewport_height);		glMatrixMode(GL_MODELVIEW);		glPushMatrix();		glOrtho(x0, x1, y0, y1, -1, 1);		glEnable(GL_BLEND);		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	// GL_MODULATE		glDisable(GL_TEXTURE_2D);		// Clear the background, if background color has alpha > 0.		if (background_color.m_a > 0)		{			// Draw a big quad.			apply_color(background_color);			glBegin(GL_QUADS);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -