コード例 #1
0
/**
 * @name	context_2d_draw_point_sprites
 * @brief	Draws pointsprites using the given options (in batch along a line)
 * @param	ctx - (context_2d *) context to draw to
 * @param	url - (const char *) name of the texture to draw from
 * @param	point_size - (float) point sprite size
 * @param	step_size - (float) step size to take between drawn pointsprites
 * @param	color - (rgba *) color to draw with
 * @param	x1 - (float) starting x-coordinate to draw along
 * @param	y1 - (float) starting y-coordinate to draw along
 * @param	x2 - (float) ending x-coordinate to draw along
 * @param	y2 - (float) ending y-coordinate to draw along
 * @retval	NONE
 */
void context_2d_draw_point_sprites(context_2d *ctx, const char *url, float point_size, float step_size, rgba *color, float x1, float y1, float x2, float y2) {
	draw_textures_flush();
	context_2d_bind(ctx);
	texture_2d *tex = texture_manager_load_texture(texture_manager_get(), url);

	// If texture is not finished loading,
	if (!tex || !tex->loaded) {
		return;
	}

	static GLfloat     *vertex_buffer = NULL;
	static unsigned int vertex_max = 64;
	tealeaf_shaders_bind(DRAWING_SHADER);
	matrix_3x3_multiply_m_f_f_f_f(GET_MODEL_VIEW_MATRIX(ctx), x1, y1, &x1, &y1);
	matrix_3x3_multiply_m_f_f_f_f(GET_MODEL_VIEW_MATRIX(ctx), x2, y2, &x2, &y2);

	// Allocate vertex array buffer
	if (vertex_buffer == NULL) {
		vertex_buffer = malloc(vertex_max * 2 * sizeof(GLfloat));
	}

	// Add points to the buffer so there are drawing points every X pixels
	unsigned int count = ceilf(sqrtf((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) / step_size);

	if (count < 1) {
		count = 1;
	}

	unsigned int vertex_count = 0;
	unsigned int i;

	for (i = 0; i < count; ++i) {
		if (vertex_count == vertex_max) {
			vertex_max = 2 * vertex_max;
			vertex_buffer = realloc(vertex_buffer, vertex_max * 2 * sizeof(GLfloat));
		}

		vertex_buffer[2 * vertex_count + 0] = x1 + (x2 - x1) * ((GLfloat)i / (GLfloat)count);
		vertex_buffer[2 * vertex_count + 1] = y1 + (y2 - y1) * ((GLfloat)i / (GLfloat)count);
		vertex_count += 1;
	}

	GLTRACE(glActiveTexture(GL_TEXTURE0));
	GLTRACE(glBindTexture(GL_TEXTURE_2D, tex->name));
	GLTRACE(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
	GLTRACE(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
	GLTRACE(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
	GLTRACE(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
	GLTRACE(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
	// Render the vertex array
	GLTRACE(glUniform1f(global_shaders[DRAWING_SHADER].point_size, point_size));
	GLTRACE(glVertexAttribPointer(global_shaders[DRAWING_SHADER].vertex_coords, 2, GL_FLOAT, GL_FALSE, 0, (float *) vertex_buffer));
	float alpha = color->a * ctx->globalAlpha[ctx->mvp];
	GLTRACE(glUniform4f(global_shaders[DRAWING_SHADER].draw_color, alpha * color->r, alpha * color->g, alpha * color->b, alpha));
	GLTRACE(glDrawArrays(GL_POINTS, 0, vertex_count));
	tealeaf_shaders_bind(PRIMARY_SHADER);
}
コード例 #2
0
/**
 * @name	context_2d_fillText
 * @brief	fills text on the given context using given options
 * @param	ctx - (context_2d *) ctx to fill text on
 * @param	img - (texture_2d *) bitmap font texture to use
 * @param	srcRect - (const rect_2d *) source rectangle on the texture to draw from
 * @param	destRect - (const rect_2d *) destination rect to draw to
 * @param	alpha - (float) alpha to draw with
 * @param	composite_op - (int) composite operation to draw with
 * @retval	NONE
 */
void context_2d_fillText(context_2d *ctx, texture_2d *img, const rect_2d *srcRect, const rect_2d *destRect, float alpha) {
	context_2d_bind(ctx);

	if (img && img->loaded) {
		draw_textures_item(ctx, GET_MODEL_VIEW_MATRIX(ctx), img->name, img->width, img->height, img->originalWidth, img->originalHeight, *srcRect, *destRect, *GET_CLIPPING_BOUNDS(ctx), ctx->globalAlpha[ctx->mvp] * alpha, ctx->globalCompositeOperation[ctx->mvp], &ctx->filter_color, ctx->filter_type);
	}
}
コード例 #3
0
/**
 * @name	context_2d_drawImage
 * @brief	darws an image to the given context using given options
 * @param	ctx - (context_2d *) context to draw to
 * @param	srcTex - (int) deprecated
 * @param	url - (const char *) name of the texture to draw from
 * @param	srcRect - (const rect_2d *) source rectangle on the texture to draw from
 * @param	destRect - (const rect_2d *) destination rect to draw to
 * @param	composite_op - (int) composite operation to draw with
 * @retval	NONE
 */
void context_2d_drawImage(context_2d *ctx, int srcTex, const char *url, const rect_2d *srcRect, const rect_2d *destRect) {
	context_2d_bind(ctx);
	texture_2d *tex = texture_manager_load_texture(texture_manager_get(), url);

	if (tex && tex->loaded) {
		draw_textures_item(ctx, GET_MODEL_VIEW_MATRIX(ctx), tex->name, tex->width, tex->height, tex->originalWidth, tex->originalHeight, *srcRect, *destRect, * GET_CLIPPING_BOUNDS(ctx), ctx->globalAlpha[ctx->mvp], ctx->globalCompositeOperation[ctx->mvp], &ctx->filter_color, ctx->filter_type);
	}
}
コード例 #4
0
/**
 * @name	context_2d_setClip
 * @brief	sets the clipping rectangle on the given context
 * @param	ctx - (context_2d *) context to set the clipping rectangle on
 * @param	clip - (rect_2d) the clipping rectangle
 * @retval	NONE
 */
void context_2d_setClip(context_2d *ctx, rect_2d clip) {
	matrix_3x3 *modelView = GET_MODEL_VIEW_MATRIX(ctx);
	//  LOG("setClip: %f %f %f %f", clip.x, clip.y, clip.width, clip.height);
	// TODO: clipping with rectangles doesn't work so great with rotated or scaled coordinates...
	float x1, y1, x2, y2;
	matrix_3x3_multiply(modelView, clip.x, clip.y, &x1, &y1);
	matrix_3x3_multiply(modelView, clip.x + clip.width, clip.y + clip.height, &x2, &y2);
	clip.x = x1;
	clip.y = y1;
	clip.width = x2 - x1;
	clip.height = y2 - y1;
	int i = ctx->mvp - 1;
	rect_2d ctx_clip;
	ctx_clip.x = ctx->clipStack[i].x;
	ctx_clip.y = ctx->clipStack[i].y;
	ctx_clip.width = ctx->clipStack[i].width;
	ctx_clip.height = ctx->clipStack[i].height;

	//flip the y to be back at top left for easier readability of intersection testing
	if (ctx->on_screen && clip.height > 0) {
		ctx_clip.y = -ctx_clip.y +  ctx->canvas->framebuffer_height + ctx->canvas->framebuffer_offset_bottom - ctx_clip.height;
	}

	//width = -1 if view is not clipping so ignore it
	if (ctx_clip.width > -1) {
		//set clip rect to empty if the clip coming in is outside of the clip stack's top clipping rect
		if (clip.x >= ctx_clip.x + ctx_clip.width || clip.x + clip.width <= ctx_clip.x ||
		        clip.y >= ctx_clip.y + ctx_clip.height || clip.y + clip.height <= ctx_clip.y) {
			clip.x = clip.y = clip.height = clip.width = 0;
		} else {
			clip.x = ctx_clip.x > x1 ?   ctx_clip.x :  x1;
			clip.y = ctx_clip.y > y1 ?   ctx_clip.y :  y1;
			clip.width = (ctx_clip.x + ctx_clip.width < x2 ? ctx_clip.x + ctx_clip.width :  x2) - clip.x;
			clip.height = (ctx_clip.y + ctx_clip.height < y2 ? ctx_clip.y + ctx_clip.height :   y2) - clip.y;
		}
	}

	// scissor is with respect to lower-left corner
	// activeFrameBufferHeight is the height of the off-screen buffer
	// activeFrameBufferOffsetBottom -- the viewport actually goes past the bottom of the texture
	//   to the nearest power of two, so when we convert to y-coordinates from the lower-left viewport
	//   corner, we need to add the offsetBottom to get to the bottom of the viewable texture
	if (ctx->on_screen && clip.height > 0) {
		clip.y = ctx->canvas->framebuffer_height - (clip.height + clip.y) + ctx->canvas->framebuffer_offset_bottom;
	}

	rect_2d bounds = {clip.x, clip.y, clip.width, clip.height};

	if (rect_2d_equals(GET_CLIPPING_BOUNDS(ctx), &bounds)) {
		return;
	}

	*GET_CLIPPING_BOUNDS(ctx) = bounds;
	enable_scissor(ctx);
}
コード例 #5
0
ファイル: tealeaf_context.c プロジェクト: vvega/native-core
void context_2d_setTransform(context_2d *ctx, double m11, double m12, double m21, double m22, double dx, double dy) {
    context_2d_bind(ctx);
    matrix_3x3 *m = GET_MODEL_VIEW_MATRIX(ctx);
    m->m00 = m11;
    m->m01 = m21;
    m->m10 = m12;
    m->m11 = m22;
    m->m02 = dx;
    m->m12 = dy;

}
コード例 #6
0
/**
 * @name	context_2d_clearRect
 * @brief	clears the given rect on the given context
 * @param	ctx - (context_2d *) context to clear a rect from
 * @param	rect - (const rect_2d *) rect to clear from the context
 * @retval	NONE
 */
void context_2d_clearRect(context_2d *ctx, const rect_2d *rect) {
	draw_textures_flush();
	context_2d_bind(ctx);
	// Draw a rectangle using triangle strip:
	//    (0,1)-(2,3)-(4,5) and (2,3)-(4,5)-(6,7)
	//
	// With coordinates:
	//    4,5  -  6,7
	//     |   \   |
	//    0,1  -  2,3
	GLfloat v[8];
	matrix_3x3_multiply(GET_MODEL_VIEW_MATRIX(ctx), rect, (float *)&v[4], (float *)&v[5], (float *)&v[6], (float *)&v[7], (float *)&v[2], (float *)&v[3], (float *)&v[0], (float *)&v[1]);
	glBlendFunc(GL_ONE, GL_ZERO);
	glUniform4f(global_shaders[PRIMARY_SHADER].draw_color, 0, 0, 0, 0); // set color to 0
	glVertexAttribPointer(global_shaders[PRIMARY_SHADER].vertex_coords, 2, GL_FLOAT, GL_FALSE, 0, v);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
コード例 #7
0
/**
 * @name	context_2d_fillRect
 * @brief	fills a rectangle on the given context using given options
 * @param	ctx - (context_2d *) context to fill a rectangle on
 * @param	rect - (const rect_2d *) rect to be filled
 * @param	color - (const rgba *) color to fill with
 * @param	composite_op - deprecated
 * @retval	NONE
 */
void context_2d_fillRect(context_2d *ctx, const rect_2d *rect, const rgba *color) {
	if (use_single_shader) {
		return;
	}

	draw_textures_flush();
	context_2d_bind(ctx);
	tealeaf_shaders_bind(FILL_RECT_SHADER);
	apply_composite_operation(ctx->globalCompositeOperation[ctx->mvp]);
	rect_2d_vertices in, out;
	rect_2d_to_rect_2d_vertices(rect, &in);
	matrix_3x3_multiply_m_r_r(GET_MODEL_VIEW_MATRIX(ctx), &in, &out);
	float alpha = color->a * ctx->globalAlpha[ctx->mvp];
	// TODO: will pre-multiplied alpha cause a loss-of-precision in color for filling rectangles?
	GLTRACE(glUniform4f(global_shaders[FILL_RECT_SHADER].draw_color, alpha * color->r, alpha * color->g, alpha * color->b, alpha));
	GLTRACE(glVertexAttribPointer(global_shaders[FILL_RECT_SHADER].vertex_coords, 2, GL_FLOAT, GL_FALSE, 0, &out));
	GLTRACE(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
	tealeaf_shaders_bind(PRIMARY_SHADER);
}
コード例 #8
0
/**
 * @name	context_2d_scale
 * @brief	scales the given context by given options
 * @param	ctx - (context_2d *) context to scale
 * @param	x - (float) amount along the x-coordinate to scale
 * @param	y - (float) amount along the x-coordinate to scale
 * @retval	NONE
 */
void context_2d_scale(context_2d *ctx, float x, float y) {
	matrix_3x3_scale(GET_MODEL_VIEW_MATRIX(ctx), x, y);
}
コード例 #9
0
void context_2d_transform(context_2d *ctx, float a, float b, float c, float d, float dx, float dy) {
    matrix_3x3_transform(GET_MODEL_VIEW_MATRIX(ctx), a, b, c, d, dx, dy);
}
コード例 #10
0
/**
 * @name	context_2d_translate
 * @brief	translate's the given context by given options
 * @param	ctx - (context_2d *) context to translate
 * @param	x - (float) amount along the x-axis to translate by
 * @param	y - (float) amount along the y-axis to translate by
 * @retval	NONE
 */
void context_2d_translate(context_2d *ctx, float x, float y) {
	if (x != 0 || y != 0) {
		matrix_3x3_translate(GET_MODEL_VIEW_MATRIX(ctx), x, y);
	}
}
コード例 #11
0
/**
 * @name	context_2d_rotate
 * @brief	rotates the given context by given options
 * @param	ctx - (context_2d *) context to rotate
 * @param	angle - (float) angle to rotate by
 * @retval	NONE
 */
void context_2d_rotate(context_2d *ctx, float angle) {
	if (angle != 0) {
		matrix_3x3_rotate(GET_MODEL_VIEW_MATRIX(ctx), angle);
	}
}
コード例 #12
0
/**
 * @name	context_2d_loadIdentity
 * @brief	loads the identity matrix into the given context's model view matrix
 * @param	ctx - (context_2d *) context to load the identity matrix into
 * @retval	NONE
 */
void context_2d_loadIdentity(context_2d *ctx) {
	matrix_3x3_identity(GET_MODEL_VIEW_MATRIX(ctx));
}
コード例 #13
0
/**
 * @name	context_2d_setClip
 * @brief	sets the clipping rectangle on the given context
 * @param	ctx - (context_2d *) context to set the clipping rectangle on
 * @param	clip - (rect_2d) the clipping rectangle
 * @retval	NONE
 */
void context_2d_setClip(context_2d *ctx, rect_2d clip) {
	matrix_3x3 *modelView = GET_MODEL_VIEW_MATRIX(ctx);

#ifdef MATRIX_3x3_ALLOW_SKEW
	// TODO: Can this be done more efficiently?
	float clip_x, clip_y, clip_w, clip_h;
	float x1, y1, x2, y2, x3, y3, x4, y4;

	matrix_3x3_multiply(modelView, clip.x, clip.y, &x1, &y1);
	matrix_3x3_multiply(modelView, clip.x + clip.width, clip.y + clip.height, &x2, &y2);
	matrix_3x3_multiply(modelView, clip.x, clip.y + clip.height, &x3, &y3);
	matrix_3x3_multiply(modelView, clip.x + clip.width, clip.y, &x4, &y4);

	clip_x = x1;
	if (x2 < clip_x) {
		clip_x = x2;
	}
	if (x3 < clip_x) {
		clip_x = x3;
	}
	if (x4 < clip_x) {
		clip_x = x4;
	}
	
	clip_y = y1;
	if (y2 < clip_y) {
		clip_y = y2;
	}
	if (y3 < clip_y) {
		clip_y = y3;
	}
	if (y4 < clip_y) {
		clip_y = y4;
	}
	
	clip_w = x1;
	if (x2 > clip_w) {
		clip_w = x2;
	}
	if (x3 > clip_w) {
		clip_w = x3;
	}
	if (x4 > clip_w) {
		clip_w = x4;
	}
	
	clip_h = y1;
	if (y2 > clip_h) {
		clip_h = y2;
	}
	if (y3 > clip_h) {
		clip_h = y3;
	}
	if (y4 > clip_h) {
		clip_h = y4;
	}
	
	clip.x = clip_x;
	clip.y = clip_y;
	clip.width = clip_w - clip_x;
	clip.height = clip_h - clip_y;
#else
	float clip0x = clip.x, clip0y = clip.y;
	float clip1x = clip0x + clip.width, clip1y = clip0y + clip.height;

	// float x1, y1, x2, y2, x3, y3, x4, y4;
	// x1 = clip0x * modelView->m00 + clip0y * modelView->m01 + modelView->m02;
	// y1 = clip0x * modelView->m10 + clip0y * modelView->m11 + modelView->m12;
	// x2 = clip1x * modelView->m00 + clip0y * modelView->m01 + modelView->m02;
	// y2 = clip1x * modelView->m10 + clip0y * modelView->m11 + modelView->m12;
	// x3 = clip1x * modelView->m00 + clip1y * modelView->m01 + modelView->m02;
	// y3 = clip1x * modelView->m10 + clip1y * modelView->m11 + modelView->m12;
	// x4 = clip0x * modelView->m00 + clip1y * modelView->m01 + modelView->m02;
	// y4 = clip0x * modelView->m10 + clip1y * modelView->m11 + modelView->m12;

	float m00 = modelView->m00, m01 = modelView->m01, m10 = modelView->m10, m11 = modelView->m11;
	float a = clip0x * m00;
	float b = clip1x * m10;
	float c = clip0y * m11;
	float d = clip0y * m01;
	float e = clip1x * m00;
	float f = clip1y * m01;
	float g = clip0x * m10;
	float h = clip1y * m11;

	// If x1 < x2,
	if ((clip0x < clip1x) ^ (m00 < 0)) {
		// If x2 < x3,
		if ((clip0y < clip1y) ^ (m01 < 0)) {
			// (x1, y2) -> (x3, y4)
			clip.x = a + d;
			clip.y = b + c;
			clip.width = e + f;
			clip.height = g + h;
		} else {
			// (x4, y1) -> (x2, y3)
			clip.x = a + f;
			clip.y = g + c;
			clip.width = e + d;
			clip.height = b + h;
		}
	} else {
		// If x2 < x3,
		if ((clip0y < clip1y) ^ (m01 < 0)) {
			// (x2, y3) -> (x4, y1)
			clip.x = e + d;
			clip.y = b + h;
			clip.width = a + f;
			clip.height = g + c;
		} else {
			// (x3, y4) -> (x1, y2)
			clip.x = e + f;
			clip.y = g + h;
			clip.width = a + d;
			clip.height = b + c;
		}
	}

	clip.width -= clip.x;
	clip.height -= clip.y;
	clip.x += modelView->m02;
	clip.y += modelView->m12;
#endif

	// Clip with screen bounds
	if (clip.x < 0) {
		clip.width += clip.x;
		if (clip.width < 0) {
			clip.width = 0;
		}
		clip.x = 0;
	}
	if (clip.y < 0) {
		clip.height += clip.y;
		if (clip.height < 0) {
			clip.height = 0;
		}
		clip.y = 0;
	}

	// If entirely clipped,
	if (clip.width <= 0 || clip.height <= 0) {
		clip.x = clip.y = clip.width = clip.height = 0;
	} else {
		// Lookup parent bounds
		int i = ctx->mvp - 1;
		rect_2d ctx_clip;
		ctx_clip.x = ctx->clipStack[i].x;
		ctx_clip.y = ctx->clipStack[i].y;
		ctx_clip.width = ctx->clipStack[i].width;
		ctx_clip.height = ctx->clipStack[i].height;

		// If context is on screen,
		if (ctx->on_screen) {
			// Flip to frame buffer sense
			ctx_clip.y = -ctx_clip.y +  ctx->canvas->framebuffer_height + ctx->canvas->framebuffer_offset_bottom - ctx_clip.height;
		}

		// If parent is clipping,
		if (ctx_clip.width > -1) {
			// Calculate (x1, y1) for new and old clip regions
			float clip1x = clip.x + clip.width, clip1y = clip.y + clip.height;
			float ctx1x = ctx_clip.x + ctx_clip.width, ctx1y = ctx_clip.y + ctx_clip.height;

			// If new clip is entirely outside parent,
			if (clip.x >= ctx1x || clip1x <= ctx_clip.x ||
				clip.y >= ctx1y || clip1y <= ctx_clip.y) {
				// Empty clip region
				clip.x = clip.y = clip.width = clip.height = 0;
			} else {
				// Trim new clip with parent
				clip.x = ctx_clip.x > clip.x ? ctx_clip.x : clip.x;
				clip.y = ctx_clip.y > clip.y ? ctx_clip.y : clip.y;
				clip.width = (ctx1x < clip1x ? ctx1x : clip1x) - clip.x;
				clip.height = (ctx1y < clip1y ? ctx1y : clip1y) - clip.y;
			}
		}

		// scissor is with respect to lower-left corner
		// activeFrameBufferHeight is the height of the off-screen buffer
		// activeFrameBufferOffsetBottom -- the viewport actually goes past the bottom of the texture
		//   to the nearest power of two, so when we convert to y-coordinates from the lower-left viewport
		//   corner, we need to add the offsetBottom to get to the bottom of the viewable texture
		if (ctx->on_screen && clip.height > 0) {
			// Flip from frame buffer sense
			clip.y = ctx->canvas->framebuffer_height - (clip.height + clip.y) + ctx->canvas->framebuffer_offset_bottom;
		}
	}

	rect_2d bounds = {
		clip.x, clip.y,
		clip.width, clip.height
	};

	if (rect_2d_equals(GET_CLIPPING_BOUNDS(ctx), &bounds)) {
		return;
	}

	*GET_CLIPPING_BOUNDS(ctx) = bounds;
	enable_scissor(ctx);
}