[Bf-blender-cvs] [8327795] blender2.8: OpenGL: draw image empties with new API

Mike Erwin noreply at git.blender.org
Tue Oct 18 06:12:40 CEST 2016


Commit: 8327795f8db13b4a66ba70c4bc01091bab1d847b
Author: Mike Erwin
Date:   Mon Oct 17 20:33:59 2016 -0400
Branches: blender2.8
https://developer.blender.org/rB8327795f8db13b4a66ba70c4bc01091bab1d847b

OpenGL: draw image empties with new API

This extensive rewrite caches the image texture in VRAM. Can handle images up to OpenGL limits (8K or 16K).

Part of T49043 & T49450

===================================================================

M	source/blender/editors/space_view3d/drawobject.c

===================================================================

diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 9472624..408d27e 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -633,92 +633,104 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
 static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
 {
 	Image *ima = ob->data;
-	ImBuf *ibuf = BKE_image_acquire_ibuf(ima, ob->iuser, NULL);
 
-	if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
-		IMB_rect_from_float(ibuf);
-	}
+	const float ob_alpha = ob->col[3];
+	float width, height;
 
-	int ima_x, ima_y;
+	const int texUnit = GL_TEXTURE0;
+	int bindcode = 0;
 
-	/* Get the buffer dimensions so we can fallback to fake ones */
-	if (ibuf && ibuf->rect) {
-		ima_x = ibuf->x;
-		ima_y = ibuf->y;
+	if (ima) {
+		if (ob_alpha > 0.0f) {
+			glActiveTexture(texUnit);
+			bindcode = GPU_verify_image(ima, ob->iuser, GL_TEXTURE_2D, 0, false, false, false);
+			/* don't bother drawing the image if alpha = 0 */
+		}
+
+		int w, h;
+		BKE_image_get_size(ima, ob->iuser, &w, &h);
+		width = w;
+		height = h;
 	}
 	else {
-		ima_x = 1;
-		ima_y = 1;
+		/* if no image, make it a 1x1 empty square, honor scale & offset */
+		width = height = 1.0f;
 	}
 
-	float sca_x = 1.0f;
-	float sca_y = 1.0f;
+	const float aspect = height / width;
 
-	/* Get the image aspect even if the buffer is invalid */
-	if (ima) {
-		if (ima->aspx > ima->aspy) {
-			sca_y = ima->aspy / ima->aspx;
-		}
-		else if (ima->aspx < ima->aspy) {
-			sca_x = ima->aspx / ima->aspy;
-		}
-	}
+	float left = ob->ima_ofs[0];
+	float right = ob->ima_ofs[0] + ob->empty_drawsize;
+	float top = ob->ima_ofs[1] + ob->empty_drawsize * aspect;
+	float bottom = ob->ima_ofs[1];
 
-	/* Calculate the scale center based on object's origin */
-	float ofs_x = ob->ima_ofs[0] * ima_x;
-	float ofs_y = ob->ima_ofs[1] * ima_y;
+	bool use_blend = false;
 
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
+	if (bindcode) {
+		use_blend = ob_alpha < 1.0f || BKE_image_has_alpha(ima);
 
-	/* Calculate Image scale */
-	float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y);
+		if (use_blend) {
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		}
 
-	/* Set the object scale */
-	glScalef(scale * sca_x, scale * sca_y, 1.0f);
+		VertexFormat *format = immVertexFormat();
+		unsigned pos = add_attrib(format, "position", GL_FLOAT, 2, KEEP_FLOAT);
+		unsigned texCoord = add_attrib(format, "texcoord", GL_FLOAT, 2, KEEP_FLOAT);
+		immBindBuiltinProgram(GPU_SHADER_2D_TEXTURE_2D); /* TODO: rename GPU_SHADER_3D_IMAGE_2D_MODULATE_ALPHA */
+		immUniform1f("alpha", ob_alpha);
+		immUniform1i("texture_map", texUnit); /* TODO: rename "image" */
 
-	if (ibuf && ibuf->rect) {
-		const bool use_clip = (U.glalphaclip != 1.0f);
-		int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP) ? GL_NEAREST : GL_LINEAR;
-		/* Setup GL params */
-		glEnable(GL_BLEND);
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		immBegin(GL_TRIANGLE_FAN, 4);
+		immAttrib2f(texCoord, 0.0f, 0.0f);
+		immVertex2f(pos, left, bottom);
 
-		if (use_clip) {
-			glEnable(GL_ALPHA_TEST);
-			glAlphaFunc(GL_GREATER, U.glalphaclip);
-		}
+		immAttrib2f(texCoord, 1.0f, 0.0f);
+		immVertex2f(pos, right, bottom);
 
-		/* Use the object color and alpha */
-		glColor4fv(ob->col);
+		immAttrib2f(texCoord, 1.0f, 1.0f);
+		immVertex2f(pos, right, top);
 
-		/* Draw the Image on the screen */
-		glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect);
+		immAttrib2f(texCoord, 0.0f, 1.0f);
+		immVertex2f(pos, left, top);
+		immEnd();
 
-		glDisable(GL_BLEND);
+		immUnbindProgram();
 
-		if (use_clip) {
-			glDisable(GL_ALPHA_TEST);
-			glAlphaFunc(GL_ALWAYS, 0.0f);
-		}
+		glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */
 	}
 
-	if ((dflag & DRAW_CONSTCOLOR) == 0) {
-		glColor3ubv(ob_wire_col);
+	/* Draw the image outline */
+	glLineWidth(1.5f);
+	unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+	const bool picking = dflag & DRAW_CONSTCOLOR;
+	if (picking) {
+		/* TODO: deal with picking separately, use this function just to draw */
+		immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+		if (use_blend) {
+			glDisable(GL_BLEND);
+		}
+
+		imm_draw_line_box(pos, left, bottom, right, top);
 	}
+	else {
+		immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+		immUniformColor3ubv(ob_wire_col);
+		glEnable(GL_LINE_SMOOTH);
 
-	/* Calculate the outline vertex positions */
-	glBegin(GL_LINE_LOOP);
-	glVertex2f(ofs_x, ofs_y);
-	glVertex2f(ofs_x + ima_x, ofs_y);
-	glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
-	glVertex2f(ofs_x, ofs_y + ima_y);
-	glEnd();
+		if (!use_blend) {
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		}
 
-	/* Reset GL settings */
-	glPopMatrix();
+		imm_draw_line_box(pos, left, bottom, right, top);
 
-	BKE_image_release_ibuf(ima, ibuf, NULL);
+		glDisable(GL_LINE_SMOOTH);
+		glDisable(GL_BLEND);
+	}
+
+	immUnbindProgram();
 }
 
 static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4])




More information about the Bf-blender-cvs mailing list