Пример #1
0
void tealeaf_context_update_shader(context_2d *ctx, unsigned int shader_type, bool force) {
    int width = ctx->backing_width;
    int height = ctx->backing_height;
    tealeaf_shader *shader = &global_shaders[shader_type];
    matrix_4x4 m;
    matrix_3x3 *proj;

    if (shader->last_width != width || shader->last_height != height || force) {
        //Need to copy the 3x3 projection matrix into a 4x4 matrix since that
        //is the form used in the shader. Note that in the future the shaders
        //could be changed to use 3x3 matrices rather than 4x4
        proj = &ctx->proj_matrix;
        m.m00 = proj->m00;
        m.m01 = proj->m01;
        m.m02 = 0;
        m.m03 = proj->m02;
        m.m10 = proj->m10;
        m.m11 = proj->m11;
        m.m12 = 0;
        m.m13 = proj->m12;
        m.m20 = 0;
        m.m21 = 0;
        m.m22 = 1;
        m.m23 = 0;
        m.m30 = proj->m20;
        m.m31 = proj->m21;
        m.m32 = 0;
        m.m33 = proj->m22;
        GLTRACE(glUseProgram(shader->program));
        GLTRACE(glUniformMatrix4fv(shader->proj_matrix, 1, false, (float *) &m));
        shader->last_width = width;
        shader->last_height = height;
        GLTRACE(glUseProgram(global_shaders[current_shader].program));
    }
}
/**
 * @name	enable_scissor
 * @brief   enables the use of glScissors using proprties from the given context
 * @param	ctx - (context_2d *)
 * @retval	NONE
 */
void enable_scissor(context_2d *ctx) {
	rect_2d *bounds = GET_CLIPPING_BOUNDS(ctx);

	if (rect_2d_equals(&last_scissor_rect, bounds)) {
		return;
	}

	draw_textures_flush();
	last_scissor_rect.x = bounds->x;
	last_scissor_rect.y = bounds->y;
	last_scissor_rect.width = bounds->width;
	last_scissor_rect.height = bounds->height;
	GLTRACE(glScissor((int) bounds->x, (int) bounds->y, (int) bounds->width, (int) bounds->height));
	GLTRACE(glEnable(GL_SCISSOR_TEST));
}
Пример #3
0
/**
 * @name	tealeaf_canvas_bind_texture_buffer
 * @brief	binds the given context's texture backing to gl to draw to
 * @param	ctx - (context_2d *) pointer to the context to bind
 * @retval	NONE
 */
void tealeaf_canvas_bind_texture_buffer(context_2d *ctx) {
    texture_2d *tex = texture_manager_get_texture(texture_manager_get(), ctx->url);

    if (!tex) {
        return;
    }

    GLTRACE(glBindTexture(GL_TEXTURE_2D, tex->name));
    GLTRACE(glFinish());
    GLTRACE(glBindFramebuffer(GL_FRAMEBUFFER, canvas.offscreen_framebuffer));
    GLTRACE(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->name, 0));
    canvas.framebuffer_width = tex->originalWidth;
    canvas.framebuffer_height = tex->originalHeight;
    canvas.framebuffer_offset_bottom = tex->height - tex->originalHeight;
}
/**
 * @name	tealeaf_context_update_viewport
 * @brief	updates the gl viewport using the context's properties
 * @param	ctx - (context_2d *) context to update the viewport by
 * @param	force - (bool) force an updating of shaders
 * @retval	NONE
 */
void tealeaf_context_update_viewport(context_2d *ctx, bool force) {
	tealeaf_context_update_shader(ctx, DRAWING_SHADER, force);
	tealeaf_context_update_shader(ctx, PRIMARY_SHADER, force);
	tealeaf_context_update_shader(ctx, FILL_RECT_SHADER, force);
	tealeaf_context_update_shader(ctx, LINEAR_ADD_SHADER, force);
	GLTRACE(glViewport(0, 0, ctx->backing_width, ctx->backing_height));
}
Пример #5
0
/**
 * @name	tealeaf_canvas_resize
 * @brief	resize's the onscreen canvas
 * @param	w - (int) width to resize to
 * @param	h - (int) height to resize to
 * @retval	NONE
 */
void tealeaf_canvas_resize(int w, int h) {
    LOG("{canvas} Resizing screen to (%d, %d)", w, h);

    context_2d *ctx = canvas.onscreen_ctx;
    context_2d_resize(ctx, w, h);

    if (canvas.active_ctx == canvas.onscreen_ctx) {
        tealeaf_canvas_bind_render_buffer(ctx);
        tealeaf_context_update_viewport(ctx, true);
        context_2d_clear(ctx);
    }

    GLTRACE(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
    GLTRACE(glEnable(GL_BLEND));
    config_set_screen_width(w);
    config_set_screen_height(h);
    canvas.should_resize = true;
}
/**
 * @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);
}
/**
 * @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);
	tealeaf_shaders_bind(PRIMARY_SHADER);

	// 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]);
	GLTRACE(glBlendFunc(GL_ONE, GL_ZERO));
	GLTRACE(glUniform4f(global_shaders[PRIMARY_SHADER].draw_color, 0, 0, 0, 0)); // set color to 0
	GLTRACE(glVertexAttribPointer(global_shaders[PRIMARY_SHADER].vertex_coords, 2, GL_FLOAT, GL_FALSE, 0, v));
	GLTRACE(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
	GLTRACE(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
}
Пример #8
0
/**
 * @name	tealeaf_canvas_init
 * @brief	initilizes the tealeaf canvas object
 * @param	framebuffer_name - (int) gl id of the onscreen framebuffer
 * @retval	NONE
 */
void tealeaf_canvas_init(int framebuffer_name) {
    LOG("{canvas} Initializing Canvas");

    int width = config_get_screen_width();
    int height = config_get_screen_height();
    GLuint offscreen_buffer_name;
    GLTRACE(glGenFramebuffers(1, &offscreen_buffer_name));
    canvas.offscreen_framebuffer = offscreen_buffer_name;
    canvas.view_framebuffer = framebuffer_name;
    canvas.onscreen_ctx = context_2d_init(&canvas, "onscreen", -1, true);
    canvas.onscreen_ctx->width = width;
    canvas.onscreen_ctx->height = height;
    canvas.active_ctx = 0;

    // TODO: should_resize is not respected on iOS

    tealeaf_canvas_context_2d_bind(canvas.onscreen_ctx);
}
/**
 * @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);
}
/**
 * @name	disable_scissor
 * @brief	disables the use of glScissors
 * @param	ctx - deprecated
 * @retval	NONE
 */
void disable_scissor(context_2d *ctx) {
	draw_textures_flush();
	last_scissor_rect.x = last_scissor_rect.y = 0;
	last_scissor_rect.width = last_scissor_rect.height = -1;
	GLTRACE(glDisable(GL_SCISSOR_TEST));
}
Пример #11
0
/**
 * @name	tealeaf_canvas_bind_render_buffer
 * @brief	bind's the render buffer and set's it's height / width to the given context's props
 * @param	ctx - (context_2d *) pointer to the context to use the width / height from
 * @retval	NONE
 */
void tealeaf_canvas_bind_render_buffer(context_2d *ctx) {
    GLTRACE(glBindFramebuffer(GL_FRAMEBUFFER, canvas.view_framebuffer));
    canvas.framebuffer_width = ctx->width;
    canvas.framebuffer_height = ctx->height;
    canvas.framebuffer_offset_bottom = 0;
}