Shader coding with PB possible?

Everything related to 3D programming
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Re: Shader coding with PB possible?

Post by [blendman] »

Hi

Thanks for this great code !

I have added a simple save/load and Runshader system (I have delete all the previous shader, but you can add them in this code) :

Code: Select all

;/ GLSL example to test new OpenGLGadget - PJ 06/2014.

EnableExplicit

Enumeration ;/ Window
  #Window_Main
EndEnumeration
Enumeration ;/ Gadget
  #Gad_OpenGL
  #Gad_Editor
  #Gad_ShaderSelector_Combo
EndEnumeration
Enumeration ;/ Menu
  #Menu_Open
  #Menu_Save
  #Menu_Run
EndEnumeration


Structure System
  Width.i
  Height.i
  Shader_Width.i
  Shader_Height.i
  Event.i
  Exit.i
  MouseX.i
  MouseY.i
  
  App_CurrentTime.i
  App_StartTime.i
  Editor_LastText.s
  
  Shader_Vertex_Text.s
  Shader_Fragment_Text.s
  Shader_Vertex.i
  Shader_Fragment.i
  Shader_Program.i
  
  Shader_Uniform_Time.i
  Shader_Uniform_Resolution.i
  Shader_Uniform_Mouse.i
  Shader_Uniform_SurfacePosition.i
  
  FPS_Timer.i
  Frames.i
  FPS.i
EndStructure

Global System.System

