Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Shaders available, no output error, but loading from either file or memory fails  (Read 449 times)

0 Members and 1 Guest are viewing this topic.

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
My experience with shaders is minimal, my experience is SFML is a little more, with C++ a little more than that. Now combining them, and stumped after trying and chasing the issues I can think of. Help / Ideas are appreciated.

This text drawn to the graphics window confirms that shaders are available.
    std::string debugText = "";
    if ( sf::Shader::isAvailable() )
        debugText = "Shaders are available on this system";
    else
        debugText = "No shaders, sorry";

This was my initial attempt, using an external GLSL file, and after drawing a base tile layer, loading subsequent layers (roots, rocks, grass) and drawing them to the render texture called terrainGrassLayer using that shader:
    sf::Shader tileBlend;
    bool shaderLoaded = tileBlend.loadFromFile( "src/TerrainTest.glsl", sf::Shader::Fragment );
        ...
                if ( sf::Shader::isAvailable() && shaderLoaded )
                {
                    // do alpha setting each tile for each terrain layer (potentially blending over texture) with GLSL
                    ...                  
                    terrainGrassLayer.draw( terrainLayer, &tileBlend );
                }
                else
                {
                    // tile blend shader not found, just draw tile with tile center alpha value
                    terrainLayer.setColor( pixelAlpha );
                    terrainGrassLayer.draw( terrainLayer );
                    // in other words, do far less interesting alpha assignment and draw to a render texture
                }
        ...
        // (then in main loop)
        ...
        // draw calls
        rWin.clear();
        rWin.setView( vw );
        rWin.draw( terrainLayerSprite );
        ...

With the above, I can confirm (again) Shaders are available, but that the shader did not load. I can confirm the shader did not load by commenting out the draw( terrainLayer ) line and seeing only a base terrain tile layer (dirt) drawn earlier on. So, only the else block works at this time, and shaderLoaded must be false.

I tried moving the filepath (project directory, cpp source directory, image asset directory in my project), tried re-writing the shader a couple times, including GLSL from SFML examples.

So, I tried loading from memory instead (figuring my GLSL, even the most basic I can make it) isn't right:
    const std::string fragmentShader = \
    "uniform sampler2D tSample;" \
    "uniform float tileAlphaCenter;" \
    "void main()" \
    "{" \
    "    vec4 pixel = texture2d( tSample, gl_TexCoord[0].xy );" \
    "    pixel.a = tileAlphaCenter;" \
    "    gl_FragColor = gl_Color * pixel;" \
    "}";
    bool shaderLoaded = tileBlend.loadFromMemory( fragmentShader, sf::Shader::Fragment );

Still, shaderLoaded is false, and frustratingly, there is no standard error output. But, there should be, if the load didn't work, right? The idea that there is no SFML output, just warnings from the compiler regarding C++11 standards leads me to wonder if I'm looking for SFML errors in the wrong place in CodeBlocks. :\ Like, I say, I'm stumped and up for any ideas. 'Much appreciated.

'Need to see the GLSL file I tried?

uniform sampler2D tSample;
uniform float tileAlphaCenter;

void main()
{
    vec4 pixel = texture2d( tSample, gl_TexCoord[0].xy );
    pixel.a = tileAlphaCenter;
    gl_FragColor = gl_Color * pixel;
}

I'll save the much fancier GLSL file I started with for another time. ;)
« Last Edit: April 03, 2020, 10:59:07 pm by SuperApe »

Hapax

  • Hero Member
  • *****
  • Posts: 3020
  • My number of posts is shown in hexadecimal.
    • View Profile
texture2D has a capital D.

It should show shader-compilation errors though.
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
Thank you, yes, fixed. (the fancier original had a capital D there) 'Appreciated.

And, I agree, there should be a compilation error nestled in the build log output somewhere, but I'm not seeing it. Incidentally, another thing I tried was to insert my GLSL attempts into an online sandbox. SFML should output something if I just try and load a non-existent file or empty string, yeah?

    // TEST FORCE COMPILATION ERROR MSG
    sf::Shader dummy;
    dummy.loadFromMemory("", sf::Shader::Fragment);

