//========================================================================== // // // //========================================================================== void GLWall::DoDrawDecals() { if (seg->sidedef && seg->sidedef->AttachedDecals) { if (lightlist != NULL) { gl_RenderState.EnableSplit(true); } else { gl_SetFog(lightlevel, rellight + getExtraLight(), &Colormap, false); } DBaseDecal *decal = seg->sidedef->AttachedDecals; while (decal) { DrawDecal(decal); decal = decal->WallNext; } if (lightlist != NULL) { gl_RenderState.EnableSplit(false); } } }
void GLWall::RenderFogBoundary() { if (gl_fogmode && mDrawer->FixedColormap == 0) { if (!gl.legacyMode) { int rel = rellight + getExtraLight(); mDrawer->SetFog(lightlevel, rel, &Colormap, false); gl_RenderState.EnableDrawBuffers(1); gl_RenderState.SetEffect(EFF_FOGBOUNDARY); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -128.0f); RenderWall(RWF_BLANK); glPolygonOffset(0.0f, 0.0f); glDisable(GL_POLYGON_OFFSET_FILL); gl_RenderState.SetEffect(EFF_NONE); gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount()); } else { RenderFogBoundaryCompat(); } } }
void GLWall::RenderTextured(int rflags) { int tmode = gl_RenderState.GetTextureMode(); int rel = rellight + getExtraLight(); if (flags & GLWF_GLOW) { gl_RenderState.EnableGlow(true); gl_RenderState.SetGlowPlanes(topplane, bottomplane); gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); } gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); if (type == RENDERWALL_M2SNF) { if (flags & GLT_CLAMPY) { if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); } gl_SetFog(255, 0, NULL, false); } float absalpha = fabsf(alpha); if (lightlist == NULL) { gl_SetColor(lightlevel, rel, Colormap, absalpha); if (type != RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add); RenderWall(rflags); } else { gl_RenderState.EnableSplit(true); for (unsigned i = 0; i < lightlist->Size(); i++) { secplane_t &lowplane = i == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[i + 1].plane; // this must use the exact same calculation method as GLWall::Process etc. float low1 = lowplane.ZatPoint(vertexes[0]); float low2 = lowplane.ZatPoint(vertexes[1]); if (low1 < ztop[0] || low2 < ztop[1]) { int thisll = (*lightlist)[i].caster != NULL ? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; FColormap thiscm; thiscm.FadeColor = Colormap.FadeColor; thiscm.CopyFrom3DLight(&(*lightlist)[i]); gl_SetColor(thisll, rel, thiscm, absalpha); if (type != RENDERWALL_M2SNF) gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add); gl_RenderState.SetSplitPlanes((*lightlist)[i].plane, lowplane); RenderWall(rflags); } if (low1 <= zbottom[0] && low2 <= zbottom[1]) break; } gl_RenderState.EnableSplit(false); } gl_RenderState.SetTextureMode(tmode); gl_RenderState.EnableGlow(false); }
void GLWall::RenderTranslucentWall() { bool transparent = gltexture? gltexture->GetTransparent() : false; // currently the only modes possible are solid, additive or translucent // and until that changes I won't fix this code for the new blending modes! bool isadditive = RenderStyle == STYLE_Add; if (gl_fixedcolormap == CM_DEFAULT && gl_lights && (gl.flags & RFL_BUFFER_STORAGE)) { SetupLights(); } if (!transparent) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); int extra; if (gltexture) { gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW)); gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); extra = getExtraLight(); } else { gl_RenderState.EnableTexture(false); extra = 0; } int tmode = gl_RenderState.GetTextureMode(); gl_SetColor(lightlevel, extra, Colormap, fabsf(alpha)); if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, extra, &Colormap, isadditive); else { if (flags & GLT_CLAMPY) { if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); } gl_SetFog(255, 0, NULL, false); } RenderWall(RWF_TEXTURED|RWF_NOSPLIT); // restore default settings if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (!gltexture) { gl_RenderState.EnableTexture(true); } gl_RenderState.EnableGlow(false); gl_RenderState.SetTextureMode(tmode); }
//========================================================================== // // // //========================================================================== void GLFlat::Draw(int pass, bool trans) // trans only has meaning for GLPASS_LIGHTSONLY { int rel = getExtraLight(); #ifdef _DEBUG if (sector->sectornum == gl_breaksec) { int a = 0; } #endif switch (pass) { case GLPASS_PLAIN: // Single-pass rendering case GLPASS_ALL: gl_SetColor(lightlevel, rel, Colormap,1.0f); gl_SetFog(lightlevel, rel, &Colormap, false); gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_SetPlaneTextureRotation(&plane, gltexture); DrawSubsectors(pass, (pass == GLPASS_ALL || dynlightindex > -1), false); gl_RenderState.EnableTextureMatrix(false); break; case GLPASS_LIGHTSONLY: if (!trans || gltexture) { ProcessLights(trans); } break; case GLPASS_TRANSLUCENT: if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE); gl_SetColor(lightlevel, rel, Colormap, alpha); gl_SetFog(lightlevel, rel, &Colormap, false); gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); if (!gltexture) { gl_RenderState.EnableTexture(false); DrawSubsectors(pass, false, true); gl_RenderState.EnableTexture(true); } else { gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_SetPlaneTextureRotation(&plane, gltexture); DrawSubsectors(pass, true, true); gl_RenderState.EnableTextureMatrix(false); } if (renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; } }
void GLWall::RenderFogBoundary() { if (gl_fogmode && gl_fixedcolormap == 0) { int rel = rellight + getExtraLight(); gl_SetFog(lightlevel, rel, &Colormap, false); gl_RenderState.SetEffect(EFF_FOGBOUNDARY); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -128.0f); RenderWall(RWF_BLANK); glPolygonOffset(0.0f, 0.0f); glDisable(GL_POLYGON_OFFSET_FILL); gl_RenderState.SetEffect(EFF_NONE); } }
//----------------------------------------------------------------------------- // // HWHorizonPortal::DrawContents // //----------------------------------------------------------------------------- void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) { Clocker c(PortalAll); FMaterial * gltexture; GLSectorPlane * sp = &origin->plane; auto &vp = di->Viewpoint; gltexture = FMaterial::ValidateTexture(sp->texture, false, true); if (!gltexture) { state.ClearScreen(); return; } di->SetCameraPos(vp.Pos); if (gltexture && gltexture->tex->isFullbright()) { // glowing textures are always drawn full bright without color di->SetColor(state, 255, 0, false, origin->colormap, 1.f); di->SetFog(state, 255, 0, false, &origin->colormap, false); } else { int rel = getExtraLight(); di->SetColor(state, origin->lightlevel, rel, di->isFullbrightScene(), origin->colormap, 1.0f); di->SetFog(state, origin->lightlevel, rel, di->isFullbrightScene(), &origin->colormap, false); } state.SetMaterial(gltexture, CLAMP_NONE, 0, -1); state.SetObjectColor(origin->specialcolor); state.SetPlaneTextureRotation(sp, gltexture); state.AlphaFunc(Alpha_GEqual, 0.f); state.SetRenderStyle(STYLE_Source); for (unsigned i = 0; i < vcount; i += 4) { state.Draw(DT_TriangleStrip, voffset + i, 4, true);// i == 0); } state.Draw(DT_TriangleStrip, voffset + vcount, 10, false); state.EnableTextureMatrix(false); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // // 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, true); if (!gltexture) { ClearScreen(); PortalAll.Unclock(); return; } z=FIXED2FLOAT(sp->texheight); if (gltexture && gltexture->tex->isFullbright()) { // glowing textures are always drawn full bright without color gl_SetColor(255, 0, NULL, 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); } gltexture->Bind(origin->colormap.colormap); gl_RenderState.EnableAlphaTest(false); gl_RenderState.BlendFunc(GL_ONE,GL_ZERO); gl_RenderState.Apply(); bool pushed = gl_SetPlaneTextureRotation(sp, gltexture); float vx=FIXED2FLOAT(viewx); float vy=FIXED2FLOAT(viewy); // Draw to some far away boundary for(float x=-32768+vx; x<32768+vx; x+=4096) { for(float y=-32768+vy; y<32768+vy;y+=4096) { glBegin(GL_TRIANGLE_FAN); glTexCoord2f(x/64, -y/64); glVertex3f(x, z, y); glTexCoord2f(x/64 + 64, -y/64); glVertex3f(x + 4096, z, y); glTexCoord2f(x/64 + 64, -y/64 - 64); glVertex3f(x + 4096, z, y + 4096); glTexCoord2f(x/64, -y/64 - 64); glVertex3f(x, z, y + 4096); glEnd(); } } float vz=FIXED2FLOAT(viewz); 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 glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(512.f, 0); glVertex3f(-32768+vx, z, -32768+vy); glTexCoord2f(512.f, tz); glVertex3f(-32768+vx, vz, -32768+vy); glTexCoord2f(-512.f, 0); glVertex3f(-32768+vx, z, 32768+vy); glTexCoord2f(-512.f, tz); glVertex3f(-32768+vx, vz, 32768+vy); glTexCoord2f(512.f, 0); glVertex3f( 32768+vx, z, 32768+vy); glTexCoord2f(512.f, tz); glVertex3f( 32768+vx, vz, 32768+vy); glTexCoord2f(-512.f, 0); glVertex3f( 32768+vx, z, -32768+vy); glTexCoord2f(-512.f, tz); glVertex3f( 32768+vx, vz, -32768+vy); glTexCoord2f(512.f, 0); glVertex3f(-32768+vx, z, -32768+vy); glTexCoord2f(512.f, tz); glVertex3f(-32768+vx, vz, -32768+vy); glEnd(); if (pushed) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); } 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); }
//========================================================================== // // 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.GetFixedColormap(); 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(Colormap.colormap); float fviewx = FIXED2FLOAT(viewx); float fviewy = FIXED2FLOAT(viewy); float fviewz = FIXED2FLOAT(viewz); gl_RenderState.Apply(); bool pushed = gl_SetPlaneTextureRotation(&plane, gltexture); glBegin(GL_TRIANGLE_FAN); 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); glTexCoord2f(px1 / 64, -py1 / 64); glVertex3f(px1, planez, py1); glTexCoord2f(px2 / 64, -py2 / 64); glVertex3f(px2, planez, py2); glTexCoord2f(px3 / 64, -py3 / 64); glVertex3f(px3, planez, py3); glTexCoord2f(px4 / 64, -py4 / 64); glVertex3f(px4, planez, py4); glEnd(); if (pushed) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); } }
//========================================================================== // // 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, false, 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); gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); float fviewx = ViewPos.X; float fviewy = ViewPos.Y; float fviewz = ViewPos.Z; 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); FQuadDrawer qd; qd.Set(0, px1, planez, py1, px1 / 64, -py1 / 64); qd.Set(1, px2, planez, py2, px2 / 64, -py2 / 64); qd.Set(2, px3, planez, py3, px3 / 64, -py3 / 64); qd.Set(3, px4, planez, py4, px4 / 64, -py4 / 64); qd.Render(GL_TRIANGLE_FAN); gl_RenderState.EnableTextureMatrix(false); }
//========================================================================== // // // //========================================================================== void GLWall::DrawDecal(DBaseDecal *decal) { line_t * line=seg->linedef; side_t * side=seg->sidedef; int i; fixed_t zpos; int light; int rel; float a; bool flipx, flipy, loadAlpha; DecalVertex dv[4]; FTextureID decalTile; if (decal->RenderFlags & RF_INVISIBLE) return; if (type==RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures. //if (decal->sprite != 0xffff) { decalTile = decal->PicNum; flipx = !!(decal->RenderFlags & RF_XFLIP); flipy = !!(decal->RenderFlags & RF_YFLIP); } /* else { decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0]; flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1; } */ FTexture *texture = TexMan[decalTile]; if (texture == NULL) return; FMaterial *tex; if (texture->UseType == FTexture::TEX_MiscPatch) { // We need to create a clone of this texture where we can force the // texture filtering offset in. if (texture->gl_info.DecalTexture == NULL) { texture->gl_info.DecalTexture = new FCloneTexture(texture, FTexture::TEX_Decal); } tex = FMaterial::ValidateTexture(texture->gl_info.DecalTexture); } else tex = FMaterial::ValidateTexture(texture); // the sectors are only used for their texture origin coordinates // so we don't need the fake sectors for deep water etc. // As this is a completely split wall fragment no further splits are // necessary for the decal. sector_t *frontsector; // for 3d-floor segments use the model sector as reference if ((decal->RenderFlags&RF_CLIPMASK)==RF_CLIPMID) frontsector=decal->Sector; else frontsector=seg->frontsector; switch (decal->RenderFlags & RF_RELMASK) { default: // No valid decal can have this type. If one is encountered anyway // it is in some way invalid so skip it. return; //zpos = decal->z; //break; case RF_RELUPPER: if (type!=RENDERWALL_TOP) return; if (line->flags & ML_DONTPEGTOP) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } else { zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling); } break; case RF_RELLOWER: if (type!=RENDERWALL_BOTTOM) return; if (line->flags & ML_DONTPEGBOTTOM) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } else { zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor); } break; case RF_RELMID: if (type==RENDERWALL_TOP || type==RENDERWALL_BOTTOM) return; if (line->flags & ML_DONTPEGBOTTOM) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor); } else { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } } if (decal->RenderFlags & RF_FULLBRIGHT) { light = 255; rel = 0; } else { light = lightlevel; rel = rellight + getExtraLight(); } int r = RPART(decal->AlphaColor); int g = GPART(decal->AlphaColor); int b = BPART(decal->AlphaColor); FColormap p = Colormap; if (glset.nocoloredspritelighting) { int v = (Colormap.LightColor.r * 77 + Colormap.LightColor.g*143 + Colormap.LightColor.b*35)/255; p.LightColor = PalEntry(p.colormap, v, v, v); } float red, green, blue; if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha) { loadAlpha = true; p.colormap=CM_SHADE; if (glset.lightmode != 8) { gl_GetLightColor(light, rel, &p, &red, &green, &blue); } else { gl_GetLightColor(lightlevel, rellight, &p, &red, &green, &blue); } if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites) { float result[3]; fixed_t x, y; decal->GetXY(seg->sidedef, x, y); gl_GetSpriteLight(NULL, x, y, zpos, sub, Colormap.colormap-CM_DESAT0, result, line, side == line->sidedef[0]? 0:1); if (glset.lightmode != 8) { red = clamp<float>(result[0]+red, 0, 1.0f); green = clamp<float>(result[1]+green, 0, 1.0f); blue = clamp<float>(result[2]+blue, 0, 1.0f); } else { gl_RenderState.SetDynLight(result[0], result[1], result[2]); } } BYTE R = xs_RoundToInt(r * red); BYTE G = xs_RoundToInt(g * green); BYTE B = xs_RoundToInt(b * blue); gl_ModifyColor(R,G,B, Colormap.colormap); red = R/255.f; green = G/255.f; blue = B/255.f; } else { loadAlpha = false; red = 1.f; green = 1.f; blue = 1.f; } a = FIXED2FLOAT(decal->Alpha); // now clip the decal to the actual polygon float decalwidth = tex->TextureWidth(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleX); float decalheight= tex->TextureHeight(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleY); float decallefto = tex->GetLeftOffset(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleX); float decaltopo = tex->GetTopOffset(GLUSE_PATCH) * FIXED2FLOAT(decal->ScaleY); float leftedge = glseg.fracleft * side->TexelLength; float linelength = glseg.fracright * side->TexelLength - leftedge; // texel index of the decal's left edge float decalpixpos = (float)side->TexelLength * decal->LeftDistance / (1<<30) - (flipx? decalwidth-decallefto : decallefto) - leftedge; float left,right; float lefttex,righttex; // decal is off the left edge if (decalpixpos < 0) { left = 0; lefttex = -decalpixpos; } else { left = decalpixpos; lefttex = 0; } // decal is off the right edge if (decalpixpos + decalwidth > linelength) { right = linelength; righttex = right - decalpixpos; } else { right = decalpixpos + decalwidth; righttex = decalwidth; } if (right<=left) return; // nothing to draw // one texture unit on the wall as vector float vx=(glseg.x2-glseg.x1)/linelength; float vy=(glseg.y2-glseg.y1)/linelength; dv[1].x=dv[0].x=glseg.x1+vx*left; dv[1].y=dv[0].y=glseg.y1+vy*left; dv[3].x=dv[2].x=glseg.x1+vx*right; dv[3].y=dv[2].y=glseg.y1+vy*right; zpos+= FRACUNIT*(flipy? decalheight-decaltopo : decaltopo); tex->BindPatch(p.colormap, decal->Translation); dv[1].z=dv[2].z = FIXED2FLOAT(zpos); dv[0].z=dv[3].z = dv[1].z - decalheight; dv[1].v=dv[2].v = tex->GetVT(); dv[1].u=dv[0].u = tex->GetU(lefttex / FIXED2FLOAT(decal->ScaleX)); dv[3].u=dv[2].u = tex->GetU(righttex / FIXED2FLOAT(decal->ScaleX)); dv[0].v=dv[3].v = tex->GetVB(); // now clip to the top plane float vzt=(ztop[1]-ztop[0])/linelength; float topleft=this->ztop[0]+vzt*left; float topright=this->ztop[0]+vzt*right; // completely below the wall if (topleft<dv[0].z && topright<dv[3].z) return; if (topleft<dv[1].z || topright<dv[2].z) { // decal has to be clipped at the top // let texture clamping handle all extreme cases dv[1].v=(dv[1].z-topleft)/(dv[1].z-dv[0].z)*dv[0].v; dv[2].v=(dv[2].z-topright)/(dv[2].z-dv[3].z)*dv[3].v; dv[1].z=topleft; dv[2].z=topright; } // now clip to the bottom plane float vzb=(zbottom[1]-zbottom[0])/linelength; float bottomleft=this->zbottom[0]+vzb*left; float bottomright=this->zbottom[0]+vzb*right; // completely above the wall if (bottomleft>dv[1].z && bottomright>dv[2].z) return; if (bottomleft>dv[0].z || bottomright>dv[3].z) { // decal has to be clipped at the bottom // let texture clamping handle all extreme cases dv[0].v=(dv[1].z-bottomleft)/(dv[1].z-dv[0].z)*(dv[0].v-dv[1].v) + dv[1].v; dv[3].v=(dv[2].z-bottomright)/(dv[2].z-dv[3].z)*(dv[3].v-dv[2].v) + dv[2].v; dv[0].z=bottomleft; dv[3].z=bottomright; } if (flipx) { float ur = tex->GetUR(); for(i=0;i<4;i++) dv[i].u=ur-dv[i].u; } if (flipy) { float vb = tex->GetVB(); for(i=0;i<4;i++) dv[i].v=vb-dv[i].v; } // fog is set once per wall in the calling function and not per decal! if (loadAlpha) { glColor4f(red, green, blue, a); if (glset.lightmode == 8) { if (gl_fixedcolormap) glVertexAttrib1f(VATTR_LIGHTLEVEL, 1.0); else glVertexAttrib1f(VATTR_LIGHTLEVEL, gl_CalcLightLevel(light, rel, false) / 255.0); } } else { if (glset.lightmode == 8) { gl_SetColor(light, rel, &p, a, extralight); // Korshun. } else { gl_SetColor(light, rel, &p, a); } } PalEntry fc = gl_RenderState.GetFogColor(); if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) { gl_RenderState.SetFog(0,-1); } gl_SetRenderStyle(decal->RenderStyle, false, false); // If srcalpha is one it looks better with a higher alpha threshold if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); else gl_RenderState.AlphaFunc(GL_GREATER, 0.f); gl_RenderState.Apply(); glBegin(GL_TRIANGLE_FAN); for(i=0;i<4;i++) { glTexCoord2f(dv[i].u,dv[i].v); glVertex3f(dv[i].x,dv[i].z,dv[i].y); } glEnd(); rendered_decals++; gl_RenderState.SetFog(fc,-1); gl_RenderState.SetDynLight(0,0,0); }
void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) { bool brightflash = false; unsigned int i; int lightlevel=0; FColormap cm; sector_t * fakesec, fs; AActor * playermo=players[consoleplayer].camera; player_t * player=playermo->player; // this is the same as the software renderer if (!player || !r_drawplayersprites || !camera->player || (player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) return; float bobx, boby, wx, wy; DPSprite *weapon; P_BobWeapon(camera->player, &bobx, &boby, r_TicFracF); // Interpolate the main weapon layer once so as to be able to add it to other layers. if ((weapon = camera->player->FindPSprite(PSP_WEAPON)) != nullptr) { if (weapon->firstTic) { wx = weapon->x; wy = weapon->y; } else { wx = weapon->oldx + (weapon->x - weapon->oldx) * r_TicFracF; wy = weapon->oldy + (weapon->y - weapon->oldy) * r_TicFracF; } } else { wx = 0; wy = 0; } if (gl_fixedcolormap) { lightlevel=255; cm.Clear(); fakesec = viewsector; } else { fakesec = gl_FakeFlat(viewsector, &fs, false); // calculate light level for weapon sprites lightlevel = gl_ClampLight(fakesec->lightlevel); // calculate colormap for weapon sprites if (viewsector->e->XFloor.ffloors.Size() && !glset.nocoloredspritelighting) { TArray<lightlist_t> & lightlist = viewsector->e->XFloor.lightlist; for(i=0;i<lightlist.Size();i++) { double lightbottom; if (i<lightlist.Size()-1) { lightbottom=lightlist[i+1].plane.ZatPoint(ViewPos); } else { lightbottom=viewsector->floorplane.ZatPoint(ViewPos); } if (lightbottom<player->viewz) { cm = lightlist[i].extra_colormap; lightlevel = gl_ClampLight(*lightlist[i].p_lightlevel); break; } } } else { cm=fakesec->ColorMap; if (glset.nocoloredspritelighting) cm.ClearColor(); } lightlevel = gl_CalcLightLevel(lightlevel, getExtraLight(), true); if (glset.lightmode == 8) { // Korshun: the way based on max possible light level for sector like in software renderer. float min_L = 36.0 / 31.0 - ((lightlevel / 255.0) * (63.0 / 31.0)); // Lightlevel in range 0-63 if (min_L < 0) min_L = 0; else if (min_L > 1.0) min_L = 1.0; lightlevel = (1.0 - min_L) * 255; } else { lightlevel = (2 * lightlevel + 255) / 3; } lightlevel = gl_CheckSpriteGlow(viewsector, lightlevel, playermo->Pos()); } // Korshun: fullbright fog in opengl, render weapon sprites fullbright (but don't cancel out the light color!) if (glset.brightfog && ((level.flags&LEVEL_HASFADETABLE) || cm.FadeColor != 0)) { lightlevel = 255; } PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff; ThingColor.a = 255; visstyle_t vis; vis.RenderStyle=playermo->RenderStyle; vis.Alpha=playermo->Alpha; vis.colormap = NULL; if (playermo->Inventory) { playermo->Inventory->AlterWeaponSprite(&vis); if (vis.colormap >= SpecialColormaps[0].Colormap && vis.colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap && gl_fixedcolormap == CM_DEFAULT) { // this only happens for Strife's inverted weapon sprite vis.RenderStyle.Flags |= STYLEF_InvertSource; } } // Set the render parameters int OverrideShader = -1; float trans = 0.f; if (vis.RenderStyle.BlendOp >= STYLEOP_Fuzz && vis.RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub) { vis.RenderStyle.CheckFuzz(); if (vis.RenderStyle.BlendOp == STYLEOP_Fuzz) { if (gl_fuzztype != 0) { // Todo: implement shader selection here vis.RenderStyle = LegacyRenderStyles[STYLE_Translucent]; OverrideShader = gl_fuzztype + 4; trans = 0.99f; // trans may not be 1 here } else { vis.RenderStyle.BlendOp = STYLEOP_Shadow; } } } gl_SetRenderStyle(vis.RenderStyle, false, false); if (vis.RenderStyle.Flags & STYLEF_TransSoulsAlpha) { trans = transsouls; } else if (vis.RenderStyle.Flags & STYLEF_Alpha1) { trans = 1.f; } else if (trans == 0.f) { trans = vis.Alpha; } // now draw the different layers of the weapon gl_RenderState.EnableBrightmap(true); gl_RenderState.SetObjectColor(ThingColor); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold); gl_RenderState.BlendEquation(GL_FUNC_ADD); // hack alert! Rather than changing everything in the underlying lighting code let's just temporarily change // light mode here to draw the weapon sprite. int oldlightmode = glset.lightmode; if (glset.lightmode == 8) glset.lightmode = 2; for(DPSprite *psp = player->psprites; psp != nullptr && psp->GetID() < PSP_TARGETCENTER; psp = psp->GetNext()) { if (psp->GetState() != nullptr) { FColormap cmc = cm; int ll = lightlevel; if (isBright(psp)) { if (fakesec == viewsector || in_area != area_below) { cmc.LightColor.r= cmc.LightColor.g= cmc.LightColor.b=0xff; } else { // under water areas keep most of their color for fullbright objects cmc.LightColor.r = (3 * cmc.LightColor.r + 0xff) / 4; cmc.LightColor.g = (3*cmc.LightColor.g + 0xff)/4; cmc.LightColor.b = (3*cmc.LightColor.b + 0xff)/4; } ll = 255; } // set the lighting parameters if (vis.RenderStyle.BlendOp == STYLEOP_Shadow) { gl_RenderState.SetColor(0.2f, 0.2f, 0.2f, 0.33f, cmc.desaturation); } else { if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites) { gl_SetDynSpriteLight(playermo, NULL); } gl_SetColor(ll, 0, cmc, trans, true); } if (psp->firstTic) { // Can't interpolate the first tic. psp->firstTic = false; psp->oldx = psp->x; psp->oldy = psp->y; } float sx = psp->oldx + (psp->x - psp->oldx) * r_TicFracF; float sy = psp->oldy + (psp->y - psp->oldy) * r_TicFracF; if (psp->Flags & PSPF_ADDBOB) { sx += bobx; sy += boby; } if (psp->Flags & PSPF_ADDWEAPON && psp->GetID() != PSP_WEAPON) { sx += wx; sy += wy; } DrawPSprite(player, psp, sx, sy, hudModelStep, OverrideShader, !!(vis.RenderStyle.Flags & STYLEF_RedIsAlpha)); } } gl_RenderState.SetObjectColor(0xffffffff); gl_RenderState.SetDynLight(0, 0, 0); gl_RenderState.EnableBrightmap(false); glset.lightmode = oldlightmode; }
//========================================================================== // // // //========================================================================== void GLWall::DrawDecal(DBaseDecal *decal) { line_t * line=seg->linedef; side_t * side=seg->sidedef; int i; float zpos; int light; int rel; float a; bool flipx, flipy; DecalVertex dv[4]; FTextureID decalTile; if (decal->RenderFlags & RF_INVISIBLE) return; if (type==RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures. //if (decal->sprite != 0xffff) { decalTile = decal->PicNum; flipx = !!(decal->RenderFlags & RF_XFLIP); flipy = !!(decal->RenderFlags & RF_YFLIP); } /* else { decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0]; flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1; } */ FTexture *texture = TexMan[decalTile]; if (texture == NULL) return; FMaterial *tex; tex = FMaterial::ValidateTexture(texture, true); // the sectors are only used for their texture origin coordinates // so we don't need the fake sectors for deep water etc. // As this is a completely split wall fragment no further splits are // necessary for the decal. sector_t *frontsector; // for 3d-floor segments use the model sector as reference if ((decal->RenderFlags&RF_CLIPMASK)==RF_CLIPMID) frontsector=decal->Sector; else frontsector=seg->frontsector; switch (decal->RenderFlags & RF_RELMASK) { default: // No valid decal can have this type. If one is encountered anyway // it is in some way invalid so skip it. return; //zpos = decal->z; //break; case RF_RELUPPER: if (type!=RENDERWALL_TOP) return; if (line->flags & ML_DONTPEGTOP) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } else { zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling); } break; case RF_RELLOWER: if (type!=RENDERWALL_BOTTOM) return; if (line->flags & ML_DONTPEGBOTTOM) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } else { zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor); } break; case RF_RELMID: if (type==RENDERWALL_TOP || type==RENDERWALL_BOTTOM) return; if (line->flags & ML_DONTPEGBOTTOM) { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor); } else { zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); } } if (decal->RenderFlags & RF_FULLBRIGHT) { light = 255; rel = 0; } else { light = lightlevel; rel = rellight + getExtraLight(); } FColormap p = Colormap; if (glset.nocoloredspritelighting) { p.Decolorize(); } a = decal->Alpha; // now clip the decal to the actual polygon float decalwidth = tex->TextureWidth() * decal->ScaleX; float decalheight= tex->TextureHeight() * decal->ScaleY; float decallefto = tex->GetLeftOffset() * decal->ScaleX; float decaltopo = tex->GetTopOffset() * decal->ScaleY; float leftedge = glseg.fracleft * side->TexelLength; float linelength = glseg.fracright * side->TexelLength - leftedge; // texel index of the decal's left edge float decalpixpos = (float)side->TexelLength * decal->LeftDistance - (flipx? decalwidth-decallefto : decallefto) - leftedge; float left,right; float lefttex,righttex; // decal is off the left edge if (decalpixpos < 0) { left = 0; lefttex = -decalpixpos; } else { left = decalpixpos; lefttex = 0; } // decal is off the right edge if (decalpixpos + decalwidth > linelength) { right = linelength; righttex = right - decalpixpos; } else { right = decalpixpos + decalwidth; righttex = decalwidth; } if (right<=left) return; // nothing to draw // one texture unit on the wall as vector float vx=(glseg.x2-glseg.x1)/linelength; float vy=(glseg.y2-glseg.y1)/linelength; dv[1].x=dv[0].x=glseg.x1+vx*left; dv[1].y=dv[0].y=glseg.y1+vy*left; dv[3].x=dv[2].x=glseg.x1+vx*right; dv[3].y=dv[2].y=glseg.y1+vy*right; zpos+= (flipy? decalheight-decaltopo : decaltopo); dv[1].z=dv[2].z = zpos; dv[0].z=dv[3].z = dv[1].z - decalheight; dv[1].v=dv[2].v = tex->GetVT(); dv[1].u=dv[0].u = tex->GetU(lefttex / decal->ScaleX); dv[3].u=dv[2].u = tex->GetU(righttex / decal->ScaleX); dv[0].v=dv[3].v = tex->GetVB(); // now clip to the top plane float vzt=(ztop[1]-ztop[0])/linelength; float topleft=this->ztop[0]+vzt*left; float topright=this->ztop[0]+vzt*right; // completely below the wall if (topleft<dv[0].z && topright<dv[3].z) return; if (topleft<dv[1].z || topright<dv[2].z) { // decal has to be clipped at the top // let texture clamping handle all extreme cases dv[1].v=(dv[1].z-topleft)/(dv[1].z-dv[0].z)*dv[0].v; dv[2].v=(dv[2].z-topright)/(dv[2].z-dv[3].z)*dv[3].v; dv[1].z=topleft; dv[2].z=topright; } // now clip to the bottom plane float vzb=(zbottom[1]-zbottom[0])/linelength; float bottomleft=this->zbottom[0]+vzb*left; float bottomright=this->zbottom[0]+vzb*right; // completely above the wall if (bottomleft>dv[1].z && bottomright>dv[2].z) return; if (bottomleft>dv[0].z || bottomright>dv[3].z) { // decal has to be clipped at the bottom // let texture clamping handle all extreme cases dv[0].v=(dv[1].z-bottomleft)/(dv[1].z-dv[0].z)*(dv[0].v-dv[1].v) + dv[1].v; dv[3].v=(dv[2].z-bottomright)/(dv[2].z-dv[3].z)*(dv[3].v-dv[2].v) + dv[2].v; dv[0].z=bottomleft; dv[3].z=bottomright; } if (flipx) { float ur = tex->GetUR(); for(i=0;i<4;i++) dv[i].u=ur-dv[i].u; } if (flipy) { float vb = tex->GetVB(); for(i=0;i<4;i++) dv[i].v=vb-dv[i].v; } // calculate dynamic light effect. if (gl_lights && GLRenderer->mLightCount && !gl_fixedcolormap && gl_light_sprites) { // Note: This should be replaced with proper shader based lighting. double x, y; decal->GetXY(seg->sidedef, x, y); gl_SetDynSpriteLight(NULL, x, y, zpos, sub); } // alpha color only has an effect when using an alpha texture. if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha) { gl_RenderState.SetObjectColor(decal->AlphaColor|0xff000000); } gl_SetRenderStyle(decal->RenderStyle, false, false); gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha)); // If srcalpha is one it looks better with a higher alpha threshold if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold); else gl_RenderState.AlphaFunc(GL_GREATER, 0.f); gl_SetColor(light, rel, p, a); // for additively drawn decals we must temporarily set the fog color to black. PalEntry fc = gl_RenderState.GetFogColor(); if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) { gl_RenderState.SetFog(0,-1); } FQuadDrawer qd; for (i = 0; i < 4; i++) { qd.Set(i, dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v); } if (lightlist == NULL) { gl_RenderState.Apply(); qd.Render(GL_TRIANGLE_FAN); } else { for (unsigned k = 0; k < lightlist->Size(); k++) { secplane_t &lowplane = k == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[k + 1].plane; float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y); float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y); if (low1 < dv[1].z || low2 < dv[2].z) { int thisll = (*lightlist)[k].caster != NULL ? gl_ClampLight(*(*lightlist)[k].p_lightlevel) : lightlevel; FColormap thiscm; thiscm.FadeColor = Colormap.FadeColor; thiscm.CopyFrom3DLight(&(*lightlist)[k]); gl_SetColor(thisll, rel, thiscm, a); if (glset.nocoloredspritelighting) thiscm.Decolorize(); gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add); gl_RenderState.SetSplitPlanes((*lightlist)[k].plane, lowplane); gl_RenderState.Apply(); qd.Render(GL_TRIANGLE_FAN); } if (low1 <= dv[0].z && low2 <= dv[3].z) break; } } rendered_decals++; gl_RenderState.SetTextureMode(TM_MODULATE); gl_RenderState.SetObjectColor(0xffffffff); gl_RenderState.SetFog(fc,-1); gl_RenderState.SetDynLight(0,0,0); }
//========================================================================== // // // //========================================================================== void GLWall::Draw(int pass) { int rel; int tmode; #ifdef _DEBUG if (seg->linedef-lines==879) { int a = 0; } #endif switch (pass) { case GLPASS_LIGHTSONLY: SetupLights(); break; case GLPASS_ALL: SetupLights(); // fall through case GLPASS_PLAIN: rel = rellight + getExtraLight(); gl_SetColor(lightlevel, rel, Colormap,1.0f); tmode = gl_RenderState.GetTextureMode(); if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, false); else { if (flags & GLT_CLAMPY) { if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); } gl_SetFog(255, 0, NULL, false); } gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW)); gl_RenderState.SetMaterial(gltexture, flags & 3, false, -1, false); RenderWall(RWF_TEXTURED|RWF_GLOW); gl_RenderState.EnableGlow(false); gl_RenderState.SetTextureMode(tmode); break; case GLPASS_TRANSLUCENT: switch (type) { case RENDERWALL_MIRRORSURFACE: RenderMirrorSurface(); break; case RENDERWALL_FOGBOUNDARY: RenderFogBoundary(); break; case RENDERWALL_COLORLAYER: glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -128.0f); RenderTranslucentWall(); glDisable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0, 0); default: RenderTranslucentWall(); break; } } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // // 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(); }