/** * @brief Starts the rendering engine. */ static void gl_fontRenderStart( const glFontStash* font, double x, double y, const glColour *c ) { double a; /* Enable textures. */ glEnable(GL_TEXTURE_2D); /* Set up matrix. */ gl_matrixMode(GL_MODELVIEW); gl_matrixPush(); gl_matrixTranslate( round(x), round(y) ); /* Handle colour. */ if (font_restoreLast) { a = (c==NULL) ? 1. : c->a; ACOLOUR(*font_lastCol,a); } else { if (c==NULL) glColor4d( 1., 1., 1., 1. ); else COLOUR(*c); } font_restoreLast = 0; /* Activate the appropriate VBOs. */ gl_vboActivateOffset( font->vbo_tex, GL_TEXTURE_COORD_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( font->vbo_vert, GL_VERTEX_ARRAY, 0, 2, GL_SHORT, 0 ); }
/** * @brief Renders a rectangle. * * @param x X position to render rectangle at. * @param y Y position to render rectangle at. * @param w Rectangle width. * @param h Rectangle height. * @param c Rectangle colour. */ void gl_renderRectEmpty( double x, double y, double w, double h, const glColour *c ) { GLfloat vx, vy, vxw, vyh; GLfloat vertex[5*2], col[5*4]; /* Helper variables. */ vx = (GLfloat) x; vy = (GLfloat) y; vxw = vx + (GLfloat) w; vyh = vy + (GLfloat) h; /* Set the vertex. */ vertex[0] = vx; vertex[1] = vy; vertex[2] = vxw; vertex[3] = vy; vertex[4] = vxw; vertex[5] = vyh; vertex[6] = vx; vertex[7] = vyh; vertex[8] = vx; vertex[9] = vy; gl_vboSubData( gl_renderVBO, 0, sizeof(vertex), vertex ); gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); /* Set the colour. */ col[0] = c->r; col[1] = c->g; col[2] = c->b; col[3] = c->a; col[4] = col[0]; col[5] = col[1]; col[6] = col[2]; col[7] = col[3]; col[8] = col[0]; col[9] = col[1]; col[10] = col[2]; col[11] = col[3]; col[12] = col[0]; col[13] = col[1]; col[14] = col[2]; col[15] = col[3]; col[16] = col[0]; col[17] = col[1]; col[18] = col[2]; col[19] = col[3]; gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, sizeof(col), col ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); /* Draw. */ glDrawArrays( GL_LINE_STRIP, 0, 5 ); /* Clear state. */ gl_vboDeactivate(); /* Check errors. */ gl_checkErr(); }
/** * @brief Draws a mission marker on the map. * * @param x X position to draw at. * @param y Y position to draw at. * @param r Radius of system. * @param num Total number of markers. * @param cur Current marker to draw. * @param type Type to draw. */ static void map_drawMarker( double x, double y, double r, int num, int cur, int type ) { const double beta = M_PI / 9; static const glColour* colours[] = { &cGreen, &cBlue, &cRed, &cOrange }; int i; double alpha, cos_alpha, sin_alpha; GLfloat vertex[3*(2+4)]; /* Calculate the angle. */ if ((num == 1) || (num == 2) || (num == 4)) alpha = M_PI/4.; else if (num == 3) alpha = M_PI/6.; else if (num == 5) alpha = M_PI/10.; else alpha = M_PI/2.; alpha += M_PI*2. * (double)cur/(double)num; cos_alpha = r * cos(alpha); sin_alpha = r * sin(alpha); r = 3 * r; /* Draw the marking triangle. */ vertex[0] = x + cos_alpha; vertex[1] = y + sin_alpha; vertex[2] = x + cos_alpha + r * cos(beta + alpha); vertex[3] = y + sin_alpha + r * sin(beta + alpha); vertex[4] = x + cos_alpha + r * cos(beta - alpha); vertex[5] = y + sin_alpha - r * sin(beta - alpha); for (i=0; i<3; i++) { vertex[6 + 4*i + 0] = colours[type]->r; vertex[6 + 4*i + 1] = colours[type]->g; vertex[6 + 4*i + 2] = colours[type]->b; vertex[6 + 4*i + 3] = colours[type]->a; } glEnable(GL_POLYGON_SMOOTH); gl_vboSubData( map_vbo, 0, sizeof(GLfloat) * 3*(2+4), vertex ); gl_vboActivateOffset( map_vbo, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( map_vbo, GL_COLOR_ARRAY, sizeof(GLfloat) * 2*3, 4, GL_FLOAT, 0 ); glDrawArrays( GL_TRIANGLES, 0, 3 ); gl_vboDeactivate(); glDisable(GL_POLYGON_SMOOTH); }
/** * @brief Renders a rectangle. * * @param x X position to render rectangle at. * @param y Y position to render rectangle at. * @param w Rectangle width. * @param h Rectangle height. * @param c Rectangle colour. */ void gl_renderRect( double x, double y, double w, double h, const glColour *c ) { GLfloat vertex[4*2], col[4*4]; /* Set the vertex. */ /* 1--2 * | | * 3--4 */ vertex[0] = (GLfloat)x; vertex[4] = vertex[0]; vertex[2] = vertex[0] + (GLfloat)w; vertex[6] = vertex[2]; vertex[1] = (GLfloat)y; vertex[3] = vertex[1]; vertex[5] = vertex[1] + (GLfloat)h; vertex[7] = vertex[5]; gl_vboSubData( gl_renderVBO, 0, 4*2*sizeof(GLfloat), vertex ); gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); /* Set the colour. */ col[0] = c->r; col[1] = c->g; col[2] = c->b; col[3] = c->a; col[4] = col[0]; col[5] = col[1]; col[6] = col[2]; col[7] = col[3]; col[8] = col[0]; col[9] = col[1]; col[10] = col[2]; col[11] = col[3]; col[12] = col[0]; col[13] = col[1]; col[14] = col[2]; col[15] = col[3]; gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, 4*4*sizeof(GLfloat), col ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); /* Draw. */ glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); /* Clear state. */ gl_vboDeactivate(); /* Check errors. */ gl_checkErr(); }
/** * @brief Draws an outline. * * If lc is NULL, colour will be flat. * * @param x X position to draw at. * @param y Y position to draw at. * @param w Width. * @param h Height. * @param b Border width. * @param c Colour. * @param lc Light colour. */ void toolkit_drawOutline( int x, int y, int w, int h, int b, glColour* c, glColour* lc ) { GLint lines[4][2]; glColour colours[4]; /* Set shade model. */ glShadeModel( (lc==NULL) ? GL_FLAT : GL_SMOOTH ); x -= b, w += 2 * b; y -= b, h += 2 * b; lc = lc ? lc : c; /* Lines. */ lines[0][0] = x; /* left-up */ lines[0][1] = y; colours[0] = *lc; lines[1][0] = x; /* left-down */ lines[1][1] = y + h; colours[1] = *c; lines[2][0] = x + w; /* right-down */ lines[2][1] = y + h; colours[2] = *c; lines[3][0] = x + w; /* right-up */ lines[3][1] = y; colours[3] = *lc; /* Upload to the VBO. */ gl_vboSubData( toolkit_vbo, 0, sizeof(lines), lines ); gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours ); /* Set up the VBO. */ gl_vboActivateOffset( toolkit_vbo, GL_VERTEX_ARRAY, 0, 2, GL_INT, 0 ); gl_vboActivateOffset( toolkit_vbo, GL_COLOR_ARRAY, toolkit_vboColourOffset, 4, GL_FLOAT, 0 ); /* Draw the VBO. */ glDrawArrays( GL_LINE_LOOP, 0, 4 ); /* Deactivate VBO. */ gl_vboDeactivate(); }
/** * @brief Draws a rectangle. * * If lc is NULL, colour will be flat. * * @param x X position to draw at. * @param y Y position to draw at. * @param w Width. * @param h Height. * @param c Colour. * @param lc Light colour. */ void toolkit_drawRect( int x, int y, int w, int h, glColour* c, glColour* lc ) { GLint vertex[4][2]; glColour colours[4]; /* Set shade model. */ glShadeModel( (lc) ? GL_SMOOTH : GL_FLAT ); lc = lc == NULL ? c : lc; /* Set up vertices and colours. */ vertex[0][0] = x; /* left-up */ vertex[0][1] = y; colours[0] = *c; vertex[1][0] = x; /* left-down */ vertex[1][1] = y + h; colours[1] = *lc; vertex[2][0] = x + w; /* right-up */ vertex[2][1] = y; colours[2] = *c; vertex[3][0] = x + w; /* right-down */ vertex[3][1] = y + h; colours[3] = *lc; /* Upload to the VBO. */ gl_vboSubData( toolkit_vbo, 0, sizeof(vertex), vertex ); gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(colours), colours ); /* Set up the VBO. */ gl_vboActivateOffset( toolkit_vbo, GL_VERTEX_ARRAY, 0, 2, GL_INT, 0 ); gl_vboActivateOffset( toolkit_vbo, GL_COLOR_ARRAY, toolkit_vboColourOffset, 4, GL_FLOAT, 0 ); /* Draw the VBO. */ glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); /* Deactivate VBO. */ gl_vboDeactivate(); }
/** * @brief Renders a cross at a given position. * * @param x X position to center at. * @param y Y position to center at. * @param r Radius of cross. * @param c Colour to use. */ void gl_renderCross( double x, double y, double r, const glColour *c ) { int i; GLfloat vertex[2*4], colours[4*4]; GLfloat vx,vy, vr; /* Set up stuff. */ vx = x; vy = y; vr = r; /* the + sign in the middle of the radar representing the player */ for (i=0; i<4; i++) { colours[4*i + 0] = c->r; colours[4*i + 1] = c->g; colours[4*i + 2] = c->b; colours[4*i + 3] = c->a; } gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, sizeof(GLfloat) * 4*4, colours ); /* Set up vertex. */ vertex[0] = vx+0.; vertex[1] = vy-vr; vertex[2] = vx+0.; vertex[3] = vy+vr; vertex[4] = vx-vr; vertex[5] = vy+0.; vertex[6] = vx+vr; vertex[7] = vy+0.; gl_vboSubData( gl_renderVBO, 0, sizeof(GLfloat) * 4*2, vertex ); /* Draw tho VBO. */ gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); glDrawArrays( GL_LINES, 0, 4 ); gl_vboDeactivate(); }
/** * @brief Renders a window border. * * @param w Window to render */ static void window_renderBorder( Window* w ) { int i; GLint cx, cy; double x, y; glColour *lc, *c, *dc, *oc; GLint vertex[31*4]; GLfloat colours[31*4]; /* position */ x = w->x - (double)SCREEN_W/2.; y = w->y - (double)SCREEN_H/2.; /* colours */ lc = &cGrey90; c = &cGrey70; dc = &cGrey50; oc = &cGrey30; /* * Case fullscreen. */ if (window_isFlag( w, WINDOW_FULLSCREEN )) { /* Background. */ toolkit_drawRect( x, y, w->w, 0.6*w->h, dc, c ); toolkit_drawRect( x, y+0.6*w->h, w->w, 0.4*w->h, c, NULL ); /* Name. */ gl_printMidRaw( &gl_defFont, w->w, x + (double)SCREEN_W/2., y + w->h - 20. + (double)SCREEN_H/2., &cBlack, w->name ); return; } /* * window shaded bg */ /* main body */ toolkit_drawRect( x+21, y, w->w-42., 0.6*w->h, dc, c ); toolkit_drawRect( x+21, y+0.6*w->h, w->w-42., 0.4*w->h, c, NULL ); glShadeModel(GL_SMOOTH); /* Both sides. */ gl_vboActivateOffset( toolkit_vbo, GL_COLOR_ARRAY, toolkit_vboColourOffset, 4, GL_FLOAT, 0 ); gl_vboActivateOffset( toolkit_vbo, GL_VERTEX_ARRAY, 0, 2, GL_INT, 0 ); /* Colour is shared. */ colours[0] = c->r; colours[1] = c->g; colours[2] = c->r; colours[3] = c->a; for (i=0; i<7; i++) { colours[4 + 4*i + 0] = dc->r; colours[4 + 4*i + 1] = dc->g; colours[4 + 4*i + 2] = dc->r; colours[4 + 4*i + 3] = dc->a; } for (i=0; i<8; i++) { colours[32 + 4*i + 0] = c->r; colours[32 + 4*i + 1] = c->g; colours[32 + 4*i + 2] = c->r; colours[32 + 4*i + 3] = c->a; } gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(GLfloat) * 4*16, colours ); /* Left side vertex. */ cx = x; cy = y; vertex[0] = cx + 21; vertex[1] = cy + 0.6*w->h; vertex[2] = cx + 21; vertex[3] = cy; vertex[4] = cx + 15; vertex[5] = cy + 1; vertex[6] = cx + 10; vertex[7] = cy + 3; vertex[8] = cx + 6; vertex[9] = cy + 6; vertex[10] = cx + 3; vertex[11] = cy + 10; vertex[12] = cx + 1; vertex[13] = cy + 15; vertex[14] = cx; vertex[15] = cy + 21; vertex[16] = cx; vertex[17] = cy + 0.6*w->h; vertex[18] = cx; cy = y + w->h; vertex[19] = cy - 21; vertex[20] = cx + 1; vertex[21] = cy - 15; vertex[22] = cx + 3; vertex[23] = cy - 10; vertex[24] = cx + 6; vertex[25] = cy - 6; vertex[26] = cx + 10; vertex[27] = cy - 3; vertex[28] = cx + 15; vertex[29] = cy - 1; vertex[30] = cx + 21; vertex[31] = cy; gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*16, vertex ); glDrawArrays( GL_POLYGON, 0, 16 ); /* Right side vertex. */ cx = x + w->w; cy = y; vertex[0] = cx - 21; vertex[1] = cy + 0.6*w->h; vertex[2] = cx - 21; vertex[3] = cy; vertex[4] = cx - 15; vertex[5] = cy + 1; vertex[6] = cx - 10; vertex[7] = cy + 3; vertex[8] = cx - 6; vertex[9] = cy + 6; vertex[10] = cx - 3; vertex[11] = cy + 10; vertex[12] = cx - 1; vertex[13] = cy + 15; vertex[14] = cx; vertex[15] = cy + 21; vertex[16] = cx; vertex[17] = cy + 0.6*w->h; vertex[18] = cx; cy = y + w->h; vertex[19] = cy - 21; vertex[20] = cx - 1; vertex[21] = cy - 15; vertex[22] = cx - 3; vertex[23] = cy - 10; vertex[24] = cx - 6; vertex[25] = cy - 6; vertex[26] = cx - 10; vertex[27] = cy - 3; vertex[28] = cx - 15; vertex[29] = cy - 1; vertex[30] = cx - 21; vertex[31] = cy; gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*16, vertex ); glDrawArrays( GL_POLYGON, 0, 16 ); /* * inner outline */ /* Colour. */ for (i=0; i<7; i++) { colours[4*i + 0] = c->r; colours[4*i + 1] = c->g; colours[4*i + 2] = c->b; colours[4*i + 3] = c->a; } for (; i<7+16; i++) { colours[4*i + 0] = lc->r; colours[4*i + 1] = lc->g; colours[4*i + 2] = lc->b; colours[4*i + 3] = lc->a; } for (; i<7+16+8; i++) { colours[4*i + 0] = c->r; colours[4*i + 1] = c->g; colours[4*i + 2] = c->b; colours[4*i + 3] = c->a; } gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(GLfloat) * 4*31, colours ); /* Vertex. */ /* Left side. */ cx = x + 1; cy = y + 1; vertex[0] = cx + 21; vertex[1] = cy; vertex[2] = cx + 15; vertex[3] = cy + 1; vertex[4] = cx + 10; vertex[5] = cy + 3; vertex[6] = cx + 6; vertex[7] = cy + 6; vertex[8] = cx + 3; vertex[9] = cy + 10; vertex[10] = cx + 1; vertex[11] = cy + 15; vertex[12] = cx; vertex[13] = cy + 21; vertex[14] = cx; vertex[15] = cy + 0.6*w->h - 1; cy = y + w->h - 1; vertex[16] = cx; vertex[17] = cy - 21; vertex[18] = cx + 1; vertex[19] = cy - 15; vertex[20] = cx + 3; vertex[21] = cy - 10; vertex[22] = cx + 6; vertex[23] = cy - 6; vertex[24] = cx + 10; vertex[25] = cy - 3; vertex[26] = cx + 15; vertex[27] = cy - 1; vertex[28] = cx + 21; vertex[29] = cy; /* Right side via top. */ cx = x + w->w - 1; cy = y + w->h - 1; vertex[30] = cx - 21; vertex[31] = cy; vertex[32] = cx - 15; vertex[33] = cy - 1; vertex[34] = cx - 10; vertex[35] = cy - 3; vertex[36] = cx - 6; vertex[37] = cy - 6; vertex[38] = cx - 3; vertex[39] = cy - 10; vertex[40] = cx - 1; vertex[41] = cy - 15; vertex[42] = cx; vertex[43] = cy - 21; cy = y + 1; vertex[44] = cx; vertex[45] = cy + 0.6*w->h - 1; vertex[46] = cx; vertex[47] = cy + 21; vertex[48] = cx - 1; vertex[49] = cy + 15; vertex[50] = cx - 3; vertex[51] = cy + 10; vertex[52] = cx - 6; vertex[53] = cy + 6; vertex[54] = cx - 10; vertex[55] = cy + 3; vertex[56] = cx - 15; vertex[57] = cy + 1; vertex[58] = cx - 21; vertex[59] = cy; cx = x + 1; cy = y + 1; vertex[60] = cx + 21; vertex[61] = cy; gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*31, vertex ); glDrawArrays( GL_LINE_LOOP, 0, 31 ); /* * outter outline */ glShadeModel(GL_FLAT); /* Colour. */ for (i=0; i<31; i++) { colours[4*i + 0] = oc->r; colours[4*i + 1] = oc->g; colours[4*i + 2] = oc->b; colours[4*i + 3] = oc->a; } gl_vboSubData( toolkit_vbo, toolkit_vboColourOffset, sizeof(GLfloat) * 4*31, colours ); /* Vertex. */ /* Left side. */ cx = x; cy = y; vertex[0] = cx + 21; vertex[1] = cy; vertex[2] = cx + 15; vertex[3] = cy + 1; vertex[4] = cx + 10; vertex[5] = cy + 3; vertex[6] = cx + 6; vertex[7] = cy + 6; vertex[8] = cx + 3; vertex[9] = cy + 10; vertex[10] = cx + 1; vertex[11] = cy + 15; vertex[12] = cx; vertex[13] = cy + 21; vertex[14] = cx; vertex[15] = cy + 0.6*w->h; cy = y + w->h; vertex[16] = cx; vertex[17] = cy - 21; vertex[18] = cx + 1; vertex[19] = cy - 15; vertex[20] = cx + 3; vertex[21] = cy - 10; vertex[22] = cx + 6; vertex[23] = cy - 6; vertex[24] = cx + 10; vertex[25] = cy - 3; vertex[26] = cx + 15; vertex[27] = cy - 1; vertex[28] = cx + 21; vertex[29] = cy; /* Right side via top. */ cx = x + w->w; cy = y + w->h; vertex[30] = cx - 21; vertex[31] = cy; vertex[32] = cx - 15; vertex[33] = cy - 1; vertex[34] = cx - 10; vertex[35] = cy - 3; vertex[36] = cx - 6; vertex[37] = cy - 6; vertex[38] = cx - 3; vertex[39] = cy - 10; vertex[40] = cx - 1; vertex[41] = cy - 15; vertex[42] = cx; vertex[43] = cy - 21; cy = y; vertex[44] = cx; vertex[45] = cy + 0.6*w->h; vertex[46] = cx; vertex[47] = cy + 21; vertex[48] = cx - 1; vertex[49] = cy + 15; vertex[50] = cx - 3; vertex[51] = cy + 10; vertex[52] = cx - 6; vertex[53] = cy + 6; vertex[54] = cx - 10; vertex[55] = cy + 3; vertex[56] = cx - 15; vertex[57] = cy + 1; vertex[58] = cx - 21; vertex[59] = cy; cx = x; cy = y; vertex[60] = cx + 21; vertex[61] = cy; gl_vboSubData( toolkit_vbo, 0, sizeof(GLint) * 2*31, vertex ); glDrawArrays( GL_LINE_LOOP, 0, 31 ); /* Clean up. */ gl_vboDeactivate(); /* * render window name */ gl_printMidRaw( &gl_defFont, w->w, x + (double)SCREEN_W/2., y + w->h - 20. + (double)SCREEN_H/2., &cBlack, w->name ); }
/** * @brief Draws a circle in a rectangle. * * @param cx X position of the center in screen coordinates.. * @param cy Y position of the center in screen coordinates. * @param r Radius of the circle. * @param rx X position of the rectangle limiting the circle in screen coords. * @param ry Y position of the rectangle limiting the circle in screen coords. * @param rw Width of the limiting rectangle. * @param rh Height of the limiting rectangle. * @param c Colour to use. */ void gl_drawCircleInRect( const double cx, const double cy, const double r, const double rx, const double ry, const double rw, const double rh, const glColour *c, int filled ) { int i, j; double rxw,ryh, x,y,p, w,h, tx,ty, tw,th, r2; GLfloat vertex[2*OPENGL_RENDER_VBO_SIZE], col[4*OPENGL_RENDER_VBO_SIZE]; rxw = rx+rw; ryh = ry+rh; /* is offscreen? */ if ((cx+r < rx) || (cy+r < ry) || (cx-r > rxw) || (cy-r > ryh)) return; /* can be drawn normally? */ else if ((cx-r > rx) && (cy-r > ry) && (cx+r < rxw) && (cy+r < ryh)) { gl_drawCircle( cx, cy, r, c, filled ); return; } /* Case if filled. */ if (filled) { r2 = 2.*r; /* Clamp bottom left. */ x = CLAMP( rx, rxw, cx-r ); y = CLAMP( ry, ryh, cy-r ); /* Clamp width. */ w = CLAMP( rx, rxw, cx+r ) - x; h = CLAMP( ry, ryh, cy+r ) - y; /* Calculate texture bottom left. */ tx = x - (cx-r); tx *= gl_circle->srw / r2; /* Transform to unitary coordinates. */ ty = y - (cy-r); ty *= gl_circle->srh / r2; /* Calculate dimensions of texture. */ tw = w/r2 * gl_circle->srw; th = h/r2 * gl_circle->srh; /* Render. */ gl_blitTexture( gl_circle, x, y, w, h, tx, ty, tw, th, c ); return; } /* Starting parameters. */ i = 0; x = 0; y = r; p = (5. - (r*4.)) / 4.; PIXEL( cx, cy+y ); PIXEL( cx, cy-y ); PIXEL( cx+y, cy ); PIXEL( cx-y, cy ); while (x<y) { x++; if (p < 0) p += 2*(double)(x)+1; else p += 2*(double)(x-(--y))+1; if (x==0) { PIXEL( cx, cy+y ); PIXEL( cx, cy-y ); PIXEL( cx+y, cy ); PIXEL( cx-y, cy ); } else if (x==y) { PIXEL( cx+x, cy+y ); PIXEL( cx-x, cy+y ); PIXEL( cx+x, cy-y ); PIXEL( cx-x, cy-y ); } else if (x<y) { PIXEL( cx+x, cy+y ); PIXEL( cx-x, cy+y ); PIXEL( cx+x, cy-y ); PIXEL( cx-x, cy-y ); PIXEL( cx+y, cy+x ); PIXEL( cx-y, cy+x ); PIXEL( cx+y, cy-x ); PIXEL( cx-y, cy-x ); } } gl_vboSubData( gl_renderVBO, 0, i*2*sizeof(GLfloat), vertex ); gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); /* Set up the colour. */ for (j=0; j<i; j++) { col[4*j+0] = c->r; col[4*j+1] = c->g; col[4*j+2] = c->b; col[4*j+3] = c->a; } gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, i*4*sizeof(GLfloat), col ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); /* Draw. */ glDrawArrays( GL_POINTS, 0, i ); /* Clear state. */ gl_vboDeactivate(); }
static void gl_drawCircleEmpty( const double cx, const double cy, const double r, const glColour *c ) { int i, j; double x,y,p; GLfloat vertex[2*OPENGL_RENDER_VBO_SIZE], col[4*OPENGL_RENDER_VBO_SIZE]; /* Starting parameters. */ i = 0; x = 0; y = r; p = (5. - (r*4.)) / 4.; PIXEL( cx, cy+y ); PIXEL( cx, cy-y ); PIXEL( cx+y, cy ); PIXEL( cx-y, cy ); while (x<y) { x++; if (p < 0) p += 2*(double)(x)+1; else p += 2*(double)(x-(--y))+1; if (x==0) { PIXEL( cx, cy+y ); PIXEL( cx, cy-y ); PIXEL( cx+y, cy ); PIXEL( cx-y, cy ); } else if (x==y) { PIXEL( cx+x, cy+y ); PIXEL( cx-x, cy+y ); PIXEL( cx+x, cy-y ); PIXEL( cx-x, cy-y ); } else if (x<y) { PIXEL( cx+x, cy+y ); PIXEL( cx-x, cy+y ); PIXEL( cx+x, cy-y ); PIXEL( cx-x, cy-y ); PIXEL( cx+y, cy+x ); PIXEL( cx-y, cy+x ); PIXEL( cx+y, cy-x ); PIXEL( cx-y, cy-x ); } } gl_vboSubData( gl_renderVBO, 0, i*2*sizeof(GLfloat), vertex ); gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); /* Set up the colour. */ for (j=0; j<i; j++) { col[4*j+0] = c->r; col[4*j+1] = c->g; col[4*j+2] = c->b; col[4*j+3] = c->a; } gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, j*4*sizeof(GLfloat), col ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); /* Draw. */ glDrawArrays( GL_POINTS, 0, i ); /* Clear state. */ gl_vboDeactivate(); }
/** * @brief Texture blitting backend. * * @param texture Texture to blit. * @param x X position of the texture on the screen. (units pixels) * @param y Y position of the texture on the screen. (units pixels) * @param w Width on the screen. (units pixels) * @param h Height on the screen. (units pixels) * @param tx X position within the texture. [0:1] * @param ty Y position within the texture. [0:1] * @param tw Texture width. [0:1] * @param th Texture height. [0:1] * @param c Colour to use (modifies texture colour). */ void gl_blitTexture( const glTexture* texture, const double x, const double y, const double w, const double h, const double tx, const double ty, const double tw, const double th, const glColour *c ) { GLfloat vertex[4*2], tex[4*2], col[4*4]; /* Bind the texture. */ glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D, texture->texture); /* Must have colour for now. */ if (c == NULL) c = &cWhite; /* Set the vertex. */ vertex[0] = (GLfloat)x; vertex[4] = vertex[0]; vertex[2] = vertex[0] + (GLfloat)w; vertex[6] = vertex[2]; vertex[1] = (GLfloat)y; vertex[3] = vertex[1]; vertex[5] = vertex[1] + (GLfloat)h; vertex[7] = vertex[5]; gl_vboSubData( gl_renderVBO, 0, 4*2*sizeof(GLfloat), vertex ); gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); /* Set the texture. */ tex[0] = (GLfloat)tx; tex[4] = tex[0]; tex[2] = tex[0] + (GLfloat)tw; tex[6] = tex[2]; tex[1] = (GLfloat)ty; tex[3] = tex[1]; tex[5] = tex[1] + (GLfloat)th; tex[7] = tex[5]; gl_vboSubData( gl_renderVBO, gl_renderVBOtexOffset, 4*2*sizeof(GLfloat), tex ); gl_vboActivateOffset( gl_renderVBO, GL_TEXTURE_COORD_ARRAY, gl_renderVBOtexOffset, 2, GL_FLOAT, 0 ); /* Set the colour. */ col[0] = c->r; col[1] = c->g; col[2] = c->b; col[3] = c->a; col[4] = col[0]; col[5] = col[1]; col[6] = col[2]; col[7] = col[3]; col[8] = col[0]; col[9] = col[1]; col[10] = col[2]; col[11] = col[3]; col[12] = col[0]; col[13] = col[1]; col[14] = col[2]; col[15] = col[3]; gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, 4*4*sizeof(GLfloat), col ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); /* Draw. */ glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); /* Clear state. */ gl_vboDeactivate(); glDisable(GL_TEXTURE_2D); /* anything failed? */ gl_checkErr(); }
/** * @brief Renders the custom map widget. * * @param bx Base X position to render at. * @param by Base Y position to render at. * @param w Width of the widget. * @param h Height of the widget. */ static void map_render( double bx, double by, double w, double h, void *data ) { (void) data; int i,j, n,m; double x,y,r, tx,ty, fuel; StarSystem *sys, *jsys, *hsys, *lsys; glColour *col, c; GLfloat vertex[8*(2+4)]; int sw, sh; /* Parameters. */ r = round(CLAMP(5., 15., 6.*map_zoom)); x = round((bx - map_xpos + w/2) * 1.); y = round((by - map_ypos + h/2) * 1.); /* background */ gl_renderRect( bx, by, w, h, &cBlack ); /* * First pass renders everything almost (except names and markers). */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* check to make sure system is known or adjacent to known (or marked) */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED) && !space_sysReachable(sys)) continue; tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; /* draws the disk representing the faction */ if (sys_isKnown(sys) && (sys->faction != -1)) { sw = gl_faction_disk->sw; sh = gl_faction_disk->sw; col = faction_colour(sys->faction); c.r = col->r; c.g = col->g; c.b = col->b; c.a = 0.7; gl_blitTexture( gl_faction_disk, tx - sw/2, ty - sh/2, sw, sh, 0., 0., gl_faction_disk->srw, gl_faction_disk->srw, &c ); } /* Draw the system. */ if (!sys_isKnown(sys) || (sys->nfleets==0)) col = &cInert; else if (sys->security >= 1.) col = &cGreen; else if (sys->security >= 0.6) col = &cOrange; else if (sys->security >= 0.3) col = &cRed; else col = &cDarkRed; gl_drawCircleInRect( tx, ty, r, bx, by, w, h, col, 0 ); /* If system is known fill it. */ if (sys_isKnown(sys) && (sys->nplanets > 0)) { /* Planet colours */ if (!sys_isKnown(sys)) col = &cInert; else if (sys->nplanets==0) col = &cInert; else col = faction_getColour( sys->faction); /* Radius slightly shorter. */ gl_drawCircleInRect( tx, ty, 0.5*r, bx, by, w, h, col, 1 ); } if (!sys_isKnown(sys)) continue; /* we don't draw hyperspace lines */ /* draw the hyperspace paths */ glShadeModel(GL_SMOOTH); col = &cDarkBlue; /* first we draw all of the paths. */ for (j=0; j<sys->njumps; j++) { jsys = system_getIndex( sys->jumps[j] ); if (hyperspace_target != -1) hsys = system_getIndex( cur_system->jumps[hyperspace_target] ); /* Draw the lines. */ vertex[0] = x + sys->pos.x * map_zoom; vertex[1] = y + sys->pos.y * map_zoom; vertex[2] = vertex[0] + (jsys->pos.x - sys->pos.x)/2. * map_zoom; vertex[3] = vertex[1] + (jsys->pos.y - sys->pos.y)/2. * map_zoom; vertex[4] = x + jsys->pos.x * map_zoom; vertex[5] = y + jsys->pos.y * map_zoom; vertex[6] = col->r; vertex[7] = col->g; vertex[8] = col->b; vertex[9] = 0.; vertex[10] = col->r; vertex[11] = col->g; vertex[12] = col->b; vertex[13] = col->a; vertex[14] = col->r; vertex[15] = col->g; vertex[16] = col->b; vertex[17] = 0.; gl_vboSubData( map_vbo, 0, sizeof(GLfloat) * 3*(2+4), vertex ); gl_vboActivateOffset( map_vbo, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( map_vbo, GL_COLOR_ARRAY, sizeof(GLfloat) * 2*3, 4, GL_FLOAT, 0 ); glDrawArrays( GL_LINE_STRIP, 0, 3 ); gl_vboDeactivate(); } glShadeModel( GL_FLAT ); } /* Now we'll draw over the lines with the new pathways. */ if (map_path != NULL) { lsys = cur_system; glShadeModel(GL_SMOOTH); col = &cGreen; fuel = player->fuel; for (j=0; j<map_npath; j++) { jsys = map_path[j]; if (fuel == player->fuel) col = &cGreen; else if (fuel < 100.) col = &cRed; else col = &cYellow; fuel -= 100; /* Draw the lines. */ vertex[0] = x + lsys->pos.x * map_zoom; vertex[1] = y + lsys->pos.y * map_zoom; vertex[2] = vertex[0] + (jsys->pos.x - lsys->pos.x)/2. * map_zoom; vertex[3] = vertex[1] + (jsys->pos.y - lsys->pos.y)/2. * map_zoom; vertex[4] = x + jsys->pos.x * map_zoom; vertex[5] = y + jsys->pos.y * map_zoom; vertex[6] = col->r; vertex[7] = col->g; vertex[8] = col->b; vertex[9] = 0.; vertex[10] = col->r; vertex[11] = col->g; vertex[12] = col->b; vertex[13] = col->a; vertex[14] = col->r; vertex[15] = col->g; vertex[16] = col->b; vertex[17] = 0.; gl_vboSubData( map_vbo, 0, sizeof(GLfloat) * 3*(2+4), vertex ); gl_vboActivateOffset( map_vbo, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( map_vbo, GL_COLOR_ARRAY, sizeof(GLfloat) * 2*3, 4, GL_FLOAT, 0 ); glDrawArrays( GL_LINE_STRIP, 0, 3 ); gl_vboDeactivate(); lsys = jsys; } glShadeModel( GL_FLAT ); } /* * Second pass - System names */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* Skip system. */ if (!sys_isKnown(sys) || (map_zoom <= 0.5 )) continue; tx = x + (sys->pos.x+11.) * map_zoom; ty = y + (sys->pos.y-5.) * map_zoom; gl_print( &gl_smallFont, tx + SCREEN_W/2., ty + SCREEN_H/2., &cWhite, sys->name ); } /* * Third pass - system markers */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* We only care about marked now. */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) continue; /* Get the position. */ tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; /* Count markers. */ n = (sys_isFlag(sys, SYSTEM_CMARKED)) ? 1 : 0; n += sys->markers_misc; n += sys->markers_cargo; n += sys->markers_rush; /* Draw the markers. */ j = 0; if (sys_isFlag(sys, SYSTEM_CMARKED)) { map_drawMarker( tx, ty, r, n, j, 0 ); j++; } for (m=0; m<sys->markers_misc; m++) { map_drawMarker( tx, ty, r, n, j, 1 ); j++; } for (m=0; m<sys->markers_rush; m++) { map_drawMarker( tx, ty, r, n, j, 2 ); j++; } for (m=0; m<sys->markers_cargo; m++) { map_drawMarker( tx, ty, r, n, j, 3 ); j++; } } /* Selected planet. */ if (map_selected != -1) { sys = system_getIndex( map_selected ); gl_drawCircleInRect( x + sys->pos.x * map_zoom, y + sys->pos.y * map_zoom, 1.5*r, bx, by, w, h, &cRed, 0 ); } /* Current planet. */ gl_drawCircleInRect( x + cur_system->pos.x * map_zoom, y + cur_system->pos.y * map_zoom, 1.5*r, bx, by, w, h, &cRadar_tPlanet, 0 ); }
/** * @brief Draws the minimap weapons (used in player.c). * * @param res Minimap resolution. * @param w Width of minimap. * @param h Height of minimap. * @param shape Shape of the minimap. * @param alpha Alpha to draw points at. */ void weapon_minimap( const double res, const double w, const double h, const RadarShape shape, double alpha ) { int i, rc, p; double x, y; Weapon *wp; glColour *c; GLsizei offset; /* Get offset. */ p = 0; offset = weapon_vboSize; if (shape==RADAR_CIRCLE) rc = (int)(w*w); /* Draw the points for weapons on all layers. */ for (i=0; i<nwbackLayer; i++) { wp = wbackLayer[i]; /* Make sure is in range. */ if (!pilot_inRange( player, wp->solid->pos.x, wp->solid->pos.y )) continue; /* Get radar position. */ x = (wp->solid->pos.x - player->solid->pos.x) / res; y = (wp->solid->pos.y - player->solid->pos.y) / res; /* Make sure in range. */ if (shape==RADAR_RECT && (ABS(x)>w/2. || ABS(y)>h/2.)) continue; if (shape==RADAR_CIRCLE && (((x)*(x)+(y)*(y)) > rc)) continue; /* Choose colour based on if it'll hit player. */ if (outfit_isSeeker(wp->outfit) && (wp->target != PLAYER_ID)) c = &cNeutral; else if ((wp->target == PLAYER_ID) || !areAllies(FACTION_PLAYER, wp->faction)) c = &cHostile; else c = &cNeutral; /* Set the colour. */ weapon_vboData[ offset + 4*p + 0 ] = c->r; weapon_vboData[ offset + 4*p + 1 ] = c->g; weapon_vboData[ offset + 4*p + 2 ] = c->b; weapon_vboData[ offset + 4*p + 3 ] = alpha; /* Put the pixel. */ weapon_vboData[ 2*p + 0 ] = x; weapon_vboData[ 2*p + 1 ] = y; /* "Add" pixel. */ p++; } for (i=0; i<nwfrontLayer; i++) { wp = wfrontLayer[i]; /* Make sure is in range. */ if (!pilot_inRange( player, wp->solid->pos.x, wp->solid->pos.y )) continue; /* Get radar position. */ x = (wp->solid->pos.x - player->solid->pos.x) / res; y = (wp->solid->pos.y - player->solid->pos.y) / res; /* Make sure in range. */ if (shape==RADAR_RECT && (ABS(x)>w/2. || ABS(y)>h/2.)) continue; if (shape==RADAR_CIRCLE && (((x)*(x)+(y)*(y)) > rc)) continue; /* Choose colour based on if it'll hit player. */ if (outfit_isSeeker(wp->outfit) && (wp->target != PLAYER_ID)) c = &cNeutral; else if ((wp->target == PLAYER_ID) || !areAllies(FACTION_PLAYER, wp->faction)) c = &cHostile; else c = &cNeutral; /* Set the colour. */ weapon_vboData[ offset + 4*p + 0 ] = c->r; weapon_vboData[ offset + 4*p + 1 ] = c->g; weapon_vboData[ offset + 4*p + 2 ] = c->b; weapon_vboData[ offset + 4*p + 3 ] = alpha; /* Put the pixel. */ weapon_vboData[ 2*p + 0 ] = x; weapon_vboData[ 2*p + 1 ] = y; /* "Add" pixel. */ p++; } /* Only render with something to draw. */ if (p > 0) { /* Upload data changes. */ gl_vboSubData( weapon_vbo, 0, sizeof(GLfloat) * 2*p, weapon_vboData ); gl_vboSubData( weapon_vbo, offset * sizeof(GLfloat), sizeof(GLfloat) * 4*p, &weapon_vboData[offset] ); /* Activate VBO. */ gl_vboActivateOffset( weapon_vbo, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( weapon_vbo, GL_COLOR_ARRAY, offset * sizeof(GLfloat), 4, GL_FLOAT, 0 ); /* Render VBO. */ glDrawArrays( GL_POINTS, 0, p ); /* Disable VBO. */ gl_vboDeactivate(); } }
/** * @brief Draws a circle in a rectangle. * * @param cx X position of the center in screen coordinates.. * @param cy Y position of the center in screen coordinates. * @param r Radius of the circle. * @param rx X position of the rectangle limiting the circle in screen coords. * @param ry Y position of the rectangle limiting the circle in screen coords. * @param rw Width of the limiting rectangle. * @param rh Height of the limiting rectangle. * @param c Colour to use. */ void gl_drawCircleInRect( const double cx, const double cy, const double r, const double rx, const double ry, const double rw, const double rh, const glColour *c, int filled ) { int i, j; double rxw,ryh, x,y,p, w,h; GLfloat vertex[2*OPENGL_RENDER_VBO_SIZE], col[4*OPENGL_RENDER_VBO_SIZE]; rxw = rx+rw; ryh = ry+rh; /* is offscreen? */ if ((cx+r < rx) || (cy+r < ry) || (cx-r > rxw) || (cy-r > ryh)) return; /* can be drawn normally? */ else if ((cx-r > rx) && (cy-r > ry) && (cx+r < rxw) && (cy+r < ryh)) { gl_drawCircle( cx, cy, r, c, filled ); return; } /* Case if filled. */ if (filled) { x = CLAMP( rx, rxw, cx-r ); y = CLAMP( ry, ryh, cy-r ); w = CLAMP( 0., rxw-x, 2.*r ); h = CLAMP( 0., ryh-y, 2.*r ); gl_blitTexture( gl_circle, x, y, w, h, (x-(cx-r))/(2.*r) * gl_circle->srw, (y-(cy-r))/(2.*r) * gl_circle->srh, (w/(2.*r)) * gl_circle->srw, (h/(2.*r)) * gl_circle->srh, c ); return; } /* Starting parameters. */ i = 0; x = 0; y = r; p = (5. - (r*4.)) / 4.; PIXEL( cx, cy+y ); PIXEL( cx, cy-y ); PIXEL( cx+y, cy ); PIXEL( cx-y, cy ); while (x<y) { x++; if (p < 0) p += 2*(double)(x)+1; else p += 2*(double)(x-(--y))+1; if (x==0) { PIXEL( cx, cy+y ); PIXEL( cx, cy-y ); PIXEL( cx+y, cy ); PIXEL( cx-y, cy ); } else if (x==y) { PIXEL( cx+x, cy+y ); PIXEL( cx-x, cy+y ); PIXEL( cx+x, cy-y ); PIXEL( cx-x, cy-y ); } else if (x<y) { PIXEL( cx+x, cy+y ); PIXEL( cx-x, cy+y ); PIXEL( cx+x, cy-y ); PIXEL( cx-x, cy-y ); PIXEL( cx+y, cy+x ); PIXEL( cx-y, cy+x ); PIXEL( cx+y, cy-x ); PIXEL( cx-y, cy-x ); } } gl_vboSubData( gl_renderVBO, 0, i*2*sizeof(GLfloat), vertex ); gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); /* Set up the colour. */ for (j=0; j<i; j++) { col[4*j+0] = c->r; col[4*j+1] = c->g; col[4*j+2] = c->b; col[4*j+3] = c->a; } gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, i*4*sizeof(GLfloat), col ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); /* Draw. */ glDrawArrays( GL_POINTS, 0, i ); /* Clear state. */ gl_vboDeactivate(); }
/** * @brief Renders the nebula using the multitexture approach. * * @param dt Current delta tick. */ static void nebu_renderMultitexture( const double dt ) { GLfloat col[4]; int temp; double sx, sy; /* calculate frame to draw */ nebu_timer -= dt; if (nebu_timer < 0.) { /* Time to change. */ temp = cur_nebu[0] - cur_nebu[1]; cur_nebu[1] = cur_nebu[0]; cur_nebu[0] += temp; if (cur_nebu[0] >= NEBULA_Z) cur_nebu[0] = cur_nebu[1] - 1; else if (cur_nebu[0] < 0) cur_nebu[0] = cur_nebu[1] + 1; /* Change timer. */ nebu_timer += nebu_dt; /* Case it hasn't rendered in a while so it doesn't go crazy. */ if (nebu_timer < 0) nebu_timer = nebu_dt; } /* Set the colour */ col[0] = cBlue.r; col[1] = cBlue.g; col[2] = cBlue.b; col[3] = (nebu_dt - nebu_timer) / nebu_dt; /* Set up the targets */ /* Texture 0 */ nglActiveTexture( GL_TEXTURE0 ); glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D, nebu_textures[cur_nebu[1]]); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); /* Texture 1 */ nglActiveTexture( GL_TEXTURE1 ); glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D, nebu_textures[cur_nebu[0]]); /* Prepare it */ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE ); glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE ); /* Colour */ glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col ); /* Arguments */ /* Arg0 */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR ); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA ); /* Arg1 */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA ); /* Arg2 */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA ); /* Compensate possible rumble */ spfx_getShake( &sx, &sy ); gl_matrixPush(); gl_matrixTranslate( -sx, -sy ); /* Now render! */ gl_vboActivateOffset( nebu_vboBG, GL_VERTEX_ARRAY, sizeof(GL_FLOAT) * 0*2*4, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( nebu_vboBG, GL_TEXTURE0, sizeof(GL_FLOAT) * 1*2*4, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( nebu_vboBG, GL_TEXTURE1, sizeof(GL_FLOAT) * 2*2*4, 2, GL_FLOAT, 0 ); glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); gl_vboDeactivate(); gl_matrixPop(); /* Set values to defaults */ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glDisable(GL_TEXTURE_2D); nglActiveTexture( GL_TEXTURE0 ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glDisable(GL_TEXTURE_2D); /* Anything failed? */ gl_checkErr(); }
/** * @brief Texture blitting backend for interpolated texture. * * Value blitted is ta*inter + tb*(1.-inter). * * @param ta Texture A to blit. * @param tb Texture B to blit. * @param inter Amount of interpolation to do. * @param x X position of the texture on the screen. * @param y Y position of the texture on the screen. * @param tx X position within the texture. * @param ty Y position within the texture. * @param tw Texture width. * @param th Texture height. * @param c Colour to use (modifies texture colour). */ static void gl_blitTextureInterpolate( const glTexture* ta, const glTexture* tb, const double inter, const double x, const double y, const double w, const double h, const double tx, const double ty, const double tw, const double th, const glColour *c ) { GLfloat vertex[4*2], tex[4*2], col[4*4]; GLfloat mcol[4] = { 0., 0., 0. }; /* No interpolation. */ if (!conf.interpolate || (tb == NULL)) { gl_blitTexture( ta, x, y, w, h, tx, ty, tw, th, c ); return; } /* Corner cases. */ if (inter == 1.) { gl_blitTexture( ta, x, y, w, h, tx, ty, tw, th, c ); return; } else if (inter == 0.) { gl_blitTexture( tb, x, y, w, h, tx, ty, tw, th, c ); return; } /* No multitexture. */ if (nglActiveTexture == NULL) { if (inter > 0.5) gl_blitTexture( ta, x, y, w, h, tx, ty, tw, th, c ); else gl_blitTexture( tb, x, y, w, h, tx, ty, tw, th, c ); } /* Set default colour. */ if (c == NULL) c = &cWhite; /* Bind the textures. */ /* Texture 0. */ nglActiveTexture( GL_TEXTURE0 ); glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D, ta->texture); /* Set the mode. */ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); /* Interpolate texture and alpha. */ glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE ); glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE ); mcol[3] = inter; glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, mcol ); /* Arguments. */ /* Arg0. */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0 ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR ); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0 ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA ); /* Arg1. */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1 ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR ); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE1 ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA ); /* Arg2. */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA ); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA ); /* Texture 1. */ nglActiveTexture( GL_TEXTURE1 ); glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D, tb->texture); /* Set the mode. */ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); /* Interpolate texture and alpha. */ glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE ); glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE ); /* Arguments. */ /* Arg0. */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR ); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA ); /* Arg1. */ glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR ); glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR ); glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA ); /* Set the colour. */ col[0] = c->r; col[1] = c->g; col[2] = c->b; col[3] = c->a; col[4] = col[0]; col[5] = col[1]; col[6] = col[2]; col[7] = col[3]; col[8] = col[0]; col[9] = col[1]; col[10] = col[2]; col[11] = col[3]; col[12] = col[0]; col[13] = col[1]; col[14] = col[2]; col[15] = col[3]; gl_vboSubData( gl_renderVBO, gl_renderVBOcolOffset, 4*4*sizeof(GLfloat), col ); gl_vboActivateOffset( gl_renderVBO, GL_COLOR_ARRAY, gl_renderVBOcolOffset, 4, GL_FLOAT, 0 ); /* Set the vertex. */ vertex[0] = (GLfloat)x; vertex[4] = vertex[0]; vertex[2] = vertex[0] + (GLfloat)w; vertex[6] = vertex[2]; vertex[1] = (GLfloat)y; vertex[3] = vertex[1]; vertex[5] = vertex[1] + (GLfloat)h; vertex[7] = vertex[5]; gl_vboSubData( gl_renderVBO, 0, 4*2*sizeof(GLfloat), vertex ); gl_vboActivateOffset( gl_renderVBO, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); /* Set the texture. */ tex[0] = (GLfloat)tx; tex[4] = tex[0]; tex[2] = tex[0] + (GLfloat)tw; tex[6] = tex[2]; tex[1] = (GLfloat)ty; tex[3] = tex[1]; tex[5] = tex[1] + (GLfloat)th; tex[7] = tex[5]; gl_vboSubData( gl_renderVBO, gl_renderVBOtexOffset, 4*2*sizeof(GLfloat), tex ); gl_vboActivateOffset( gl_renderVBO, GL_TEXTURE0, gl_renderVBOtexOffset, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( gl_renderVBO, GL_TEXTURE1, gl_renderVBOtexOffset, 2, GL_FLOAT, 0 ); /* Draw. */ glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); /* Clear state. */ gl_vboDeactivate(); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glDisable(GL_TEXTURE_2D); nglActiveTexture( GL_TEXTURE0 ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glDisable(GL_TEXTURE_2D); /* anything failed? */ gl_checkErr(); }
/** * @brief Renders the nebula overlay (hides what player can't see). * * @param dt Current delta tick. */ void nebu_renderOverlay( const double dt ) { (void) dt; double gx, gy; double ox, oy; double z; double sx, sy; /* Get GUI offsets. */ gui_getOffset( &gx, &gy ); /* Get zoom. */ z = cam_getZoom(); /* * Renders the puffs */ nebu_renderPuffs( 0 ); /* Prepare the matrix */ ox = gx; oy = gy; spfx_getShake( &sx, &sy ); ox += sx; oy += sy; gl_matrixPush(); gl_matrixTranslate( SCREEN_W/2.+ox, SCREEN_H/2.+oy ); gl_matrixScale( z, z ); /* * Mask for area player can still see (partially) */ glShadeModel(GL_SMOOTH); gl_vboActivateOffset( nebu_vboOverlay, GL_VERTEX_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( nebu_vboOverlay, GL_COLOR_ARRAY, sizeof(GLfloat)*2*18, 4, GL_FLOAT, 0 ); glDrawArrays( GL_TRIANGLE_FAN, 0, 18 ); /* * Solid nebula for areas the player can't see */ glShadeModel(GL_FLAT); /* Colour is shared. */ gl_vboActivateOffset( nebu_vboOverlay, GL_COLOR_ARRAY, sizeof(GLfloat)*((2+4)*18 + 2*28), 4, GL_FLOAT, 0 ); /* Top left. */ gl_vboActivateOffset( nebu_vboOverlay, GL_VERTEX_ARRAY, sizeof(GLfloat)*((2+4)*18 + 0*2*7), 2, GL_FLOAT, 0 ); glDrawArrays( GL_TRIANGLE_FAN, 0, 7 ); /* Top right. */ gl_vboActivateOffset( nebu_vboOverlay, GL_VERTEX_ARRAY, sizeof(GLfloat)*((2+4)*18 + 1*2*7), 2, GL_FLOAT, 0 ); glDrawArrays( GL_TRIANGLE_FAN, 0, 7 ); /* Bottom right. */ gl_vboActivateOffset( nebu_vboOverlay, GL_VERTEX_ARRAY, sizeof(GLfloat)*((2+4)*18 + 2*2*7), 2, GL_FLOAT, 0 ); glDrawArrays( GL_TRIANGLE_FAN, 0, 7 ); /* Bottom left. */ gl_vboActivateOffset( nebu_vboOverlay, GL_VERTEX_ARRAY, sizeof(GLfloat)*((2+4)*18 + 3*2*7), 2, GL_FLOAT, 0 ); glDrawArrays( GL_TRIANGLE_FAN, 0, 7 ); gl_vboDeactivate(); gl_matrixPop(); /* Reset puff movement. */ puff_x = 0.; puff_y = 0.; gl_checkErr(); }
/** * @brief Adds a font glyph to the texture stash. */ static int gl_fontAddGlyphTex( glFontStash *stsh, font_char_t *ch, glFontGlyph *glyph ) { int i, j, n; GLubyte *data; glFontRow *r, *gr; glFontTex *tex; GLfloat *vbo_tex; GLshort *vbo_vert; GLfloat tx, ty, txw, tyh; GLfloat fw, fh; GLshort vx, vy, vw, vh; /* Find free row. */ gr = NULL; for (i=0; i<array_size( stsh->tex ); i++) { for (j=0; j<MAX_ROWS; j++) { r = &stsh->tex->rows[j]; /* Fits in current row, so use that. */ if ((r->h == ch->h) && (r->x+ch->w < stsh->tw)) { tex = &stsh->tex[i]; gr = r; break; } /* If not empty row, skip. */ if (r->h != 0) continue; /* See if height fits. */ if ((j==0) || (stsh->tex->rows[j-1].y+stsh->tex->rows[j-1].h+ch->h < stsh->th)) { r->h = ch->h; if (j>0) r->y = stsh->tex->rows[j-1].y + stsh->tex->rows[j-1].h; tex = &stsh->tex[i]; gr = r; break; } } } /* Allocate new texture. */ if (gr == NULL) { tex = &array_grow( &stsh->tex ); memset( stsh->tex, 0, sizeof(glFontTex) ); glGenTextures( 1, &tex->id ); glBindTexture( GL_TEXTURE_2D, tex->id ); /* Shouldn't ever scale - we'll generate appropriate size font. */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); /* Clamp texture .*/ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); /* Initialize size. */ data = calloc( 2*stsh->tw*stsh->th, sizeof(GLubyte) ); glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, stsh->tw, stsh->th, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data ); free(data); /* Check for errors. */ gl_checkErr(); gr = &tex->rows[0]; gr->h = ch->h; } /* Upload data. */ glBindTexture( GL_TEXTURE_2D, tex->id ); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexSubImage2D( GL_TEXTURE_2D, 0, gr->x, gr->y, ch->w, ch->h, GL_ALPHA, GL_UNSIGNED_BYTE, ch->data ); /* Check for error. */ gl_checkErr(); /* Update VBOs. */ stsh->nvbo++; if (stsh->nvbo > stsh->mvbo) { stsh->mvbo *= 2; stsh->vbo_tex_data = realloc( stsh->vbo_tex_data, 8*stsh->mvbo*sizeof(GLfloat) ); stsh->vbo_vert_data = realloc( stsh->vbo_vert_data, 8*stsh->mvbo*sizeof(GLshort) ); } n = 8*stsh->nvbo; vbo_tex = &stsh->vbo_tex_data[n-8]; vbo_vert = &stsh->vbo_vert_data[n-8]; /* We do something like the following for vertex coordinates. * * * +----------------- top reference \ <------- font->h * | | * | | --- off_y * +----------------- glyph top / * | * | * +----------------- glyph bottom * | * v y * * * +----+-------------> x * | | * | glyph start * | * side reference * * \----/ * off_x */ /* Temporary variables. */ fw = (GLfloat) stsh->tw; fh = (GLfloat) stsh->th; tx = (GLfloat) gr->x / fw; ty = (GLfloat) gr->y / fh; txw = (GLfloat) (gr->x + ch->w) / fw; tyh = (GLfloat) (gr->y + ch->h) / fh; vx = ch->off_x; vy = ch->off_y - ch->h; vw = ch->w; vh = ch->h; /* Texture coords. */ vbo_tex[ 0 ] = tx; /* Top left. */ vbo_tex[ 1 ] = ty; vbo_tex[ 2 ] = txw; /* Top right. */ vbo_tex[ 3 ] = ty; vbo_tex[ 4 ] = txw; /* Bottom right. */ vbo_tex[ 5 ] = tyh; vbo_tex[ 6 ] = tx; /* Bottom left. */ vbo_tex[ 7 ] = tyh; /* Vertex coords. */ vbo_vert[ 0 ] = vx; /* Top left. */ vbo_vert[ 1 ] = vy+vh; vbo_vert[ 2 ] = vx+vw; /* Top right. */ vbo_vert[ 3 ] = vy+vh; vbo_vert[ 4 ] = vx+vw; /* Bottom right. */ vbo_vert[ 5 ] = vy; vbo_vert[ 6 ] = vx; /* Bottom left. */ vbo_vert[ 7 ] = vy; /* Update vbos. */ gl_vboData( stsh->vbo_tex, sizeof(GLfloat)*n, stsh->vbo_tex_data ); gl_vboData( stsh->vbo_vert, sizeof(GLshort)*n, stsh->vbo_vert_data ); /* Add space for the new character. */ gr->x += ch->w; /* Save glyph data. */ glyph->vbo_id = (n-8)/2; glyph->tex = tex; /* Since the VBOs have possibly changed, we have to reset the data. */ gl_vboActivateOffset( stsh->vbo_tex, GL_TEXTURE_COORD_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( stsh->vbo_vert, GL_VERTEX_ARRAY, 0, 2, GL_SHORT, 0 ); return 0; }