So, if this should show me an error, clearly, I'm not looking in the right place for it.

[EDIT:] ... and watching the shader variable, tracing via breakpoints, and watching the progress logged only confirms that, yes, the previous loading operations mentioned fail without mention in (all) console logs and, yes, the data in these is left uninitialized. :\
« Last Edit: April 04, 2020, 01:44:14 am by SuperApe »

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
I'd be happy to entertain ideas, to double check how shaders ought to be configured and executed. Clearly, I've done something wrong, and I'm asking for suggestions as to what that might be.

I'll move on to other tasks, and come back to take another run at this in the near future. (shader practice was a primary goal for this current project)

All help is appreciated. :D

Hapax

  • Hero Member
  • *****
  • Posts: 3020
  • My number of posts is shown in hexadecimal.
    • View Profile
Since I didn't have how you use the tileCenter uniform, I removed it from my test.
Are you setting that (or is it defaulting) to zero? That would cause alpha to always be zero...

That stuff aside, you'd be better providing a minimal and complete example that reproduces the problem so we can be testing the same thing.
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
[EDIT: more complete version in next reply]

I understand. I tried to provide relevant code to the problem I've reduced it to: loadFromMemory and loadFromFile both return false.

If you think the problem is less about loadFromMemory or loadFromFile, I'm all ears.

I wish the problem were actually GLSL related, because I think I could work through that well enough. For example, if setting my float uniform wasn't working, and gave me a default zero value, I'd have a chance to see that with a hard-coded alpha value in GLSL for comparison.

