Shader avec PureBasic

Partagez votre expérience de PureBasic avec les autres utilisateurs.
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Shader avec PureBasic

Message par comtois »

J'en ai déjà parlé dans un autre post, je rappelle le lien ici
l'auteur original est pjay, merci à lui.

Je me suis contenté de remettre en forme légèrement le code pour ouvrir un fichier texte contenant le shader plutôt que le coder en dur comme c'est le cas dans le code original.
L'idée serait de le modifier par la suite pour en faire un petit éditeur...(j'ai commencé)

Vous trouverez d'autres shaders sur ce site !
http://glslsandbox.com/?page=1

Il suffit de copier le code du shader qui vous intéresse dans le blocnote et de le sauvegarder et enfin d'ouvrir ce fichier avec le code ci-dessous (bouton droit de la souris pour ouvrir le menu) :
Je vous conseille de tester le dauphin , c'est sublime !

IMPORTANT : Il faut désactiver l'unicode dans les options du compilo (ou trouver comment le faire fonctionner en unicode, car on aura bientôt plus le choix)

Code : Tout sélectionner

;EnableExplicit

Enumeration ;/ Window
  #Window_Main
  #Window_OpenGl  
  #Menu
  #Window_Error
EndEnumeration

Enumeration ;/ Gadget
  #Gad_OpenGL
  #Gad_PopupMenu
  #Gad_Editor
  #Gad_Editor_error
  #Gad_Button_error
EndEnumeration

Structure Shader
  Width.i
  Height.i
  Vertex_Text.s
  Fragment_Text.s
  Program.i
  
  Uniform_Time.i
  Uniform_Resolution.i
  Uniform_Mouse.i
  Uniform_SurfacePosition.i
EndStructure

Structure System
  Event.i
  MouseX.i
  MouseY.i
  
  App_CurrentTime.i
  App_StartTime.i
  Editor_LastText.s
  
  FPS_Timer.i
  Frames.i
  FPS.i
EndStructure

Structure Screen
  Width.i
  Height.i
EndStructure

Define Event
Global Screen.Screen
Global System.System
Global Shader.Shader
Shader\Width = 600
Shader\Height = 600
Shader\Vertex_Text = "attribute vec3 position;"
Shader\Vertex_Text + "attribute vec2 surfacePosAttrib;"
Shader\Vertex_Text + "varying vec2 surfacePosition;"
Shader\Vertex_Text + "	void main() {"
Shader\Vertex_Text + "		surfacePosition = surfacePosAttrib;"
Shader\Vertex_Text + "		gl_Position = vec4( position, 1.0 );"
Shader\Vertex_Text + "	}"

Screen\Width = 800
Screen\Height = 600

Declare FenetreErreur(Text.s, Ligne.i)
Declare Erreur(Titre.s, Message.s)
Declare Init_Main()
Declare Init_OpenGL()
Declare Shader_Compile_Link_Use(Vertex.s,Fragment.s,Use.i=1)
Declare LoadSource()
Declare SaveSource()
Declare Shader_Set()
Declare Render()

