Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Danfun64

Rendering OCD

Recommended Posts

Despite being a few years old as of this writing, I literally just noticed this thread, and it caught my interest. For whatever reason, certain ports align textures and sprites differently than others. Chocolate Doom, Boom and MBF look "right" when compared to DOS Doom, but other ports, like Eternity, PrBoom-Plus and even Crispy Doom look "wrong"... if you really want to be OCD about it.
 

Spoiler

 

On 6/19/2013 at 8:11 PM, Holering said:

dosbox_fullscreen
xOOGvGI.png

chocolate-doom_fullscreen
i1j6o0K.png

prboom-plus_fullscreen_4x3aspect
J1j8EFt.png
prboom-plus_fullscreen_5x4aspect
c8qst3C.png
prboom-plus_fullscreen_autoaspect
X4E3uQA.png

eternity_fullscreen_4x3aspect
7OOsYo4.png
eternity_fullscreen_5x4aspect
C6NZ9UT.png
eternity_fullscreen_legacy
2VM5AtT.png

odamex_fullscreen_stretch_doublehorizontal-doublevertical_640x400
QkecWKE.png

These are all double scaled from 320x200 to 640x400.

 

 

 

 

Here's my own pics of Crispy Doom, Crispy Doom Low Detail, Boom, and MBF 640x400 (open tab for full size)
 

Spoiler


6GzW8e.png

pQvt0F.png

jGEUeQ.png

TmFn2p.png


So my question is... why do certain ports have these kind of alignment problems... and more importantly, do they really matter?

Edited by Danfun64 : add additonal linebreak

Share this post


Link to post

One thing I can say for certain: I believe that the released Doom source code uses a different algorithm for drawing wall columns and flat spans, written in C, whereas the originals are written in assembly, included as a little extra with the source code, but not compiled by default. I don't know how much the column drawer differs, but the new span drawer does have some differences (and perhaps some improvements? I remember reading that Doom's normal span drawer starts getting uglier as it draws further to the right). EE's differences can likely be explained by the shift to the floating point based renderer, and PrBoom's renderer does have a lot of changes and bugfixes applied on top of it, which have likely changed things over the years. I do not know if its using drawers based on the asm originals or the c versions in the linuxdoom source.

 

The chocolate doom screenshot is darker than the dosbox screenshot, but I wouldn't be surprised if that's just due to the 6-bit color conversion.

Share this post


Link to post

When comparing the Vanilla screenshot with the Crispy 320x200 one, the most significant change can be found in the rendering of the flats. I am sure this can be explained by two fixes to the Vanilla code which led to distorted flat rendering (which became especially noticeable in the higher resolution), i.e.

https://github.com/fabiangreffrath/crispy-doom/blob/master/src/doom/r_plane.c#L138

and

https://github.com/fabiangreffrath/crispy-doom/blob/master/src/doom/r_draw.c#L977 .

 

Regarding the rendering of the segs in the distance, I think this can be attributed to the "line wiggle" and "long wall wobble" fixes. ;)

 

Also, which Crispy version was used for the screenshots? I have fiddled around with the fake contrast code at some point, but this has been fixed for the 4.3 release.

Share this post


Link to post

So you're saying that the way the flats are rendered in Vanilla/Chocolate/Boom/MBF is wrong? Considering how Crispy, Eternity, PrBoom-Plus, Odamex fix the rendering issues differently, is there a "right" way for the flats to be rendered/aligned?

 

As for the version of Crispy I am using... It's commit d4b04411

Share this post


Link to post

Excert from Chocolate r_draw.c

Spoiler

    // Blocky mode, need to multiply by 2.
    ds_x1 <<= 1;
    ds_x2 <<= 1;

    dest = ylookup[ds_y] + columnofs[ds_x1];

    do
    {
	// Calculate current texture index in u,v.
        ytemp = (position >> 4) & 0x0fc0;
        xtemp = (position >> 26);
        spot = xtemp | ytemp;

	// Lowres/blocky mode does it twice,
	//  while scale is adjusted appropriately.
	*dest++ = ds_colormap[ds_source[spot]];
	*dest++ = ds_colormap[ds_source[spot]];

	position += step;

    } while (count--);

 

 

