Implementing proper lighting in DX9 ($100-$150 REWARD to the person who helps me!)

Started by
18 comments, last by Tom_W 4 years, 3 months ago

(IMMEDIATE $$100−$$150 DOLLAR REWARD TO THE PERSON WHO HELPS ME FIRST/THE MOST IN SOLVING THIS--*MUST* be ZELLE, not PayPal, PayPal banned my SSN in 2007 for ad-clicking back when I was a teenager writing botnets.)

Hey guys,

I'm writing my own game engine in C++ using DirectX 9(Don't ask why I'm not using 10/11, long story, I'll port it later when finished). In order to get the engine going, I'm starting out by making a little crappy slenderman-type horror game. Everything is going well, except for one part -- lighting. My engine parses BSP maps, so you can use map editors such as GTKRadiant and load them into the engine and she'll spit 'em out just fine, with perfect physics and all. But the lighting is terrible, as you'll see in the video provided. My engine is capable(or to *become* capable of both 2D and 3D games, and in the 3D aspect of the engine, to parse BSP trees, I borrowed a header file from Ken Wright's tutorials from xbdev.net(well, I essentially stole the damn thing) to parse BSP-tree's because I wasn't going to spent two months learning everything little particular thing about every class/struct for every item, shader, etc. I have "bsp.h" in my project, which is on my Google Drive below:

https://drive.google.com/open?id=16Q6pKQAPGZ_K4_K5lomSEsxZuwBhhcNV (If you're having problems helping me out and are still willing, I'd suggest looking at his source code for his projects on his site. The man's a genius in my eyes).

****If you're going to try and run his projects you will not be able to get any lighting whatsoever, you need to add pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); in DrawFace() under BSP.h to get *any* lighting effect whatsoever.

Now, normally a simple 3D game with a simple map wouldn't have the problem I'm having, because each face is created by two opposing tri-primitives to form a square/box/etc. Thing is, with BSP maps, they save the amount of tris drawn by, for example, making a massive roof out of two simple tri's and having the texture repeat itself over and over, giving the illusion of a large roof. This is, *I think*, where my problem lies. In my video, you'll see that the ceiling/floor simply disappear-reappear. This is because the ceiling and floor are just one massive face comprised of two tri's, and therefore, a simply point/spot light will not illuminate it as evenly as the walls around the player (the lightsource's position is the player/camera's position, so it illuminates as the player moves). So, as you can see in the video of my crappy test game, the lighting is in no way fluid and even, walls light up quickly, ceilings disappear altogether. This is a major brick wall I've hit in my engine thus far and am willing to pay the person who is able to give me the solution to this problem -- I'm traditionally an OpenGL guy, I'm no expert in DirectX by any stretch of the imagination, so please give me your answers in a way a toddler could understand. If I hear suggestions about altering Rendering Pipelines/Index/Vertex-Buffers/HLSL/Pixel Shading/Parallax mapping/Phenn-Phong-ping-pong-chinaman lighting without elaboration my head will explode, so please treat me as the mouth-breathing knuckle-dragging idiot I am.

Here is the video of my test game thus far(holy JESUS It's running at 20-odd FPS instead of ~65 because of the concurrent video capturing device sucking my GPU..I promise the game is not this horrible at run-time):

https://www.youtube.com/watch?v=bYK8agRr7M4

(The cursor is only visible due to the video capture, but that's irrelevant).

You can see as early as 0:40 seconds that the lighting is in no way even. I go into my debug console and adjust the lighting level accordingly, you can see the changes.

At 1:23, the scene looks really nice. Then the player approaches the wall and SNAP everything is lit.

At 1:55, you'll see the player is looking up, and there's no roof whatsoever. Just Blackness. Then I adjust the "brightness level", which is just the range of the spot light. Then boom, roof.

At various points throughout the video I go into wireframe mode, to attempt to show you guys the amount of polygons drawn. You'll notice there's only *one* line for the ceiling, hence I believe why it is not being illuminated. Everything except the lighting goes nicely, except I make too much damn noise, wake the monster, he gets his ass stuck in my yet-to-be-perfected pathfinding class, as you can see in the top-down view. Then, as the supreme humiliation, I get an access violation code in one of my linked lists because I've been rushing. This is a pre-pre-alpha experimental version of a game engine, please don't knock me for not coming to you guys with a perfect game with only a lighting problem :)

I'd like to be able to make it so the player is holding a flashlight, I'll just throw in a mesh for a light, render it, inverse the matrix to keep it rotating with the player. But I obviously cannot do that with lighting effects that are this bad. There *has* to be a way in DirectX to get around this, the last book I read on DX was for DX6 by Andre Lamothe and I was 12 years old. Not much knowledge was retained. So I really need the help of you fine gentlemen.

Now, as to the cash reward, I'm not joking. If you're able to find a solution to this problem, which I know I must not be the first to come into and the makers of this API must've anticipated, I *will* pay. You have my full name on YouTube, and if you still do not trust me, then make a video of you doing it successfully, send it to me, and I will pay you upfront prior to you sending me any kind of help. Why am I so desperate to get this done quickly? I'm on a deadline -- I have to show a judge that I've been able to write a perfect game engine by February 18th or I face 2-9 years in prison because one of my firearms was unregistered. I'm(actually ...was..) a paralegal in law school and worked with the DA's office for years and the understanding is I get off on probation, on a VIOLENT FELONY(it's *very* bad in NY to possess an unregistered firearm, it's a mandatory minimum of 3.5-15(Violent C) years in prison irrelevant to your criminal history, even though that breaks the second amendment, Article VI Section II of the constitution, and the mandatory minimum abridges the 8th amendment, but screw it NY does what it likes), and the DA I'm negotiating with is into IT as well. So I really need your help here, guys. Please.

tl;dr: Watch my video. Lighting is uneven regardless of how I fill a light/material structure and apply to device. I want to have the lighting fluid and even, going with the player, not random polygons illuminating/disappearing. Attenuation has had no effect on this whatsoever. It's how the polygons are drawn and lighting is applied that is the problem. Will pay for quick/easy-to-understand solution.

Thank you all very much in advance for your support. I'm really counting on someone here to help me out of this jam I'm in. Thanks!

Advertisement

Because of the questions I've been asked by other programmers regarding this issue, I've produced a video of my engine giving perfect lighting:



This is because the number of prims are even around the player at all times. Come now people, my reward still stands!

Tom_W said:
Thing is, with BSP maps, they save the amount of tris drawn by, for example, making a massive roof out of two simple tri's and having the texture repeat itself over and over, giving the illusion of a large roof. This is, *I think*, where my problem lies. In my video, you'll see that the ceiling/floor simply disappear-reappear. This is because the ceiling and floor are just one massive face comprised of two tri's, and therefore, a simply point/spot light will not illuminate it as evenly as the walls around the player (the lightsource's position is the player/camera's position, so it illuminates as the player moves).

Did only read this far - to read the whole post, i want more $$$ :D

Ok, seems you're right, and i see 3 options to address the problem:

  1. Use per pixel lighting in the pixel shader and replace your current vertex lighting approach with that. This is what everybody is doing nowadays.
  2. Tessellate (subdivide) your geometry, so triangles become smaller but also more of them. Notice this could become more complicated if you use BSP traversal and PVS for occlusion culling like Quake did - the new triangles would need a link to the the original large triangles to keep this stuff working.
  3. Don't use dynamic lighting at all, but use lightmaps, which your level editor tools should be able to generate. Additionally, use a fog effect to make distant stuff disappear.

JoeJ said:

Tom_W said:
Thing is, with BSP maps, they save the amount of tris drawn by, for example, making a massive roof out of two simple tri's and having the texture repeat itself over and over, giving the illusion of a large roof. This is, *I think*, where my problem lies. In my video, you'll see that the ceiling/floor simply disappear-reappear. This is because the ceiling and floor are just one massive face comprised of two tri's, and therefore, a simply point/spot light will not illuminate it as evenly as the walls around the player (the lightsource's position is the player/camera's position, so it illuminates as the player moves).

Did only read this far - to read the whole post, i want more $$$ :D

Ok, seems you're right, and i see 3 options to address the problem:

  1. Use per pixel lighting in the pixel shader and replace your current vertex lighting approach with that. This is what everybody is doing nowadays.
  2. Tessellate (subdivide) your geometry, so triangles become smaller but also more of them. Notice this could become more complicated if you use BSP traversal and PVS for occlusion culling like Quake did - the new triangles would need a link to the the original large triangles to keep this stuff working.
  3. Don't use dynamic lighting at all, but use lightmaps, which your level editor tools should be able to generate. Additionally, use a fog effect to make distant stuff disappear.

Thank you for your insightful reply. Tessellation is out of the question because a) BPS's PVS_Render()'s function would have to be completely redone, and even if I had the know-how, DX9 doesn't support Tessellation. It has the flags in d3dx9types.h, but doesn't seem to have them implemented. Option three is interesting, but it seems like using HLSL Per Pixel shading is the way to go. I've looked at some tutorials and have had very limited success(30 mins worth of trying) to implement a shader(Remember, I'm very inexperienced with Direct3D, although eager to learn). After loading a .fx shader as a resource file, loading it using DirectX's shader loading function, then filling in the global effect variable, you render like this?

 g_pDevice->SetVertexDeclaration(g_pVertexDecl);
    g_pDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(Vertex));

    // Render the cube.
    if (SUCCEEDED(g_pEffect->SetTechnique(hTechnique)))
    {
        if (SUCCEEDED(g_pEffect->Begin(&totalPasses, 0)))
        {
            for (UINT pass = 0; pass < totalPasses; ++pass)
            {
                if (SUCCEEDED(g_pEffect->BeginPass(pass)))
                {
                    g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 12);
                    g_pEffect->EndPass();
                }
            }

            g_pEffect->End();
        }
    }