Init_OpenGL()
HideWindow(#Window_OpenGl, 1)

;{[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")
;}

Init_Main()

Repeat
  
  Repeat
    System\Event = WindowEvent()
    Select System\Event
        
      Case #PB_Event_Menu
        
        Select EventMenu()  ; To see which menu has been selected
          Case 1            ; Load
            LoadSource()
          Case 2 
            SaveSource()
          Case 3            ; Compiler
            HideWindow(#Window_OpenGl, 0)
            Shader_Set()
            
          Case 4 ; Quit
            Quit = 1
            
          Case 8 ; About
            MessageRequester("About", "Cool Menu example", 0)
            
          Default
            MessageRequester("Info", "MenuItem: "+Str(EventMenu()), 0)
            
        EndSelect
        
      Case #PB_Event_Gadget
        Select EventGadget()
            
          Case #Gad_Button_error
            CloseWindow(#Window_Error)
            
          Case #Gad_OpenGL
            Select EventType()
              Case   #PB_EventType_RightButtonDown 
                DisplayPopupMenu(#Gad_PopupMenu, WindowID(#Window_Main))  ; now display the popup-menu
                
              Case #PB_EventType_MouseMove
                System\MouseX = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseX)
                System\MouseY = GetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_MouseY)
                glUniform2f(Shader\Uniform_Mouse,System\MouseX / Shader\Width,(Shader\Height-System\MouseY) / Shader\Height)
            EndSelect
        EndSelect
        
      Case #PB_Event_CloseWindow
        If EventWindow() = #Window_OpenGl
          shader\Program = 0
          HideWindow(#Window_OpenGl, 1)
        Else  
          Quit = 1
        EndIf  
        
    EndSelect
  Until System\Event = 0
  
  System\App_CurrentTime = ElapsedMilliseconds()
  If shader\Program
    Render()
  EndIf  
  
Until Quit = 1

Procedure Erreur(Titre.s, Message.s)
  MessageRequester(Titre, Message, #PB_MessageRequester_Ok)
  End 
EndProcedure

Procedure FenetreErreur(Text.s, Ligne.i)
  If Ligne > 10 
    Ligne = 10
  EndIf 
  
  OpenWindow(#Window_Error,0,0,400,Ligne*25 + 25,"Erreur compilation",#PB_Window_ScreenCentered)
  EditorGadget(#Gad_Editor_error,0,0,400,Ligne*25, #PB_Editor_WordWrap) 
  ButtonGadget(#Gad_Button_error,180,Ligne*25+2, 40, 20, "OK") 
  
  SetGadgetText(#Gad_Editor_error, Text)
  
EndProcedure

Procedure LoadSource()
  Protected file$, length, bytes, *MemoryID
  file$ = OpenFileRequester("Select a file","","frag (.frag)|*.frag|All files (*.*)|*.*",0)
  If file$
    If ReadFile(0, file$)
      Shader\Fragment_Text = ""
      While Eof(0) = 0           ; loop as long the 'end of file' isn't reached
        Shader\Fragment_Text + ReadString(0)    
        Shader\Fragment_Text + Chr(10)
      Wend
      
      CloseFile(0)
    EndIf
  EndIf
  SetGadgetText(#Gad_Editor, Shader\Fragment_Text)
EndProcedure 

Procedure SaveSource()
  Protected file$, length, bytes, *MemoryID
  file$ = SaveFileRequester("Select a file","","frag (.frag)|*.frag|All files (*.*)|*.*",0)
  If file$
    If CreateFile(0, file$)
      WriteString(0, GetGadgetText(#Gad_Editor))
      CloseFile(0)
    EndIf
  EndIf
EndProcedure 

Procedure Init_Main()
  
  If OpenWindow(#Window_Main,0,0,Screen\Width,Screen\Height,"Editeur GLSL",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) = 0
    Erreur("OpenWindow", "Erreur lors de la création de la fenêtre principale")
  EndIf
  
  If CreateMenu(#Menu, WindowID(#Window_Main))
    MenuTitle("File")
    MenuItem( 1, "&Load...")
    MenuItem( 2, "Save")
    MenuItem( 3, "Compiler")
    MenuItem( 4, "&Quit")
  EndIf
  
  EditorGadget(#Gad_Editor, 0, 0, Screen\Width,Screen\Height)
  
  System\App_StartTime = ElapsedMilliseconds()
  
EndProcedure

Procedure Init_OpenGL()
  
  If OpenWindow(#Window_OpenGl,0,0,Shader\Width,Shader\Height,"Editeur GLSL",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) = 0
    Erreur("OpenWindow", "Erreur lors de la création de la fenêtre principale")
  EndIf
  
  If OpenGLGadget(#Gad_OpenGL,0,0,Shader\Width,Shader\Height,#PB_OpenGL_Keyboard) = 0
    Erreur("OpenGLGadget", "Erreur lors de la création du OpenGLGadget")
  EndIf 
  
EndProcedure


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)
  
  If Mytext
    FenetreErreur(Mytext, CountString(Mytext, Chr(10)))
  EndIf  
  
  ;/ 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()
  If Shader\Program <> 0 ;/ delete the previous shaders
    glUseProgram(0)      ;
  EndIf
  
  ;LoadSource()
  Shader\Fragment_Text = GetGadgetText(#Gad_Editor)
  
  Shader\Program = Shader_Compile_Link_Use(Shader\Vertex_Text,Shader\Fragment_Text)
  
  If Shader\Program = 0
    MessageRequester("Unsupported Device?","No Shader Support Available",#PB_MessageRequester_Ok)
    End
  EndIf
  
  ;/ store shader uniform locations
  Debug "Shader: " + Shader\Program
  Shader\Uniform_Time = glGetUniformLocation(Shader\Program, "time")
  Shader\Uniform_Mouse = glGetUniformLocation(Shader\Program, "mouse")
  Shader\Uniform_Resolution = glGetUniformLocation(Shader\Program, "resolution")
  Shader\Uniform_SurfacePosition = glGetUniformLocation(Shader\Program, "surfacePosition")
  Debug "Time location: "+Shader\Uniform_Time
  Debug "Mouse location: "+Shader\Uniform_Mouse
  Debug "Res location: "+Shader\Uniform_Resolution
  Debug "SurfacePos location: "+Shader\Uniform_SurfacePosition
  
  ;SetGadgetText(#Gad_Editor,System\Shader_Fragment_Text)
EndProcedure

Procedure Render()
  ;/ set shader Uniform values
  glUniform2f(Shader\Uniform_Resolution,Shader\Width, Shader\Height)
  glUniform1f(Shader\Uniform_Time,(System\App_CurrentTime-System\App_StartTime) / 1000.0)
  glUniform2i(Shader\Uniform_SurfacePosition,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_OpenGl,"GLSL viewer - FPS: "+Str(System\FPS))
  EndIf
  
  SetGadgetAttribute(#Gad_OpenGL,#PB_OpenGL_FlipBuffers,1)
  
EndProcedure
La prochaine étape sera de pouvoir copier le code du shader directement dans l'éditeur, de pouvoir le sauvegarder, le modifier et le visualiser.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
comtois
Messages : 5172
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Shader avec PureBasic

Message par comtois »

J'ai modifié le code dans le premier post, il n'y a plus besoin du blocnote, il suffit de copier un shader (ou de l'écrire dans l'éditeur) puis de le sauvegarder ou le compiler pour l'afficher.
Par exemple copier ce code dans l'éditeur, puis 'Compiler' (bouton droit pour accéder au menu)

MPORTANT : Il faut désactiver l'unicode dans les options du compilo

Code : Tout sélectionner

#ifdef GL_ES
precision lowp float;
#endif
#extension GL_OES_standard_derivatives : enable


uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;


uniform vec3      iResolution;
 
uniform float     iChannelTime[4];
uniform vec4      iMouse;
uniform vec4      iDate;
uniform float     iSampleRate;
uniform vec3      iChannelResolution[4];
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform sampler2D iChannel3;
// Created by inigo quilez - iq/2014    Adapted gigatron
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

//#define HIGH_QUALITY_NOISE
float iGlobalTime= time;
float noise( in vec2 x )
{
    vec2 p = floor(x);
    vec2 f = fract(x);
	f = f*f*(3.0-2.0*f);
#ifdef HIGH_QUALITY_NOISE	
	float a = texture2D( iChannel0, (p+vec2(0.5,0.5))/256.0, -100.0 ).x;
	float b = texture2D( iChannel0, (p+vec2(1.5,0.5))/256.0, -100.0 ).x;
	float c = texture2D( iChannel0, (p+vec2(0.5,1.5))/256.0, -100.0 ).x;
	float d = texture2D( iChannel0, (p+vec2(1.5,1.5))/256.0, -100.0 ).x;
	return -1.0 + 2.0*mix( mix(a,b,f.x), mix(c,d,f.x), f.y );
#else
	return -1.0 + 2.0*texture2D( iChannel0, (p+f+0.5)/256.0, -100.0 ).x;
#endif	
}

vec2 sd2Segment( vec3 a, vec3 b, vec3 p )
{
	vec3  pa = p - a;
	vec3  ba = b - a;
	float t = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
	vec3  v = pa - ba*t;
	return vec2( dot(v,v), t );
}

float udBox(vec3 p, vec3 b)
{
    return length(max(abs(p)-b, 0.0));
}

float udRoundBox( vec3 p, vec3 b, float r )
{
    return length(max(abs(p)-b,0.0))-r;
}

float smin( float a, float b, float k )
{
	float h = clamp( 0.5 + 0.5*(b-a)/k, 0.0, 1.0 );
	return mix( b, a, h ) - k*h*(1.0-h);
}

//-----------------------------------------------------------------------------------

#define NUMI 11
#define NUMF 11.0

vec3 fishPos;
float fishTime;
float isJump;
float isJump2;

vec2 anima( float ih, float t )
{
    float an1 = 0.9*(0.5+0.2*ih)*cos(5.0*ih - 3.0*t + 6.2831/4.0);
    float an2 = 1.0*cos(3.5*ih - 1.0*t + 6.2831/4.0);
    float an = mix( an1, an2, isJump );
    float ro = 0.4*cos(4.0*ih - 1.0*t)*(1.0-0.5*isJump);
	return vec2( an, ro );
}

vec3 anima2( void )
{
    vec3 a1 = vec3(0.0,        sin(3.0*fishTime+6.2831/4.0),0.0);
    vec3 a2 = vec3(0.0,1.5+2.5*cos(1.0*fishTime),0.0);
	vec3 a = mix( a1, a2, isJump );
	a.y *= 0.5;
	a.x += 0.1*sin(0.1 - 1.0*fishTime)*(1.0-isJump);
    return a;
}

vec2 sdDolphinCheap( vec3 p )
{
    vec2 res = vec2( 1000.0, 0.0 );

	p -= fishPos;
		
	vec3 a = anima2();
	
	float or = 0.0;
	float th = 0.0;
	float hm = 0.0;

	vec3 mp = a;
	for( int i=0; i<NUMI; i++ )
	{	
		float ih = float(i)/NUMF;
		vec2 anim = anima( ih, fishTime );
		
		float ll = 0.48; if( i==0 ) ll=0.655;
		vec3 b = a + ll*normalize(vec3(sin(anim.y), sin(anim.x), cos(anim.x)));
		
		vec2 dis = sd2Segment( a, b, p );

		if( dis.x<res.x ) {res=vec2(dis.x,ih+dis.y/NUMF); mp=a+(b-a)*dis.y; }
		
		a = b;
	}
	float h = res.y;
	float ra = 0.04 + h*(1.0-h)*(1.0-h)*2.7;

	res.x = 0.75 * (distance(p,mp) - ra);

	return res;
}

vec3 ccd, ccp;
	
vec2 sdDolphin( vec3 p )
{
    vec2 res = vec2( 1000.0, 0.0 );

	p -= fishPos;

	vec3 a = anima2();
	
	float or = 0.0;
	float th = 0.0;
	float hm = 0.0;

	vec3 p1 = a; vec3 d1=vec3(0.0);
	vec3 p2 = a; vec3 d2=vec3(0.0);
	vec3 p3 = a; vec3 d3=vec3(0.0);
	vec3 mp = a;
	for( int i=0; i<NUMI; i++ )
	{	
		float ih = float(i)/NUMF;
		vec2 anim = anima( ih, fishTime );
		float ll = 0.48; if( i==0 ) ll=0.655;
		vec3 b = a + ll*normalize(vec3(sin(anim.y), sin(anim.x), cos(anim.x)));
		
		vec2 dis = sd2Segment( a, b, p );

		if( dis.x<res.x ) {res=vec2(dis.x,ih+dis.y/NUMF); mp=a+(b-a)*dis.y; ccd = b-a;}
		
		if( i==3 ) { p1=a; d1 = b-a; }
		if( i==4 ) { p3=a; d3 = b-a; }
		if( i==(NUMI-1) ) { p2=b; d2 = b-a; }

		a = b;
	}
	ccp = mp;
	
	float h = res.y;
	float ra = 0.05 + h*(1.0-h)*(1.0-h)*2.7;
	ra += 7.0*max(0.0,h-0.04)*exp(-30.0*max(0.0,h-0.04)) * smoothstep(-0.1, 0.1, p.y-mp.y);
	ra -= 0.03*(smoothstep(0.0, 0.1, abs(p.y-mp.y)))*(1.0-smoothstep(0.0,0.1,h));
	ra += 0.05*clamp(1.0-3.0*h,0.0,1.0);
    ra += 0.035*(1.0-smoothstep( 0.0, 0.025, abs(h-0.1) ))* (1.0-smoothstep(0.0, 0.1, abs(p.y-mp.y)));
	
	// body
	res.x = 0.75 * (distance(p,mp) - ra);
	//res.x = 0.75 * (res.x*3.0 - ra);

    // fin	
	d3 = normalize(d3);
	float k = sqrt(1.0 - d3.y*d3.y);
	mat3 ms = mat3(  d3.z/k, -d3.x*d3.y/k, d3.x,
				        0.0,            k, d3.y,
				    -d3.x/k, -d3.y*d3.z/k, d3.z );
	vec3 ps = p - p3;
	ps = ms*ps;
	ps.z -= 0.1;
    float d5 = length(ps.yz) - 0.9;
	d5 = max( d5, -(length(ps.yz-vec2(0.6,0.0)) - 0.35) );
	d5 = max( d5, udRoundBox( ps+vec3(0.0,-0.5,0.5), vec3(0.0,0.5,0.5), 0.02 ) );
	res.x = smin( res.x, d5, 0.1 );

	
#if 1
    // fin	
	d1 = normalize(d1);
	k = sqrt(1.0 - d1.y*d1.y);
	ms = mat3(  d1.z/k, -d1.x*d1.y/k, d1.x,
				   0.0,            k, d1.y,
               -d1.x/k, -d1.y*d1.z/k, d1.z );
	ps = p - p1;
	ps = ms*ps;
	ps.x = abs(ps.x);
	float l = ps.x;
	l=clamp( (l-0.4)/0.5, 0.0, 1.0 );
	l=4.0*l*(1.0-l);
	l *= 1.0-clamp(5.0*abs(ps.z+0.2),0.0,1.0);
	ps.xyz += vec3(-0.2,0.36,-0.2);
    d5 = length(ps.xz) - 0.8;
	d5 = max( d5, -(length(ps.xz-vec2(0.2,0.4)) - 0.8) );
	d5 = max( d5, udRoundBox( ps+vec3(0.0,0.0,0.0), vec3(1.0,0.0,1.0), 0.015+0.05*l ) );
	res.x = smin( res.x, d5, 0.12 );
#endif
	
    // tail	
	d2 = normalize(d2);
	mat2 mf = mat2( d2.z, d2.y, -d2.y, d2.z );
	vec3 pf = p - p2 - d2*0.25;
	pf.yz = mf*pf.yz;
    float d4 = length(pf.xz) - 0.6;
	d4 = max( d4, -(length(pf.xz-vec2(0.0,0.8)) - 0.9) );
	d4 = max( d4, udRoundBox( pf, vec3(1.0,0.005,1.0), 0.005 ) );
	res.x = smin( res.x, d4, 0.1 );
	
	
	return res;
}

const mat2 m2 = mat2( 0.80, -0.60, 0.60, 0.80 );

vec3 sdWater( vec3 p )
{
	vec2 q = 0.16*p.xz;
    q.y *= 0.75;

	float f = 0.0;
    f += 0.50000*abs(noise( q )); q = m2*q*2.02; q -= 0.1*iGlobalTime;
    f += 0.25000*abs(noise( q )); q = m2*q*2.03; q += 0.2*iGlobalTime;
    f += 0.12500*abs(noise( q )); q = m2*q*2.01; q -= 0.4*iGlobalTime;
    f += 0.06250*abs(noise( q )); q = m2*q*2.02; q += 1.0*iGlobalTime;
    f += 0.03125*abs(noise( q ));
	
	float sss = abs(sdDolphinCheap(p).x);
	float spla = exp(-4.0*sss);
	spla += 0.5*exp(-14.0*sss);
	spla *= mix(1.0,texture2D( iChannel0, 0.2*p.xz ).x,spla*spla);
	spla *= -0.85;
	spla *= isJump;
	spla *= mix( 1.0, smoothstep(0.0,0.5,p.z-fishPos.z-1.5), isJump2 );

	return vec3( p.y-1.5+1.2*f + 0.1 + spla, f, sss );
}

float sdWaterCheap( vec3 p )
{
	vec2 q = 0.16*p.xz;
    q.y *= 0.75;

	float f = 0.0;
    f += 0.50000*abs(noise( q )); q = m2*q*2.02; q -= 0.1*iGlobalTime;
    f += 0.25000*abs(noise( q )); q = m2*q*2.03; q += 0.2*iGlobalTime;
    f += 0.12500*abs(noise( q )); q = m2*q*2.01; q -= 0.4*iGlobalTime;
    f += 0.06250*abs(noise( q )); q = m2*q*2.02; q += 1.0*iGlobalTime;
    f += 0.03125*abs(noise( q ));
	return f;
}

vec2 intersectDolphin( in vec3 ro, in vec3 rd )
{
	const float maxd = 10.0;
	const float precis = 0.001;
    float h = precis*3.0;
    float t = 0.0;
	float l = 0.0;
    for( int i=0; i<50; i++ )
    {
        //if( h>precis && t<maxd )
		if( h<precis || t>maxd ) break;
		{
        t += h;
	    vec2 res = sdDolphin( ro+rd*t );
        h = res.x;
		l = res.y;
		}
    }

    if( t>maxd ) t=-1.0;
    return vec2( t, l);
}

vec3 intersectWater( vec3 ro, in vec3 rd )
{
	const float precis = 0.001;
    float h = precis*3.0;
	float l = 0.0;
	float s = 0.0;

	float t = (2.5-ro.y)/rd.y; 
	if( t<0.0 ) return vec3(-1.0);

	for( int i=0; i<12; i++ )
    {
		if( h<precis ) break;
		{
        t += h;
	    vec3 res = sdWater( ro+rd*t );
        h = res.x;
		l = res.y;
		s = res.z;
		}
    }

    return vec3( t, l, s );
}


vec3 calcNormalFish( in vec3 pos )
{
    const vec3 eps = vec3(0.08,0.0,0.0);
	float v = sdDolphin(pos).x;
	return normalize( vec3(
           sdDolphin(pos+eps.xyy).x - v,
           sdDolphin(pos+eps.yxy).x - v,
           sdDolphin(pos+eps.yyx).x - v ) );
}

vec3 calcNormalWater( in vec3 pos )
{
    const vec3 eps = vec3(0.025,0.0,0.0);
    float v = sdWater(pos).x;	
	return normalize( vec3( sdWater(pos+eps.xyy).x - v,
                            eps.x,
                            sdWater(pos+eps.yyx).x - v ) );
}

float softshadow( in vec3 ro, in vec3 rd, float mint, float k )
{
    float res = 1.0;
    float t = mint;
	float h = 1.0;
    for( int i=0; i<25; i++ )
    {
        h = sdDolphinCheap(ro + rd*t).x;
        res = min( res, k*h/t );
		t += clamp( h, 0.05, 0.5 );
		if( h<0.0001 ) break;
    }
    return clamp(res,0.0,1.0);
}

//vec3 lig = normalize(vec3(0.9,0.15,0.5));
const vec3 lig = vec3(0.86,0.15,0.48);

vec3 doLighting( in vec3 pos, in vec3 nor, in vec3 rd, float glossy, float glossy2, float shadows, in vec3 col, float occ )
{
	vec3 ref = reflect(rd,nor);
	
    // lighting
    float sky = clamp(nor.y,0.0,1.0);
	float bou = clamp(-nor.y,0.0,1.0);
    float dif = max(dot(nor,lig),0.0);
    float bac = max(0.3 + 0.7*dot(nor,-vec3(lig.x,0.0,lig.z)),0.0);
    float sha = 1.0-shadows; if( (shadows*dif)>0.001 ) sha=softshadow( pos+0.01*nor, lig, 0.0005, 32.0 );
    float fre = pow( clamp( 1.0 + dot(nor,rd), 0.0, 1.0 ), 5.0 );
    float spe = max( 0.0, pow( clamp( dot(lig,ref), 0.0, 1.0), 0.01+glossy ) ) * glossy;
    float sss = pow( clamp( 1.0 + dot(nor,rd), 0.0, 1.0 ), 3.0 );
		
    // lights
    vec3 brdf = vec3(0.0);
	brdf += 8.0*dif*vec3(1.80,1.35,0.90)*vec3(sha,sha*0.5+0.5*sha*sha,sha*sha);
    brdf += 1.0*sky*vec3(0.20,0.40,0.55)*occ;
    brdf += 1.0*bac*vec3(0.40,0.60,0.70)*occ;
    brdf += 1.0*bou*vec3(0.10,0.20,0.25);
    brdf += 1.0*sss*vec3(0.40,0.40,0.40)*(0.3+0.7*dif*sha)*glossy*occ;
    brdf += 0.5*spe*vec3(1.3,1.0,0.8)*sha*(0.3+0.7*fre)*occ*glossy;
    brdf += glossy*0.3*vec3(0.8,0.9,1.0)*occ*smoothstep( 0.0, 0.2, ref.y )*(0.5+0.5*smoothstep( 0.0, 1.0, ref.y ));//*smoothstep(-0.1,0.0,dif);
	
    col = col*brdf;

    col += (0.5 + 1.5*fre)*occ*glossy2*glossy2*10.0*vec3(1.0,0.9,0.8)*smoothstep( 0.0, 0.2, ref.y )*(0.5+0.5*smoothstep( 0.0, 1.0, ref.y ));//*smoothstep(-0.1,0.0,dif);
    col += 0.25*glossy*pow(spe/(0.01+glossy),8.0)*vec3(1.3,1.0,0.8)*sha*(0.3+0.7*fre)*occ;
	
	return col;
}

vec3 normalMap( in vec2 pos )
{
	pos *= 6.0;
	pos.y *= 0.375;
	
	float v = texture2D( iChannel2, 0.015*pos ).x;
	vec3 nor = vec3( texture2D( iChannel2, 0.015*pos+vec2(1.0/1024.0,0.0)).x - v,
	                 1.0/16.0,
	                 texture2D( iChannel2, 0.015*pos+vec2(0.0,1.0/1024.0)).x - v );
	nor.xz *= -1.0;
	return normalize( nor );
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 q = fragCoord.xy / resolution.xy;
    vec2 p = -1.0 + 2.0 * q;
    p.x *= resolution.x/resolution.y;
    vec2 m = vec2(0.5);
	if( mouse.x>0.0 ) m = mouse.xy/resolution.xy;


    //-----------------------------------------------------
    // animate
    //-----------------------------------------------------
	
	fishTime = 0.6 + 2.0*iGlobalTime - 20.0;
	
	fishPos = vec3( 0.0, 0.0-0.2, -1.1*fishTime );
	
	isJump  = 0.5 + 0.5*cos(     -0.4+0.5*fishTime);
	isJump2 = 0.5 + 0.5*cos( 0.6+0.5*fishTime);
	float isJump3 = 0.5 + 0.5*cos(-1.4+0.5*fishTime);

    //-----------------------------------------------------
    // camera
    //-----------------------------------------------------

	float an = 1.2 + 0.1*iGlobalTime - 12.0*(m.x-0.5);

	vec3 ta = vec3(fishPos.x,0.8,fishPos.z) - vec3(0.0,0.0,-2.0);
	vec3 ro = ta + vec3(4.0*sin(an),3.1,4.0*cos(an));

    // shake
	ro += 0.05*sin(4.0*iGlobalTime*vec3(1.1,1.2,1.3)+vec3(3.0,0.0,1.0) );
	ta += 0.05*sin(4.0*iGlobalTime*vec3(1.7,1.5,1.6)+vec3(1.0,2.0,1.0) );

    // camera matrix
    vec3 ww = normalize( ta - ro );
    //vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) );
	vec3 uu = normalize( vec3(-ww.z,0.0,ww.x) );
    vec3 vv = normalize( cross(uu,ww));
	
	// create view ray
	vec3 rd = normalize( p.x*uu + p.y*vv + 2.0*ww*(1.0+0.7*smoothstep(-0.4,0.4,sin(0.34*iGlobalTime))) );

    //-----------------------------------------------------
	// render
    //-----------------------------------------------------

	float t = 1000.0;
	
	vec3 col = vec3(0.0);
	vec3 bgcol = vec3(0.6,0.7,0.8) - .2*clamp(rd.y,0.0,1.0);

    // quick step till y=3 bounding plane
	float pt = (3.0-ro.y)/rd.y;
	if( rd.y<0.0 && pt>0.0 ) ro=ro+rd*pt;

	// raymarch
    vec2 tmat1 = intersectDolphin(ro,rd);
	vec3 posy = vec3(-100000.0);
    if( tmat1.x>0.0 )
    {
		vec2 tmat = tmat1;
		t = tmat.x;
        // geometry
        vec3 pos = ro + tmat.x*rd;
        vec3 nor = calcNormalFish(pos);
		vec3 ref = reflect( rd, nor );
		vec3 fpos = pos - fishPos;

		vec3 auu = normalize( vec3(-ccd.z,0.0,ccd.x) );
		vec3 avv = normalize( cross(ccd,auu) );
		vec3 ppp = vec3( dot(fpos-ccp,auu),  dot(fpos-ccp,avv),  tmat.y );
		vec2 uv = vec2( 1.0*atan(ppp.x,ppp.y)/3.1416, 4.0*ppp.z );

		vec3 bnor = -1.0+2.0*texture2D(iChannel0,uv).xyz;
        nor += 0.01*bnor;

		vec3 te = texture2D( iChannel2, uv ).xyz;
		vec4 mate;
		mate.w = 17.0;
        mate.xyz = mix( vec3(0.3,0.35,0.4), vec3(0.8,0.85,0.9)*0.9, 0.8*smoothstep(-0.05,0.05,ppp.y) );;

        mate.xyz *= 1.0 + 0.3*te;
		mate.xyz *= smoothstep( 0.0, 0.06, distance(vec3(abs(ppp.x),ppp.yz)*vec3(1.0,1.0,4.0),vec3(0.35,0.0,0.4)) );
		mate.xyz *= 1.0 - 0.75*(1.0-smoothstep( 0.0, 0.02, abs(ppp.y) ))*(1.0-smoothstep( 0.07, 0.11, tmat.y ));
		
		mate.xyz *= 0.1*0.23;
		
        mate.w *= (0.7+0.3*te.x)*smoothstep( 0.0, 0.01, pos.y-sdWaterCheap( pos ) );
			
        // surface-light interacion
        col = doLighting( pos, nor, rd, mate.w, 0.0, 0.0, mate.xyz, 1.0 );
	
		posy = pos;
	}

	
    vec3 tmat2 = intersectWater(ro,rd);
	vec3 col2 = vec3(0.0);
	if( tmat2.x>0.0 && (tmat1.x<0.0 || tmat2.x<tmat1.x) )
	{
		vec3 tmat = tmat2;

        t = tmat.x;

        vec3 pos = ro + tmat.x*rd;
        vec3 nor = calcNormalWater(pos);
		vec3 ref = reflect( rd, nor );

        vec4 mate = vec4(0.4,0.4,0.4,0.0);

		vec3 bnor = normalMap(pos.xz);
        nor = normalize( nor + 0.2*bnor );

        float fre = pow( clamp(1.0 + dot( rd, nor ),0.0,1.0), 2.0 );

		mate.xyz = 0.3*mix( vec3(0.0,0.03,0.07), 0.1*vec3(0.0,0.3,0.4), fre );
		mate.w = fre;	

        float foam = 1.0-smoothstep( 0.1, 0.65, tmat.y );
        foam *= smoothstep( 0.0, 0.3, abs(nor.x) );
		
        foam *= clamp(1.0-texture2D( iChannel2, vec2(1.0,0.75)*0.45*pos.xz ).x*2.0,0.0,1.0);
        mate = mix( mate, vec4(0.7,0.7,0.7,0.0), 0.2*foam );

		float al = clamp( 0.5 + 0.2*(pos.y - posy.y), 0.0, 1.0 );
		
		//foam = exp( -3.0*abs(sdFishCheap(pos).x) );
		foam = exp( -3.0*abs(tmat.z) );
		
		foam *= texture2D( iChannel3, pos.zx ).x;
		foam = clamp( foam*3.0, 0.0, 1.0 );
		foam *= isJump;
		foam *= mix( 1.0, smoothstep(0.0,0.5,pos.z-fishPos.z-1.5), isJump2 );
		mate.xyz = mix( mate.xyz, vec3(0.9,0.95,1.0)*0.3, foam*foam );
		col = mix( col, vec3(0.9,0.95,1.0)*1.2, foam );
		al *= 1.0-foam;

		float occ = clamp(3.5*sdDolphinCheap(pos+vec3(0.0,0.4,0.0)).x * sdDolphinCheap(pos+vec3(0.0,1.0,0.0)).x,0.0,1.0);
        occ = mix(1.0,occ,isJump);
        occ = 0.35 + 0.65*occ;
		mate.xyz *= occ;
        col *= occ;

		mate.xyz = doLighting( pos, nor, rd, mate.w*10.0, mate.w*0.5, 1.0, mate.xyz, occ );
		
        // caustics
        float cc  = 0.65*texture2D( iChannel0, 2.5*0.02*posy.xz + 0.007*iGlobalTime*vec2( 1.0, 0.0) ).x;
        cc += 0.35*texture2D( iChannel0, 1.8*0.04*posy.xz + 0.011*iGlobalTime*vec2( 0.0, 1.0) ).x;
        cc = 0.6*(1.0-smoothstep( 0.0, 0.05, abs(cc-0.5))) + 
	         0.4*(1.0-smoothstep( 0.0, 0.20, abs(cc-0.5)));
        col *= 1.0 + 0.8*cc;
		
		col = mix( col, mate.xyz, al );
	}
		
	
	float sun = pow( max(0.0,dot( lig, rd )),8.0 );
	col += vec3(0.8,0.5,0.1)*sun*0.3;

    // gamma
	col = pow( clamp(col,0.0,1.0), vec3(0.45) );

    // color
	col = col*vec3(0.9,0.85,0.8) + 0.4*col*col*(3.0-2.0*col);
		
    // vigneting	
	col *= 0.5 + 0.5*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1 );

    // fade	
	col *= smoothstep( 0.0, 1.0, iGlobalTime );
	
	fragColor = vec4( col, 1.0 );
}

void main( void ){vec4 color = vec4(0.0,0.0,0.0,1.0);mainImage( color, gl_FragCoord.xy );color.w = 1.0;gl_FragColor = color;}
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Shader avec PureBasic

Message par Ar-S »

ça marche nikel même si sur mon portable ça rame du cucul.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
kwandjeen
Messages : 204
Inscription : dim. 16/juil./2006 21:44

Re: Shader avec PureBasic

Message par kwandjeen »

C'est vraiment pas mal.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Shader avec PureBasic

Message par blendman »

pareil, chez moi, ça marche mais ça rame à mort ton exemple (j'ai 2 fps ^^)
Répondre