That’s the right idea, though remember that the render2d coordinate system has a range of 2.0 in both dimensions (it goes from -1 to 1), so the actual scale to exactly match an 800 x 600 window will be twice what you have (that is, divide by 400, 300 instead of dividing by 800, 600). That’s why you’re not quite matching up yet.
Note that you can write the font texture out to disk, for instance as a .png file, so you can look at it closely outside of Panda and see exactly how big your letters are in the texture. In order to get pixel-accurate text, these must be exactly the same pixel size in the texture as they appear onscreen.
While I was testing this, I discovered that when you have set Texture.FTNearest as the minfilter and you are rendering very small text, the graphics card is likely to choose the wrong pixel as the nearest pixel on alternating letters–so you end up with text that doesn’t line up on the baseline. An easy fix is to offset the text by 0.5 of a texel in u and v, which should put the UV coordinate exactly in the center of the texel. This appears to fix the baseline problem, at least on my graphics card.
I’ll check in this fix, so it will get picked up by future versions of Panda; in the meantime, you can work around it by putting an explicit texture transform of (0.5/256, -0.5/256) on your TextNodes. Or even better, (0.4/256, -0.4/256), which will work with current versions of Panda, as well as with new versions that have my fix.
Here’s your example, modified to give truly pixel-accurate text, or at least as truly pixel-accurate as your 3-D card can do. (Note that 3-D cards in general don’t actually ever promise to deliver pixel-accurate rendering, so your mileage may vary.)
from direct.directbase.DirectStart import *
from pandac.PandaModules import *
#Load the ttf font.
f = loader.loadFont("Font/arial.ttf")
#Create a text node for a 800x600 pixels screen.
tx1 = TextNode("myText")
tn1 = render2d.attachNewNode(tx1)
# Apply an offset to fix the low-level pixel accuracy.
tn1.setTexOffset(TextureStage.getDefault(), 0.4/256, -0.4/256)
# Generate the text immediately, to force the letters
# into the font now, so we can dump the font to disk.
# Dump the font texture into an image file, so we
# can inspect it outside of Panda and observe its
# pixel size directly.