Here's a little more complete version of the steps I'm taking after trying to load. (pls excuse breaking Demeter's law at this stage):

    sf::Shader tileBlend;
    //bool shaderLoaded = tileBlend.loadFromFile( "src/TerrainTest.glsl", sf::Shader::Fragment );
    //bool shaderLoaded = tileBlend.loadFromFile( "src/TerrainTileBlend.glsl", sf::Shader::Fragment );

    const std::string fragmentShader = \
    "uniform sampler2D tSample;" \
    "uniform float tileAlphaCenter;" \
    "void main()" \
    "{" \
    "    vec4 pixel = texture2D( tSample, gl_TexCoord[0].xy );" \
    "    pixel.a = tileAlphaCenter;" \
    "    gl_FragColor = gl_Color * pixel;" \
    "}";
    bool shaderLoaded = tileBlend.loadFromMemory( fragmentShader, sf::Shader::Fragment );
    ...
            // selection of the next terrain layer texture to draw as ltexture
            ...
                // getX and getY relate to pixel coordinates of a repeatable noise texture
                pixelAlpha.a = texMgr.texMaskNoise.copyToImage().getPixel(getX, getY).a;

                if ( sf::Shader::isAvailable() && shaderLoaded )
                {
                    // blending across tile to surrounding eight mask pixel alpha values
                    // 1 2 3
                    // 4 X 5
                    // 6 7 8
                    // configure and utilize tileBlend shader
                    tileBlend.setUniform("tSample", lTexture);
                    pixelAlpha.a = texMgr.texMaskNoise.copyToImage().getPixel(getX, getY).a;
                    float centerA = (float)(pixelAlpha.a/255);
                    tileBlend.setUniform("tileAlphaCenter", centerA);
                    ...
                    // (the fancier stuff mentioned in original post, linear interpolation between centerA and surrounding tile alpha values as found from noise texture, set those uniforms the same way)
                    terrainGrassLayer.draw( terrainLayer, &tileBlend );
                }
                else {
                    // tile blend shader not found, just draw tile with tile center alpha value
                    terrainLayer.setColor( pixelAlpha );
                    terrainGrassLayer.draw( terrainLayer );
                }
    ...
    if ( shaderLoaded )
        debugText += "\n... and shader loaded!";
    else
        debugText += "\n... and shader not loaded";

'Hope that helps without dumping all the prototype code I have. It doesn't appear the things related to GLSL are even being used, because they're apparently not being loaded.

Again, it's the shaderLoaded bool that's indicating the problem. The lack of console feedback is another (related?) mystery.
« Last Edit: April 04, 2020, 07:38:32 pm by SuperApe »

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
I hope this is complete enough to review. It's not elegant of course:

#include <math.h>
#include <cmath>
#include <string>

#include <SFML/Graphics.hpp>
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Audio.hpp>

// from headers --
sf::Font titleFont, headingFont, textFont;
bool FontInit() {
    bool loadFontOkay = true;
    if ( !titleFont.loadFromFile("image/fontTitle.ttf") ||
            !headingFont.loadFromFile("image/fontHeading.ttf") ||
            !textFont.loadFromFile("image/fontText.ttf") ) {
        // error
        loadFontOkay = false;
    }
    return loadFontOkay;
}

sf::IntRect texSize = sf::IntRect(0, 0, 32, 32);

class TextureManager {
public:
    sf::Texture texMaskNoise;
    TextureManager() { MaskTextureInit(); }
private:
    void MaskTextureInit()
    {
        texMaskNoise.loadFromFile("image/Mask_Noise.png", texSize);
    }
};

static TextureManager texMgr;
// -- end from headers

// C++, SFML, OpenGL

int main()
{
    // rand seed
    srand(time(NULL));

    // main game setup //

    // window
    sf::RenderWindow rWin( sf::VideoMode( 1024, 576, 256 ), "X" );
    sf::VideoMode vm( sf::VideoMode::getDesktopMode() );
    rWin.setPosition( sf::Vector2i( (( vm.width / 2 ) - 512 ) , (( vm.height / 2 ) - 320 ) ) );

    // time and space
    sf::Clock frameTimer;
    frameTimer.restart();
    float timeDelta = 0.f;
    float globalTime = 1.f;
    float globalScale = 2.f;

    // view port
    sf::View vw;
    vw.setSize(1024.f, 576.f);
    vw.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
    vw.setCenter(320.f, 320.f);

    // terrain
    // TODO: implement terrain manager
    // holds all terrain textures + noise mask
    // uses terrain layer offsets from custom Scene class
    // handles render texture + tile blend shader
    // scrolls with offset to draw tiles in view, based on player position, with updated render texture center
    // 10x10 tiles = 320x320 pixels
    // 32x32 tiles = 1024x1024 pixels
    sf::Texture tTexture;
    if ( !tTexture.loadFromFile("image/Terrain_Soil_Base.png", sf::IntRect(0,0,32,32) ) )
    {
        // error
    }
    tTexture.setRepeated(true);
    tTexture.setSmooth(false);
    sf::Sprite terrain;
    terrain.setTexture(tTexture);
    terrain.setTextureRect(sf::IntRect(0, 0, 32 * 10, 32 * 10));
    terrain.setOrigin(160.f, 160.f);
    terrain.setScale(globalScale, globalScale);
    terrain.setPosition(320.f, 320.f);

    // terrain layer prototype
    sf::RenderTexture terrainGrassLayer;
    sf::ContextSettings settings;
    settings.depthBits = 8;
    terrainGrassLayer.create( 32 * 10 * globalScale, 32 * 10 * globalScale, settings );

    sf::Texture lTexture;
    if ( !lTexture.loadFromFile("image/Terrain_Soil_Grass.png", sf::IntRect(0,0,32,32) ) )
    {
        // error
    }
    tTexture.setRepeated(true);
    tTexture.setSmooth(false);
    sf::Sprite terrainLayer;
    terrainLayer.setTexture(lTexture);
    terrainLayer.setTextureRect(sf::IntRect(0,0,32,32));
    terrainLayer.setOrigin(160.f, 160.f);
    terrainLayer.setScale(globalScale, globalScale);
    terrainLayer.setPosition(320.f, 320.f);

    terrainGrassLayer.draw( terrain );
    // find all 1024 alpha values of the noise mask texture pixels, use them to set alpha of each layer 32x32 tile
    // TODO: store these values instead of continually reading from image file

    // attempt to load shader
    // FIXME: shaders are available, but failing to load, either from src/ or image/
    sf::Shader tileBlend;
    //bool shaderLoaded = tileBlend.loadFromFile( "src/TerrainTest.glsl", sf::Shader::Fragment );
    //bool shaderLoaded = tileBlend.loadFromFile( "src/TerrainTileBlend.glsl", sf::Shader::Fragment );

    const std::string vertexShader = \
    "void main()" \
    "{" \
    "   // transform the vertex position" \
    "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" \
    "" \
    "   // transform the texture coordinates" \
    "   gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;" \
    "" \
    "   // forward the vertex color" \
    "   gl_FrontColor = gl_Color;" \
    "}";
    const std::string fragmentShader = \
    "uniform sampler2D tSample;" \
    "uniform float tileAlphaCenter;" \
    "void main()" \
    "{" \
    "    vec4 pixel = texture2D( tSample, gl_TexCoord[0].xy );" \
    "    pixel.a = tileAlphaCenter;" \
    "    gl_FragColor = gl_Color * pixel;" \
    "}";
    //bool shaderLoaded = tileBlend.loadFromMemory( vertexShader, fragmentShader );
    bool shaderLoaded = tileBlend.loadFromMemory( fragmentShader, sf::Shader::Fragment );

    std::string debugText = "";
    if ( sf::Shader::isAvailable() )
        debugText += "Shaders are available on this system";
    else
        debugText = "No shaders, sorry";

    /*
    // TEST FORCE COMPILATION ERROR MSG
    sf::Shader dummy;
    if ( !dummy.loadFromMemory("", sf::Shader::Fragment) )
    {
        debugText += "\n... dummy fails ...";
    }
    */


    for ( int t=0; t<5; t++ )
    {
        int offsetX, offsetY;
        offsetX = 0;
        offsetY = 0;
        switch (t)
        {
            case 0:
                lTexture.loadFromFile("image/Terrain_Soil_Rock.png", sf::IntRect(0,0,32,32) );
                break;
            case 1:
                lTexture.loadFromFile("image/Terrain_Soil_Root.png", sf::IntRect(0,0,32,32) );
                break;
            case 2:
                lTexture.loadFromFile("image/Terrain_Soil_Pebble.png", sf::IntRect(0,0,32,32) );
                break;
            case 3:
                lTexture.loadFromFile("image/Terrain_Soil_Grass.png", sf::IntRect(0,0,32,32) );
                break;
            case 4:
                lTexture.loadFromFile("image/Terrain_Soil_Flower.png", sf::IntRect(0,0,32,32) );
                break;
        }
        offsetX = (rand() % 32);
        offsetY = (rand() % 32);

        for ( int i=0; i<32; i++ )
        {
            for ( int n=0; n<32; n++ )
            {
                // TODO: migrate to function
                // TODO: allow function to return alpha value from pixel 'wrapped around' texture edge
                terrainLayer.setPosition( 320.f + (i * 32 * globalScale), 320.f + (n * 32 * globalScale) );
                sf::Color pixelAlpha = sf::Color::White;
                unsigned int getX, getY;
                getX = i + offsetX;
                getY = n + offsetY;
                if ( getX > 31 )
                    getX -= 31;
                if ( getY > 31 )
                    getY -= 31;
                pixelAlpha.a = texMgr.texMaskNoise.copyToImage().getPixel(getX, getY).a;

                if ( sf::Shader::isAvailable() && shaderLoaded )
                {
                    // blending across tile to surrounding eight mask pixel alpha values
                    // 1 2 3
                    // 4 X 5
                    // 6 7 8
                    // configure and utilize tileBlend shader
                    tileBlend.setUniform("tSample", lTexture);
                    pixelAlpha.a = texMgr.texMaskNoise.copyToImage().getPixel(getX, getY).a;
                    float centerA = (float)(pixelAlpha.a/255);
                    tileBlend.setUniform("tileAlphaCenter", centerA);

                    float topleftA = 0.f;
                    if ( getX > 0 && getY > 0 )
                    {
                        topleftA = (float)(texMgr.texMaskNoise.copyToImage().getPixel((getX-1),(getY-1)).a / 255);
                        topleftA += centerA;
                        topleftA /= 2.f;
                    }
                    else
                        topleftA = centerA;
                    float topA = 0.f;
                    if ( getY > 0 )
                    {
                        topA = (float)(texMgr.texMaskNoise.copyToImage().getPixel(getX,(getY-1)).a / 255);
                        topA += centerA;
                        topA /= 2.f;
                    }
                    else
                        topA = centerA;
                    float toprightA = 0.f;
                    if ( getX < 31 && getY > 0 )
                    {
                        toprightA = (float)(texMgr.texMaskNoise.copyToImage().getPixel((getX+1),(getY-1)).a / 255);
                        toprightA += centerA;
                        toprightA /= 2.f;
                    }
                    else
                        toprightA = centerA;
                    float leftA = 0.f;
                    if ( getX > 0 )
                    {
                        leftA = (float)(texMgr.texMaskNoise.copyToImage().getPixel((getX-1),getY).a / 255);
                        leftA += centerA;
                        leftA /= 2.f;
                    }
                    else
                        leftA = centerA;
                    float rightA = 0.f;
                    if ( getX < 31 )
                    {
                        rightA = (float)(texMgr.texMaskNoise.copyToImage().getPixel((getX+1),getY).a / 255);
                        rightA += centerA;
                        rightA /= 2.f;
                    }
                    else
                        rightA = centerA;
                    float bottomleftA = 0.f;
                    if ( getX > 0 && getY < 31 )
                    {
                        bottomleftA = (float)(texMgr.texMaskNoise.copyToImage().getPixel((getX-1),(getY+1)).a / 255);
                        bottomleftA += centerA;
                        bottomleftA /= 2.f;
                    }
                    else
                        bottomleftA = centerA;
                    float bottomA = 0.f;
                    if ( getY < 31 )
                    {
                        bottomA = (float)(texMgr.texMaskNoise.copyToImage().getPixel(getX,(getY+1)).a / 255);
                        bottomA += centerA;
                        bottomA /= 2.f;
                    }
                    else
                        bottomA = centerA;
                    float bottomrightA = 0.f;
                    if ( getX < 31 && getY < 31 )
                    {
                        bottomrightA = (float)(texMgr.texMaskNoise.copyToImage().getPixel((getX+1),(getY+1)).a / 255);
                        bottomrightA += centerA;
                        bottomrightA /= 2.f;
                    }
                    else
                        bottomrightA = centerA;
                    tileBlend.setUniform("tileAlphaTopLeft", topleftA);
                    tileBlend.setUniform("tileAlphaTop", topA);
                    tileBlend.setUniform("tileAlphaTopRight", toprightA);
                    tileBlend.setUniform("tileAlphaLeft", leftA);
                    tileBlend.setUniform("tileAlphaRight", rightA);
                    tileBlend.setUniform("tileAlphaBottomLeft", bottomleftA);
                    tileBlend.setUniform("tileAlphaBottom", bottomA);
                    tileBlend.setUniform("tileAlphaBottomRight", bottomrightA);
                    terrainGrassLayer.draw( terrainLayer, &tileBlend );
                }
                else
                {
                    // tile blend shader not found, just draw tile with tile center alpha value
                    terrainLayer.setColor( pixelAlpha );
                    terrainGrassLayer.draw( terrainLayer );
                }
            }
        }
    }
    if ( shaderLoaded )
        debugText += "\n... and shader loaded!";
    else
        debugText += "\n... and shader not loaded";

    terrainGrassLayer.display();
    sf::Sprite terrainLayerSprite;
    terrainLayerSprite.setTexture( terrainGrassLayer.getTexture() );

    // debug feedback
    sf::Text debugLine;
    debugLine.setFont(textFont);
    debugLine.setScale(.381f,.381f);
    debugLine.setPosition(32.f,48.f);

    // main loop
    rWin.setActive();
    rWin.setFramerateLimit(60);
    while ( rWin.isOpen() )
    {
        // time delta
        timeDelta = frameTimer.restart().asSeconds() * globalTime;

        // window events
        sf::Event event;
        while (rWin.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                rWin.close();
            if (event.type == sf::Event::Resized) {
                rWin.setSize( sf::Vector2u( 1024, 576 ) );
                rWin.setPosition( sf::Vector2i( (( vm.width / 2 ) - 512 ) , (( vm.height / 2 ) - 320 ) ) );
            }
        }

        // draw calls
        rWin.clear();
        rWin.setView( vw );
        rWin.draw( terrainLayerSprite );

        // debug
        debugLine.setString(debugText);
        if ( debugLine.getString() != "" )
            rWin.draw(debugLine);
        rWin.display();
    }
}
 

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
Creating a separate version was a good idea. Compiled and got a loaded shader (from memory), and saw something I think you said.

                    pixelAlpha.a = texMgr.texMaskNoise.copyToImage().getPixel(getX, getY).a;
                    float centerA = (float)(pixelAlpha.a/255);
                    tileBlend.setUniform("tileAlphaCenter", centerA);
...wasn't going to work, and the results showed alpha clipping to either full or not.

Corrected to:
                    pixelAlpha.a = texMgr.texMaskNoise.copyToImage().getPixel(getX, getY).a;
                    float centerA = (pixelAlpha.a/255.f);
                    tileBlend.setUniform("tileAlphaCenter", centerA);

So, I was able to migrate that fix throughout the fancy stuff, and fix at least one issue: passing floats that weren't floats. Okay, with the shader loaded in this version, I can now focus on what might be wrong loading GLSL from file. (first, I'll check paths again, then focus on the GLSL)

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
Now that shaders load (and _why_ no output errors?), I see something that causes my fancy GLSL file to fail.