Excert from Crispy r_draw.c

Spoiler

    // Blocky mode, need to multiply by 2.
    ds_x1 <<= 1;
    ds_x2 <<= 1;

    dest = ylookup[(ds_y << hires)] + columnofs[ds_x1];
    dest2 = ylookup[(ds_y << hires) + 1] + columnofs[ds_x1];

    do
    {
	// Calculate current texture index in u,v.
        // [crispy] fix flats getting more distorted the closer they are to the right
        ytemp = (ds_yfrac >> 10) & 0x0fc0;
        xtemp = (ds_xfrac >> 16) & 0x3f;
        spot = xtemp | ytemp;

	// Lowres/blocky mode does it twice,
	//  while scale is adjusted appropriately.
	*dest++ = ds_colormap[ds_source[spot]];
	*dest++ = ds_colormap[ds_source[spot]];
	if (hires)
	{
	    *dest2++ = ds_colormap[ds_source[spot]];
	    *dest2++ = ds_colormap[ds_source[spot]];
	}

//	position += step;
	ds_xfrac += ds_xstep;
	ds_yfrac += ds_ystep;


    } while (count--);

 

 

Excert from Chocolate r_draw.c

Spoiler

#ifdef RANGECHECK
    if (x2 < x1
     || x1 < 0
     || x2 >= viewwidth
     || y > viewheight)
    {
	I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
    }
#endif

    if (planeheight != cachedheight[y])
    {
	cachedheight[y] = planeheight;
	distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
	ds_xstep = cachedxstep[y] = FixedMul (distance,basexscale);
	ds_ystep = cachedystep[y] = FixedMul (distance,baseyscale);
    }
    else
    {
	distance = cacheddistance[y];
	ds_xstep = cachedxstep[y];
	ds_ystep = cachedystep[y];
    }

 


Excert from Crispy r_plane.c

Spoiler

#ifdef RANGECHECK
    if (x2 < x1
     || x1 < 0
     || x2 >= viewwidth
     || y > viewheight)
    {
	I_Error ("R_MapPlane: %i, %i at %i",x1,x2,y);
    }
#endif

// [crispy] visplanes with the same flats now match up far better than before
// adapted from prboom-plus/src/r_plane.c:191-239, translated to fixed-point math

    if (!(dy = abs(centery - y)))
    {
	return;
    }

    if (planeheight != cachedheight[y])
    {
	cachedheight[y] = planeheight;
	distance = cacheddistance[y] = FixedMul (planeheight, yslope[y]);
	ds_xstep = cachedxstep[y] = FixedMul (viewsin, planeheight) / dy;
	ds_ystep = cachedystep[y] = FixedMul (viewcos, planeheight) / dy;
    }
    else
    {
	distance = cacheddistance[y];
	ds_xstep = cachedxstep[y];
	ds_ystep = cachedystep[y];
    }

 

 

Share this post


Link to post
14 hours ago, Linguica said:

So uh how does this fix anything? I wish the comments would actually explain what has been changed and why.

 

I have to admit that it is not obvious (not even to me right now), but in the original code (which is still present but commented out) there was some accumulated precision loss due to rounding errors caused by repeated right shifting. That's why the distortion became more apparent on the right side of the screen (increasing horizontal screen coordinate).

 

> is there a "right" way for the flats to be rendered/aligned

 

I guess that the approach in Crispy (which I have taken over from PrBoom+, which in turn has taken it from ZDoom, I believe) is mathematically more correct, but the other code is Vanilla and thus "good enough" by itself. ;) However, the rendering distortion becomes worse with increased screen resolution and even with Crispy's 640x480 there were some places where this really hurt, and so I decided to fix the code.

 

PS: Isn't this thread better suited to the "Source Ports" section?

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×