raysan5 / raylib

A simple and easy-to-use library to enjoy videogames programming
http://www.raylib.com
zlib License
21.99k stars 2.22k forks source link

[rcore] Transparent colours not drawing correctly when using RenderTexture2D #3820

Closed JamesC01 closed 5 months ago

JamesC01 commented 7 months ago

Issue description

Today I updated my game to allow screen resizing, by using a rendertexture, but I noticed a problem that happens when I clear the background inside the proper BeginDraw()/EndDraw(). It causes any transparent colours to be tinted, despite the fact that they're drawing above textures that were drawn on top of the cleared background. I've provided some screenshots.

Environment

Provide your Platform, Operating System, OpenGL version, GPU details where you experienced the issue. Windows 10 (Using linux with WSL) GTX 1050 ti INFO: GL: OpenGL device information: INFO: > Vendor: Microsoft Corporation INFO: > Renderer: D3D12 (NVIDIA GeForce GTX 1050 Ti) INFO: > Version: 4.2 (Core Profile) INFO: > GLSL: 4.20

I tested this on a separate computer and it does the same thing, it was also linux.

Issue Screenshot

This is how it's meant to look, this what what happens when I don't clear inside the BeginDraw/EndDraw functions (which is also what it looked liked before using a render texture): when not clearing

And this is what happens when I clear to BLACK before rendering the rendertexture to the screen: when clearing

As you can see, it just looks wrong. The most noticeable difference is the tinted tiles on the ground. They're completely dim!

Code Example

I'm essentially just doing my drawing inside of BeginTextureMode/EndTextureMode, rendering to a RenderTexture2D, and then using BeginDraw/EndDraw to draw that texture, scaled up to the screen (with some extra stuff to maintain aspect ratio.


RenderTexture2D target = LoadRenderTexture(width, height);

BeginTextureMode(target);

// do my game's drawing

EndTextureMode();

BeginDrawing();

ClearBackground(BLACK);

Rectangle src = {0, 0, virtualWidth, virtualHeight};
Rectangle dst = {0, 0, GetScreenWidth(), GetScreenHeight()};
DrawTexturePro(target.texture, src, dst, Vector2Zero(), 0, WHITE);

EndDrawing();

That's effectively what I'm doing, but without being too specific.

mikaib commented 7 months ago

I have the same problem here. For me the colors and transparancy change drastically when drawing to RenderTextures

GideonSerf commented 7 months ago

As far as I can tell, this has to do with the blending mode. When you draw a texture with an alpha value over a texture without one, the resultant alpha value by default will be $A_r = A_s \cdot A_s + A_d \cdot (1-A_s)$, with $A_r,A_s$ and $A_d$ being the resultant, source and destination alphas respectively.

You can instead use your own blending mode that separates the blending modes for the RGB and alpha values. You'll have to include rlgl.h and then set your own blending factors like this: rlSetBlendFactorsSeparate(RL_SRC_ALPHA, RL_ONE_MINUS_SRC_ALPHA, RL_ONE, RL_ONE, RL_FUNC_ADD, RL_MAX). In this case we say keep the same blending mode for the RGB values, but use the max alpha for the alpha value. This will result in an opaque texture if one of the textures is opaque. You'll have to call BeginBlendMode(RL_BLEND_CUSTOM_SEPARATE) and EndBlendMode() to use this blend mode.

So in total you would have something like this:

#include "raylib.h"
#include "rlgl.h"
int main(void)
{
    // Initialization here
    rlSetBlendFactorsSeparate(RL_SRC_ALPHA, RL_ONE_MINUS_SRC_ALPHA, RL_ONE, RL_ONE, RL_FUNC_ADD, RL_MAX);
    while (!WindowShouldClose())
    {
        BeginTextureMode(target);
        BeginBlendMode(RL_BLEND_CUSTOM_SEPARATE);
        //Do your drawing on the texture here
        EndBlendMode();
        EndTextureMode();

        BeginDrawing();
        ClearBackground(BLACK);
        // Draw texture here
        EndDrawing();
    }
    CloseWindow();
    return 0;
}

Hope this works for you. You can read more about what this does here.

raysan5 commented 7 months ago

It seems this issue is related to https://github.com/raysan5/raylib/issues/1334

raysan5 commented 5 months ago

Undoubtely is related to blending mode. Actually proposed solution is what I usually use on my tools.