Compare commits

...
Author SHA1 Message Date
alufolie91 3f68b0f8c1 OpenGL: prefer GL_RGBA for water screen copy
as per recommended https://wikis.khronos.org/opengl/Common_Mistakes
2026-10-01 19:30:35 +02:00
alufolie91 938c95c80d Merge branch 'Saturn-Next' into waterrefract 2026-08-23 03:30:14 +02:00
alufolie91 dfc7b5482e Merge branch 'Saturn-Next' into waterrefract 2026-07-20 16:45:18 +02:00
alufolie91 d258c920de Merge remote-tracking branch 'origin/Saturn-Next' into waterrefract 2026-07-20 11:47:31 +02:00
alufolie91 b3eac23977 dont draw refraction planes in wireframe mode
idk but this prob just fucks shit up
2026-07-17 22:43:31 +02:00
alufolie91 a114dd840b Merge branch 'Saturn-Next' into waterrefract 2026-07-17 22:43:28 +02:00
alufolie91 87fa339c8d tweak ripple and refraction shaders
this much much more closely resembles the software effect
i manually tweaked this until it looked very similar
its still not quite perfect probably, but in many cases its a close match
2026-07-17 08:39:26 +02:00
alufolie91 afb5b717fe smol change to GL_DrawWaterPolygon
this doesent need anything, its basically just a blank polygon, so can save some work and also pass less stuff to this
2026-07-16 20:20:45 +02:00
alufolie91 1a7dc425d2 remove horizonline handling for refraction planes
forgot those wont work with fofs anyways
still need to look into that sometime
but thisll save some perf
2026-07-16 18:31:45 +02:00
alufolie91 038e8f0864 clean up the refraction shader a bit
most stuff wasnt needed, forgot to remove it earlier
2026-07-16 18:18:36 +02:00
alufolie91 8ac506bf35 change how water refraction is handled
split it into its own pass
we will draw "refraction planes" before drawing anything translucent
this way we wont cause any draw order issues or anything like that
this is also a bit faster and more sane than the other approach
only caveat: translucent stuff behind water planes is unaffected by refraction
but better than it was before, and sure better than trying to copy the screen per plane or shit like that lol
like this, this should be mostly feasible to actually use, the skybox water stuff kinda was a non issue since i noticed even just normal water does not draw over the map geometry (must have misremembered that part since software does do that), but still might be worth looking into at some point
2026-07-16 17:57:55 +02:00
alufolie91 6cf2561dd3 dedupe GL_DrawWaterPolygon 2026-07-16 17:57:52 +02:00
alufolie91 3e459d4a21 WIP: OpenGL water refraction
tries to replicate the effect from software renderer
this is quite a mess, but finally feel like pushing this since i finally figured out the depth testing stuff
this still has some issues:
-map geometry in front of skybox water will just draw over it completely (not super sure how to fix this other than deferring water rendering after rendering both skybox and normal scene)
-translucent geometry is not included in refraction (and may draw in front of it?), software also suffers from this in certain cases, i just hope its not that visible

this really needs a cleanup at some point
and due to how this is setup for floor and ceiling planes this also costs quite a lot of gpu time (atleast on the cpu side this costs barely anything)
2026-07-16 17:57:46 +02:00
9 changed files with 401 additions and 12 deletions

No files matched your search

