Menu

Ocean Shader + memoryViewer

Help
Daniel
2017-11-07
2017-11-07
  • Daniel

    Daniel - 2017-11-07

    Hi all!

    Once again I call for your help!

    I'm working on implementing the code from the GLSL ocean shader demo into my program.
    The problem I have is that when I have another memoryViewer, unrelated to the ocean, and do:

    GLMemoryViewer2.Render;
    GLMemoryViewer2.CopyToTexture(glplane1.Material.Texture);
    

    Then the shader doesn't work.

    Any idea why not?
    I can upload the sample if needed.

    Cheers!

     
  • Daniel

    Daniel - 2017-11-08

    Hi again!

    I might have solved it temporarily, but still do not understand...

    Now I instead have a problem that it runs out of memory after using the shader for a few minutes.
    I'm bad at the GLSL, but some variable is building up an eating the memory in the ocean.
    The 'time' variable is being reset in my program, so it's some other variable.
    How can I prevent the shader from running out of memory?

     
  • Daniel

    Daniel - 2017-11-08
    #version 120
    uniform float Time;
    uniform vec4  EyePos;
    
    varying vec3   EyeVec;
    varying mat3 ObjToTangentSpace;
    
    const float cTexScale = 0.2;
    const float cBumpScale = 0.15;
    const float cBumpSpeed = 0.4;
    
    // Waves parameters
    
    #define NWAVES 3
    struct Wave {
       float freq;  // 2*PI / wavelength
       float amp;   // amplitude
       float phase; // speed * 2*PI / wavelength
       vec2 dir;
    };
    Wave wave[NWAVES];
    
    const float k = 2.0;
    
    Wave initWave(float freq, float amp, float phase, vec2 dir)
    {
       Wave result;
       result.freq = freq;
       result.amp = amp;
       result.phase = phase;
       result.dir = dir;
       return result;
    }
    
    vec2 evaluateWave(Wave w, vec2 pos, float t)
    {
       vec2 result;
    
       float wavePos = dot(w.dir, pos)*w.freq + t*w.phase;
       float waveAmp = sin(wavePos)*0.5 + 0.5;
    
       result.x = w.amp * pow(waveAmp, k);
       result.y = k*w.freq*w.amp * pow(waveAmp, k-1.0) * cos(wavePos);
    
       return result;
    }
    
    void main()
    {
       vec4 P = gl_Vertex;
    
       wave[0] = initWave( 0.2, 0.9, 12.0, vec2(1.0, 0.0) );
       wave[1] = initWave( 0.3, 0.7, 9.0,  vec2(0.98, 0.2) );
       wave[2] = initWave( 0.4, 0.5, 8.0,  vec2(0.99, -0.15) );
    
       // sum waves
       vec2 dd = vec2(0.0, 0.0);
       for(int i=0; i<NWAVES; i++) {
          vec2 waveEval = evaluateWave(wave[i], P.xy, Time);
          P.z += waveEval.x;
          dd += waveEval.y * wave[i].dir;
       }
    
       gl_Position = gl_ModelViewProjectionMatrix * P;
    
       // compute tangent basis
       vec3 B = vec3(1.0, 0.0, dd.x);
       vec3 T = vec3(0.0, 1.0, dd.y);
       vec3 N = vec3(-dd.x, -dd.y, 1);
    
       // compute the 3x3 tranform from tangent space to object space
       // first rows are the tangent and binormal scaled by the bump scale
       ObjToTangentSpace[0] = cBumpScale * normalize(T);
       ObjToTangentSpace[1] = cBumpScale * normalize(B);
       ObjToTangentSpace[2] = normalize(N);
    
       float texTime = Time*cBumpSpeed;
       gl_TexCoord[0].xy = gl_Vertex.xy*cTexScale + texTime;
       gl_TexCoord[1].xy = gl_Vertex.xy*(2.0*cTexScale) - texTime;
    
       EyeVec = normalize(gl_Vertex.xyz - EyePos.xyz);
    }
    
     
  • Jerome.D (BeanzMaster)

    Hi Daniel concerning the MemViewer if i'm remember this bug is solved in GLScene 1.5.
    For the problem with shader :
    1) I don't think the problem comes from the GLSL Script
    2) Can you put also the VertexShader Script and how you do for instantiate the Shader, and how you pass parameters to it or can you make a little sample i'll can check

    Thanks

     
  • Daniel

    Daniel - 2017-11-08

    Hi Jerome!
    Thank you again for helping!
    The above code is from the vertexShader.
    Here is the fragment shader:

    //#ifndef __GLSL_CG_DATA_TYPES
    # define half float
    # define half3x3 mat3
    # define half3 vec3
    # define half4 vec4
    //#endif
    
    uniform sampler2D NormalMap;
    uniform samplerCube EnvironmentMap;
    
    varying half3 EyeVec;
    varying half3x3 ObjToTangentSpace;
    
    const float cFresnelBias = 0.1;
    const half3 cDeepColor = half3(0.0, 0.1, 0.2);
    const half3 cShallowColor = half3(0.0, 0.2, 0.4);
    
    const half3 cNormalCorrection = vec3(-1.0, -1.0, 0.0);
    
    void main()
    {
        // sum normal maps
        half3 t0 = texture2D(NormalMap, gl_TexCoord[0].xy).rgb;
        half3 t1 = texture2D(NormalMap, gl_TexCoord[1].xy).rgb;
        half3 normal = t0 + t1 + cNormalCorrection;
    
        half3 nW = normalize(ObjToTangentSpace * normal);
    
        half3 r = reflect(EyeVec, nW);
        half4 rColor = textureCube(EnvironmentMap, r);
        half hdr = 0.15+0.1*rColor.a;
    
        half  facing = 1.0-max(dot(normalize(-EyeVec), nW), 0.0);
        half3 waterColor = mix(cDeepColor, cShallowColor, facing);
    
        half fresnel = cFresnelBias + (1.0-cFresnelBias)*pow(facing, 4.0);
    
        gl_FragColor = vec4(waterColor + (fresnel*hdr)*rColor.rgb, 1.0);
    }
    

    Another vertexshader I tried:

    //#ifndef __GLSL_CG_DATA_TYPES
    # define half float
    # define half3x3 mat3
    # define half2 vec2
    # define half3 vec3
    # define half4 vec4
    //#endif
    
    uniform float Time;
    uniform vec4  EyePos;
    
    varying half3   EyeVec;
    varying half3x3 ObjToTangentSpace;
    
    const half cTexScale = 0.4;
    const half cBumpScale = 0.4;
    const half cBumpSpeed = 0.6;
    
    // Waves parameters
    
    #define NWAVES 4
    struct Wave {
       half freq;  // 2*PI / wavelength
       half amp;   // amplitude
       half phase; // speed * 2*PI / wavelength
       half2 dir;
    };
    Wave wave[NWAVES];
    
    const half k = 2.0;
    
    Wave initWave(half freq, half amp, half phase, half2 dir)
    {
       Wave result;
       result.freq = freq;
       result.amp = amp;
       result.phase = phase;
       result.dir = dir;
       return result;
    }
    
    half2 evaluateWave(Wave w, vec2 pos, float t)
    {
       vec2 result;
    
       float wavePos = dot(w.dir, pos)*w.freq + t*w.phase;
       half waveAmp = sin(wavePos)*0.5 + 0.5;
    
       result.x = w.amp * pow(waveAmp, k);
       result.y = k*w.freq*w.amp * pow(waveAmp, k-1.0) * cos(wavePos);
    
       return result;
    }
    
    void main()
    {
       vec4 P = gl_Vertex;
    
       wave[0] = initWave( 0.9, 0.3, 0.8, half2(0.5, 0.5) );
       wave[1] = initWave( 1.9, 0.4, 2.0,  half2(0.2, -0.8) );
       wave[2] = initWave( 1.5, 0.5, 8.0,  half2(0.7, -0.15) );
       wave[3] = initWave( 3.5, 0.2, 6.0,  half2(0.9, -1.15) );
    
       // sum waves
       vec2 dd = vec2(0.0, 0.0);
       for(int i=0; i<NWAVES; i++) {
          vec2 waveEval = evaluateWave(wave[i], P.xy, Time);
          P.z += waveEval.x;
          dd += waveEval.y * wave[i].dir;
       }
    
       gl_Position = gl_ModelViewProjectionMatrix * P;
    
       // compute tangent basis
       half3 B = half3(1.0, 0.0, dd.x);
       half3 T = half3(0.0, 1.0, dd.y);
       half3 N = half3(-dd.x, -dd.y, 1);
    
       // compute the 3x3 tranform from tangent space to object space
       // first rows are the tangent and binormal scaled by the bump scale
       ObjToTangentSpace[0] = cBumpScale * normalize(T);
       ObjToTangentSpace[1] = cBumpScale * normalize(B);
       ObjToTangentSpace[2] = normalize(N);
    
       float texTime = Time*cBumpSpeed;
       gl_TexCoord[0].xy = gl_Vertex.xy*cTexScale + texTime;
       gl_TexCoord[1].xy = gl_Vertex.xy*(2.0*cTexScale) - texTime;
    
       EyeVec = normalize(gl_Vertex.xyz - EyePos.xyz);
    }
    
     
  • Daniel

    Daniel - 2017-11-08

    Something generates an error after ~5 minutes running the program. Last time it was a error directing to this function in GLScene.pas: function TGLBaseSceneObject.AbsoluteMatrixAsAddress : PMatrix;
    Sometimes its an out of memory error.

    This is the code I use:

    procedure TForm1.InitRender(Sender: TObject; var rci: TRenderContextInfo);
    begin
    
       if not (    GL_ARB_shader_objects and GL_ARB_vertex_program and GL_ARB_vertex_shader
               and GL_ARB_fragment_shader) then begin
          ShowMessage('Your hardware/driver doesn''t support GLSL and can''t execute this demo!');
          Halt;
       end;
    
       if init.Tag<>0 then Exit;
       init.Tag:=1;
    
       programObject:=TGLProgramHandle.CreateAndAllocate;
    
       programObject.AddShader(TGLVertexShaderHandle, LoadStringFromFile('ocean_vp.glsl'), True);
       programObject.AddShader(TGLFragmentShaderHandle, LoadStringFromFile('ocean_fp.glsl'), True);
    
       if not programObject.LinkProgram then
          raise Exception.Create(programObject.InfoLog);
    
       if not programObject.ValidateProgram then
          raise Exception.Create(programObject.InfoLog);
    
       // initialize the heightmap
       with MatLib.LibMaterialByName('waterGLSL') do begin
          PrepareBuildList;
          glActiveTextureARB(GL_TEXTURE0_ARB);
          glBindTexture(GL_TEXTURE_2D, Material.Texture.Handle);
          glActiveTextureARB(GL_TEXTURE0_ARB);
       end;
    
       // initialize the heightmap
       with MatLib.LibMaterialByName('cubeMapGLSL') do begin
          PrepareBuildList;
          glActiveTextureARB(GL_TEXTURE1_ARB);
          glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, Material.Texture.Handle);
          glActiveTextureARB(GL_TEXTURE0_ARB);
       end;
    
       programObject.UseProgramObject;
    
       programObject.Uniform1i['NormalMap']:=0;
       programObject.Uniform1i['EnvironmentMap']:=1;
    
       programObject.EndUseProgramObject;
    
       CheckOpenGLError;
    
    end;
    
    procedure TForm1.GLUserShader1DoApply(Sender: TObject;
      var rci: TRenderContextInfo);
    var
       mat : TMatrix;
       camPos : TVector;
    begin
    
       glGetFloatv(GL_MODELVIEW_MATRIX, @mat);
       InvertMatrix(mat);
    
       programObject.UseProgramObject;
    
       programObject.Uniform1f['Time']:= OceanShaderTimeVar * 30 * 0.1;
    
       camPos:=GLCamera3.AbsolutePosition;
       programObject.Uniform4f['EyePos']:=camPos;
    end;
    
    procedure TForm1.GLUserShader1DoUnApply(Sender: TObject; Pass: Integer;
      var rci: TRenderContextInfo; var Continue: Boolean);
    begin
         programObject.EndUseProgramObject;
    end;
    
    procedure TForm1.OceanDGLRender(Sender: TObject;
      var rci: TRenderContextInfo);
    var
       x, y : Integer;
       v : TTexPointList;
       cont : Boolean;
    begin
    
       GLUserShader1DoApply(Self, rci);
       glEnableClientState(GL_VERTEX_ARRAY);
    
       if not Assigned(vbo) then begin
          v:=TTexPointList.Create;
    
          v.Capacity:=Sqr(200+1);
          y:=-200; while y<200 do begin
             x:=-200; while x<=200 do begin
                v.Add(y, x);
                v.Add(y+2, x);
                Inc(x, 2);
             end;
             Inc(y, 2);
             v.Add(y, 200);
             v.Add(y, -200);
          end;
    
          vbo:=TGLVBOArrayBufferHandle.CreateAndAllocate();
          vbo.Bind;
          vbo.BufferData(v.List, v.DataSize, GL_STATIC_DRAW_ARB);
          nbVerts:=v.Count;
    
          glVertexPointer(2, GL_FLOAT, 0, nil);
          glDrawArrays(GL_QUAD_STRIP, 0, nbVerts);
    
          vbo.UnBind;
    
          v.Free;
       end else begin
          vbo.Bind;
    
          glVertexPointer(2, GL_FLOAT, 0, nil);
          glDrawArrays(GL_TRIANGLE_STRIP, 0, nbVerts);
    
          vbo.UnBind;
       end;
    
       glDisableClientState(GL_VERTEX_ARRAY);
       GLUserShader1DoUnApply(Self, 0, rci, cont);
    
    end;
    
     

    Last edit: Daniel 2017-11-08
  • Daniel

    Daniel - 2017-11-08

    Now after 12 minutes I got, Error: "Unknown uniform 'Time' or program not in use (D:.....\Source\GLContext,pas, line 1487)"

    And then

    Vertex info
    .--------------
    (0) : fatal error C9999: out of memory - internal malloc failed

     
  • Jerome.D (BeanzMaster)

    Try to pass the follwing part

    if not Assigned(vbo) then begin
          v:=TTexPointList.Create;
    
          v.Capacity:=Sqr(200+1);
          y:=-200; while y<200 do begin
             x:=-200; while x<=200 do begin
                v.Add(y, x);
                v.Add(y+2, x);
                Inc(x, 2);
             end;
             Inc(y, 2);
             v.Add(y, 200);
             v.Add(y, -200);
          end;
    
          vbo:=TGLVBOArrayBufferHandle.CreateAndAllocate();
          vbo.Bind;
          vbo.BufferData(v.List, v.DataSize, GL_STATIC_DRAW_ARB);
          nbVerts:=v.Count;
    
          glVertexPointer(2, GL_FLOAT, 0, nil);
          glDrawArrays(GL_QUAD_STRIP, 0, nbVerts);
    
          vbo.UnBind;
    
          v.Free;
    

    in you InitRender procedure

    and becarefull

    you have

    glVertexPointer(2, GL_FLOAT, 0, nil);
    glDrawArrays(GL_QUAD_STRIP, 0, nbVerts);
    

    else you have

    glVertexPointer(2, GL_FLOAT, 0, nil);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, nbVerts);
    

    I suppose it's your error

     
  • Daniel

    Daniel - 2017-11-09

    Thanks Jerome!
    I solved it now! It was a bad loop calling the initRender over and over...
    I will stress test it and see if it works as intended!!

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.