dogo / oslib

OldSchool Library (OSLib), a 2D graphics library for the PSP.
http://dogo.github.io/oslib/
GNU General Public License v2.0
45 stars 11 forks source link

"multiply" blending mode? #9

Closed suicvne closed 3 months ago

suicvne commented 8 years ago

is a "multiply" blending mode possible at all? i'd like to use it to implement some psuedo 2D lighting (which I've done before in XNA) but the best I could get was additive which didn't look as good.

suicvne commented 8 years ago

i experimented with the source code a bit trying the following blend func:

sceGuBlendFunc(GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);

it works with a non-transparent image (ie: black background white radial gradient) but completely breaks with a transparent one (only renders the pixels in the corners as full black?)

essentially, what my custom "mult" mode looks like is this:

sceGuBlendFunc(GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);
sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
sceGuAmbientColor(coeff1);
osl_currentAlphaCoeff = coeff1;
osl_currentAlphaCoeff2 = coeff2;

i'm not quite familiar with sceGuTexFunc or sceGuAmbientColor so I just left those similar as the other cases.

the method i use is:

  1. draw the base scene
  2. set blend to mult
  3. overlay a rectangle with the 'ambient light'
  4. draw lightmaps

image here is a non-transparent png being used as the base light

image and here is a semi-transparent png being used as the base light.

both images are identical with the exception of one having a black background and the other having a transparent background.

something like this is essentially what i'm going for

dogo commented 3 months ago

@suicvne to achieve a multiply blend mode, you'll need to use a blend function that multiplies the source and destination colors together. Here is a typical setup for a multiply blend mode:

sceGuBlendFunc(GU_ADD, GU_SRC_COLOR, GU_DST_COLOR, 0, 0);

In this setup:

Here's an updated version of your method:

  1. Draw the base scene.
  2. Set blend mode to multiply.
  3. Overlay a rectangle with the 'ambient light'.
  4. Draw lightmaps.
// Step 1: Draw the base scene (ensure no blending here)
sceGuDisable(GU_BLEND);
// Draw your base scene here

// Step 2: Set blend mode to multiply
sceGuEnable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_COLOR, GU_DST_COLOR, 0, 0);

// Step 3: Overlay a rectangle with the 'ambient light'
// Make sure the ambient light texture has appropriate alpha values
// Draw the ambient light overlay here

// Step 4: Draw lightmaps
// Ensure lightmaps are drawn with appropriate alpha values
// Draw your lightmaps here

// Restore the default blend mode if necessary
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);

Additionally, ensure that your textures and lightmaps have appropriate alpha values and that your framebuffer supports alpha blending.

If you're encountering issues with transparency, double-check the alpha values in your textures. The blend function you were experimenting with (GU_FIX) fixes the color value and may not work well with textures that have transparency.

You mentioned using sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA) and sceGuAmbientColor(coeff1). These functions are typically used to configure texture environment settings and ambient color. Ensure these settings are appropriate for your blending operation:

Lastly, make sure that the ambient light rectangle and lightmaps are correctly positioned and that their alpha values are appropriately set to achieve the desired lighting effect.