+1
View File
@@ -191,6 +191,7 @@ enum
SHADER_SPRITE,
SHADER_MODEL,
SHADER_WATER,
SHADER_WATERREFRACT,
SHADER_FOG,
SHADER_SKY,
SHADER_PALETTE_POSTPROCESS,
+1
View File
@@ -39,6 +39,7 @@ void GL_EnableStencilTest(void);
void GL_DisableStencilTest(void);
void GL_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
void GL_DrawWaterPolygon(FOutVector *pOutVerts, FUINT iNumPts);
void GL_DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray);
void GL_Draw2DLine(F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
+261 -4
View File
@@ -103,6 +103,8 @@ static constexpr INT32 bsp_culling_distances[] = {
// Performance stats
ps_metric_t ps_hw_nodesorttime = {};
ps_metric_t ps_hw_nodedrawtime = {};
ps_metric_t ps_hw_waterdrawtime = {};
ps_metric_t ps_hw_spritesorttime = {};
ps_metric_t ps_hw_spritedrawtime = {};
@@ -712,7 +714,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
if (PolyFlags & PF_Fog)
shader = SHADER_FOG;
else if (cv_ripplewater.value && (PolyFlags & PF_Ripple))
{
shader = SHADER_WATER;
}
else
shader = SHADER_FLOOR;
@@ -807,6 +811,164 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
#undef SETUP3DVERT
}
// cut down version of HWR_RenderPlane
// which renders only the refracted scene in place of planes
// FIXME: we probably could just use stencil stuff for this
// but i hate messing with that
static void HWR_RenderRefractionPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, sector_t *FOFsector)
{
FOutVector *v3d;
polyvertex_t *pv;
pslope_t *slope = NULL;
size_t nrPlaneVerts;
INT32 i;
float height; // constant y for all points on the convex flat polygon
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
poly_t *planepoly = xsub->planepoly;
// no convex poly were generated for this subsector
if (!planepoly)
return;
nrPlaneVerts = planepoly->numpts;
if (nrPlaneVerts < 3) // not even a triangle ?
return;
const sector_t *sec = FOFsector;
// Get the slope pointer to simplify future code
if (!isceiling && sec->f_slope)
slope = sec->f_slope;
else if (isceiling && sec->c_slope)
slope = sec->c_slope;
height = FixedToFloat(fixedheight);
// Allocate plane-vertex buffer if we need to
if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts)
{
numAllocedPlaneVerts = (UINT16)nrPlaneVerts;
Z_Free(planeVerts);
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
}
pv = planepoly->pts;
#define SETUP3DVERT(vert, vx, vy) {\
vert->s = 0.0f;\
vert->t = 0.0f;\
\
if (slope)\
{\
fixedheight = P_GetSlopeZAt(slope, FloatToFixed((vx)), FloatToFixed((vy)));\
height = FixedToFloat(fixedheight);\
}\
\
vert->x = (vx);\
vert->y = height;\
vert->z = (vy);\
\
}
for (i = 0, v3d = planeVerts; i < (INT32)nrPlaneVerts; i++, v3d++, pv++)
SETUP3DVERT(v3d, pv->x, pv->y);
GL_DrawWaterPolygon(planeVerts, nrPlaneVerts);
//FIXME: horizonlines with fofs dont work in gl for some reason!
(void)subsector;
/*if (gl_maphashorizonlines && subsector && cv_glhorizonlines.value)
{
// Horizon lines
FOutVector horizonpts[6];
float dist, vx, vy;
float x1, y1, xd, yd;
UINT8 numplanes, j;
vertex_t v; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion;
static constexpr float renderdist = 27000.0f; // How far out to properly render the plane
static constexpr float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
const seg_t *line = &segs[subsector->firstline];
for (i = 0; i < subsector->numlines; i++, line++)
{
if (line->polyseg)
continue;
line_t* ld = line->linedef;
// this check sucks and is a hotspot lel
if (LIKELY(ld->special != HORIZONSPECIAL))
continue;
if (R_PointOnSegSide(viewx, viewy, line) != 0)
continue;
P_ClosestPointOnLine(viewx, viewy, ld, &v);
dist = FixedToFloat(R_PointToDist(v.x, v.y));
x1 = (line->fv1.x);
y1 = (line->fv1.y);
xd = (line->fv2.x) - x1;
yd = (line->fv2.y) - y1;
// Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion
dist = sqrtf((xd*xd) + (yd*yd)) / dist / 16.0f;
if (dist > 100.0f)
numplanes = 100;
else
numplanes = (UINT8)dist + 1;
for (j = 0; j < numplanes; j++)
{
// Left side
vx = x1 + xd * j / numplanes;
vy = y1 + yd * j / numplanes;
SETUP3DVERT((&horizonpts[1]), vx, vy);
dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2));
vx = (vx - gl_viewx) * renderdist / dist + gl_viewx;
vy = (vy - gl_viewy) * renderdist / dist + gl_viewy;
SETUP3DVERT((&horizonpts[0]), vx, vy);
// Right side
vx = x1 + xd * (j+1) / numplanes;
vy = y1 + yd * (j+1) / numplanes;
SETUP3DVERT((&horizonpts[2]), vx, vy);
dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2));
vx = (vx - gl_viewx) * renderdist / dist + gl_viewx;
vy = (vy - gl_viewy) * renderdist / dist + gl_viewy;
SETUP3DVERT((&horizonpts[3]), vx, vy);
// Horizon fills
vx = (horizonpts[0].x - gl_viewx) * farrenderdist / renderdist + gl_viewx;
vy = (horizonpts[0].z - gl_viewy) * farrenderdist / renderdist + gl_viewy;
SETUP3DVERT((&horizonpts[5]), vx, vy);
horizonpts[5].y = gl_viewz;
vx = (horizonpts[3].x - gl_viewx) * farrenderdist / renderdist + gl_viewx;
vy = (horizonpts[3].z - gl_viewy) * farrenderdist / renderdist + gl_viewy;
SETUP3DVERT((&horizonpts[4]), vx, vy);
horizonpts[4].y = gl_viewz;
// Draw
GL_DrawWaterPolygon(&Surf, horizonpts, 6, PF_NoTexture|PF_Ripple);
}
}
}
*/
#undef SETUP3DVERT
}
#ifdef WALLSPLATS
static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
{
@@ -4225,7 +4387,9 @@ static void HWR_RenderDrawNodes(void)
// Reversed order
for (i = 0; i < numdrawnodes; i++)
{
sortindex[i] = numdrawnodes - i - 1;
}
// The order is correct apart from planes in the same subsector.
// So scan the list and sort out these cases.
@@ -4301,7 +4465,6 @@ static void HWR_RenderDrawNodes(void)
HWR_RenderPolyObjectPlane(polyplane->polysector, polyplane->isceiling, polyplane->fixedheight, polyplane->blend, polyplane->lightlevel,
polyplane->lumpnum, polyplane->FOFSector, polyplane->alpha, polyplane->planecolormap);
}
break;
case DRAWNODE_WALL:
@@ -4325,6 +4488,89 @@ static void HWR_RenderDrawNodes(void)
drawnodes.clear(); // clear so our size is 0 again!
}
static void HWR_RenderRefractionWater(void)
{
// this basically just draws a refracted screen copy in the place of water planes
// best approach i can think of to handle translucent things being drawn behind water planes
// this means other translucent shit will appear "correctly" and does not cause any sorting issues
// caveat: anything translucent behind water planes will be unaffected by the refraction effect
// there just is no better way to do this unless we wanna trash performance to hell by doing a screen copy per water plane
// it "might" be possible to only partially copy the screen like the software renderer
// but that will be rather tricky to implement since we dont really have "screen bounds" we can use for this
// plus i also immensely suck at maths
static std::vector<gl_drawnode_t> waterdrawnodes;
const size_t numdrawnodes = drawnodes.size();
// no drawnodes...
if (!numdrawnodes)
return;
waterdrawnodes.reserve(DRAWNODES_INIT_SIZE/2); // surely there will be less water than other stuff, right?
// go through our drawnodes to pull out the water
// HWR_RenderDrawNodes will skip those
// we do this before since trying to capture
// anything translucent in the refraction is utter arse pain
for (size_t w = 0; w < numdrawnodes; w++)
{
gl_drawnode_t *drawnode = &drawnodes[w];
// gotta be a plane duh
if (drawnode->type != DRAWNODE_PLANE)
continue;
planeinfo_t *plane = &drawnode->u.plane;
// uh dont think we actually need this lol
// but better be safe for now
if (plane->alpha >= 255)
continue;
// this only applies to translucent water with ripple effect!
if (!(plane->blend & PF_Ripple))
continue;
waterdrawnodes.push_back(drawnodes[w]);
}
const size_t numwaterdrawnodes = waterdrawnodes.size();
// no water....
if (!numwaterdrawnodes)
return;
// this is probably a bit wasteful
// since we only copy the screen once
// but you might be able to see both planes not overlap if you look from a wonky angle
auto wotercompare = [](const void *p1, const void *p2)
{
const gl_drawnode_t *n1 = (const gl_drawnode_t *)p1;
const gl_drawnode_t *n2 = (const gl_drawnode_t *)p2;
return abs(n2->u.plane.fixedheight - viewz) -
abs(n1->u.plane.fixedheight - viewz);
};
qs22j(waterdrawnodes.data(), waterdrawnodes.size(), sizeof(gl_drawnode_t), wotercompare);
GL_SetTransform(&atransform);
GL_CopyMainFramebufferTexture();
GL_CopyMainFramebufferDepth();
// now finally render the refraction planes
for (auto &drawnode : waterdrawnodes)
{
planeinfo_t *plane = &drawnode.u.plane;
gl_frontsector = NULL;
HWR_RenderRefractionPlane(NULL, plane->xsub, plane->isceiling, plane->fixedheight, plane->FOFSector);
}
waterdrawnodes.clear();
}
// --------------------------------------------------------------------------
// Draw all vissprites
// --------------------------------------------------------------------------
@@ -5601,9 +5847,20 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, int stencil_level, bool
HWR_DrawSprites<DrawSpritesType::kSprites>();
PS_STOP_TIMING(ps_hw_spritedrawtime);
ps_numdrawnodes.value.i = 0;
ps_hw_nodesorttime.value.p = 0;
ps_hw_nodedrawtime.value.p = 0;
ps_numdrawnodes.value.i = 0;
ps_hw_nodesorttime.value.p = 0;
ps_hw_nodedrawtime.value.p = 0;
ps_hw_waterdrawtime.value.p = 0;
// thisll be a good mess making this toggable
if (cv_ripplewater.value && HWR_UseShader() && !wireframe) // dont need this without shaders do we
{
// should we not do this during portal render?
// wonder how bad the perf will be....
PS_START_TIMING(ps_hw_waterdrawtime);
HWR_RenderRefractionWater();
PS_STOP_TIMING(ps_hw_waterdrawtime);
}
HWR_RenderDrawNodes();
+1
View File
@@ -68,6 +68,7 @@ enum
// Performance stats
extern ps_metric_t ps_hw_nodesorttime;
extern ps_metric_t ps_hw_nodedrawtime;
extern ps_metric_t ps_hw_waterdrawtime;
extern ps_metric_t ps_hw_spritesorttime;
extern ps_metric_t ps_hw_spritedrawtime;
+3
View File
@@ -41,6 +41,9 @@ static struct {
// Water shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
// Water refraction shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATERREFRACT_FRAGMENT_SHADER},
// Fog shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
+38 -8
View File
@@ -243,23 +243,30 @@
// Water surface shader
//
// Mostly guesstimated, rather than the rest being built off Software science.
// Still needs to distort things underneath/around the water...
// Still needs to distort things underneath/around the water... // huehueuehuehue
//
// readjusted to match software much more closely
#define GLSL_WATER_CONST \
"const float freq = 0.07;\n" \
"const float amp = 0.07;\n" \
"const float amp_t = 0.025;\n" \
"const float speed = 4.0;\n" \
"const float pi = 3.14159;\n" \
"const float falltresh = 0.007;\n" \
#define GLSL_WATER_TEXEL \
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
"float sdistort = sin(a) * amp;\n" \
"float cdistort = cos(a) * amp;\n" \
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n"
"float falloff = 1.0 / (1.0 + water_z * falltresh);\n" \
"float distort = sin(a) * amp * falloff;\n" \
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - distort, gl_TexCoord[0].t));\n" \
#define GLSL_WATER_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_FLOOR_FUDGES \
"const float freq = 0.025;\n" \
"const float amp = 0.025;\n" \
"const float speed = 2.0;\n" \
"const float pi = 3.14159;\n" \
GLSL_WATER_CONST \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
@@ -294,6 +301,29 @@
"}\n" \
"#endif\0"
// water refraction stuff
// this is probably complete shit but i dont care
// got the idea for depth testing from https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html
#define GLSL_WATERREFRACT_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_WATER_CONST \
"uniform sampler2D scene_tex;\n" \
"uniform sampler2D scene_depth_tex;\n" \
"uniform vec2 scr_resolution;\n" \
"uniform float leveltime;\n" \
"void main(void) {\n" \
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
"float falloff = 1.0 / (1.0 + water_z * falltresh);\n" \
"float distort = sin(a) * amp * falloff;\n" \
"vec2 uv = (gl_FragCoord.xy / scr_resolution) + vec2(distort, distort * 2.0) * 0.04;\n" \
"float scenedepth = texture2D(scene_depth_tex, uv).r;\n" \
"if (scenedepth < gl_FragCoord.z) {\n" \
"discard;\n" \
"}\n" \
"gl_FragColor = texture2D(scene_tex, uv);\n" \
"}\0"
//
// Fog block shader
//
+91
View File
@@ -173,6 +173,15 @@ boolean supportstencil = false;
// can know when the textures aren't there, as textures are always considered resident in their virtual memory
static GLuint screenTextures[NUMSCREENTEXTURES] = {};
// for water refraction
enum
{
SCENE_TEX,
SCENE_DEPTHTEX,
NUMSCENETEXTURES
};
static GLuint sceneTextures[NUMSCENETEXTURES] = {};
#define byte2float(byte) (GLfloat)(byte / 255.0f)
// -----------------+
@@ -723,6 +732,9 @@ typedef enum
gluniform_palette_lookup_tex, // 3d texture containing the rgb->index lookup table
gluniform_lighttable_tex, // 2d texture containing a light table
gluniform_scene_tex,
gluniform_scene_depth_tex,
// misc.
gluniform_leveltime,
@@ -2386,6 +2398,9 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
// misc.
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
shader->uniforms[gluniform_scene_tex] = GETUNI("scene_tex");
shader->uniforms[gluniform_scene_depth_tex] = GETUNI("scene_depth_tex");
#undef GETUNI
// set permanent uniform values
@@ -2400,6 +2415,9 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
UNIFORM_1(shader->uniforms[gluniform_palette_lookup_tex], 1, pglUniform1i);
UNIFORM_1(shader->uniforms[gluniform_lighttable_tex], 2, pglUniform1i);
UNIFORM_1(shader->uniforms[gluniform_scene_tex], 4, pglUniform1i);
UNIFORM_1(shader->uniforms[gluniform_scene_depth_tex], 5, pglUniform1i);
// restore gl shader state
pglUseProgram(gl_shaderstate.program);
#undef UNIFORM_1
@@ -2480,6 +2498,24 @@ void GL_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, F
Clamp2D(GL_TEXTURE_WRAP_T);
}
void GL_DrawWaterPolygon(FOutVector *pOutVerts, FUINT iNumPts)
{
GL_SetShader(HWR_GetShaderFromTarget(SHADER_WATERREFRACT));
pglActiveTexture(GL_TEXTURE4);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_TEX]);
pglActiveTexture(GL_TEXTURE0);
pglActiveTexture(GL_TEXTURE5);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_DEPTHTEX]);
pglActiveTexture(GL_TEXTURE0);
GL_PreparePolygon(NULL, PF_NoTexture|PF_Ripple);
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
}
void GL_DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray)
{
GL_PreparePolygon(pSurf, PolyFlags);
@@ -3384,6 +3420,57 @@ void GL_Framebuffer_Disable(void)
}
#endif
// faster than fbo blitting ig...
// just copies the whole framebuffer as a texture
void GL_CopyMainFramebufferTexture(void)
{
if (!sceneTextures[SCENE_TEX])
{
pglGenTextures(1, &sceneTextures[SCENE_TEX]);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_TEX]);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglBindTexture(GL_TEXTURE_2D, 0);
}
// now copy the whole scene
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_TEX]);
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen_width, screen_height);
// not sure why, but this is needed
// otherwise bad things happen
tex_downloaded = sceneTextures[SCENE_TEX];
pglBindTexture(GL_TEXTURE_2D, 0);
}
void GL_CopyMainFramebufferDepth(void)
{
if (!sceneTextures[SCENE_DEPTHTEX])
{
pglGenTextures(1, &sceneTextures[SCENE_DEPTHTEX]);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_DEPTHTEX]);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, screen_width, screen_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglBindTexture(GL_TEXTURE_2D, 0);
}
// and copy the depth from the scene
// we need this for depth testing within the shader
// so we can discard stuff in front of the water
// this aint reflections after all!
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_DEPTHTEX]);
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen_width, screen_height);
pglBindTexture(GL_TEXTURE_2D, 0);
}
static const float defaultscreenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
@@ -3505,6 +3592,10 @@ void GL_FlushScreenTextures(void)
{
pglDeleteTextures(NUMSCREENTEXTURES, screenTextures);
memset(screenTextures, 0, sizeof(screenTextures));
// gotta wipe the scene textures for the water refraction stuff aswell
pglDeleteTextures(NUMSCENETEXTURES, sceneTextures);
memset(sceneTextures, 0, sizeof(sceneTextures));
}
void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags)
+3
View File
@@ -104,6 +104,9 @@ void GL_Framebuffer_Disable(void);
extern int supportFBO;
#endif
void GL_CopyMainFramebufferTexture(void);
void GL_CopyMainFramebufferDepth(void);
// ==========================================================================
// GLOBAL
// ==========================================================================
+2
View File
@@ -98,6 +98,7 @@ perfstatrow_t rendertime_rows[] = {
{" sprdraw", " Sprite render: ", &ps_hw_spritedrawtime, PS_TIME|PS_LEVEL|PS_HW},
{" nodesrt", " Drwnode sort: ", &ps_hw_nodesorttime, PS_TIME|PS_LEVEL|PS_HW},
{" nodedrw", " Drwnode render:", &ps_hw_nodedrawtime, PS_TIME|PS_LEVEL|PS_HW},
{" wtrdrw", " Water render: ", &ps_hw_waterdrawtime, PS_TIME|PS_LEVEL|PS_HW},
{" other ", " Other: ", &ps_otherrendertime, PS_TIME|PS_LEVEL|PS_HW},
#endif
@@ -536,6 +537,7 @@ static void PS_UpdateFrameStats(void)
ps_skyboxtime.value.p +
ps_hw_nodesorttime.value.p +
ps_hw_nodedrawtime.value.p +
ps_hw_waterdrawtime.value.p +
ps_hw_spritesorttime.value.p +
ps_hw_spritedrawtime.value.p;