Struggling to find point light resources

Finally, success kosmo! I am very close now. I wasn’t setting my DiffuseTexture in the shader this whole time :frowning:

I ended up grabbing the texture from the current model and set it during draw. Don’t mind the terrible pixel art, just a placeholder. I’ve included two screenshots, one with a blue light and one lit somewhat normally. I’ve circled the bottom screenshot to highlight that for some reason, whatever I set sunlight to (In the below case, black), it colors whole surfaces that color. I’m still playing and tweaking, but I suspect this is something small.

If you have any insights on things I can tweak and try, I’d love to hear them. I cannot thank you enough for your help with all of this. I’ve learned so much! Now I have this feeling that I must keep going and learn more and more!

EDIT: I also noticed that lights will bleed through walls, but I suspect this is more due to intensity settings on my part.

Hey, that looks good!

light will bleed through walls and and all walls that look in the opposite of the sun light direction will get sunlight.

Light bleeds through walls because right now the pixels get colored depending on their normal (the direction they are facing) and their distance to the point lights. They have no clue that they are actually in shadow.

If you want to eliminate light bleeding you have to implement shadows! :stuck_out_tongue:

One thing though: If you do not want to write your own engine and learn 3d rendering on a basic level I would highly recommend switching to a proper engine that does that for you.
Shadows, lighting, material behaviour, animation etc. all would have to be implemented by yourself otherwise.
Personally I love this whole affair though, so I’ll stick with MonoGame right now.

I come from a more traditional coding background, -!; I love the challenges that 3D is giving me. I’m going to take the next step and learn how to implement shadows, hopefully I can get something work tonight. I too love doing things this way. The “experts” will tell you not to implement your own engine, but to me it is where the fun lies.

I’ll keep showIng oh my progress, more for fun than anything else! Once I get shadows in place, I’m going to put the shader out for free along with a tutorial.

great, I’m the same and 3d is super fun :slight_smile:

Actually I haven’t needed point light shadows yet, but I think I’ll try to do some myself today maybe

1 Like

Nice! I’d be curious to see what you come up with if you intend to share :slight_smile:

I’m going to try to do the same. I’m still trying to figure it out from there, but I’m hoping to make progress.

I struggle with how you apply the two shaders. It seems like shadow mapping only has the position of light, not any shading data, because you use the position to determine the normal data from the light position, I’m trying to understand how you overlay the shadow data around what’s lit or the other way around. Either way I’m playing with it until I can figure it out!

When @kosmonautgames says he intends to try something, it can end up in a full blog post detailing the entire process. It’s happened before. :wink:

2 Likes

ok guys, I’ve set up a new blog post about … nah not yet.

However, I build a new monogame project with the shader.

I’ve noticed I made another mistake in the specular shader, where i mistakenly forgot a minus

here is a better version

float4 CalcSpecularLight(float3 normal, float3 lightDirection, float3 cameraDirection, float4 lightColor, float lightIntensity)
{
    float3 halfVector = normalize(-lightDirection + -cameraDirection);
    float specular = saturate(dot(halfVector, normal));

    //I have all models be the same reflectance
    float specularPower = 20;

    return lightIntensity * lightColor * pow(abs(specular), specularPower);
}

Another note: I set it up so you can easily replace the diffuse and specular with more sophisticated shaders, like a diffuse Oren-Nayar model and a specular Cook-Torrance.
These are more expensive but lights look more realistic. Not sure if you need that though, just a note if you think the lighting is lacking.

Point light shadows are a huge pain actually, but I’ve got them working somehow in the most unefficient way possible.

3 Likes

Nice results :slight_smile: , are you using CubeMap Shadows or Dual-Paraboloid Shadows?

cubemap. Huge pain. Very unefficient so far. I do not cull at all and all maps are VSM shadows

Yeah, that’s why I implemented Dual-Paraboloid Shadow Maps. This technique uses only two textures instead of six cube map faces. It’s actually possible to render both paraboloids into one texture by writing depth to different color channels. :slight_smile:
Here is a shot of this technique (using Dual-Paraboloid Variance Shadow Maps) used in my engine:

Oh nice. How is artifacting toward the edges? Why do all big engines go the 6 projections way instead?

Well, there are actually two problems with this technique and they are tricky to hide.
First one is the seam between two shadow halves (paraboloids) after you blur the shadow map, but you can solve this by adjusting the blur on the edges of the map, or by offseting the depth by near plane distance (yeah, that’s weird but it works in my case).
The second one is the wrong vertex displacement due to low scene tessellation, but I haven’t encountered this yet.

This technique is great if you want to save on memory, 2 textures instead of 6.

Actually worse for memory, you need ~1.64 times the resolution for the same pixels covered since you have so much blank space. Plus the texel density is not as uniform obviously.

Much cheaper to render though, with cubemaps you have 3 times the drawcalls in the worst case.

It’s not worse for memory, although with Dual-Paraboloids you loose some of the texture space because of the spherical displacement, but it’s still two textures instead of six. Even if you want to have the resolution 1.64 times bigger you use less memory than when using cubemaps. :slight_smile:
In my case using 128x128 blurred maps is enough, so I don’t have to worry about the resolution. :wink:

Here’s a nice comparison of these two written by Wolfgang Engel: http://diaryofagraphicsprogrammer.blogspot.com/2008/12/dual-paraboloid-shadow-maps.html

worse for memory for the same quality i mean, if you have a 128x128x6 cubemap you would need to go at least 512x512x2 to match / exceed the quality, 256x256x2 is not sufficient in that case. But i guess that’s obvious.

EDIT nvm I thougth you linked this http://graphicsrunner.blogspot.de/2008/07/dual-paraboloid-shadow-maps.html

EDIT2: In case anyone reads this here is a link to an implementation of DPSM shadows in XNA http://www.kylehayward.com/Projects/paraboloid.htm this could surely help if you want to go this route :slight_smile:

These few posts are more information than I’ve technically found myself. I find myself learning more and more every time I turn around.

Kosmo,

Would you mind sharing your whole point light shader in its current state? No matter what I try with the specular, it just looks inverted and messed up. I think I’ve screwed it up along the way. I’m hoping to use yours to compare for mistakes so that I can learn what I did wrong. Somehow, even back to the specularLight question I asked some time ago, I can’t seem to get that working. I actually removed all of the specular code until I saw your screenshot. Sorry for being a pest, just not sure what to try next.

float4 CalcDiffuseLight(float3 normal, float3 lightDirection, float4 lightColor, float lightIntensity)
{
    return saturate(dot(normal, -lightDirection)) * lightIntensity * lightColor;
}

float4 CalcSpecularLight(float3 normal, float3 lightDirection, float3 cameraDirection, float4 lightColor, float lightIntensity)
{
    float3 halfVector = normalize(-lightDirection + -cameraDirection);
    float specular = saturate(dot(halfVector, normal));

    //I have all models be the same reflectance
    float specularPower = 20;

    return lightIntensity * lightColor * pow(abs(specular), specularPower);
}

// The squared length of a vector
float lengthSquared(float3 v1)
{
    return v1.x * v1.x + v1.y * v1.y + v1.z * v1.z;
}

//  Our pixel Shader

float4 BasePixelShader(VertexShaderOutput input) : SV_TARGET
{
    float4 baseColor = float4(0.7f, 0.7f, 0.7f, 1); //DiffuseTexture.Sample(textureSampler, input.TexCoord);

    float4 diffuseLight = float4(0, 0, 0, 0);
    float4 specularLight = float4(0, 0, 0, 0);

    //calculate our viewDirection
    float3 cameraDirection = normalize(input.WorldPos - CameraPosition);

    //calculate our sunlight
    diffuseLight += CalcDiffuseLight(input.Normal, SunLightDirection, SunLightColor, SunLightIntensity);
    specularLight += CalcSpecularLight(input.Normal, SunLightDirection, cameraDirection, SunLightColor, SunLightIntensity);

     [loop]
    for (int i = 0; i < MaxLightsRendered; i++)
    {
        float3 PointLightDirection = input.WorldPos - PointLightPosition[i];
                           
        float DistanceSq = lengthSquared(PointLightDirection);



        float radius = PointLightRadius[i];
             
        [branch]
        if (DistanceSq < abs(radius * radius))
        {
            float Distance = sqrt(DistanceSq);

            PointLightDirection /= Distance;

            float du = Distance / (1 - DistanceSq / (radius * radius - 1));

            float denom = du / abs(radius) + 1;

            //The attenuation is the falloff of the light depending on distance basically
            float attenuation = 1 / (denom * denom);

            diffuseLight += CalcDiffuseLight(input.Normal, PointLightDirection, PointLightColor[i], PointLightIntensity[i]) * attenuation;
            
            specularLight += CalcSpecularLight(input.Normal, PointLightDirection, cameraDirection, PointLightColor[i], PointLightIntensity[i]) * attenuation;
        }
    }

    //calculate our pointLights

    return diffuseLight * baseColor + specularLight;
}

technique BasicLightShader
{
    pass Pass1
    {
        VertexShader = compile vs_5_0 BaseVertexShader();
        PixelShader = compile ps_5_0 BasePixelShader();
    }
}

Well Kosmo,

I deeply thank you for all your help. I’m running into the below now when standing at the corner of a block. I’m sure that this is something I’m doing, but I don’t have enough knowledge to continue right now. I’m going to keep playing with it, but I won’t keep bugging you with the issues I have. Thank you for your guidance, I’m sure I can conquer these shaders if I continue learning.

EDIT: I finally solved it! I’m going to get some sleep now and I’ll post more tomorrow. In the past few hours I’ve learned that I’ve been confusing what I’ve been trying to achieve with the technique I was using. I realized that the ellipses on my models were the specular reflection :blush: What I’ve really been after is a default illumination for the whole scene, which I’ve achieved with my own, from scratch, ambient shader! I’m so f#%$&@ happy right now. Thanks again for everything buddy!