3
\$\begingroup\$

In my game, I have a 3D shader that does lighting using color ramps on models with very low resolution textures. Basically, the vertex shader calculates color values for direct light and ambient occlusion, and then I look up into a color ramp what color to draw, and multiply this by the texture map.

Here's some pseudocode for that:

// vertex shader:
color_vert.r = ambient_occlusion(vertex)
color_vert.g = direct_lighting(vertex)
color_vert.b = shadow_lighting(vertex)

// fragment shader:
// First, the color is whatever the direct lighting was
color_fragment = direct_lighting_ramp_lookup(color_vert.g)
// Multiply by ambient occlusion and shadow
color_fragment *= ambient_lighting_ramp_lookup(color_vert.r)
color_fragment *= shadow_lighting_ramp_lookup(color_vert.b)
// Mutiply by the surface texture
color_fragment *= texture_lookup(color_vert.uv)

Now, this kind of lighting would be fine if I had very high resolution textures, but unfortunately my textures are very low resolution. So each texel (that is, the block of pixels corresponding to one pixel of the texture) is quite large, and lighting gets interpolated across the texel.

Here's an image of what that looks like: per-pixel lighting image And here's a closeup to show you what I mean: enter image description here

Notice how the color is smoothly getting interpolated accross the low-resolution texels? How can I write my shader such that the lighting gets clamped on a per-texel basis? Is such a thing even possible? The only solution I can think of is to first generate a lightmap for the whole scene with 1-1 mapping to texels, but I'm afraid that would be too slow / use too much memory.

\$\endgroup\$
1
\$\begingroup\$

BTW, I ended up solving this using a lightmap. My process was as follows:

  1. Generate a UV map for the mesh by packing all the triangles together using a simple scanline algorithm.

  2. Render the scene directly to the UV map instead of to the screen. This way, pixels are 1:1 related to texels.

  3. Render the scene again to the screen, this time using the generated UV light map as a texture.

Here's what the lightmap ended up looking like:

enter image description here

And the final composite:

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.