SpiderPig Posted February 23 Share Posted February 23 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); Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted February 24 Author Share Posted February 24 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. 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. #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; } Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted February 24 Author Share Posted February 24 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); Quote Link to comment Share on other sites More sharing options...
klepto2 Posted February 24 Share Posted February 24 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 } } 1 Quote Windows 10 Pro 64-Bit-Version NVIDIA Geforce 1080 TI Link to comment Share on other sites More sharing options...
SpiderPig Posted February 24 Author Share Posted February 24 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.... Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted February 24 Author Share Posted February 24 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. Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted February 24 Author Share Posted February 24 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. Quote Link to comment Share on other sites More sharing options...
klepto2 Posted February 24 Share Posted February 24 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; 1 Quote Windows 10 Pro 64-Bit-Version NVIDIA Geforce 1080 TI Link to comment Share on other sites More sharing options...
Solution SpiderPig Posted February 24 Author Solution Share Posted February 24 I think I've fixed it! Thanks very much for your help, with your input it made me look in the right places. It was the sun direction calculation, I had missed a simple multiplication. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.