#version 330 core

So, with that commented out, I actually see stuff blending with a loaded shader file, and I think I can work things out from here.

To sum up the original issue: it looks like I'm not seeing (have not seen) output from SFML complaining about the loading attempts; just failed to load until I tried in this separate test. But, for sure, adding #version causes SFML to bork.

[EDIT] Best guess is (based on what changed to make loading possible) the fixes to the floats being set to uniforms was the only issue for loading. Additionally, "#version..." caused loading to fail. No compile error output to be found in any console windows. (shrug) On the plus side, with shader loading working, I was able to get my fancy GLSL blending working as designed, so it was good practice. Thank you, Hapax! Thanks for your patience. :D
« Last Edit: April 05, 2020, 12:48:46 am by SuperApe »

Hapax

  • Hero Member
  • *****
  • Posts: 3020
  • My number of posts is shown in hexadecimal.
    • View Profile
I'll try to have a more throrough read of all of your posts at a later date.

the fixes to the floats being set to uniforms was the only issue for loading. Additionally, "#version..." caused loading to fail.
This is not actually a loading error. The problem you had with the alpha was dividing an integer up to 255 by another integer that is 255. Anything below 255 divided by 255 is 0, while 255 divided by 255 is 1. The result was then C-style cast to a float.
Your fix - changing the divisor to a float - promotes the integer to a float before dividing so the accurate result is calculated correctly.
Another way to "fix" the original version would be to cast the first value to float and then divide by 255. The 255 would automatically be promoted to float for the calculation. That said, using the float value (your fix) is probably the better solution and is clearer too!
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32463
    • View Profile
    • SFML's website
    • Email
Quote
and _why_ no output errors?
Do you see what you print to std::cerr? Do you see what you print to sf::err()? In case you don't see anything, you can redirect sf::err() to whatever you want, using standard C++ iostream redirection.
Laurent Gomila - SFML developer

SuperApe

  • Newbie
  • *
  • Posts: 17
    • View Profile
Super big thank you, Hapax and Laurent! This is helpful.

(I appreciate the sanity check, Hapax. A result of what I was going for is now displayed on the screenshot thread)

I now have a good set of things to try and chase down, Laurent, thank you. First, my sneaking suspicion is that if I weren't using Code::Blocks (VS instead), the output would be clearly displayed. (maybe) But, this is a new set of things to try and they will help me improve my debugging workflow. 'Very much appreciated!  :D

 

anything