Jump to content

Does Texture::SetPixels() destroy current texture in GPU memory?


SpiderPig
 Share

Go to solution Solved by SpiderPig,

Recommended Posts

I've been using a texture to store variables for a lot of my shaders.   I've just decided today to see if I can update those variables in real-time.  While it does work, I am seeing a bit of flicking - which in this case I'm assuming is due the to fact that when I'm setting a textures pixels there may be a few shader updates were that information is either gone or invalid?  I've tried both render hooks as well.  HOOKID_TRANSFER reduces it a bit but not completely.

Just wondering if this is a good idea before I continue with it.  :)

buffer->PokeInt(index, value);
texture->SetPixels(buffer);

 

Link to comment
Share on other sites

I can't seem to reproduce this on a smaller scale.  It's more than likely an issue with the shader itself but I can't for the life of me narrow it down.  :blink:

Anyway I've attached code and shaders if someone would like to take a look as well.  It's like the shader doesn't like some of the vectors of the sun position and it causes it to flicker black sometimes.  Any help is appreciated, I'll be tackling this in the shadows. :ph34r:

 

 

#include "UltraEngine.h"
#include "ComponentSystem.h"
using namespace UltraEngine;


int main(int argc, const char* argv[])
{
    auto displays = GetDisplays();
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * displays[0]->scale, 720 * displays[0]->scale, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    auto framebuffer = CreateFramebuffer(window);

    auto world = CreateWorld();
    world->RecordStats(true);

    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->Move(0, 2, 0);
    camera->AddComponent<CameraControls>();

    auto light = CreateDirectionalLight(world);
    light->SetRotation(45, 35, 0);
    light->SetColor(2);

    auto plane = CreatePlane(world, 100, 100);

    auto sphere = CreateSphere(world, 512, 32);
    auto mat = LoadMaterial("Materials\\DynamicSky\\DynamicSky.mat");
    sphere->SetMaterial(mat);

    auto size = 8;
    auto buffer = CreateBuffer(size * size * 4);
    auto texture = CreateTexture(TEXTURE_2D, size, size);
    mat->SetTexture(texture, 15);


    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        Vec3 speed = Vec3(0.02, 0, 0);
        light->Turn(speed.x, speed.y, speed.z);

        auto yoffset = 300;
        auto dir = Vec3(light->matrix.k.x, light->matrix.k.y, light->matrix.k.z).Normalize();
        auto sun_raw_pos = Vec3(-dir.x, -dir.y, -dir.z);
        auto camera_range = camera->GetRange().y;
        auto sun_pos = Vec3(-dir.x, -dir.y + (yoffset / camera_range), -dir.z).Normalize();

        auto index = 0;
        buffer->PokeFloat(index, sun_pos.x);
        buffer->PokeFloat(index + 4, sun_pos.y);
        buffer->PokeFloat(index + 8, sun_pos.z);

        texture->SetPixels(buffer);

        auto stats = world->renderstats;
        window->SetText("FPS : " + WString(stats.framerate) + " --- verts : " + WString(stats.vertices) +
        " --- polys : " + WString(stats.polygons) + " --- instances : " + WString(stats.instances));

        world->Update();
        world->Render(framebuffer, false);
    }
    return 0;
}

 

Link to comment
Share on other sites

Something that tells me it's not a problem with SetPixels is that if I poke the buffer with a constant value it doesn't flicker - ever.

sun_pos = Vec3(1, 1, 0).Normalize();

auto index = 0;
buffer->PokeFloat(index, sun_pos.x);
buffer->PokeFloat(index + 4, sun_pos.y);
buffer->PokeFloat(index + 8, sun_pos.z);

texture->SetPixels(buffer);

 

Link to comment
Share on other sites

I haven't seen this problem in my applications, of course the update might be a bit off, but i don't see flickering. But maybe its because i use WritePixel with a Float32 pixmap directly instead of a using a buffer.

I have something like this:

class MaterialExtensionInfo : public Object
{
private:
	shared_ptr<Pixmap> _data;
	shared_ptr<Texture> _dataTexture;
	int current_ptr = 0;
	
public:
	MaterialExtensionInfo();
	void Sync();