Procedure Init_Main()
  Protected MyLoop.i
  
  System\Width.i = 1024
  System\Height = 480
  System\Shader_Width = 640
  System\Shader_Height = 480
  
  OpenWindow(#Window_Main,0,0,System\Width,System\Height,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  
  If CreateMenu(0, WindowID(#Window_Main))
    MenuTitle("File")
    MenuItem(#Menu_Open,"Open")
    MenuItem(#Menu_Save,"Save")
    MenuBar()
    MenuItem(#Menu_Run,"Run Shader")
    
  EndIf
  
  OpenGLGadget(#Gad_OpenGL,0,0,System\Shader_Width,System\Shader_Height,#PB_OpenGL_Keyboard)
  ComboBoxGadget(#Gad_ShaderSelector_Combo,System\Shader_Width+4,2,System\Width - (System\Shader_Width+8),24)
AddGadgetItem(#Gad_ShaderSelector_Combo,-1,"Shader: "+Str(1)) 

  
  SetGadgetState(#Gad_ShaderSelector_Combo,0)
  EditorGadget(#Gad_Editor,System\Shader_Width+4,30,System\Width - (System\Shader_Width+8),System\Height-30)
  
  System\App_StartTime = ElapsedMilliseconds()
  
  
  System\Shader_Vertex_Text = "attribute vec3 position;"
  System\Shader_Vertex_Text + "attribute vec2 surfacePosAttrib;"
  System\Shader_Vertex_Text + "varying vec2 surfacePosition;"
  System\Shader_Vertex_Text + "	void main() {"
  System\Shader_Vertex_Text + "		surfacePosition = surfacePosAttrib;"
  System\Shader_Vertex_Text + "		gl_Position = vec4( position, 1.0 );"
  System\Shader_Vertex_Text + "	}"
EndProcedure

Init_Main()

;{ Opengl shader setup & routines

#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30

Prototype glCreateShader(type.l)
Prototype glCreateProgram()
Prototype glCompileShader(shader.l)
Prototype glLinkProgram(shader.l)
Prototype glUseProgram(shader.l)
Prototype glAttachShader(Program.l, shader.l)
Prototype glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) : 
Prototype.i glGetUniformLocation(Program.i, name.s)
Prototype glUniform1i(location.i, v0.i)
Prototype glUniform2i(location.i, v0.i, v1.i)
Prototype glUniform1f(location.i, v0.f)
Prototype glUniform2f(location.i, v0.f, v1.f)
Prototype glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)

Global glCreateShader.glCreateShader = wglGetProcAddress_("glCreateShader")
Global glCreateProgram.glCreateProgram = wglGetProcAddress_("glCreateProgram")
Global glCompileShader.glCompileShader = wglGetProcAddress_("glCompileShader")
Global glLinkProgram.glLinkProgram = wglGetProcAddress_("glLinkProgram")
Global glUseProgram.glUseProgram = wglGetProcAddress_("glUseProgram")
Global glAttachShader.glAttachShader = wglGetProcAddress_("glAttachShader")
Global glShaderSource.glShaderSource = wglGetProcAddress_("glShaderSource")
Global glGetUniformLocation.glGetUniformLocation = wglGetProcAddress_("glGetUniformLocation")
Global glUniform1i.glUniform1i = wglGetProcAddress_("glUniform1i")
Global glUniform2i.glUniform2i = wglGetProcAddress_("glUniform2i")
Global glUniform1f.glUniform1f = wglGetProcAddress_("glUniform1f")
Global glUniform2f.glUniform2f = wglGetProcAddress_("glUniform2f")
Global glGetShaderInfoLog.glGetShaderInfoLog = wglGetProcAddress_("glGetShaderInfoLog")

Procedure Shader_Compile_Link_Use(Vertex.s,Fragment.s,Use.i=1)
  Protected VertShader.i, FragShader.i, *TxtPointer, Program.i
  Protected Textlength.i, Mytext.s = Space(1024)
  
  ;/ Compile Vertex shader
  VertShader.i = glCreateShader(#GL_VERTEX_SHADER)
  *TxtPointer = @Vertex
  glShaderSource(VertShader, 1, @*TxtPointer, #Null)
  glCompileShader(VertShader)
  Debug "Vert: "+VertShader
  glGetShaderInfoLog(VertShader,1023,@Textlength,@Mytext)
  Debug MyText
  ;/ Compile Fragment Shader
  FragShader.i = glCreateShader(#GL_FRAGMENT_SHADER)
  *TxtPointer = @Fragment
  glShaderSource(FragShader, 1, @*TxtPointer, #Null)
  glCompileShader(FragShader)
  Debug "Frag: "+FragShader
  glGetShaderInfoLog(FragShader,1023,@Textlength,@Mytext)
  Debug MyText
  
  ;/ Create Shader Program
  Program = glCreateProgram()
  glAttachShader(Program,VertShader)
  Debug "Attached Vert Shader"
  glAttachShader(Program,FragShader)
  Debug "Attached Frag Shader"
  glLinkProgram(Program)
  Debug "Link program"
  
  If Use = 1
    glUseProgram(Program)
  EndIf
  
  ProcedureReturn Program  
EndProcedure
;}

Procedure Shader_Set(Fragment.i, shader$="")
  
  If System\Shader_Program <> 0 ;/ delete the previous shaders
    glUseProgram(0);
  EndIf
  
  If Fragment = -2 ; run the shader    
    System\Shader_Fragment_Text = GetGadgetText(#Gad_Editor)    
  ElseIf Fragment = -1 ; load the shader
      System\Shader_Fragment_Text = shader$+Chr(10)
  Else
    
   Select Fragment
    Case 0
      System\Shader_Fragment_Text = "uniform float time;"+Chr(10)
      System\Shader_Fragment_Text + "uniform vec2 resolution;"+Chr(10)
      System\Shader_Fragment_Text + ""+Chr(10)
      System\Shader_Fragment_Text + "void main( void ) {"+Chr(10)
      System\Shader_Fragment_Text + "	vec2 p = ( gl_FragCoord.xy / resolution.xy ) - 0.2;"+Chr(10)
      System\Shader_Fragment_Text + "	float sx = 0.3 * (p.x + 0.8) * sin( 3.0 * p.x - 1. * time);"+Chr(10)
      System\Shader_Fragment_Text + "	float dy = 4./ ( 123. * abs(p.y - sx));"+Chr(10)
      System\Shader_Fragment_Text + "	dy += 1./ (160. * length(p - vec2(p.x, 0.)));"+Chr(10)
      System\Shader_Fragment_Text + "	gl_FragColor = vec4( (p.x + 0.1) * dy, 0.3 * dy, dy, 2.1 );"+Chr(10)
      System\Shader_Fragment_Text + "}"+Chr(10)
   
   
    
      
  EndSelect
  
  EndIf

  System\Shader_Program = Shader_Compile_Link_Use(System\Shader_Vertex_Text,System\Shader_Fragment_Text)
  
  If System\Shader_Program = 0
    MessageRequester("Unsupported Device?","No Shader Support Available",#PB_MessageRequester_Ok)
    End
  EndIf
  
  ;/ store shader uniform locations
  Debug "Shader: "+System\Shader_Program
  System\Shader_Uniform_Time = glGetUniformLocation(System\Shader_Program, "time")
  System\Shader_Uniform_Mouse = glGetUniformLocation(System\Shader_Program, "mouse")
  System\Shader_Uniform_Resolution = glGetUniformLocation(System\Shader_Program, "resolution")
  System\Shader_Uniform_SurfacePosition.i = glGetUniformLocation(System\Shader_Program, "surfacePosition")
  Debug "Time location: "+System\Shader_Uniform_Time
  Debug "Mouse location: "+System\Shader_Uniform_Mouse
  Debug "Res location: "+System\Shader_Uniform_Resolution
  Debug "SurfacePos location: "+System\Shader_Uniform_SurfacePosition
  
  SetGadgetText(#Gad_Editor,System\Shader_Fragment_Text)
  
EndProcedure

Procedure OpenShader()
  Define filename$ ="", txt$ = ""
  
  filename$ = OpenFileRequester("Open shader","","All|*.*",0)
  
  If filename$ <> ""
    
    If ReadFile(0, filename$) 
      While Eof(0) = 0           
        txt$ + ReadString(0) +Chr(10) 
      Wend
      CloseFile(0)  
      Shader_Set(-1,txt$)

    Else
      MessageRequester("Information","Impossible d'ouvrir le fichier!")
    EndIf

  EndIf
  
EndProcedure
Procedure SaveShader()
  Define filename$ =""
  
  filename$ = SaveFileRequester("Save","","txt|*.txt",0)
  
  If filename$ <> ""
    
    If OpenFile(0, filename$) 
      WriteStringN(0, GetGadgetText(#Gad_Editor))
      CloseFile(0)
    EndIf
    
  EndIf
  
EndProcedure
Procedure RunShader()
  
  Shader_Set(-2)
  
EndProcedure

Shader_Set(0)

Procedure Render()
  ;/ set shader Uniform values
  glUniform2f(System\Shader_Uniform_Resolution,System\Shader_Width,System\Shader_Height)
  glUniform1f(System\Shader_Uniform_Time,(System\App_CurrentTime-System\App_StartTime) / 1000.0)
  glUniform2i(System\Shader_Uniform_SurfacePosition.i,1.0,1.0)
  
  glBegin_(#GL_QUADS)
    glVertex2f_(-1,-1) 
    glVertex2f_( 1,-1) 
    glVertex2f_( 1, 1) 
    glVertex2f_(-1, 1) 
  glEnd_()           
  
  System\Frames + 1
  If System\App_CurrentTime > System\FPS_Timer
    System\FPS = System\Frames
    System\Frames = 0
    System\FPS_Timer = System\App_CurrentTime  + 1000
    SetWindowTitle(#Window_Main,"GLSL Testing - PJ 07/06/2014 - FPS: "+Str(System\FPS))
  EndIf
  
  SetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_FlipBuffers,1)
  
EndProcedure

Repeat
  
  Repeat
    
    System\Event = WindowEvent()
    
    Select System\Event
        
      Case #PB_Event_Menu
        Select EventMenu()
          Case #Menu_Open
            OpenShader()
          Case #Menu_Save
            SaveShader()
          Case #Menu_Run
            RunShader()
            
        EndSelect
        
      Case #PB_Event_CloseWindow        
        System\Exit = #True
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Gad_ShaderSelector_Combo
            Select EventType()
              Case #PB_EventType_Change
                Debug "Set to: "+GetGadgetState(#Gad_ShaderSelector_Combo)
                Shader_Set(GetGadgetState(#Gad_ShaderSelector_Combo))
            EndSelect
          Case #Gad_OpenGL
            Select EventType()
              Case #PB_EventType_MouseMove
                System\MouseX = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseX)
                System\MouseY = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseY)
                glUniform2f(System\Shader_Uniform_Mouse,System\MouseX / System\Shader_Width,(System\Shader_Height-System\MouseY) / System\Shader_Height)
            EndSelect
        EndSelect
    EndSelect
    
  Until System\Event = 0
  
  
  System\App_CurrentTime = ElapsedMilliseconds()
  
  Render()
  
Until System\Exit 
And some shader examples:
Blob

Code: Select all

// Blobs by @paulofalcao
uniform float time;
uniform vec2 resolution;

 
float makePoint(float x,float y,float fx,float fy,float sx,float sy,float t){
   float xx=x+sin(t*fx)*sx;
   float yy=y+cos(t*fy)*sy;
   return 1.0/sqrt(xx*xx+yy*yy);
}

void main( void ) {
	
   vec2 p=(gl_FragCoord.xy/resolution.x)*2.0-vec2(1.0,resolution.y/resolution.x);
   
   p=p*2.0;
   
   float x=p.x;
   float y=p.y;

   float a=
       makePoint(x,y,3.3,2.9,0.3,0.3,time);
   a=a+makePoint(x,y,1.9,2.0,0.4,0.4,time);
   a=a+makePoint(x,y,0.8,0.7,0.4,0.5,time);
   a=a+makePoint(x,y,2.3,0.1,0.6,0.3,time);
   a=a+makePoint(x,y,0.8,1.7,0.5,0.4,time);
   a=a+makePoint(x,y,0.3,1.0,0.4,0.4,time);
   a=a+makePoint(x,y,1.4,1.7,0.4,0.5,time);
   a=a+makePoint(x,y,1.3,2.1,0.6,0.3,time);
   a=a+makePoint(x,y,1.8,1.7,0.5,0.4,time);   
   
   float b=
       makePoint(x,y,1.2,1.9,0.3,0.3,time);
   b=b+makePoint(x,y,0.7,2.7,0.4,0.4,time);
   b=b+makePoint(x,y,1.4,0.6,0.4,0.5,time);
   b=b+makePoint(x,y,2.6,0.4,0.6,0.3,time);
   b=b+makePoint(x,y,0.7,1.4,0.5,0.4,time);
   b=b+makePoint(x,y,0.7,1.7,0.4,0.4,time);
   b=b+makePoint(x,y,0.8,0.5,0.4,0.5,time);
   b=b+makePoint(x,y,1.4,0.9,0.6,0.3,time);
   b=b+makePoint(x,y,0.7,1.3,0.5,0.4,time);

   float c=
       makePoint(x,y,3.7,0.3,0.3,0.3,time);
   c=c+makePoint(x,y,1.9,1.3,0.4,0.4,time);
   c=c+makePoint(x,y,0.8,0.9,0.4,0.5,time);
   c=c+makePoint(x,y,1.2,1.7,0.6,0.3,time);
   c=c+makePoint(x,y,0.3,0.6,0.5,0.4,time);
   c=c+makePoint(x,y,0.3,0.3,0.4,0.4,time);
   c=c+makePoint(x,y,1.4,0.8,0.4,0.5,time);
   c=c+makePoint(x,y,0.2,0.6,0.6,0.3,time);
   c=c+makePoint(x,y,1.3,0.5,0.5,0.4,time);
   
   vec3 d=vec3(a,b,c)/32.0;
   
   gl_FragColor = vec4(d.x,d.y,d.z,1.0);
}
Flame :

Code: Select all

// code by shadertoy ?
uniform vec2 resolution;
uniform float time;


float snoise(vec3 uv, float res)
{
	const vec3 s = vec3(1e0, 1e2, 1e3);
	
	uv *= res;
	
	vec3 uv0 = floor(mod(uv, res))*s;
	vec3 uv1 = floor(mod(uv+vec3(1.), res))*s;
	
	vec3 f = fract(uv); f = f*f*(3.0-2.0*f);

	vec4 v = vec4(uv0.x+uv0.y+uv0.z, uv1.x+uv0.y+uv0.z,
		      	  uv0.x+uv1.y+uv0.z, uv1.x+uv1.y+uv0.z);

	vec4 r = fract(sin(v*1e-1)*1e3);
	float r0 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y);
	
	r = fract(sin((v + uv1.z - uv0.z)*1e-1)*1e3);
	float r1 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y);
	
	return mix(r0, r1, f.z)*2.-1.;
}

void main(void) 
{
	vec2 p = -.5 + gl_FragCoord.xy / resolution.xy;
	p.x *= resolution.x/resolution.y;
	
	float color = 3.0 - (3.*length(2.*p));
	
	vec3 coord = vec3(atan(p.x,p.y)/6.2832+.5, length(p)*.4, .5);
	
	for(int i = 1; i <= 7; i++)
	{
		float power = pow(2.0, float(i));
		color += (1.5 / power) * snoise(coord + vec3(0.,-time*.05, time*.01), power*16.);
	}
	gl_FragColor = vec4( color, pow(max(color,0.),2.)*0.4, pow(max(color,0.),3.)*0.15 , 1.0);
}
Seascape :

Code: Select all

// "Seascape" by Alexander Alekseev aka TDM - 2014
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
uniform vec2 resolution;
uniform float time;
uniform vec4 mouse;


const int NUM_STEPS = 8;
const float PI	 	= 3.1415;
const float EPSILON	= 1e-3;
float EPSILON_NRM	= 0.1 / resolution.x;

// sea
const int ITER_GEOMETRY = 3;
const int ITER_FRAGMENT = 5;
const float SEA_HEIGHT = 0.6;
const float SEA_CHOPPY = 4.0;
const float SEA_SPEED = 0.8;
const float SEA_FREQ = 0.16;
const vec3 SEA_BASE = vec3(0.1,0.19,0.22);
const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
float SEA_TIME = time * SEA_SPEED;
mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);

// math
mat3 fromEuler(vec3 ang) {
	vec2 a1 = vec2(sin(ang.x),cos(ang.x));
    vec2 a2 = vec2(sin(ang.y),cos(ang.y));
    vec2 a3 = vec2(sin(ang.z),cos(ang.z));
    mat3 m;
    m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
	m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
	m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
	return m;
}
float hash( vec2 p ) {
	float h = dot(p,vec2(127.1,311.7));	
    return fract(sin(h)*43758.5453123);
}
float noise( in vec2 p ) {
    vec2 i = floor( p );
    vec2 f = fract( p );	
	vec2 u = f*f*(3.0-2.0*f);
    return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), 
                     hash( i + vec2(1.0,0.0) ), u.x),
                mix( hash( i + vec2(0.0,1.0) ), 
                     hash( i + vec2(1.0,1.0) ), u.x), u.y);
}

// lighting
float diffuse(vec3 n,vec3 l,float p) {
    return pow(dot(n,l) * 0.4 + 0.6,p);
}
float specular(vec3 n,vec3 l,vec3 e,float s) {    
    float nrm = (s + 8.0) / (3.1415 * 8.0);
    return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
}

// sky
vec3 getSkyColor(vec3 e) {
    e.y = max(e.y,0.0);
    vec3 ret;
    ret.x = pow(1.0-e.y,2.0);
    ret.y = 1.0-e.y;
    ret.z = 0.6+(1.0-e.y)*0.4;
    return ret;
}

// sea
float sea_octave(vec2 uv, float choppy) {
    uv += noise(uv);        
    vec2 wv = 1.0-abs(sin(uv));
    vec2 swv = abs(cos(uv));    
    wv = mix(wv,swv,wv);
    return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
}

float map(vec3 p) {
    float freq = SEA_FREQ;
    float amp = SEA_HEIGHT;
    float choppy = SEA_CHOPPY;
    vec2 uv = p.xz; uv.x *= 0.75;
    
    float d, h = 0.0;    
    for(int i = 0; i < ITER_GEOMETRY; i++) {        
    	d = sea_octave((uv+SEA_TIME)*freq,choppy);
    	d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp;        
    	uv *= octave_m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}

float map_detailed(vec3 p) {
    float freq = SEA_FREQ;
    float amp = SEA_HEIGHT;
    float choppy = SEA_CHOPPY;
    vec2 uv = p.xz; uv.x *= 0.75;
    
    float d, h = 0.0;    
    for(int i = 0; i < ITER_FRAGMENT; i++) {        
    	d = sea_octave((uv+SEA_TIME)*freq,choppy);
    	d += sea_octave((uv-SEA_TIME)*freq,choppy);
        h += d * amp;        
    	uv *= octave_m; freq *= 1.9; amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}

vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {  
    float fresnel = 1.0 - max(dot(n,-eye),0.0);
    fresnel = pow(fresnel,3.0) * 0.65;
        
    vec3 reflected = getSkyColor(reflect(eye,n));    
    vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12; 
    
    vec3 color = mix(refracted,reflected,fresnel);
    
    float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
    color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
    
    color += vec3(specular(n,l,eye,60.0));
    
    return color;
}

// tracing
vec3 getNormal(vec3 p, float eps) {
    vec3 n;
    n.y = map_detailed(p);    
    n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
    n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
    n.y = eps;
    return normalize(n);
}

float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {  
    float tm = 0.0;
    float tx = 1000.0;    
    float hx = map(ori + dir * tx);
    if(hx > 0.0) return tx;   
    float hm = map(ori + dir * tm);    
    float tmid = 0.0;
    for(int i = 0; i < NUM_STEPS; i++) {
        tmid = mix(tm,tx, hm/(hm-hx));                   
        p = ori + dir * tmid;                   
    	float hmid = map(p);
		if(hmid < 0.0) {
        	tx = tmid;
            hx = hmid;
        } else {
            tm = tmid;
            hm = hmid;
        }
    }
    return tmid;
}

// main
void main(void) {
	vec2 uv = gl_FragCoord.xy / resolution.xy;
    uv = uv * 2.0 - 1.0;
    uv.x *= resolution.x / resolution.y;    
    float _time = time * 0.3 + mouse.x*0.01;
        
    // ray
    vec3 ang = vec3(sin(_time*3.0)*0.1,sin(_time)*0.2+0.3,_time);    
    vec3 ori = vec3(0.0,3.5,_time*5.0);
    vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.15;
    dir = normalize(dir) * fromEuler(ang);
    
    // tracing
    vec3 p;
    heightMapTracing(ori,dir,p);
    vec3 dist = p - ori;
    vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
    vec3 light = normalize(vec3(0.0,1.0,0.8)); 
             
    // color
    vec3 color = mix(
        getSkyColor(dir),
        getSeaColor(p,n,light,dir,dist),
    	pow(smoothstep(0.0,-0.05,dir.y),0.3));
        
    // post
	gl_FragColor = vec4(pow(color,vec3(0.75)), 1.0);
}
Do you know a way to not "erase" the canvas, to use this canvas for a paint application for example ?
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Re: Shader coding with PB possible?

Post by [blendman] »

DK_PETER wrote:Here's a WindowedScreen() version with load/save and test current script.

link removed..
HI

I'm interested about your technic, could you please send me the link to do shader with windowedscreen ?
Thanks a lot.
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Shader coding with PB possible?

Post by applePi »

[blendman] writes: Do you know a way to not "erase" the canvas, to use this canvas for a paint application for example ?
to use this canvas for a paint application for example: i guess you mean to save the opengl graphics such as this Glsl scenes to picture
here is a working solution but (works in the dark): ie the graphics run in the background but we can't see, the only way to see it is to press space key to save the opengl glsl scene to a picture, (it is may be a small thing i miss)
the solution:
replacing the opengl gadget with the purebasic classic old way to display opengl
ie we use:
OpenWindowedScreen
InitEngine3D()
InitSprite()
CreateCamera
CreateRenderTexture
with #PB_Texture_AutomaticUpdate):
such as:
CreateRenderTexture(9, CameraID(0), CameraViewWidth(0), CameraViewHeight(0), #PB_Texture_AutomaticUpdate)
SaveRenderTexture

RenderWorld()
FlipBuffers()


when we use #PB_Texture_AutomaticUpdate we can't see the glsl graphics on the screen
press space key to save consecutive images to testxxx.png, or replace KeyboardReleased with KeyboardPushed to save avalanche of pictures. hope some one help i miss something small for sure to not see the graphics on the screen.
this is code of [blendman] changed a little by adding the above additions and removing the openGL gadget, now comment line 311 :CreateRenderTexture(9, CameraID(0), CameraViewWidth(0), CameraViewHeight(0), #PB_Texture_AutomaticUpdate)
run it again and you will see the graphics but can't save it, will give error. . the code have used also SaveRenderTexture.pb example (there is also CreateRenderTexture.pb)
change Library subsystem to OpenGL

Code: Select all

;/ GLSL example to test new OpenGLGadget - PJ 06/2014.

;EnableExplicit
InitEngine3D()
InitKeyboard()
InitSprite()
InitMouse()

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  CompilerIf Subsystem("OpenGL") = #False
    MessageRequester("Error", "Please set the Library subsystem to OpenGL from IDE : Compiler... Compiler Options")
    End
  CompilerEndIf
CompilerEndIf

Enumeration ;/ Window
  #Window_Main
EndEnumeration
Enumeration ;/ Gadget
  #Gad_OpenGL
  #Gad_Editor
  #Gad_ShaderSelector_Combo
EndEnumeration
Enumeration ;/ Menu
  #Menu_Open
  #Menu_Save
  #Menu_Run
EndEnumeration


Structure System
  Width.i
  Height.i
  Shader_Width.i
  Shader_Height.i
  Event.i
  Exit.i
  MouseX.i
  MouseY.i
  
  App_CurrentTime.i
  App_StartTime.i
  Editor_LastText.s
  
  Shader_Vertex_Text.s
  Shader_Fragment_Text.s
  Shader_Vertex.i
  Shader_Fragment.i
  Shader_Program.i
  
  Shader_Uniform_Time.i
  Shader_Uniform_Resolution.i
  Shader_Uniform_Mouse.i
  Shader_Uniform_SurfacePosition.i
  
  FPS_Timer.i
  Frames.i
  FPS.i
EndStructure

Global System.System

Procedure Init_Main()
  Protected MyLoop.i
  
  System\Width.i = 1024
  System\Height = 480
  System\Shader_Width = 640
  System\Shader_Height = 480
  
  OpenWindow(#Window_Main,0,0,System\Width, System\Height,"",#PB_Window_SystemMenu)
  OpenWindowedScreen(WindowID(#Window_Main), 0, 0, WindowWidth(#Window_Main)-170, WindowHeight(#Window_Main), 0, 0, 0)
  
  CreateCamera(0,0,0,100,100)
  MoveCamera(0,0,0,20,#PB_Absolute)
  CameraLookAt(0, 0, 0, 0)
  
  ;CreateCamera(1, 0, 0, 100, 100)
  ;MoveCamera(1, 90, 60, 0, #PB_Absolute)
  ;CameraLookAt(1, 0, 0, 0)
  ;CameraFOV(1, 80)

  If CreateMenu(0, WindowID(#Window_Main))
    MenuTitle("File")
    MenuItem(#Menu_Open,"Open")
    MenuItem(#Menu_Save,"Save")
    MenuBar()
    MenuItem(#Menu_Run,"Run Shader")
    
  EndIf
  
  ;OpenGLGadget(#Gad_OpenGL,0,0,System\Shader_Width,System\Shader_Height,#PB_OpenGL_Keyboard)
  ComboBoxGadget(#Gad_ShaderSelector_Combo,System\Shader_Width+4,2,System\Width - (System\Shader_Width+8),24)
AddGadgetItem(#Gad_ShaderSelector_Combo,-1,"Shader: "+Str(1)) 

  
  ;SetGadgetState(#Gad_ShaderSelector_Combo,0)
  EditorGadget(#Gad_Editor,System\Shader_Width+4,30,System\Width - (System\Shader_Width+8),System\Height-30)
  
  System\App_StartTime = ElapsedMilliseconds()
  
  
  System\Shader_Vertex_Text = "attribute vec3 position;"
  System\Shader_Vertex_Text + "attribute vec2 surfacePosAttrib;"
  System\Shader_Vertex_Text + "varying vec2 surfacePosition;"
  System\Shader_Vertex_Text + "   void main() {"
  System\Shader_Vertex_Text + "      surfacePosition = surfacePosAttrib;"
  System\Shader_Vertex_Text + "      gl_Position = vec4( position, 1.0 );"
  System\Shader_Vertex_Text + "   }"
EndProcedure

Init_Main()

;{ Opengl shader setup & routines

#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30

Prototype glCreateShader(type.l)
Prototype glCreateProgram()
Prototype glCompileShader(shader.l)
Prototype glLinkProgram(shader.l)
Prototype glUseProgram(shader.l)
Prototype glAttachShader(Program.l, shader.l)
Prototype glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) : 
Prototype.i glGetUniformLocation(Program.i, name.s)
Prototype glUniform1i(location.i, v0.i)
Prototype glUniform2i(location.i, v0.i, v1.i)
Prototype glUniform1f(location.i, v0.f)
Prototype glUniform2f(location.i, v0.f, v1.f)
Prototype glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)

Global glCreateShader.glCreateShader = wglGetProcAddress_("glCreateShader")
Global glCreateProgram.glCreateProgram = wglGetProcAddress_("glCreateProgram")
Global glCompileShader.glCompileShader = wglGetProcAddress_("glCompileShader")
Global glLinkProgram.glLinkProgram = wglGetProcAddress_("glLinkProgram")
Global glUseProgram.glUseProgram = wglGetProcAddress_("glUseProgram")
Global glAttachShader.glAttachShader = wglGetProcAddress_("glAttachShader")
Global glShaderSource.glShaderSource = wglGetProcAddress_("glShaderSource")
Global glGetUniformLocation.glGetUniformLocation = wglGetProcAddress_("glGetUniformLocation")
Global glUniform1i.glUniform1i = wglGetProcAddress_("glUniform1i")
Global glUniform2i.glUniform2i = wglGetProcAddress_("glUniform2i")
Global glUniform1f.glUniform1f = wglGetProcAddress_("glUniform1f")
Global glUniform2f.glUniform2f = wglGetProcAddress_("glUniform2f")
Global glGetShaderInfoLog.glGetShaderInfoLog = wglGetProcAddress_("glGetShaderInfoLog")

Procedure Shader_Compile_Link_Use(Vertex.s,Fragment.s,Use.i=1)
  Protected VertShader.i, FragShader.i, *TxtPointer, Program.i
  Protected Textlength.i, Mytext.s = Space(1024)
  
  ;/ Compile Vertex shader
  VertShader.i = glCreateShader(#GL_VERTEX_SHADER)
  *TxtPointer = @Vertex
  glShaderSource(VertShader, 1, @*TxtPointer, #Null)
  glCompileShader(VertShader)
  ;debug "Vert: "+VertShader
  glGetShaderInfoLog(VertShader,1023,@Textlength,@Mytext)
  ;debug MyText
  ;/ Compile Fragment Shader
  FragShader.i = glCreateShader(#GL_FRAGMENT_SHADER)
  *TxtPointer = @Fragment
  glShaderSource(FragShader, 1, @*TxtPointer, #Null)
  glCompileShader(FragShader)
  ;debug "Frag: "+FragShader
  glGetShaderInfoLog(FragShader,1023,@Textlength,@Mytext)
  ;debug MyText
  
  ;/ Create Shader Program
  Program = glCreateProgram()
  glAttachShader(Program,VertShader)
  ;debug "Attached Vert Shader"
  glAttachShader(Program,FragShader)
  ;debug "Attached Frag Shader"
  glLinkProgram(Program)
  ;debug "Link program"
  
  If Use = 1
    glUseProgram(Program)
  EndIf
  
  ProcedureReturn Program  
EndProcedure
;}

Procedure Shader_Set(Fragment.i, shader$="")
  
  If System\Shader_Program <> 0 ;/ delete the previous shaders
    glUseProgram(0);
  EndIf
  
  If Fragment = -2 ; run the shader    
    System\Shader_Fragment_Text = GetGadgetText(#Gad_Editor)    
  ElseIf Fragment = -1 ; load the shader
      System\Shader_Fragment_Text = shader$+Chr(10)
  Else
    
   Select Fragment
    Case 0
      System\Shader_Fragment_Text = "uniform float time;"+Chr(10)
      System\Shader_Fragment_Text + "uniform vec2 resolution;"+Chr(10)
      System\Shader_Fragment_Text + ""+Chr(10)
      System\Shader_Fragment_Text + "void main( void ) {"+Chr(10)
      System\Shader_Fragment_Text + "   vec2 p = ( gl_FragCoord.xy / resolution.xy ) - 0.2;"+Chr(10)
      System\Shader_Fragment_Text + "   float sx = 0.3 * (p.x + 0.8) * sin( 3.0 * p.x - 1. * time);"+Chr(10)
      System\Shader_Fragment_Text + "   float dy = 4./ ( 123. * abs(p.y - sx));"+Chr(10)
      System\Shader_Fragment_Text + "   dy += 1./ (160. * length(p - vec2(p.x, 0.)));"+Chr(10)
      System\Shader_Fragment_Text + "   gl_FragColor = vec4( (p.x + 0.1) * dy, 0.3 * dy, dy, 2.1 );"+Chr(10)
      System\Shader_Fragment_Text + "}"+Chr(10)
   
   
    
      
  EndSelect
  
  EndIf

  System\Shader_Program = Shader_Compile_Link_Use(System\Shader_Vertex_Text,System\Shader_Fragment_Text)
  
  If System\Shader_Program = 0
    MessageRequester("Unsupported Device?","No Shader Support Available",#PB_MessageRequester_Ok)
    End
  EndIf
  
  ;/ store shader uniform locations
  ;debug "Shader: "+System\Shader_Program
  System\Shader_Uniform_Time = glGetUniformLocation(System\Shader_Program, "time")
  System\Shader_Uniform_Mouse = glGetUniformLocation(System\Shader_Program, "mouse")
  System\Shader_Uniform_Resolution = glGetUniformLocation(System\Shader_Program, "resolution")
  System\Shader_Uniform_SurfacePosition.i = glGetUniformLocation(System\Shader_Program, "surfacePosition")
  ;debug "Time location: "+System\Shader_Uniform_Time
  ;debug "Mouse location: "+System\Shader_Uniform_Mouse
  ;debug "Res location: "+System\Shader_Uniform_Resolution
  ;debug "SurfacePos location: "+System\Shader_Uniform_SurfacePosition
  
  SetGadgetText(#Gad_Editor,System\Shader_Fragment_Text)
  
EndProcedure

Procedure OpenShader()
  Define filename$ ="", txt$ = ""
  
  filename$ = OpenFileRequester("Open shader","","All|*.*",0)
  
  If filename$ <> ""
    
    If ReadFile(0, filename$) 
      While Eof(0) = 0           
        txt$ + ReadString(0) +Chr(10) 
      Wend
      CloseFile(0)  
      Shader_Set(-1,txt$)

    Else
      MessageRequester("Information","Impossible d'ouvrir le fichier!")
    EndIf

  EndIf
  
EndProcedure
Procedure SaveShader()
  Define filename$ =""
  
  filename$ = SaveFileRequester("Save","","txt|*.txt",0)
  
  If filename$ <> ""
    
    If OpenFile(0, filename$) 
      WriteStringN(0, GetGadgetText(#Gad_Editor))
      CloseFile(0)
    EndIf
    
  EndIf
  
EndProcedure
Procedure RunShader()
  
  Shader_Set(-2)
  
EndProcedure

Shader_Set(0)

Procedure Render()
  ;/ set shader Uniform values
  glUniform2f(System\Shader_Uniform_Resolution,System\Shader_Width,System\Shader_Height)
  glUniform1f(System\Shader_Uniform_Time,(System\App_CurrentTime-System\App_StartTime) / 1000.0)
  glUniform2i(System\Shader_Uniform_SurfacePosition.i,1.0,1.0)
  
  glBegin_(#GL_QUADS)
    glVertex2f_(-1,-1) 
    glVertex2f_( 1,-1) 
    glVertex2f_( 1, 1) 
    glVertex2f_(-1, 1) 
  glEnd_()           
  
  System\Frames + 1
  If System\App_CurrentTime > System\FPS_Timer
    System\FPS = System\Frames
    System\Frames = 0
    System\FPS_Timer = System\App_CurrentTime  + 1000
    SetWindowTitle(#Window_Main,"GLSL Testing - PJ 07/06/2014 - FPS: "+Str(System\FPS))
  EndIf
  
  ;SetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_FlipBuffers,1)
      
  FlipBuffers()
  
EndProcedure


CreateRenderTexture(9, CameraID(0), CameraViewWidth(0), CameraViewHeight(0), #PB_Texture_AutomaticUpdate)
;CreateMaterial(9, TextureID(9))

Repeat
  
  Repeat
    
    System\Event = WindowEvent()
    
    Select System\Event
        
      Case #PB_Event_Menu
        Select EventMenu()
          Case #Menu_Open
            OpenShader()
          Case #Menu_Save
            SaveShader()
          Case #Menu_Run
            RunShader()
            
        EndSelect
        
      Case #PB_Event_CloseWindow        
        System\Exit = #True
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Gad_ShaderSelector_Combo
            Select EventType()
              Case #PB_EventType_Change
                ;debug "Set to: "+GetGadgetState(#Gad_ShaderSelector_Combo)
                Shader_Set(GetGadgetState(#Gad_ShaderSelector_Combo))
            EndSelect
          Case #Gad_OpenGL
            Select EventType()
              Case #PB_EventType_MouseMove
                System\MouseX = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseX)
                System\MouseY = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseY)
                glUniform2f(System\Shader_Uniform_Mouse,System\MouseX / System\Shader_Width,(System\Shader_Height-System\MouseY) / System\Shader_Height)
            EndSelect
        EndSelect
    EndSelect
    
  Until System\Event = 0
  
  
  System\App_CurrentTime = ElapsedMilliseconds()
  
  RenderWorld()
  Render()
    
  ExamineKeyboard()
If KeyboardReleased(#PB_Key_Space)
   
   No + 1
   SaveRenderTexture(9, "test2" + Str(No) + ".png")    
EndIf
  
Until System\Exit 
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Re: Shader coding with PB possible?

Post by [blendman] »

Hi ApplePi

Thank you very much for your example.
Unfortunately, I have an IMA on the line 152 :

Code: Select all

  VertShader.i = glCreateShader(#GL_VERTEX_SHADER)

I have another question :
is there a way to use your technic (rendertotexture/camera) to simple render sprite on this texture, but without "erase" the texture on each frame (to paint on it) ?
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Shader coding with PB possible?

Post by applePi »

[blendman], the error in line 152 happened with me also if the Library subsystem are not set to OpenGL
Image
i am using windows xp, and when library subsystem set to opengl it works without errors.
now i have made a work around like that in the official examples: make second camera so we can see what happened on the screen and when we want to save textures we free the second camera (so the render to screen stop while rendering to texture continue) then we SaveRenderTexture(1, "test" + Str(No) + ".png") , the first texture are empty.png while the rest are test1.png test2.png ... etc. and can be converted to animated gif using a free http://sourceforge.net/projects/gifapp/ ... ifApp-1.3/
if you want to continue watching the screen create the second camera again: look the code from line 369
i am still trying to do the same thing with usual opengl screens and does not succeed until now while it works with glsl, may be something small. but at least we are able to save the gorgeous GLSL beautiful graphics. i saw your post in games forum and will post if succeeded.

set the Library subsystem to opengl ,, press space key to save textures, press "Z" key to watch the screen again ...

Code: Select all

;/ GLSL example to test new OpenGLGadget - PJ 06/2014.

;EnableExplicit
InitEngine3D()
InitKeyboard()
InitSprite()
InitMouse()

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  CompilerIf Subsystem("OpenGL") = #False
    MessageRequester("Error", "Please set the Library subsystem to OpenGL from IDE : Compiler... Compiler Options")
    End
  CompilerEndIf
CompilerEndIf

Enumeration ;/ Window
  #Window_Main
EndEnumeration
Enumeration ;/ Gadget
  #Gad_OpenGL
  #Gad_Editor
  #Gad_ShaderSelector_Combo
EndEnumeration
Enumeration ;/ Menu
  #Menu_Open
  #Menu_Save
  #Menu_Run
EndEnumeration


Structure System
  Width.i
  Height.i
  Shader_Width.i
  Shader_Height.i
  Event.i
  Exit.i
  MouseX.i
  MouseY.i
  
  App_CurrentTime.i
  App_StartTime.i
  Editor_LastText.s
  
  Shader_Vertex_Text.s
  Shader_Fragment_Text.s
  Shader_Vertex.i
  Shader_Fragment.i
  Shader_Program.i
  
  Shader_Uniform_Time.i
  Shader_Uniform_Resolution.i
  Shader_Uniform_Mouse.i
  Shader_Uniform_SurfacePosition.i
  
  FPS_Timer.i
  Frames.i
  FPS.i
EndStructure

Global System.System

Procedure Init_Main()
  Protected MyLoop.i
  
  System\Width.i = 1024
  System\Height = 480
  System\Shader_Width = 640
  System\Shader_Height = 480
  
  OpenWindow(#Window_Main,0,0,System\Width, System\Height,"",#PB_Window_SystemMenu)
  OpenWindowedScreen(WindowID(#Window_Main), 0, 0, WindowWidth(#Window_Main)-170, WindowHeight(#Window_Main), 0, 0, 0)
  
    CreateCamera(1, 0, 0, 100, 100)
    MoveCamera(1, -100, 120, 190, #PB_Absolute)
    CameraLookAt(1, 0, 0, 0)
    
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 90, 60, 0, #PB_Absolute)
    CameraLookAt(0, 0, 0, 0)
    CameraFOV(0, 80)
    CameraProjectionMode(0, #PB_Camera_Perspective)

    ;Miroir
    ;CreateRenderTexture(1, CameraID(0), 800, 600)
    CreateRenderTexture(1, CameraID(0), CameraViewWidth(0), CameraViewHeight(0), #PB_Texture_AutomaticUpdate)
    CreateMaterial(1, TextureID(1))
    
  If CreateMenu(0, WindowID(#Window_Main))
    MenuTitle("File")
    MenuItem(#Menu_Open,"Open")
    MenuItem(#Menu_Save,"Save")
    MenuBar()
    MenuItem(#Menu_Run,"Run Shader")
    
  EndIf
  
  ;OpenGLGadget(#Gad_OpenGL,0,0,System\Shader_Width,System\Shader_Height,#PB_OpenGL_Keyboard)
  ComboBoxGadget(#Gad_ShaderSelector_Combo,System\Shader_Width+4,2,System\Width - (System\Shader_Width+8),24)
AddGadgetItem(#Gad_ShaderSelector_Combo,-1,"Shader: "+Str(1)) 

  
  ;SetGadgetState(#Gad_ShaderSelector_Combo,0)
  EditorGadget(#Gad_Editor,System\Shader_Width+4,30,System\Width - (System\Shader_Width+8),System\Height-30)
  
  System\App_StartTime = ElapsedMilliseconds()
  
  
  System\Shader_Vertex_Text = "attribute vec3 position;"
  System\Shader_Vertex_Text + "attribute vec2 surfacePosAttrib;"
  System\Shader_Vertex_Text + "varying vec2 surfacePosition;"
  System\Shader_Vertex_Text + "   void main() {"
  System\Shader_Vertex_Text + "      surfacePosition = surfacePosAttrib;"
  System\Shader_Vertex_Text + "      gl_Position = vec4( position, 1.0 );"
  System\Shader_Vertex_Text + "   }"
EndProcedure

Init_Main()

;{ Opengl shader setup & routines

#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30

Prototype glCreateShader(type.l)
Prototype glCreateProgram()
Prototype glCompileShader(shader.l)
Prototype glLinkProgram(shader.l)
Prototype glUseProgram(shader.l)
Prototype glAttachShader(Program.l, shader.l)
Prototype glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) : 
Prototype.i glGetUniformLocation(Program.i, name.s)
Prototype glUniform1i(location.i, v0.i)
Prototype glUniform2i(location.i, v0.i, v1.i)
Prototype glUniform1f(location.i, v0.f)
Prototype glUniform2f(location.i, v0.f, v1.f)
Prototype glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)

Global glCreateShader.glCreateShader = wglGetProcAddress_("glCreateShader")
Global glCreateProgram.glCreateProgram = wglGetProcAddress_("glCreateProgram")
Global glCompileShader.glCompileShader = wglGetProcAddress_("glCompileShader")
Global glLinkProgram.glLinkProgram = wglGetProcAddress_("glLinkProgram")
Global glUseProgram.glUseProgram = wglGetProcAddress_("glUseProgram")
Global glAttachShader.glAttachShader = wglGetProcAddress_("glAttachShader")
Global glShaderSource.glShaderSource = wglGetProcAddress_("glShaderSource")
Global glGetUniformLocation.glGetUniformLocation = wglGetProcAddress_("glGetUniformLocation")
Global glUniform1i.glUniform1i = wglGetProcAddress_("glUniform1i")
Global glUniform2i.glUniform2i = wglGetProcAddress_("glUniform2i")
Global glUniform1f.glUniform1f = wglGetProcAddress_("glUniform1f")
Global glUniform2f.glUniform2f = wglGetProcAddress_("glUniform2f")
Global glGetShaderInfoLog.glGetShaderInfoLog = wglGetProcAddress_("glGetShaderInfoLog")

Procedure Shader_Compile_Link_Use(Vertex.s,Fragment.s,Use.i=1)
  Protected VertShader.i, FragShader.i, *TxtPointer, Program.i
  Protected Textlength.i, Mytext.s = Space(1024)
  
  ;/ Compile Vertex shader
  VertShader.i = glCreateShader(#GL_VERTEX_SHADER)
  *TxtPointer = @Vertex
  glShaderSource(VertShader, 1, @*TxtPointer, #Null)
  glCompileShader(VertShader)
  ;debug "Vert: "+VertShader
  glGetShaderInfoLog(VertShader,1023,@Textlength,@Mytext)
  ;debug MyText
  ;/ Compile Fragment Shader
  FragShader.i = glCreateShader(#GL_FRAGMENT_SHADER)
  *TxtPointer = @Fragment
  glShaderSource(FragShader, 1, @*TxtPointer, #Null)
  glCompileShader(FragShader)
  ;debug "Frag: "+FragShader
  glGetShaderInfoLog(FragShader,1023,@Textlength,@Mytext)
  ;debug MyText
  
  ;/ Create Shader Program
  Program = glCreateProgram()
  glAttachShader(Program,VertShader)
  ;debug "Attached Vert Shader"
  glAttachShader(Program,FragShader)
  ;debug "Attached Frag Shader"
  glLinkProgram(Program)
  ;debug "Link program"
  
  If Use = 1
    glUseProgram(Program)
  EndIf
  
  ProcedureReturn Program  
EndProcedure
;}

Procedure Shader_Set(Fragment.i, shader$="")
  
  If System\Shader_Program <> 0 ;/ delete the previous shaders
    glUseProgram(0);
  EndIf
  
  If Fragment = -2 ; run the shader    
    System\Shader_Fragment_Text = GetGadgetText(#Gad_Editor)    
  ElseIf Fragment = -1 ; load the shader
      System\Shader_Fragment_Text = shader$+Chr(10)
  Else
    
   Select Fragment
    Case 0
      System\Shader_Fragment_Text = "uniform float time;"+Chr(10)
      System\Shader_Fragment_Text + "uniform vec2 resolution;"+Chr(10)
      System\Shader_Fragment_Text + ""+Chr(10)
      System\Shader_Fragment_Text + "void main( void ) {"+Chr(10)
      System\Shader_Fragment_Text + "   vec2 p = ( gl_FragCoord.xy / resolution.xy ) - 0.2;"+Chr(10)
      System\Shader_Fragment_Text + "   float sx = 0.3 * (p.x + 0.8) * sin( 3.0 * p.x - 1. * time);"+Chr(10)
      System\Shader_Fragment_Text + "   float dy = 4./ ( 123. * abs(p.y - sx));"+Chr(10)
      System\Shader_Fragment_Text + "   dy += 1./ (160. * length(p - vec2(p.x, 0.)));"+Chr(10)
      System\Shader_Fragment_Text + "   gl_FragColor = vec4( (p.x + 0.1) * dy, 0.3 * dy, dy, 2.1 );"+Chr(10)
      System\Shader_Fragment_Text + "}"+Chr(10)
   
   
    
      
  EndSelect
  
  EndIf

  System\Shader_Program = Shader_Compile_Link_Use(System\Shader_Vertex_Text,System\Shader_Fragment_Text)
  
  If System\Shader_Program = 0
    MessageRequester("Unsupported Device?","No Shader Support Available",#PB_MessageRequester_Ok)
    End
  EndIf
  
  ;/ store shader uniform locations
  ;debug "Shader: "+System\Shader_Program
  System\Shader_Uniform_Time = glGetUniformLocation(System\Shader_Program, "time")
  System\Shader_Uniform_Mouse = glGetUniformLocation(System\Shader_Program, "mouse")
  System\Shader_Uniform_Resolution = glGetUniformLocation(System\Shader_Program, "resolution")
  System\Shader_Uniform_SurfacePosition.i = glGetUniformLocation(System\Shader_Program, "surfacePosition")
  ;debug "Time location: "+System\Shader_Uniform_Time
  ;debug "Mouse location: "+System\Shader_Uniform_Mouse
  ;debug "Res location: "+System\Shader_Uniform_Resolution
  ;debug "SurfacePos location: "+System\Shader_Uniform_SurfacePosition
  
  SetGadgetText(#Gad_Editor,System\Shader_Fragment_Text)
  
EndProcedure

Procedure OpenShader()
  Define filename$ ="", txt$ = ""
  
  filename$ = OpenFileRequester("Open shader","","All|*.*",0)
  
  If filename$ <> ""
    
    If ReadFile(0, filename$) 
      While Eof(0) = 0           
        txt$ + ReadString(0) +Chr(10) 
      Wend
      CloseFile(0)  
      Shader_Set(-1,txt$)

    Else
      MessageRequester("Information","Impossible d'ouvrir le fichier!")
    EndIf

  EndIf
  
EndProcedure
Procedure SaveShader()
  Define filename$ =""
  
  filename$ = SaveFileRequester("Save","","txt|*.txt",0)
  
  If filename$ <> ""
    
    If OpenFile(0, filename$) 
      WriteStringN(0, GetGadgetText(#Gad_Editor))
      CloseFile(0)
    EndIf
    
  EndIf
  
EndProcedure
Procedure RunShader()
  
  Shader_Set(-2)
  
EndProcedure

Shader_Set(0)

Procedure Render()
  ;/ set shader Uniform values
  glUniform2f(System\Shader_Uniform_Resolution,System\Shader_Width,System\Shader_Height)
  glUniform1f(System\Shader_Uniform_Time,(System\App_CurrentTime-System\App_StartTime) / 1000.0)
  glUniform2i(System\Shader_Uniform_SurfacePosition.i,1.0,1.0)
  
  glBegin_(#GL_QUADS)
    glVertex2f_(-1,-1) 
    glVertex2f_( 1,-1) 
    glVertex2f_( 1, 1) 
    glVertex2f_(-1, 1) 
  glEnd_()           
  
  System\Frames + 1
  If System\App_CurrentTime > System\FPS_Timer
    System\FPS = System\Frames
    System\Frames = 0
    System\FPS_Timer = System\App_CurrentTime  + 1000
    SetWindowTitle(#Window_Main,"GLSL Testing - PJ 07/06/2014 - FPS: "+Str(System\FPS))
  EndIf
  
  ;SetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_FlipBuffers,1)
      
  ;FlipBuffers()
  
EndProcedure

;CreateRenderTexture(1, CameraID(0), CameraViewWidth(0), CameraViewHeight(0), #PB_Texture_AutomaticUpdate)
;CreateMaterial(9, TextureID(9))

Repeat
  
  Repeat
    
    System\Event = WindowEvent()
    
    Select System\Event
        
      Case #PB_Event_Menu
        Select EventMenu()
          Case #Menu_Open
            OpenShader()
          Case #Menu_Save
            SaveShader()
          Case #Menu_Run
            RunShader()
            
        EndSelect
        
      Case #PB_Event_CloseWindow        
        System\Exit = #True
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Gad_ShaderSelector_Combo
            Select EventType()
              Case #PB_EventType_Change
                ;debug "Set to: "+GetGadgetState(#Gad_ShaderSelector_Combo)
                Shader_Set(GetGadgetState(#Gad_ShaderSelector_Combo))
            EndSelect
          Case #Gad_OpenGL
            Select EventType()
              Case #PB_EventType_MouseMove
                System\MouseX = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseX)
                System\MouseY = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseY)
                glUniform2f(System\Shader_Uniform_Mouse,System\MouseX / System\Shader_Width,(System\Shader_Height-System\MouseY) / System\Shader_Height)
            EndSelect
        EndSelect
    EndSelect
    
  Until System\Event = 0
  
  
  System\App_CurrentTime = ElapsedMilliseconds()
  
  RenderWorld()
  Render()
  FlipBuffers()
    
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Space)
    t+1
    
   If flag=0 
     FreeCamera(1)
     flag=1
   EndIf
   
   If t=1
     
     SaveRenderTexture(1, "empty.png") 
   Else
   
   No + 1
   SaveRenderTexture(1, "test" + Str(No) + ".png") 
   
 EndIf
 
  EndIf
 If KeyboardReleased(#PB_Key_Z)
   If IsCamera(1) = 0
   flag=0 : t=0
   CreateCamera(1, 0, 0, 100, 100)
   EndIf
 EndIf
 
  
Until System\Exit 
User avatar
DK_PETER
Addict
Addict
Posts: 898
Joined: Sat Feb 19, 2011 10:06 am
Location: Denmark
Contact:

Re: Shader coding with PB possible?

Post by DK_PETER »

@[blendman]
Don't compile with unicode checked.
Last edited by DK_PETER on Thu Jun 04, 2015 4:06 pm, edited 1 time in total.
Current configurations:
Ubuntu 20.04/64 bit - Window 10 64 bit
Intel 6800K, GeForce Gtx 1060, 32 gb ram.
Amd Ryzen 9 5950X, GeForce 3070, 128 gb ram.
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Re: Shader coding with PB possible?

Post by [blendman] »

@DK_peter : thank you, it works great.

@ApplePi : it works with unicode unchekked (I have opengl as lib subsystem ;)).
It's cool, but I think I can't display a transparent sprite on the rendertexture ?
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Shader coding with PB possible?

Post by applePi »

DK_PETER , thanks for the info about the unicode. and the link to the examples.
[blendman], i have little experience with sprites but if i suppose what is needed is to save the sprite in example CameraProjection.pb together with its associated particles, then it seems the CreateRenderTexture with #PB_Texture_AutomaticUpdate works, but without displaying to the screen, ie only to texture, try it with the example you intend to work in.
the same plan as in the example before, press space to save textures, the rendering to screen stop but rendering to texture continue in the dark (not sure, needs more measurements) , press Z to resume rendering to screen and so on. CreateRenderTexture is the only way i know from the 2 examples in 3D sections: CreateRenderTexture.pb + SaveRenderTexture.pb. to render to texture.

Code: Select all

;
; ------------------------------------------------------------
;
;   PureBasic - CameraProjectionX/Y
;
;    (c) Fantaisie Software
;
; ------------------------------------------------------------
;

#CameraSpeed = 1

IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb"

Define.f KeyX, KeyY, MouseX, MouseY 

If InitEngine3D()
  
  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    LoadTexture(0, "flare.png")
    
    CreateMaterial(0, TextureID(0))
    DisableMaterialLighting(0, 1)
    MaterialBlendingMode   (0, #PB_Material_Add)
    
  
    CreateParticleEmitter(0, 10, 1, 1, 0)
    ParticleMaterial    (0, MaterialID(0))
    ParticleTimeToLive  (0, 0, 3)
    ParticleEmissionRate(0, 80)
    ParticleSize        (0, 8, 8)
    ParticleColorRange  (0, RGB(255, 0, 0), RGB(0, 0, 0))
    
    MoveParticleEmitter(0, -50, 0, 0)
    ParticleEmitterDirection(0, 0, -1, 0)
    
    
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0, 0, 0, 200, #PB_Absolute)
    
    CreateCamera(1, 0, 0, 100, 100)
    
    CreateRenderTexture(1, CameraID(0), CameraViewWidth(0), CameraViewHeight(0), #PB_Texture_AutomaticUpdate )
    CreateMaterial(1, TextureID(1))
    
    LoadSprite(0, #PB_Compiler_Home + "examples/3d/Data/Textures/Geebee2.bmp")
    TransparentSpriteColor(0, RGB(255, 0, 255))
    
    Repeat
      Screen3DEvents()
      
      
      If ExamineMouse()
        MouseX = MouseDeltaX() * #CameraSpeed * 0.05
        MouseY = MouseDeltaY() * #CameraSpeed * 0.05
      EndIf
      
      If ExamineKeyboard()
        If KeyboardPushed(#PB_Key_Space)
    t+1
    
   If flag=0 
     FreeCamera(1)
     flag=1
   EndIf
   
   If t=1
     
     SaveRenderTexture(1, "empty.png") 
   Else
   
   No + 1
   SaveRenderTexture(1, "test" + Str(No) + ".png") 
   
 EndIf
 
  EndIf
 If KeyboardReleased(#PB_Key_Z)
   If IsCamera(1) = 0
   flag=0 : t=0
   CreateCamera(1, 0, 0, 100, 100)
   EndIf
 EndIf
        
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed 
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed 
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed 
        Else
          KeyY = 0
        EndIf
        
      EndIf
          
      RotateCamera(0, MouseY, MouseX, RollZ, #PB_Relative)
      MoveCamera  (0, KeyX, 0, KeyY)
      
      RenderWorld()
      
      x = CameraProjectionX(0, ParticleEmitterX(0), ParticleEmitterY(0), ParticleEmitterZ(0)) - SpriteWidth(0)/2
      y = CameraProjectionY(0, ParticleEmitterX(0), ParticleEmitterY(0), ParticleEmitterZ(0)) - SpriteHeight(0)/2
      DisplayTransparentSprite(0, x, y)
      
      
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized",0)
EndIf

End
User avatar
[blendman]
Enthusiast
Enthusiast
Posts: 297
Joined: Thu Apr 07, 2011 1:14 pm
Location: 3 arks
Contact:

Re: Shader coding with PB possible?

Post by [blendman] »

@ Applepi : thank you very much ;)

I think what I need isn't possible, but :
do you think it's possible to do that :
- displaytransparentsprite() or another rendertexture if needed
- display the "rendertexture" (with transparence?) on which I can paint some sprites in real time (like on the canvas), like in a 2D application.
- displaysprite (the layer over our current rendertexture (current layer))
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Shader coding with PB possible?

Post by em_uk »

blendman: I too wanted to be able to draw to a shader display but could not figure how it is done.

It's possible that you could draw to a texture and then display the texture as a surface, bu again, I could not achieve this in PB although I can do it in C++ using SDL libraries.

I gave up trying to use PB for this purpose.
----

R Tape loading error, 0:1
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Shader coding with PB possible?

Post by applePi »

[blendman] i haven't done any example or research about the sprites so i don't know about it
except the points sprites like in this example (mandelbrot set with roses):
http://purebasic.fr/english/viewtopic.p ... 55#p459673

i have found some forum files in my hard disk about the sprites, its forum links may be useful for you. i suggest to ask sprites questions in the coding forum since they are larger community.

TransformSprite():
http://purebasic.fr/english/viewtopic.php?f=13&t=60702

opaque sprite (alphablending):
http://purebasic.fr/english/viewtopic.php?f=13&t=55059

http://www.purebasic.fr/english/viewtop ... 12&t=56885 3D Blending Mode Tester

http://www.purebasic.fr/english/viewtop ... 28&t=55200 sprite Blending mode

http://www.purebasic.fr/english/viewtop ... =7&t=45766 How to make a Blob monster

http://purebasic.fr/english/viewtopic.php?f=13&t=61992 Why doesnt spritecollision work as expected
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Shader coding with PB possible?

Post by em_uk »

Thanks applePi

I am quite comfortable with displaying traditional sprites I've written plenty of demos/games using them.

The real difficulty is using the opengl framework to blend the images & shader outputs together in PB.

None of the inbuilt PB commands can do this, its needs to be done with gl_ commands.

When I have time I may give it another go converting from C++ to PB but I was spending too many hours working on it and getting seemingly nowhere and it started to affect my health (getting 2 hours of sleep a night for months is not good!)

So I took a break :)
----

R Tape loading error, 0:1
pwd
User
User
Posts: 60
Joined: Thu Sep 06, 2012 9:39 am

Re: Shader coding with PB possible?

Post by pwd »

Here are some changes for those, who want to run pjay's code @ Linux:
  1. Add this before main code:

    Code: Select all

    CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      Import ""
        glXGetProcAddress(s.p-ascii) As "glXGetProcAddress"
      EndImport
      
    CompilerCase #PB_OS_Windows
      CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
        Import "opengl32.lib"
          wglGetProcAddress(s.p-ascii) As "_wglGetProcAddress@4"
        EndImport
        
      CompilerElse   
        Import "opengl32.lib"
          wglGetProcAddress(s.p-ascii) As "wglGetProcAddress"
        EndImport
        
      CompilerEndIf
      
    CompilerDefault
      CompilerError "Unsupported OS"
      
    CompilerEndSelect
  2. Add this after prototypes defining:

    Code: Select all

    Prototype.i glGetProcAddress(name.s)
    
    CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      Global glGetProcAddress.glGetProcAddress = @glXGetProcAddress()
      
    CompilerCase #PB_OS_Windows
      Global glGetProcAddress.glGetProcAddress = @wglGetProcAddress()
      
    CompilerDefault
      CompilerError "Unsupported OS"
      
    CompilerEndSelect
  3. Replace all "wglGetProcAddress_" calls with "glGetProcAddress"
Didaktik
User
User
Posts: 79
Joined: Fri Mar 14, 2014 2:12 pm

Re: Shader coding with PB possible?

Post by Didaktik »

applePi wrote:[blendman], the error in line 152 happened with me also if the Library subsystem are not set to OpenGL
Image
i am using windows xp, and when library subsystem set to opengl it works without errors.
now i have made a work around like that in the official examples: make second camera so we can see what happened on the screen and when we want to save textures we free the second camera (so the render to screen stop while rendering to
Until System\Exit [/code]
I see black screen on PB5.5 :oops:
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

Re: Shader coding with PB possible?

Post by applePi »

Didaktik, since it works in 5.43 ascii mode then it is a unicode issue in 5.50
it should work if we change these
*TxtPointer = @Vertex line 132 in blendman demo http://purebasic.fr/english/viewtopic.p ... 15#p465522
to *TxtPointer = Ascii(Vertex)

*TxtPointer = @Fragment line 140
to *TxtPointer = Ascii(Fragment)

the screen changed from white to black so there is some progress, something else needs to change !!!!!!
Post Reply