That's just a code snippet from a demo using blinn phong. You have to run passes for every prim?

I'm new to this, eager to learn, and willing to pay. If someone knowledgeable such as yourself, or perhaps someone else, was willing to screenshare with me on discord or something to I guess “tutor” me, I'd be willing to pay. For someone like you it'd take a half hour to an hour max to implement the effect yourself, if I threw you source code and you applied per pixel shading and sent it to me, just for me to learn, I'd pay you, or anyone else reading this. Think of it as a $100/hour or more job tutoring me or simply doing it yourself and showing me the code(I'm the type that dives in the deep end and learns to sink/swim). I have zero experience with HLSL and vertex/index buffers piss me off(hence why I'm traditionally an OpenGL guy). But I'm willing to learn, and pay. If anyone other than yourself that has the knowledge to help me out I'd be financially grateful, and grateful overall. I'm sure we could negotiate something. ATM I'm very tired and not going to try to implement HLSL per-pixel shading right now, I need to sleep before trying it myself. But having an experienced person help me along would be something I'd be willing to pay for. Contact me and let me know(if you're willing), we can negotiate a rate.

Thanks!

Looks like pvs rendering is broken, anyway you should show us the video of rendering with the same movement with and without lighting, then we can compare wat is going on, i bet pvs rendering func, hiwever you should do point lights in pixel shaders, so you know where in ps you fill what color but thia will be canceled by dissapearing walls. After this you can expect someone will answer, first we need to figure whats going on here then we can try solve it