	shared_ptr<Texture> GetDataTexture();
	void Add(int x, int y, Vec2 value);
	void Add(int x, int y, Vec3 value);
	void Add(int x, int y, Vec4 value);
	void Add(int x, int y, Mat3 value);
	void Add(int x, int y, Mat4 value);
};

MaterialExtensionInfo::MaterialExtensionInfo()
{
    _dataTexture = CreateTexture(TEXTURE_2D, 64, 32, TEXTURE_RGBA32, {}, 1, TEXTURE_DEFAULT, TEXTUREFILTER_NEAREST);
    _data = CreatePixmap(64, 32, TEXTURE_RGBA32);
}

void MaterialExtensionInfo::Sync()
{
    _dataTexture->SetPixels(_data);
}

shared_ptr<Texture> MaterialExtensionInfo::GetDataTexture()
{
    return _dataTexture;
}

void MaterialExtensionInfo::Add(int x, int y, Vec2 value)
{
    _data->WritePixel(x, y, Vec4(value.x, value.y, 0.0, 0.0));
}

void MaterialExtensionInfo::Add(int x, int y, Vec3 value)
{
    _data->WritePixel(x, y, Vec4(value.x, value.y, value.z, 0.0));
}

void MaterialExtensionInfo::Add(int x, int y, Vec4 value)
{
    _data->WritePixel(x, y, value);
}

void MaterialExtensionInfo::Add(int x, int y, Mat3 value)
{
    _data->WritePixel(x, y, Vec4(value.i.x, value.i.y, value.i.z,0.0));
    _data->WritePixel(x + 1, y, Vec4(value.j.x, value.j.y, value.j.z, 0.0));
    _data->WritePixel(x + 2, y, Vec4(value.k.x, value.k.y, value.k.z, 0.0));
}

void MaterialExtensionInfo::Add(int x, int y, Mat4 value)
{
    _data->WritePixel(x, y, value.i);
    _data->WritePixel(x + 1, y, value.j);
    _data->WritePixel(x + 2, y, value.k);
    _data->WritePixel(x + 3, y, value.t);
}

In your case, the sun direction is already available in the shader, you don't need to pass it down like that, In ultraEngine you can always access nearly anything at anytime in the shader. This itroduces a lot of possbilities: eg calculating combined atmospheric effects for multiple suns.

to iterate over all Directional Lights you can do something like this in your shader:

#include "../../Base/Lighting.glsl"

...

in main() 

...
uint n;
    uint lightIndex;

   	// Global lights (affects all cells)
    uint lightlistpos = GetGlobalLightsReadPosition();
	uint countlights = ReadLightGridValue(lightlistpos);
    for (n = 0; n < countlights; ++n)
    {
        ++lightlistpos;
        lightIndex = ReadLightGridValue(lightlistpos);
        
        int ShadowSoftness = 2;
        const float minlight = 0.004f;
        vec3 lightDir, lightPosition;
        vec4 shadowCoord, color;
        bool transparent = false;
        mat4 lightmatrix;
        uint flags, lightflags;
        int shadowMapID, lighttype, shadowcachemapID;
        float attenuation = 1.0f;
        dFloat d;
    #ifdef DOUBLE_FLOAT
        dvec2 lightrange, coneangles, shadowrange;
    #else
        vec2 lightrange, coneangles, shadowrange;
    #endif
        int shadowkernel;
        
        ExtractEntityInfo(lightIndex, lightmatrix, color, flags);	
        ExtractLightInfo(lightIndex, shadowMapID, shadowcachemapID, lightrange, coneangles, shadowrange, lightflags, shadowkernel);
        
        const int falloffmode = ((lightflags & ENTITYFLAGS_LIGHT_LINEARFALLOFF) != 0) ? LIGHTFALLOFF_LINEAR : LIGHTFALLOFF_INVERSESQUARE;
        if ((lightflags & ENTITYFLAGS_LIGHT_STRIP) != 0) lighttype = LIGHT_STRIP; // This needs to come first because the flag is a combination of others
        else if ((lightflags & ENTITYFLAGS_LIGHT_BOX) != 0) lighttype = LIGHT_BOX;
        else if ((lightflags & ENTITYFLAGS_LIGHT_DIRECTIONAL) != 0) lighttype = LIGHT_DIRECTIONAL;
        else if ((lightflags & ENTITYFLAGS_LIGHT_SPOT) != 0) lighttype = LIGHT_SPOT;
        else lighttype = LIGHT_POINT;
        
        if(lighttype == LIGHT_DIRECTIONAL)
        {
        #ifdef DOUBLE_FLOAT
                lightDir = vec3(normalize(lightmatrix[2].xyz));
        #else
                lightDir = normalize(lightmatrix[2].xyz);
        #endif
          // Do calculations, break out if needed
          }
    }

 

  • Thanks 1
  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

