Shader-Texture not seamlessly tileable?

  • #1, by caligarimarteSaturday, 26. August 2017, 14:19 7 years ago
    Yesterday I wrote a little Shader to produce Clouds through two scrolling Textures, and I made the Texture tileable by using "fract(...)" for the Coordinates, which usually works well in other Engines, but here I get an ugly Line at the Texture Seam:
    I tried clamping the Coordinates to cut off that Line, but that didn't look good and didn't work well either. I looked up some GLSL and considered glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT), but if that even can be used, I don't know where and how to implement it (as it won't work at the Beginning of the Shader-Script).

    Somewhere on the Internet I found a supposed LUA-Line for a different Engine, which goes like this: APreviouslyDefinedSprite:getTexture():setTexParameters(gl.LINEAR, gl.LINEAR, gl.REPEAT, gl.REPEAT) ... but if that somehow works in Visionaire, I wouldn't know how.

    I am still using Visionaire 4.2 instead of 5 (and running it in 4.2.5 looks the same, but I cannot really trust the Editor/Player there to truly show me 4.2.5 and not 4.2), so I don't yet know whether it would work there -- but Shaders work different in 5 and I would at first have to wrap my Head around how to even just see whether it would possibly work better in 5.

    So, does anybody ou there have a Clue how to get rid of that ugly Texture Seam?

    Forum Fan

    145 Posts


  • #2, by caligarimarteMonday, 28. August 2017, 12:34 7 years ago
    Could the Texture's Wrap-Mode possibly be set via shaderSetOptions?

    Because it usually includes comp_dst and comp_src, with Values correlating to certain GL-Composition Methods (like 4 = GL_SRC_ALPHA , and 5 = GL_ONE_MINUS_SRC_ALPHA ).
    So if there was some other Method one could write into shaderSetOptions, like a hypothetical "comp_wrap=1" to activate "GL_REPEAT", then maybe I could get rid of the Seam.

    But there is so utterly little Examples of or Documentation on Shaders in Visionaire, I have no Idea what I could possibly write in there. So, does anyone have a Clue?
    (Or maybe there is some Line in the Shader-Toolkit-Script that I have to change?)

    Forum Fan

    145 Posts

  • #3, by SimonSMonday, 28. August 2017, 12:39 7 years ago
    First of all I need to see the shader you are using, since you said you use procedural clouds. In the version 4 the engine had a transparent line at the bottom and the right, that's no more the case in 5. You can not change the wrapping mode of textures currently. Also note that repeat does not work on all gpus with non-power-of-two textures. 

    Thread Captain

    1581 Posts

  • #4, by caligarimarteMonday, 28. August 2017, 15:13 7 years ago
    Okay, thank you very much, SimonS! In that Case, I should indeed just switch over to Visionaire 5 (as that transparent Line at the Bottom and the Right you mentioned is most probably exactly what leads to my Problem), but I have a hard Time understanding how to implement Shaders there, i.e. utilizing the new "Shader"-Tab at the Top. The Problem is not writing the Shaders, I guess, but knowing how to activate them ingame, or how to apply them to just a specific Object. I have implemented the updated Shadertoolkit (i.e. shadertoolkit10.lua) into my Project to try in Visionaire 5, but alas to no Avail. Is there any Tutorial, Wiki-Page or Example-File that would help me getting re-started with that new Shader-Tab (in German or English)?

    None the less, since you have implicitly asked for it, here is my Script (the Object "TestClouds" being a 2048*512 px tilable Cloud-Texture):
    shader_effects["Wolkenmaske"] = {shader=basic_fsh..[[ 
    
    
    
    uniform float daytime; 
    
    
    
    const vec2 ar = vec2(1.6, 0.9); //ASPECT RATIO 
    
    float cloudspeed = 0.0075; 
    
    vec2 cloudsize = vec2(0.33); 
    
    float cloudsoftness = 2.3-texcoord.x*2; 
    
    vec2 cloudmoveA = vec2(0.5, 0.0) * time * cloudspeed; 
    
    vec2 cloudmoveB = vec2(-0.2, 0.0) * time * cloudspeed; 
    
    
    
    vec2 Versatz = vec2(0.75,0.75);
    
    
    
    void main() 
    
    { 
    
     vec2 uv = cloudsize * texcoord.xy; 
    
     vec4 colA = texture2D(iChannel0, fract(vec2(1.00) * uv.xy +cloudmoveA ) ); 
    
     vec4 colB = texture2D(iChannel0, fract(vec2(1.11) * uv.xy +cloudmoveB +Versatz ) );
    
     
    
    //ALTERNATIVELY CLAMP TEXTURE-COORDINATES -- very imperfect workaround...
    
    // vec4 colA = texture2D(iChannel0, clamp( fract( vec2(1.00) * uv.xy +cloudmoveA ) ,0.0,0.99928) );
    
    // vec4 colB = texture2D(iChannel0, clamp( fract( vec2(1.11) * uv.xy +cloudmoveB +Versatz ) ,0.0,0.99928) );
    
     
    
     float wolkentransparenz = ((1.0+cos(daytime*0.5*3.142)) ); 
    
    
    
     float subtraction = clamp(colA.r-colB.r, 0.0, 1.0) * wolkentransparenz; 
    
     vec4 finalColor = vec4( vec3(1.0) , pow( subtraction , cloudsoftness) ); 
    
    
    
     float w = (0.75 - texcoord.x) *4; 
    
     float h = ( (daytime-0.21) - texcoord.y) *1; 
    
     float Sun = 2* pow( 1.0 - clamp( (sqrt(pow(w,2)+pow(h,2))/(0.5)), 0.0,1.0) , 10); 
    
     finalColor.a = abs(finalColor.a - Sun); 
    
      
    
     gl_FragColor = finalColor; 
    
    } 
    
    ]]} 
    
    
    
    ----------------------------- 
    
    
    
    local eff="Wolkenmaske" 
    
    local obj = "TestClouds" 
    
    local id = 2 
    
    
    
    ----------------------------- 
    
    
    
    shaderAddEffect(eff) 
    
    shaderRemoveEffect(eff) 
    
    shader_effects[eff].num.strength=1 
    
    bind(eff, "time", field("shader_iTime")) 
    
    bind(eff, "daytime", field("Values.Daytime.Int")); 
    
    function updateWeltbildsonne() 
    
     shader_effects[eff].num.daytime = Values.Daytime.Int * 0.0125; 
    
    end 
    
    shaderSetOptions({{shader = shader_effects[eff].num(), comp_dst=5, comp_src=4 }}, id) 
    
    Objects[obj].ShaderSet = id 
    
    
    
    registerEventHandler("mainLoop", "updateWeltbildsonne") 

    Thanks for the Help.

    Forum Fan

    145 Posts

  • #5, by SimonSMonday, 28. August 2017, 22:02 7 years ago
    You can no longer write the shaders in lua, V5 uses DX11, so the shaders must be translated. Use the shader tab and create a shader, change the fragment with yours and mess around until it compiles.


    local eff="Wolkenmaske" 
    
    local obj = "TestClouds" 
    
    local id = 2 
    
    
    
    ----------------------------- 
    
    
    
    shaders[eff] = shader(eff, Shaders["ShaderName"].Compiled)
    
    shaderAddEffect(eff) 
    
    shaderRemoveEffect(eff) 
    
    shader_effects[eff].num.strength=1 
    
    bind(eff, "time", field("shader_iTime")) 
    
    bind(eff, "daytime", field("Values.Daytime.Int * 0.0125")); 
    
    Objects[obj].ShaderSet = id 


    Thread Captain

    1581 Posts

  • #6, by caligarimarteTuesday, 29. August 2017, 12:17 7 years ago
    Thank you very much! I got the Clouds to work (and at Least it is quite a Blessing that seemingly Shaders no longer depend on rightly ordered IDs). Even though there is still a reeeally miniscule "not quite wrapping" Border visible (comparable to when I clamped the Coordinates), that is next to invisible, and thusly not a big Deal. Now I am happy with that Cloud-Effect.

    Though now I am trying to implement another Shader applied to the whole Screen (namely my good old Day-&-Night Cycle), and I am following the Example from the Reference you gave me -- thank you very much for it! --, but alas, for some obscure Reason the Script just won't activate my "daynight"-Shader. Can you tell me what I am doing wrong? (I am sure the Mistake is some truly minor Detail, making this whole Question look utterly ridiculous, but I am afraid I just can't find it.)

    Here is the Shader (for the Sake of Completion)...
    #ifdef GL_ES
    
    precision lowp float;
    
    precision lowp int;
    
    #endif
    
    uniform sampler2D texel;
    
    varying vec2 uvVarying;
    
    const float pi = 3.1415926535897932384626433832795;
    
    uniform float daytime;
    
    
    
    void main ()
    
    {
    
     float x = daytime;
    
     float R = (0.75+sin((x-3.0)*0.5*pi + cos((x-3.0)*0.5*pi))*0.25);
    
     float G = (0.75+0.125+cos(x*0.5*pi)*0.125);
    
     float B = (0.75+0.125+cos(x*1.0*pi)*0.125);
    
     vec3 col = vec3(R,G,B);
    
     gl_FragColor = vec4(texture2D(texel, uvVarying.xy).rgb * col, 1.0);
    
    }

    ... and here is the Script:
    local eff = "daynight"
    
    shaders[eff] = shader(eff, Shaders[eff].Compiled)
    
    shaderAddEffect(eff)
    
    bind(eff, "daytime", field("Values.Daytime.Int"))
    
    
    
    function updateDaynight()
    
     shader_effects[eff].num.daytime = Values.Daytime.Int * 0.0125
    
    end
    
    registerEventHandler("mainLoop", "updateDaynight") 
    

    Forum Fan

    145 Posts

  • #7, by SimonSWednesday, 30. August 2017, 09:34 7 years ago
    The correct load code looks like this, seems the code was for another version of the toolkit:
    local eff = "Daynight"
    shader_effects[eff] = { shader = Shaders[eff].Compiled }
    shaderAddEffect(eff)
    bind(eff, "daytime", field("getTime() * 0.00125"))

    Also don't use that ugly main loop handler. You can do everything with the bind().

    Thread Captain

    1581 Posts

  • #8, by caligarimarteWednesday, 30. August 2017, 12:08 7 years ago
    Thank you very much, now the Shaders work! And I was quite ecstatic about not having to use the (indeed quite ugly) Main Loop, so I immediately changed the other already working Shaders from the "Without the Shader-Toolkit"-Form into the "With the Shader-Toolkit"-Form because the former didn't take the bind()-Command and thusly seemed to need the Main Loop...

    ... but this has led me to another Problem: It worked fine when I was using the "No-Toolkit"-Form with the Main Loop on two Cloud-Objects, each in a different Scene and each having its own Script adding the same Shader but with different Values. Now that I have rewritten the Code into the "With-Toolkit"-Form and using only bind() instead of the Main Loop, only the second Cloud-Object will get its Shader updated, the first will be stuck.
    Both Scripts are Definition Scripts, so maybe I would have to go the extra Mile and turn them into Execution Scripts and turn the Shaders on or off depending on what Scene the Player is in? I tried to add shaderRemoveEffect inside the Script, before shader AddEffect (which I know can work on my Day-Night-Cycle to ensure it is not running before another Scene adds it), but here with the Cloud-Shader on two separate Objects, it doesn't seem to work.
    So now I am torn between the seemingly only halfway working bind()-Form and the ugly but working Main Loop. Is there a Way to fix that Issue with the bind()-Form alone?

    (P.S.: I know it is a little bizarre that I keep up the English in a Dialogue between two German-Speakers, but in Case other People encounter the same Problems, I think the Problems and their Solutions should be available to every User on the Forum, so I prefer to keep it up.)

    Forum Fan

    145 Posts

  • #9, by afrlmeWednesday, 30. August 2017, 16:42 7 years ago
    (P.S.: I know it is a little bizarre that I keep up the English in a Dialogue between two German-Speakers, but in Case other People encounter the same Problems, I think the Problems and their Solutions should be available to every User on the Forum, so I prefer to keep it up.)

    I'm pretty sure all of us non-German speakers appreciate it. wink

    If it was up to me, the entire forum would have an enforced English only rule. You could call me biased for that because my native Language is in English, but almost every single forum/discord/voip thing I join always have the English only rule, even when the owners aren't even native English speakers.

    Anyway, this shader stuff is too complex for me. Would love to be able to learn c languages/glsl but I lack the patience to learn it. Learning new things is kind of hard for me because of my bad memory.

    Imperator

    7278 Posts

  • #10, by caligarimarteWednesday, 30. August 2017, 19:33 7 years ago
    @ AFRLme: Well, that sounds a little Bit totalitarian, doesn't it? I am reminded of the Ultima Games, where the Story-Focus lies on several very altruistic Virtues, and then in one Game these same Virtues are forced onto the People by a totalitarian Regime and all of a sudden it really doesn't sound quite as nice anymore. (Very close to Reality.)

    @ SimonS: Though I do not know that right now, I do assume that the Game's Performance might benefit anyway if a Shader is only active while the Scene it is for is running (do added Shaders on another Scene still "run" and eat up Performance, like looping Functions?), so it might be better anyway if I add and remove these specific Shaders Scene by Scene -- that Way the Shader will work fine, and maybe it'll even help the Performance. So, since I have found some Sort of Solution, I guess that last Problem of mine is of very little Importance, but none the less a Bit of a Problem (since one Shader on multiple Objects works fine with the No-Toolkit Form), and I can at last be at Peace. (Even though I am not entirely sure whether this qualifies for the Topic to be marked as "SOLVED" or not.)
    Thank you very much for all the Help so far, Simon.

    Forum Fan

    145 Posts

  • #11, by afrlmeWednesday, 30. August 2017, 20:13 7 years ago
    Maybe? grin

    I don't mind people posting in other languages, it's just that hardly anyone but native German speakers speak/type German, whereas nearly everyone who's at least had an high school education can speak at least a little bit of English. I know that's not the case with younger people that haven't studied it yet or older people that didn't bother learning it back in school as it wasn't that important to do so years ago or have just forgotten it over time.

    It would be nice if something like that DeepL thing Sebastian linked could be integrated into the site somehow, so that we could tranlate all the text on a page into a language of our choosing. I know those online translator aren't super accurate, but I think it would certainly be of use for getting a basic idea of what someone is saying/asking.

    Imperator

    7278 Posts