3D lighting -- vertex normals?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
groverburger
Prole
Posts: 49
Joined: Tue Oct 30, 2018 9:27 pm

3D lighting -- vertex normals?

Post by groverburger »

Hey guys! I'm working on a simple 3d engine for love2d 11.0 that I plan on open sourcing here on the forums. I've gotten the basics down - but I'm facing an issue with lighting, more specifically getting the vertex normal of a vertex into the vertex shader.

Here's the basic 3d shader code with no lighting:

Code: Select all

DepthShader = love.graphics.newShader[[
        uniform mat4 view;
        uniform mat4 model_matrix;

        #ifdef VERTEX
        vec4 position(mat4 transform_projection, vec4 vertex_position) {
            return view * model_matrix * vertex_position;
        }
        #endif

        #ifdef PIXEL
        vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
            vec4 texturecolor = Texel(texture, texture_coords);
            return color*texturecolor;
        }
        #endif
]]
And here's the 3d shader with basic diffuse lighting: (or at least that's what it should be if it had the right vertex normals)
The light_source vec3 is passed in with the value {0,0,0} in the draw function.

Code: Select all

DepthShader = love.graphics.newShader[[
        uniform mat4 view;
        uniform mat4 model_matrix;
        uniform vec3 light_source;

        varying mat4 modelView;
        varying mat4 modelViewTrans;
        varying vec3 normal;
        varying vec3 vposition;
        
        #ifdef VERTEX
        vec4 position(mat4 transform_projection, vec4 vertex_position) {
            modelView = view * model_matrix;
            modelViewTrans = view * model_matrix * transform_projection;
            
            // this normal calculation is wrong and needs to be replaced with the actual normal vector
            normal = vec3(normalize(modelView * vertex_position)); 
            vposition = vec3(vertex_position);

            return view * model_matrix * vertex_position;
        }
        #endif

        #ifdef PIXEL
        vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
            float distance = length(light_source - vposition);
            vec3 lightVector = normalize(light_source - vposition);
            float diffuse = max(dot(normal, lightVector), 0);
            diffuse = diffuse * (1.0 / (1.0 + (0.001 * distance * distance)));
            diffuse = min(diffuse, 1);

            vec4 texturecolor = Texel(texture, texture_coords);
            texturecolor.x *= diffuse;
            texturecolor.y *= diffuse;
            texturecolor.z *= diffuse;
            return color*texturecolor;
        }
        #endif
]]
This is the part of my draw function after calculating and sending view and light_position to the shader.
This for loop draws all the models in ModelList. Love draws the entire model in one line with this love.graphics.draw when the shader is applied.

Code: Select all

for i=1, #ModelList do
    local model = ModelList[i]
    if model.visible then
        DepthShader:send("model_matrix", model.transform)
        love.graphics.draw(model.mesh, -GraphicsWidth()/2, -GraphicsHeight()/2)
    end
end
This is where I'm stumped.

Because Love draws the entire model at once with the shader, I assume the only way to send vertex normals to the shader is by sending a massive array of all the ones in the model before drawing it. But then how would the vertex shader know which normal in that massive array to use? Or am I just misunderstanding something?

Here's a link download my current engine:
https://drive.google.com/open?id=12oRjn ... cSI2QT-R8n_

To enable my broken lighting shader:
on line 87 change: DepthShader = BasicDepthShader to DepthShader = LightingDepthShader
and uncomment line 198: DepthShader:send("light_source", {0,0,0})


Any help would be appreciated!
User avatar
slime
Solid Snayke
Posts: 3131
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: 3D lighting -- vertex normals?

Post by slime »

You can access custom vertex attributes you've set via mesh vertex formats, by declaring them with the same name as an attribute in the vertex shader code.

e.g. in your shader code you'd do something like this, since you have the "VertexNormal" attribute as part of your mesh's vertex format:

Code: Select all

attribute vec4 VertexNormal;
varying vec3 normal;

// etc.

vec4 position(mat4 transform_projection, vec4 vertex_position) {
    normal = VertexNormal;
    // etc.
}
User avatar
groverburger
Prole
Posts: 49
Joined: Tue Oct 30, 2018 9:27 pm

Re: 3D lighting -- vertex normals?

Post by groverburger »

Thanks for the quick response! I didn't know I could do that with mesh vertex formats. Works great!
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 50 guests