16 minutes ago, klepto2 said:

In your case, the sun direction is already available in the shader, you don't need to pass it down like that, In ultraEngine you can always access nearly anything at anytime in the shader. This itroduces a lot of possbilities: eg calculating combined atmospheric effects for multiple suns.

Sweet!  That should work better.  As far as using the buffer, I had it working fine on some smaller applications which leads me to believe there's a bug with my shader.  Pity we can't debug shaders....

Link to comment
Share on other sites

I just noticed your texture creation method;

_dataTexture = CreateTexture(TEXTURE_2D, 64, 32, TEXTURE_RGBA32, {}, 1, TEXTURE_DEFAULT, TEXTUREFILTER_NEAREST);

I leave my type as TEXTURE_RGBA and convert to floats like this -

float BytesToFloat( in vec4 pixel ) {
	return intBitsToFloat( ( int( ( pixel.w * 255.0f ) ) << 24 ) | ( int( ( pixel.z * 255.0f ) ) << 16 ) | ( int( ( pixel.y * 255.0f ) ) << 8 ) | int( ( pixel.x * 255.0f ) ) );
}

Would that function still work with the type TEXTURE_RGBA32 you think? I also use TexelFetch instead of sample.

Link to comment
Share on other sites

Okay, this position makes the sky black.

sun_pos = Vec3(-0.324064016,0.825100005,-0.462809354);

Yet changing the y to be 0.835 instead of 0.825 works.

sun_pos = Vec3(-0.324064016,0.835100005,-0.462809354);

Its a shader issue.  I'm getting closer.  ^_^

Link to comment
Share on other sites

it might be that you need to invert the light_direction. 

1 hour ago, SpiderPig said:

I just noticed your texture creation method;

_dataTexture = CreateTexture(TEXTURE_2D, 64, 32, TEXTURE_RGBA32, {}, 1, TEXTURE_DEFAULT, TEXTUREFILTER_NEAREST);

I leave my type as TEXTURE_RGBA and convert to floats like this -

float BytesToFloat( in vec4 pixel ) {
	return intBitsToFloat( ( int( ( pixel.w * 255.0f ) ) << 24 ) | ( int( ( pixel.z * 255.0f ) ) << 16 ) | ( int( ( pixel.y * 255.0f ) ) << 8 ) | int( ( pixel.x * 255.0f ) ) );
}

Would that function still work with the type TEXTURE_RGBA32 you think? I also use TexelFetch instead of sample.

The reason i use RGBA32 o RGBA16 is that you don't need to make any bitshifting etc. if you store a float in a RGBA32 texture the value will be the same as how you uploaded it. RGBA16 will just loose some precision, while RGBA will clamp the float to 0.0-1.0.  

As long as you store values between 0.0 and 1.0 the bytes to float should work the same. But is not needed with a RGBA32/16 texture.

I use also texelFetch, otherwise sampling might corrupt the actual value.

I simply access the data in the shader like this:

	vec4 data = texelFetch(texture2DSampler[configId],ivec2(0,i+1),0);
			cascades[i].spectrumHandle = int(data.x);
			cascades[i].normalHandle = int(data.y);
			cascades[i].size = data.z;

 

  • Thanks 1
  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...