PVS Rendering is perfect, I'm just not able to use a small spot light for a flashlight effect because the player is literally looking at 3-4 tri's. I have to implement pixel shaders. Anyone have any advice on how to do this? I've never once used pixel shading.

You draw a scene (walls) using a shader where you pass spotlight position, spotlight direction, spotlight size with knowing the fragment world position you compare if its inside spotlight cone then apply proper ligjt intensity and color, ideally you save it as a texture which you blend with the scene

Tom_W said:
Tessellation is out of the question because a) BPS's PVS_Render()'s function would have to be completely redone, and even if I had the know-how, DX9 doesn't support Tessellation.

Just to clarify, i meant tessellating the triangles on CPU, e.g. while loading the data, not using shaders. Simple method would be to take midpoints of the edges and get 4 triangles from one. Because those new triangles still lie on the same plane as the original one, both BSP traversal and PVS data would keep working for example if you store a list of new triangles for each original triangle.

Can't help with DX9 becasue i never used it. But i can mention some points why lighting is such a rabbit hole. Assuming you manage to have a small set of point lights that can illuminate all your triangles per pixel, there are still the real problems left:

Sparse point lights will still leave most of your scene unlit and too dark. Old school solution is to have a constant ambient light that illuminates everything. But then there is no real darkness. Though, you can still use a fog effect to get it in the distance.

The point lights will leak through walls. To prevent this, you'd need to look into shadow maps as well.

So… things sum up and you still have no lighting that looks good after all this work (depending an what you need and expect.)

Notice how lightmaps solve all of those issues, while being limited to static geometry ofc. With lightmaps you have realistic GI with multiple bounces and infinite number of light sources. Many current games still use them, or another form of baked lighting. Dynamic lights can be added on top - for torch light, explosions etc. But this may be less important to get a basic, satisfying result at first, which lightmaps would provide.

Just saying this in the assumption you might not have thought about some of those points.

@JoeJ I actually stumbed upon a tesselation technique for BSP maps – but the vertex structs are a tad different:

