//========================================================================== // // // //========================================================================== void FGLRenderer::FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin) { float fU1,fU2,fV1,fV2; FMaterial *gltexture=FMaterial::ValidateTexture(src, false); if (!gltexture) return; gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); // scaling is not used here. if (!local_origin) { fU1 = float(left) / src->GetWidth(); fV1 = float(top) / src->GetHeight(); fU2 = float(right) / src->GetWidth(); fV2 = float(bottom) / src->GetHeight(); } else { fU1 = 0; fV1 = 0; fU2 = float(right-left) / src->GetWidth(); fV2 = float(bottom-top) / src->GetHeight(); } gl_RenderState.ResetColor(); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(left, top, 0, fU1, fV1); ptr++; ptr->Set(left, bottom, 0, fU1, fV2); ptr++; ptr->Set(right, top, 0, fU2, fV1); ptr++; ptr->Set(right, bottom, 0, fU2, fV2); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); }
bool OpenGLFrameBuffer::Wiper_Crossfade::Run(int ticks, OpenGLFrameBuffer *fb) { Clock += ticks; float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth()); float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight()); gl_RenderState.SetTextureMode(TM_OPAQUE); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.ResetColor(); gl_RenderState.Apply(); fb->wipestartscreen->Bind(0, 0, false); FFlatVertex *ptr; unsigned int offset, count; ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(0, 0, 0, 0, vb); ptr++; ptr->Set(0, fb->Height, 0, 0, 0); ptr++; ptr->Set(fb->Width, 0, 0, ur, vb); ptr++; ptr->Set(fb->Width, fb->Height, 0, ur, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP, &offset, &count); fb->wipeendscreen->Bind(0, 0, false); gl_RenderState.SetColorAlpha(0xffffff, clamp(Clock/32.f, 0.f, 1.f)); gl_RenderState.Apply(); GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, offset, count); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f); gl_RenderState.SetTextureMode(TM_MODULATE); return Clock >= 32; }
void FDrawInfo::ClearFloodStencil(wallseg * ws) { int recursion = GLPortal::GetRecursion(); glStencilOp(GL_KEEP,GL_KEEP,GL_DECR); gl_RenderState.EnableTexture(false); glColorMask(0,0,0,0); // don't write to the graphics buffer gl_RenderState.ResetColor(); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0); ptr++; ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0); ptr++; ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0); ptr++; ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); // restore old stencil op. glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); glStencilFunc(GL_EQUAL,recursion,~0); gl_RenderState.EnableTexture(true); glColorMask(1,1,1,1); glEnable(GL_DEPTH_TEST); glDepthMask(true); }
void FDrawInfo::SetupFloodStencil(wallseg * ws) { int recursion = GLPortal::GetRecursion(); // Create stencil glStencilFunc(GL_EQUAL,recursion,~0); // create stencil glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); // increment stencil of valid pixels glColorMask(0,0,0,0); // don't write to the graphics buffer gl_RenderState.EnableTexture(false); gl_RenderState.ResetColor(); glEnable(GL_DEPTH_TEST); glDepthMask(true); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(ws->x1, ws->z1, ws->y1, 0, 0); ptr++; ptr->Set(ws->x1, ws->z2, ws->y1, 0, 0); ptr++; ptr->Set(ws->x2, ws->z2, ws->y2, 0, 0); ptr++; ptr->Set(ws->x2, ws->z1, ws->y2, 0, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); glStencilFunc(GL_EQUAL,recursion+1,~0); // draw sky into stencil glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); // this stage doesn't modify the stencil glColorMask(1,1,1,1); // don't write to the graphics buffer gl_RenderState.EnableTexture(true); glDisable(GL_DEPTH_TEST); glDepthMask(false); }
void FGLRenderer::ClearBorders() { OpenGLFrameBuffer *glscreen = static_cast<OpenGLFrameBuffer*>(screen); // Letterbox time! Draw black top and bottom borders. int width = glscreen->GetWidth(); int height = glscreen->GetHeight(); int trueHeight = glscreen->GetTrueHeight(); int borderHeight = (trueHeight - height) / 2; glViewport(0, 0, width, trueHeight); gl_RenderState.mProjectionMatrix.loadIdentity(); gl_RenderState.mProjectionMatrix.ortho(0.0f, width * 1.0f, 0.0f, trueHeight, -1.0f, 1.0f); gl_RenderState.SetColor(0.f ,0.f ,0.f ,1.f); gl_RenderState.Set2DMode(true); gl_RenderState.EnableTexture(false); gl_RenderState.Apply(); gl_RenderState.ApplyMatrices(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(0, borderHeight, 0, 0, 0); ptr++; ptr->Set(0, 0, 0, 0, 0); ptr++; ptr->Set(width, 0, 0, 0, 0); ptr++; ptr->Set(width, borderHeight, 0, 0, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); ptr->Set(0, trueHeight, 0, 0, 0); ptr++; ptr->Set(0, trueHeight - borderHeight, 0, 0, 0); ptr++; ptr->Set(width, trueHeight - borderHeight, 0, 0, 0); ptr++; ptr->Set(width, trueHeight, 0, 0, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); gl_RenderState.EnableTexture(true); glViewport(0, (trueHeight - height) / 2, width, height); }
void GLWall::RenderWall(int textured, unsigned int *store) { static texcoord tcs[4]; // making this variable static saves us a relatively costly stack integrity check. bool split = (gl_seamless && !(textured&RWF_NOSPLIT) && seg->sidedef != NULL && !(seg->sidedef->Flags & WALLF_POLYOBJ) && !(flags & GLWF_NOSPLIT)); tcs[0]=lolft; tcs[1]=uplft; tcs[2]=uprgt; tcs[3]=lorgt; if ((flags&GLWF_GLOW) && (textured & RWF_GLOW)) { gl_RenderState.SetGlowPlanes(topplane, bottomplane); gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); } if (!(textured & RWF_NORENDER)) { gl_RenderState.Apply(); gl_RenderState.ApplyLightIndex(dynlightindex); } // the rest of the code is identical for textured rendering and lights FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); unsigned int count, offset; ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[0].u, tcs[0].v); ptr++; if (split && glseg.fracleft == 0) SplitLeftEdge(tcs, ptr); ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[1].u, tcs[1].v); ptr++; if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs, ptr); ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[2].u, tcs[2].v); ptr++; if (split && glseg.fracright == 1) SplitRightEdge(tcs, ptr); ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[3].u, tcs[3].v); ptr++; if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs, ptr); count = GLRenderer->mVBO->GetCount(ptr, &offset); if (!(textured & RWF_NORENDER)) { GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, offset, count); vertexcount += count; } if (store != NULL) { store[0] = offset; store[1] = count; } }
void FGLRenderer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) { gl_RenderState.EnableTexture(false); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.AlphaFunc(GL_GREATER,0); gl_RenderState.SetColorAlpha(color, damount); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(x1, y1, 0, 0, 0); ptr++; ptr->Set(x1, y1+h, 0, 0, 0); ptr++; ptr->Set(x1+w, y1+h, 0, 0, 0); ptr++; ptr->Set(x1+w, y1, 0, 0, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); gl_RenderState.EnableTexture(true); }
//========================================================================== // // // //========================================================================== void FGLRenderer::DrawPixel(int x1, int y1, int palcolor, uint32 color) { PalEntry p = color? (PalEntry)color : GPalette.BaseColors[palcolor]; gl_RenderState.EnableTexture(false); gl_RenderState.SetColorAlpha(p, 1.f); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(x1, y1, 0, 0, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_POINTS); gl_RenderState.EnableTexture(true); }
void GLWall::MakeVertices(bool nosplit) { if (vertcount == 0) { bool split = (gl_seamless && !nosplit && seg->sidedef != NULL && !(seg->sidedef->Flags & WALLF_POLYOBJ) && !(flags & GLWF_NOSPLIT)); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v); ptr++; if (split && glseg.fracleft == 0) SplitLeftEdge(ptr); ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v); ptr++; if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(ptr); ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v); ptr++; if (split && glseg.fracright == 1) SplitRightEdge(ptr); ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v); ptr++; if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(ptr); vertcount = GLRenderer->mVBO->GetCount(ptr, &vertindex); } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // // Horizon Portal // // This simply draws the area in medium sized squares. Drawing it as a whole // polygon creates visible inaccuracies. // // Originally I tried to minimize the amount of data to be drawn but there // are 2 problems with it: // // 1. Setting this up completely negates any performance gains. // 2. It doesn't work with a 360° field of view (as when you are looking up.) // // // So the brute force mechanism is just as good. // // //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // GLHorizonPortal::DrawContents // //----------------------------------------------------------------------------- void GLHorizonPortal::DrawContents() { PortalAll.Clock(); GLSectorPlane * sp=&origin->plane; FMaterial * gltexture; PalEntry color; float z; player_t * player=&players[consoleplayer]; gltexture=FMaterial::ValidateTexture(sp->texture, false, true); if (!gltexture) { ClearScreen(); PortalAll.Unclock(); return; } gl_RenderState.SetCameraPos(ViewPos.X, ViewPos.Y, ViewPos.Z); z=sp->Texheight; if (gltexture && gltexture->tex->isFullbright()) { // glowing textures are always drawn full bright without color gl_SetColor(255, 0, origin->colormap, 1.f); gl_SetFog(255, 0, &origin->colormap, false); } else { int rel = getExtraLight(); gl_SetColor(origin->lightlevel, rel, origin->colormap, 1.0f); gl_SetFog(origin->lightlevel, rel, &origin->colormap, false); } gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_SetPlaneTextureRotation(sp, gltexture); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.BlendFunc(GL_ONE,GL_ZERO); gl_RenderState.Apply(); float vx= ViewPos.X; float vy= ViewPos.Y; // Draw to some far away boundary // This is not drawn as larher strips because it causes visual glitches. for(float x=-32768+vx; x<32768+vx; x+=4096) { for(float y=-32768+vy; y<32768+vy;y+=4096) { FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(x, z, y, x / 64, -y / 64); ptr++; ptr->Set(x + 4096, z, y, x / 64 + 64, -y / 64); ptr++; ptr->Set(x, z, y + 4096, x / 64, -y / 64 - 64); ptr++; ptr->Set(x + 4096, z, y + 4096, x / 64 + 64, -y / 64 - 64); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); } } float vz= ViewPos.Z; float tz=(z-vz);///64.0f; // fill the gap between the polygon and the true horizon // Since I can't draw into infinity there can always be a // small gap FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0); ptr++; ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz); ptr++; ptr->Set(-32768 + vx, z, 32768 + vy, -512.f, 0); ptr++; ptr->Set(-32768 + vx, vz, 32768 + vy, -512.f, tz); ptr++; ptr->Set(32768 + vx, z, 32768 + vy, 512.f, 0); ptr++; ptr->Set(32768 + vx, vz, 32768 + vy, 512.f, tz); ptr++; ptr->Set(32768 + vx, z, -32768 + vy, -512.f, 0); ptr++; ptr->Set(32768 + vx, vz, -32768 + vy, -512.f, tz); ptr++; ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0); ptr++; ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); gl_RenderState.EnableTextureMatrix(false); PortalAll.Unclock(); }
//========================================================================== // // Draw the plane segment into the gap // //========================================================================== void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling) { GLSectorPlane plane; int lightlevel; FColormap Colormap; FMaterial * gltexture; plane.GetFromSector(sec, ceiling); gltexture=FMaterial::ValidateTexture(plane.texture, true); if (!gltexture) return; if (gl_fixedcolormap) { Colormap.Clear(); lightlevel=255; } else { Colormap=sec->ColorMap; if (gltexture->tex->isFullbright()) { Colormap.LightColor.r = Colormap.LightColor.g = Colormap.LightColor.b = 0xff; lightlevel=255; } else lightlevel=abs(ceiling? sec->GetCeilingLight() : sec->GetFloorLight()); } int rel = getExtraLight(); gl_SetColor(lightlevel, rel, Colormap, 1.0f); gl_SetFog(lightlevel, rel, &Colormap, false); gltexture->Bind(); float fviewx = FIXED2FLOAT(viewx); float fviewy = FIXED2FLOAT(viewy); float fviewz = FIXED2FLOAT(viewz); gl_SetPlaneTextureRotation(&plane, gltexture); gl_RenderState.Apply(); float prj_fac1 = (planez-fviewz)/(ws->z1-fviewz); float prj_fac2 = (planez-fviewz)/(ws->z2-fviewz); float px1 = fviewx + prj_fac1 * (ws->x1-fviewx); float py1 = fviewy + prj_fac1 * (ws->y1-fviewy); float px2 = fviewx + prj_fac2 * (ws->x1-fviewx); float py2 = fviewy + prj_fac2 * (ws->y1-fviewy); float px3 = fviewx + prj_fac2 * (ws->x2-fviewx); float py3 = fviewy + prj_fac2 * (ws->y2-fviewy); float px4 = fviewx + prj_fac1 * (ws->x2-fviewx); float py4 = fviewy + prj_fac1 * (ws->y2-fviewy); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(px1, planez, py1, px1 / 64, -py1 / 64); ptr++; ptr->Set(px2, planez, py2, px2 / 64, -py2 / 64); ptr++; ptr->Set(px3, planez, py3, px3 / 64, -py3 / 64); ptr++; ptr->Set(px4, planez, py4, px4 / 64, -py4 / 64); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); gl_RenderState.EnableTextureMatrix(false); }
void GLWall::RenderWall(int textured) { gl_RenderState.Apply(); gl_RenderState.ApplyLightIndex(dynlightindex); #ifdef NO_VBO bool nosplit = !!(textured&RWF_NOSPLIT); bool split = (gl_seamless && !nosplit && seg->sidedef != NULL && !(seg->sidedef->Flags & WALLF_POLYOBJ) && !(flags & GLWF_NOSPLIT)); #if 1 // A bit quicker due to batching, still not very fast.. glBegin(GL_TRIANGLE_FAN); // lower left corner if (textured&1) glTexCoord2f(tcs[0].u,tcs[0].v); glVertex3f(glseg.x1,zbottom[0],glseg.y1); //if (split && glseg.fracleft==0) SplitLeftEdge(tcs); // upper left corner if (textured&1) glTexCoord2f(tcs[1].u,tcs[1].v); glVertex3f(glseg.x1,ztop[0],glseg.y1); //if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs); // color for right side //if (color2) glColor4fv(color2); // upper right corner if (textured&1) glTexCoord2f(tcs[2].u,tcs[2].v); glVertex3f(glseg.x2,ztop[1],glseg.y2); //if (split && glseg.fracright==1) SplitRightEdge(tcs); // lower right corner if (textured&1) glTexCoord2f(tcs[3].u,tcs[3].v); glVertex3f(glseg.x2,zbottom[1],glseg.y2); //if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs); glEnd(); vertexcount+=4; #else static FFlatVertex vtx[100]; // Yes this is static. It's only used once, and I think it's faster as the address doesn't keep changing FFlatVertex *ptr = &vtx[0]; ptr->Set(glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v); ptr++; if (split && glseg.fracleft == 0) SplitLeftEdge(ptr); ptr->Set(glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v); ptr++; if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(ptr); ptr->Set(glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v); ptr++; if (split && glseg.fracright == 1) SplitRightEdge(ptr); ptr->Set(glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v); ptr++; if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(ptr); // We can workout how many from the difference in pointers vertcount = (ptr - &vtx[0]); glTexCoordPointer(2,GL_FLOAT, sizeof(FFlatVertex),&vtx[0].u); glVertexPointer (3,GL_FLOAT, sizeof(FFlatVertex),&vtx[0].x); glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_TEXTURE_COORD_ARRAY); glDisableClientState (GL_COLOR_ARRAY); glBindBuffer (GL_ARRAY_BUFFER, 0); // NO VBO glDrawArrays (GL_TRIANGLE_FAN, 0, vertcount); vertexcount += vertcount; #endif #else if (gl.buffermethod != BM_DEFERRED) { MakeVertices(!!(textured&RWF_NOSPLIT)); } else if (vertcount == 0) { // This should never happen but in case it actually does, use the quad drawer as fallback (without edge splitting.) // This way it at least gets drawn. FQuadDrawer qd; qd.Set(0, glseg.x1, zbottom[0], glseg.y1, tcs[LOLFT].u, tcs[LOLFT].v); qd.Set(1, glseg.x1, ztop[0], glseg.y1, tcs[UPLFT].u, tcs[UPLFT].v); qd.Set(2, glseg.x2, ztop[1], glseg.y2, tcs[UPRGT].u, tcs[UPRGT].v); qd.Set(3, glseg.x2, zbottom[1], glseg.y2, tcs[LORGT].u, tcs[LORGT].v); qd.Render(GL_TRIANGLE_FAN); vertexcount += 4; return; } GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, vertindex, vertcount); vertexcount += vertcount; #endif }
void FGLRenderer::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, DAngle rotation, FDynamicColormap *colormap, int lightlevel) { if (npoints < 3) { // This is no polygon. return; } FMaterial *gltexture = FMaterial::ValidateTexture(texture, false); if (gltexture == NULL) { return; } FColormap cm; cm = colormap; // We cannot use the software light mode here because it doesn't properly calculate the light for 2D rendering. SBYTE savedlightmode = glset.lightmode; if (glset.lightmode == 8) glset.lightmode = 0; gl_SetColor(lightlevel, 0, cm, 1.f); glset.lightmode = savedlightmode; gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); int i; bool dorotate = rotation != 0; float cosrot = cos(rotation.Radians()); float sinrot = sin(rotation.Radians()); //float yoffs = GatheringWipeScreen ? 0 : LBOffset; float uscale = float(1.f / (texture->GetScaledWidth() * scalex)); float vscale = float(1.f / (texture->GetScaledHeight() * scaley)); if (gltexture->tex->bHasCanvas) { vscale = 0 - vscale; } float ox = float(originx); float oy = float(originy); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); for (i = 0; i < npoints; ++i) { float u = points[i].X - 0.5f - ox; float v = points[i].Y - 0.5f - oy; if (dorotate) { float t = u; u = t * cosrot - v * sinrot; v = v * cosrot + t * sinrot; } ptr->Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale); ptr++; } GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN); }
void FGLRenderer::DrawTexture(FTexture *img, DrawParms &parms) { double xscale = parms.destwidth / parms.texwidth; double yscale = parms.destheight / parms.texheight; double x = parms.x - parms.left * xscale; double y = parms.y - parms.top * yscale; double w = parms.destwidth; double h = parms.destheight; float u1, v1, u2, v2; int light = 255; FMaterial * gltex = FMaterial::ValidateTexture(img, false); if (parms.colorOverlay && (parms.colorOverlay & 0xffffff) == 0) { // Right now there's only black. Should be implemented properly later light = 255 - APART(parms.colorOverlay); parms.colorOverlay = 0; } gl_SetRenderStyle(parms.style, !parms.masked, false); if (!img->bHasCanvas) { int translation = 0; if (!parms.alphaChannel) { if (parms.remap != NULL && !parms.remap->Inactive) { GLTranslationPalette * pal = static_cast<GLTranslationPalette*>(parms.remap->GetNative()); if (pal) translation = -pal->GetIndex(); } } gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, translation, -1, !!(parms.style.Flags & STYLEF_RedIsAlpha)); u1 = gltex->GetUL(); v1 = gltex->GetVT(); u2 = gltex->GetUR(); v2 = gltex->GetVB(); } else { gl_RenderState.SetMaterial(gltex, CLAMP_XY_NOMIP, 0, -1, false); u1 = 0.f; v1 = 1.f; u2 = 1.f; v2 = 0.f; gl_RenderState.SetTextureMode(TM_OPAQUE); } if (parms.flipX) { float temp = u1; u1 = u2; u2 = temp; } if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { double wi = MIN(parms.windowright, parms.texwidth); x += parms.windowleft * xscale; w -= (parms.texwidth - wi + parms.windowleft) * xscale; u1 = float(u1 + parms.windowleft / parms.texwidth); u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth); } PalEntry color; if (parms.style.Flags & STYLEF_ColorIsFixed) { color = parms.fillcolor; } else { color = PalEntry(light, light, light); } color.a = (BYTE)(parms.Alpha * 255); // scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates int btm = (SCREENHEIGHT - screen->GetHeight()) / 2; btm = SCREENHEIGHT - btm; glEnable(GL_SCISSOR_TEST); int space = (static_cast<OpenGLFrameBuffer*>(screen)->GetTrueHeight()-screen->GetHeight())/2; glScissor(parms.lclip, btm - parms.dclip + space, parms.rclip - parms.lclip, parms.dclip - parms.uclip); gl_RenderState.SetColor(color); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(x, y, 0, u1, v1); ptr++; ptr->Set(x, y + h, 0, u1, v2); ptr++; ptr->Set(x + w, y, 0, u2, v1); ptr++; ptr->Set(x + w, y + h, 0, u2, v2); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); if (parms.colorOverlay) { gl_RenderState.SetTextureMode(TM_MASK); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.BlendEquation(GL_FUNC_ADD); gl_RenderState.SetColor(PalEntry(parms.colorOverlay)); gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(x, y, 0, u1, v1); ptr++; ptr->Set(x, y + h, 0, u1, v2); ptr++; ptr->Set(x + w, y, 0, u2, v1); ptr++; ptr->Set(x + w, y + h, 0, u2, v2); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); } glScissor(0, 0, screen->GetWidth(), screen->GetHeight()); glDisable(GL_SCISSOR_TEST); gl_RenderState.SetTextureMode(TM_MODULATE); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.BlendEquation(GL_FUNC_ADD); }
bool OpenGLFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLFrameBuffer *fb) { bool done; BurnTime += ticks; ticks *= 2; // Make the fire burn done = false; while (!done && ticks--) { Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density); done = (Density < 0); } if (BurnTexture != NULL) delete BurnTexture; BurnTexture = new FHardwareTexture(WIDTH, HEIGHT, true); // Update the burn texture with the new burn data BYTE rgb_buffer[WIDTH*HEIGHT*4]; const BYTE *src = BurnArray; DWORD *dest = (DWORD *)rgb_buffer; for (int y = HEIGHT; y != 0; --y) { for (int x = WIDTH; x != 0; --x) { BYTE s = clamp<int>((*src++)*2, 0, 255); *dest++ = MAKEARGB(s,255,255,255); } } float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth()); float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight()); // Put the initial screen back to the buffer. gl_RenderState.SetTextureMode(TM_OPAQUE); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.ResetColor(); gl_RenderState.Apply(); fb->wipestartscreen->Bind(0, 0, false); FFlatVertex *ptr; unsigned int offset, count; ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(0, 0, 0, 0, vb); ptr++; ptr->Set(0, fb->Height, 0, 0, 0); ptr++; ptr->Set(fb->Width, 0, 0, ur, vb); ptr++; ptr->Set(fb->Width, fb->Height, 0, ur, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP, &offset, &count); gl_RenderState.SetTextureMode(TM_MODULATE); gl_RenderState.SetEffect(EFF_BURN); gl_RenderState.ResetColor(); gl_RenderState.Apply(); // Burn the new screen on top of it. fb->wipeendscreen->Bind(0, 0, false); BurnTexture->CreateTexture(rgb_buffer, WIDTH, HEIGHT, 1, true, 0); GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, offset, count); gl_RenderState.SetEffect(EFF_NONE); // The fire may not always stabilize, so the wipe is forced to end // after an arbitrary maximum time. return done || (BurnTime > 40); }
bool OpenGLFrameBuffer::Wiper_Melt::Run(int ticks, OpenGLFrameBuffer *fb) { float ur = fb->GetWidth() / FHardwareTexture::GetTexDimension(fb->GetWidth()); float vb = fb->GetHeight() / FHardwareTexture::GetTexDimension(fb->GetHeight()); // Draw the new screen on the bottom. gl_RenderState.SetTextureMode(TM_OPAQUE); gl_RenderState.ResetColor(); gl_RenderState.Apply(); fb->wipeendscreen->Bind(0, 0, false); FFlatVertex *ptr; ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(0, 0, 0, 0, vb); ptr++; ptr->Set(0, fb->Height, 0, 0, 0); ptr++; ptr->Set(fb->Width, 0, 0, ur, vb); ptr++; ptr->Set(fb->Width, fb->Height, 0, ur, 0); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); int i, dy; bool done = false; fb->wipestartscreen->Bind(0, 0, false); // Copy the old screen in vertical strips on top of the new one. while (ticks--) { done = true; for (i = 0; i < WIDTH; i++) { if (y[i] < 0) { y[i]++; done = false; } else if (y[i] < HEIGHT) { dy = (y[i] < 16) ? y[i]+1 : 8; y[i] = MIN(y[i] + dy, HEIGHT); done = false; } if (ticks == 0) { // Only draw for the final tick. // No need for optimization. Wipes won't ever be drawn with anything else. RECT rect; POINT dpt; dpt.x = i * fb->Width / WIDTH; dpt.y = MAX(0, y[i] * fb->Height / HEIGHT); rect.left = dpt.x; rect.top = 0; rect.right = (i + 1) * fb->Width / WIDTH; rect.bottom = fb->Height - dpt.y; if (rect.bottom > rect.top) { float tw = (float)FHardwareTexture::GetTexDimension(fb->Width); float th = (float)FHardwareTexture::GetTexDimension(fb->Height); rect.bottom = fb->Height - rect.bottom; rect.top = fb->Height - rect.top; ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(rect.left, rect.bottom, 0, rect.left / tw, rect.top / th); ptr++; ptr->Set(rect.left, rect.top, 0, rect.left / tw, rect.bottom / th); ptr++; ptr->Set(rect.right, rect.bottom, 0, rect.right / tw, rect.top / th); ptr++; ptr->Set(rect.right, rect.top, 0, rect.right / tw, rect.bottom / th); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); } } } } gl_RenderState.SetTextureMode(TM_MODULATE); return done; }
void FGLRenderer::DrawPSprite (player_t * player,DPSprite *psp, float sx, float sy, bool hudModelStep, int OverrideShader, bool alphatexture) { float fU1,fV1; float fU2,fV2; float tx; float x1,y1,x2,y2; float scale; float scalex; float ftexturemid; // 4:3 16:9 16:10 17:10 5:4 17:10 21:9 static float xratio[] = {1.f, 3.f/4, 5.f/6, 40.f/51, 1.f, 40.f/51, 4.f/7}; // [BB] In the HUD model step we just render the model and break out. if ( hudModelStep ) { gl_RenderHUDModel(psp, sx, sy); return; } // decide which patch to use bool mirror; FTextureID lump = gl_GetSpriteFrame(psp->GetSprite(), psp->GetFrame(), 0, 0, &mirror); if (!lump.isValid()) return; FMaterial * tex = FMaterial::ValidateTexture(lump, true, false); if (!tex) return; gl_RenderState.SetMaterial(tex, CLAMP_XY_NOMIP, 0, OverrideShader, alphatexture); float vw = (float)viewwidth; float vh = (float)viewheight; FloatRect r; tex->GetSpriteRect(&r); // calculate edges of the shape scalex = xratio[WidescreenRatio] * vw / 320; tx = sx - (160 - r.left); x1 = tx * scalex + vw/2; if (x1 > vw) return; // off the right side x1 += viewwindowx; tx += r.width; x2 = tx * scalex + vw / 2; if (x2 < 0) return; // off the left side x2 += viewwindowx; // killough 12/98: fix psprite positioning problem ftexturemid = 100.f - sy - r.top; AWeapon * wi=player->ReadyWeapon; if (wi && wi->YAdjust != 0) { float fYAd = wi->YAdjust; if (screenblocks >= 11) { ftexturemid -= fYAd; } else if (!st_scale) { ftexturemid -= StatusBar->GetDisplacement () * fYAd; } } scale = (SCREENHEIGHT*vw) / (SCREENWIDTH * 200.0f); y1 = viewwindowy + vh / 2 - (ftexturemid * scale); y2 = y1 + (r.height * scale) + 1; if (!mirror) { fU1=tex->GetSpriteUL(); fV1=tex->GetSpriteVT(); fU2=tex->GetSpriteUR(); fV2=tex->GetSpriteVB(); } else { fU2=tex->GetSpriteUL(); fV1=tex->GetSpriteVT(); fU1=tex->GetSpriteUR(); fV2=tex->GetSpriteVB(); } if (tex->GetTransparent() || OverrideShader != -1) { gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); } gl_RenderState.Apply(); FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(x1, y1, 0, fU1, fV1); ptr++; ptr->Set(x1, y2, 0, fU1, fV2); ptr++; ptr->Set(x2, y1, 0, fU2, fV1); ptr++; ptr->Set(x2, y2, 0, fU2, fV2); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f); }
static void RenderBox(FTextureID texno, FMaterial * gltex, float x_offset, bool sky2) { FSkyBox * sb = static_cast<FSkyBox*>(gltex->tex); int faces; FMaterial * tex; gl_RenderState.EnableModelMatrix(true); gl_RenderState.mModelMatrix.loadIdentity(); if (!sky2) gl_RenderState.mModelMatrix.rotate(-180.0f+x_offset, glset.skyrotatevector.X, glset.skyrotatevector.Z, glset.skyrotatevector.Y); else gl_RenderState.mModelMatrix.rotate(-180.0f+x_offset, glset.skyrotatevector2.X, glset.skyrotatevector2.Z, glset.skyrotatevector2.Y); FFlatVertex *ptr; if (sb->faces[5]) { faces=4; // north tex = FMaterial::ValidateTexture(sb->faces[0], false); gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false); gl_RenderState.Apply(); ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(128.f, 128.f, -128.f, 0, 0); ptr++; ptr->Set(-128.f, 128.f, -128.f, 1, 0); ptr++; ptr->Set(128.f, -128.f, -128.f, 0, 1); ptr++; ptr->Set(-128.f, -128.f, -128.f, 1, 1); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); // east tex = FMaterial::ValidateTexture(sb->faces[1], false); gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false); gl_RenderState.Apply(); ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(-128.f, 128.f, -128.f, 0, 0); ptr++; ptr->Set(-128.f, 128.f, 128.f, 1, 0); ptr++; ptr->Set(-128.f, -128.f, -128.f, 0, 1); ptr++; ptr->Set(-128.f, -128.f, 128.f, 1, 1); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); // south tex = FMaterial::ValidateTexture(sb->faces[2], false); gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false); gl_RenderState.Apply(); ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(-128.f, 128.f, 128.f, 0, 0); ptr++; ptr->Set(128.f, 128.f, 128.f, 1, 0); ptr++; ptr->Set(-128.f, -128.f, 128.f, 0, 1); ptr++; ptr->Set(128.f, -128.f, 128.f, 1, 1); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); // west tex = FMaterial::ValidateTexture(sb->faces[3], false); gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false); gl_RenderState.Apply(); ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(128.f, 128.f, 128.f, 0, 0); ptr++; ptr->Set(128.f, 128.f, -128.f, 1, 0); ptr++; ptr->Set(128.f, -128.f, 128.f, 0, 1); ptr++; ptr->Set(128.f, -128.f, -128.f, 1, 1); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); } else { faces=1; tex = FMaterial::ValidateTexture(sb->faces[0], false); gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false); gl_RenderState.Apply(); ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(128.f, 128.f, -128.f, 0, 0); ptr++; ptr->Set(128.f, -128.f, -128.f, 0, 1); ptr++; ptr->Set(-128.f, 128.f, -128.f, 0.25f, 0); ptr++; ptr->Set(-128.f, -128.f, -128.f, 0.25f, 1); ptr++; ptr->Set(-128.f, 128.f, 128.f, 0.5f, 0); ptr++; ptr->Set(-128.f, -128.f, 128.f, 0.5f, 1); ptr++; ptr->Set(128.f, 128.f, 128.f, 0.75f, 0); ptr++; ptr->Set(128.f, -128.f, 128.f, 0.75f, 1); ptr++; ptr->Set(128.f, 128.f, -128.f, 1, 0); ptr++; ptr->Set(128.f, -128.f, -128.f, 1, 1); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); } // top tex = FMaterial::ValidateTexture(sb->faces[faces], false); gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false); gl_RenderState.Apply(); ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(128.f, 128.f, -128.f, 0, sb->fliptop); ptr++; ptr->Set(-128.f, 128.f, -128.f, 1, sb->fliptop); ptr++; ptr->Set(128.f, 128.f, 128.f, 0, !sb->fliptop); ptr++; ptr->Set(-128.f, 128.f, 128.f, 1, !sb->fliptop); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); // bottom tex = FMaterial::ValidateTexture(sb->faces[faces+1], false); gl_RenderState.SetMaterial(tex, CLAMP_XY, 0, -1, false); gl_RenderState.Apply(); ptr = GLRenderer->mVBO->GetBuffer(); ptr->Set(128.f, -128.f, -128.f, 0, 0); ptr++; ptr->Set(-128.f, -128.f, -128.f, 1, 0); ptr++; ptr->Set(128.f, -128.f, 128.f, 0, 1); ptr++; ptr->Set(-128.f, -128.f, 128.f, 1, 1); ptr++; GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_STRIP); gl_RenderState.EnableModelMatrix(false); }