void Bezier::tessellate(int L)  
{
 // The number of vertices along a side is 1 + num edges
 const int L1 = L + 1;

 mVertex = new BspVertex[L1*L1];
 mNumVertex = L1*L1;

 // Compute the vertices    
 for (int i = 0; i <= L; ++i)
 {
   float a = (float)i / L;
   float b = 1.0f - a;

   mVertex[i] =
     mControls[0] * (b * b) +  
     mControls[3] * (2 * b * a) +
     mControls[6] * (a * a);
 }

 for (int i = 1; i <= L; i++)  
 {
   float a = (float)i / L;
   float b = 1.0f - a;

   BspVertex temp[3];

   for (int j = 0; j < 3; j++)
   {
     int k = 3 * j;
     temp[j] =
       mControls[k + 0] * (b * b) +  
       mControls[k + 1] * (2 * b * a) +
       mControls[k + 2] * (a * a);
   }

   for(int j = 0; j <= L; ++j)  
   {
     float a = (float)j / L;
     float b = 1.0f - a;

     mVertex[i * L1 + j]=
       temp[0] * (b * b) +  
       temp[1] * (2 * b * a) +
       temp[2] * (a * a);
   }
 }

 // Compute the indices      
 mIndex = new unsigned int[L * (L + 1) * 2];
 mNumIndex = L * (L + 1) * 2;

 for (int row = 0; row < L; ++row)  
 {
   for(int col = 0; col <= L; ++col)  
   {
     mIndex[(row * (L + 1) + col) * 2 + 1] = row       * L1 + col;
     mIndex[(row * (L + 1) + col) * 2]     = (row + 1) * L1 + col;
   }
 }

 mTrianglesPerRow = new unsigned int[L];
 mRowIndex = new unsigned int[L];

 for (int row = 0; row < L; ++row)  
 {
   mTrianglesPerRow[row] = 2 * L1;
   //rowIndexes[row]      = &amp;indexes[row * 2 * L1];
   mRowIndex[row]      = row * 2 * L1;
 }

 for (int i=0; i < L1*L1; i++)
   mVertex[i].normalise();
}

with the vertex called BSPVertex: 

class BspVertex
{
public:
 BspVertex();
 BspVertex(float p[3], float texcoord[2][2], float n[3]);

 float mPosition[3];
 float mTexcoord[2][2];
 float mNormal[3];

 BspVertex operator+(BspVertex a);
 BspVertex operator*(float a);

 void normalise(void);

};

While the vertex struct used in my game is:


 struct stBSPVertex
{
 D3DXVECTOR3 p;   // Position Vertice
 D3DXVECTOR3 n;   // Vertice Normal
 DWORD  colour;  // ARGB
 float       tu1, tv1; // Texture Coordinates
 float  lu2, lv2; // Light Tex Coords
};

Any idea how I could implement this tesselation function for this struct type? At the moment I'm typing this I'm playing around with HLSL and it's not going well, I'm still learning here.

It seems I've reached an impass here. I've even done psuedo-tesselation by going into GTKRadiant and setting the polygon count higher for every face, though it makes the level look a little crazy. Trying HLSL isn't getting me far(though I haven't really gotten that far into it yet. I've considered upgrading to DX11, but my thinking behind staying with DX9 is a)All my code(and there's a lot of it) is sort of married to DX9's rendering pipeline, and b)I want my games to reach as many PC's as possible, if a simple DX11 app didn't run on my other five year old lenovo while my game did, that means my games would have a much less reach in terms of compatibility.

If I could get Tesselation to work, a simple Tesselate(int L) function for my BSP header file, I'd be happy for a long time – I could make a game and build an OOP engine around it while I learn. I have BSP.h uploaded on my Google Drive: https://drive.google.com/open?id=16Q6pKQAPGZ_K4_K5lomSEsxZuwBhhcNV

Or can someone show me a quick function that Tesselates one tri into three/etc when using DrawPrimative()? That would be great.

Someone with some serious knowledge/experience like you all seem to have, who is willing to tutor me and achieve results, I again state I'd pay you to teach me. I'm in a bit of a fix for time here – the probation dept and DA's office literally think I'm this Game developer genius, when my forte is actually writing networking apps. Come February 18th if I don't have something impressive to show, I'm screwed.



Thanks for your replies thus far ?

Ooh, fog! I just implemented fog, makes it nice and scary in combination with lights! Thank you MSDN docs! (Told you I was ignorant).

This topic is closed to new replies.

Advertisement