Shader pour OpenGL

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Shader pour OpenGL

Message par threedslider »

Hello,

Je connais assez bien la lib de OpenGL mais par contre je ne sais pas trop utiliser comment on fait créer et ensuite utiliser les shaders avec OpenGL ? Si parmi vous vous saurez m'indiquer comment faire ou un exemple sur la création shader simple et utiliser avec OpenGL en code PB, merci beaucoup !

J'ai besoin votre aide, svp et ce serait grandement un plaisir de faire cela. :arrow: :oops: :D
brossden
Messages : 819
Inscription : lun. 26/janv./2004 14:37

Re: Shader pour OpenGL

Message par brossden »

Je suis désolé mais je ne connais pas les shaders, tu pourrais expliquer ?
Denis

Bonne Jounée à tous
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: Shader pour OpenGL

Message par manababel »

bonjour ,

ici , la personne qui s'y connais le plus en shader sous Pb est "Guillot"
viewtopic.php?t=18901

sur le forum anglais , tu y trouveras quelques exemples pour debuter les shaders sous opengl

voici un petit programme trouvé sur le forum anglais
j'y ai apporté quelques modifications
utilise le bouton "load" pour charger un shader et le bouton "run" pour lancer un shader modifié

va sur le site "https://glslsandbox.com/?page=0"
fais un copier/coller du shader dans un fichier txt , puis lance le avec le programme ci-dessous

Code : Tout sélectionner

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

;EnableExplicit

Global screen_lg = 1920
Global screen_ht = 1080

Structure shaders
  file.s
  name.s
EndStructure
Global NewList ShaderList.shaders()

Global shader$

Enumeration ;/ Window
  #Window_Main
EndEnumeration
Enumeration ;/ Gadget
  #Gad_OpenGL
  #Gad_Editor
  #Gad_ShaderSelector_Combo
EndEnumeration
Enumeration ; button
  #run = 100
  #load
  #save
  #exit
  #test
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 LoadGLTextures(Names.s)
  Protected *pointer, TextureID.i, FrameBufferID.i
  
  LoadImage(0, Names) ; Load texture with name
  *pointer = EncodeImage(0, #PB_ImagePlugin_BMP,0,24);  
  FreeImage(0)
  
  ; ----- Generate texture
  glGenTextures_(1, @TextureID.i)
  glBindTexture_(#GL_TEXTURE_2D, TextureID)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
  glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
  glTexImage2D_(#GL_TEXTURE_2D, 0, 3,  PeekL(*pointer+18),  PeekL(*pointer+22), 0, #GL_BGR_EXT, #GL_UNSIGNED_BYTE,  *pointer+54);
  FreeMemory(*pointer)
  ProcedureReturn TextureID

EndProcedure




Procedure load_shader()
  Protected filename$ ="" , t$
  filename$ = OpenFileRequester("Open shader","","All|*.*",0)
  If filename$ <> ""
    If ReadFile(0,filename$)
      shader$ = ""
      While Eof(0) = 0       ; Boucle tant que la fin du fichier n'est pas atteinte. (Eof = 'End Of File') 
        shader$ = shader$ + ReadString(0) + Chr(10)
      Wend
      CloseFile(0)               ; Ferme le fichier précédemment ouvert
    Else
      Debug "???"
    EndIf
  EndIf
EndProcedure

Procedure save_shader()
  Protected filename$ ="" , r$ ,t$
  filename$ = SaveFileRequester("Save shader", "", "", 0)
  Debug filename$
  Debug GetFilePart(filename$)
  Debug GetPathPart(filename$)
  Debug GetExtensionPart(filename$)
  If filename$ <> ""
    If OpenFile(0,filename$)
      FileSeek(0, Lof(0))
      
            r$ = ""
            For i = 1 To Len(shader$)
              t$ = Mid(shader$,i,1)
              If t$ = Chr(13) Or t$ = Chr(10)
                t$ = ""
                WriteStringN(0,r$)
                r$ = ""
              Else
                r$ = r$ + t$
              EndIf
            Next
            
      CloseFile(0)
    EndIf
    
  EndIf
  
EndProcedure

;Procedure Init_Main()

  System\Width.i = screen_lg
  System\Height = screen_ht
  System\Shader_Width = screen_lg / 2
  System\Shader_Height = screen_ht
  
  OpenWindow(#Window_Main,0,0,screen_lg,screen_ht,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  OpenGLGadget(#Gad_OpenGL,screen_lg/2,0,System\Shader_Width,System\Shader_Height,#PB_OpenGL_Keyboard)

  EditorGadget(#Gad_Editor,0,30,System\Width - (System\Shader_Width+8),System\Height-30)
  
  ButtonGadget(#run,5 ,0,70,24,"run")
  ButtonGadget(#save,105 ,0,70,24,"save")
  ButtonGadget(#load,205 ,0,70,24,"load")
  ButtonGadget(#exit,305 ,0,70,24,"exit")
  ButtonGadget(#test,405 ,0,70,24,"test")
  
  System\App_StartTime = ElapsedMilliseconds()
  System\Shader_Vertex_Text = "#version 330"+Chr(10)
  System\Shader_Vertex_Text + "in vec3 position;"+Chr(10)
  System\Shader_Vertex_Text + " void main() {"+Chr(10)
  System\Shader_Vertex_Text + " gl_Position = vec4( position, 1.0 );"+Chr(10)
  System\Shader_Vertex_Text + " };"+Chr(10)
  
;EndProcedure

;Init_Main()

;{ Opengl shader setup & routines

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

;{ OpenGL
;  https://www.purebasic.fr/english/viewtopic.php?p=576628#p576628

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

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  ImportC "-framework OpenGL"
    glCreateShader(type.l) As "_glCreateShader" 
    glCreateProgram() As "_glCreateProgram"
    glDeleteShader(shader.l) As "_glDeleteShader"
    glCompileShader(shader.l) As  "_glCompileShader"
    glLinkProgram(shader.l) As "_glLinkProgram" 
    glUseProgram(shader.l) As "_glUseProgram" 
    glAttachShader(Program.l, shader.l) As  "_glAttachShader"
    glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) As  "_glShaderSource"
    glGetUniformLocation(Program.i, name.p-ascii) As  "_glGetUniformLocation"
    glUniform1i(location.i, v0.i) As "_glUniform1i"
    glUniform2i(location.i, v0.i, v1.i) As  "_glUniform2i"
    glUniform1f(location.i, v0.f) As  "_glUniform1f"
    glUniform1d(location.i, v0.d) As  "_glUniform1d"
    glUniform2f(location.i, v0.f, v1.f) As  "_glUniform2f"
    glUniform2d(location.i, v0.d, v1.d) As  "_glUniform2d"
    glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog) As  "_glGetShaderInfoLog"
  EndImport
  
CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux  
  ImportC "/usr/lib/x86_64-linux-gnu/libGL.so"
    glCreateShader(type.l)
    glCreateProgram()
    glDeleteShader(shader.l)
    glCompileShader(shader.l)
    glLinkProgram(shader.l)
    glUseProgram(shader.l)
    glAttachShader(Program.l, shader.l)
    glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) : 
    glGetUniformLocation(Program.i, name.p-ascii)
    glUniform1i(location.i, v0.i)
    glUniform2i(location.i, v0.i, v1.i)
    glUniform1f(location.i, v0.f)
    glUniform1d(location.i, v0.d)
    glUniform2f(location.i, v0.f, v1.f)
    glUniform2d(location.i, v0.d, v1.d)
    glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)
  EndImport
    
CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows
  Prototype glCreateShader(type.l)
  Prototype glCreateProgram()
  Prototype glDeleteShader(shader.l)
  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 glGetUniformLocation(Program.i, name.p-ascii)
  Prototype glUniform1i(location.i, v0.i)
  Prototype glUniform2i(location.i, v0.i, v1.i)
  Prototype glUniform1f(location.i, v0.f)
  Prototype glUniform1d(location.i, v0.d)
  Prototype glUniform2f(location.i, v0.f, v1.f)
  Prototype glUniform2d(location.i, v0.d, v1.d)
  Prototype glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)
  Global glCreateShader.glCreateShader             = wglGetProcAddress_("glCreateShader")
  Global glCreateProgram.glCreateProgram           = wglGetProcAddress_("glCreateProgram")
  Global glDeleteShader.glDeleteShader             = wglGetProcAddress_("glDeleteShader")
  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 glUniform1d.glUniform1d                   = wglGetProcAddress_("glUniform1d")
  Global glUniform2f.glUniform2f                   = wglGetProcAddress_("glUniform2f")
  Global glUniform2d.glUniform2d                   = wglGetProcAddress_("glUniform2d")
  Global glGetShaderInfoLog.glGetShaderInfoLog     = wglGetProcAddress_("glGetShaderInfoLog")
  
CompilerEndIf
;}

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 = Ascii(Vertex)
  glShaderSource(VertShader, 1, @*TxtPointer, #Null)
  glCompileShader(VertShader)
  glGetShaderInfoLog(VertShader,1023,@Textlength,@Mytext)
  ;/ Compile Fragment Shader
  FragShader.i = glCreateShader(#GL_FRAGMENT_SHADER)
  *TxtPointer = Ascii(Fragment)
  glShaderSource(FragShader, 1, @*TxtPointer, #Null)
  glCompileShader(FragShader)
  glGetShaderInfoLog(FragShader,1023,@Textlength,@Mytext)
  ;Debug PeekS(@Mytext,1023,#PB_Ascii)
  ;Debug MyText  
  ;/ Create Shader Program
  Program = glCreateProgram()
  glAttachShader(Program,VertShader)
  glAttachShader(Program,FragShader)
  glLinkProgram(Program)
  If Use = 1 : glUseProgram(Program) : EndIf 
  ProcedureReturn Program  
EndProcedure
;}

Procedure Shader_Set()
  If System\Shader_Program <> 0 :glUseProgram(0) : EndIf ;/ delete the previous shaders

  System\Shader_Fragment_Text = shader$
  
  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
  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")
  
  SetGadgetText(#Gad_Editor,shader$)
  
EndProcedure

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_CloseWindow
        System\Exit = #True 
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #load
            load_shader()
            Shader_Set()
          Case #run           
            shader$ = GetGadgetText(#Gad_Editor)
            Shader_Set()
          Case #save           
            save_shader()  
          Case #exit
            End
          Case #test

            
          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 

End


voici quelques exemples de shader , fais un copier/coller dans un fichier "txt" puis charger les avec le bouton "load"

Code : Tout sélectionner

#extension GL_OES_standard_derivatives : enable

precision highp float;

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

void main( void ) {
	
	vec4 O = vec4(0.0);
	float maxCoord = max(resolution.x, resolution.y);
	float ratio = resolution.y / resolution.x;
	
	vec2 u = gl_FragCoord.xy/maxCoord - vec2(0.5, ratio * 0.5);
	u *= 4.0;
	float T = time;
	for (float i = 0.; i < 100.0; i += .5) {
	O += .001/abs(length(u + vec2(cos(i/4. + T), sin(i*.45 + T)) * sin(T*.5+i*.35)) - sin(i+T*.5) / 60. - .01) * (1. + cos(i*.7 + T + length(u)*6. + vec4(0,1,2,0)));
	}
	
	gl_FragColor = O;
	
	return;

	vec2 position = ( gl_FragCoord.xy / resolution.xy ) + mouse / 4.0;

	float color = 0.0;
	color += sin( position.x * cos( time / 15.0 ) * 80.0 ) + cos( position.y * cos( time / 15.0 ) * 10.0 );
	color += sin( position.y * sin( time / 10.0 ) * 40.0 ) + cos( position.x * sin( time / 25.0 ) * 40.0 );
	color += sin( position.x * sin( time / 5.0 ) * 10.0 ) + sin( position.y * sin( time / 35.0 ) * 80.0 );
	color *= sin( time / 10.0 ) * 0.5;

	gl_FragColor = vec4( vec3( color, color * 0.5, sin( color + time / 3.0 ) * 0.75 ), 1.0 );

}

Code : Tout sélectionner

#extension GL_OES_standard_derivatives : enable

precision highp float;

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

vec3 palette(float t) {
	vec3 a = vec3(0.5,0.5,0.5);
	vec3 b = vec3(0.5,0.5,0.5);
	vec3 c = vec3(1.0,1.0,1.0);
	vec3 d = vec3(0.00, 0.33, 0.67);
	
	return a + b*cos( 6.28318*(c*t+d));
}

void main( void ) {
	vec3 final = vec3(0.0);
	vec2 nres = gl_FragCoord.xy / resolution.xy * 2.0 - 1.0;
	nres.x *= resolution.x / resolution.y;
	vec2 nres0 = nres;
	for (float i = 0.0; i < 4.0; i++){
		nres = fract(nres * 1.5) - 0.5;
		float d = length(nres) * exp(-length(nres0));
		vec3 col = palette(length(nres0) + i * .4 + time * .4);
		d = sin(d * 10.0 + time)/10.0;
      	 	d = abs(d);
		d = pow(0.01 / d, 1.2);
		final += col*d;
	}
	gl_FragColor = vec4(final,1.0);
}
Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Shader pour OpenGL

Message par threedslider »

Merci beaucoup @manababel ! Marche bien ici :D

C'est très jolie ! J'ai un peu étudié ton code, seulement un seul fichier shader pour faire fonctionner?? D'habitude c'est plutôt d'après ce que j'ai entendu faut le duo de vertex shader et fragment shader, non ?? Sinon c'est très fort ça :roll:

Est ce que c'est possible de faire plus simple avec des shaders (vertex et fragment) à partir d'un carré bleu sous OpenGL ? Histoire de voir comment c'est fait simplement... 8O

Merci encore pour le codes j'ai appris pas mal mais me sens pas prêt tout de même :mrgreen:
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: Shader pour OpenGL

Message par manababel »

je début aussi sur opengl et les shaders.
il est possible d’utilisé des shader avec un simple vbo , mais ça se limite a de simples forme ergométriques precalculés.

le programme poster ci-dessus utilise de "simple shaders"

les vertex : (ligne 150)
System\App_StartTime = ElapsedMilliseconds()
System\Shader_Vertex_Text = "#version 330"+Chr(10)
System\Shader_Vertex_Text + "in vec3 position;"+Chr(10)
System\Shader_Vertex_Text + " void main() {"+Chr(10)
System\Shader_Vertex_Text + " gl_Position = vec4( position, 1.0 );"+Chr(10)
System\Shader_Vertex_Text + " };"+Chr(10)

les fragment shaders : les 2 programme ci-dessus

malheureusement ,pour le moment , mes compétences s’arrête ici.
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: Shader pour OpenGL

Message par manababel »

affichage d'un cercle

Code : Tout sélectionner

#ifdef GL_ES
precision highp float;
#endif

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

void main( void ) {
	vec2 position = gl_FragCoord.xy;
	vec2 center = mouse.xy*resolution.xy;
	vec4  color = vec4(0.0, 0.0, 0.0, 1.0);
	float r = 50.0;

        if( length(center - position ) < r)
	{
		color = vec4(1.0, 0.0, 0.0, 1.0);
	}
	gl_FragColor = color;
}
affichage d'une ligne

Code : Tout sélectionner

// By: Brandon Fogerty 
// bfogerty at gmail dot com 
#ifdef GL_ES 
precision mediump float; 
#endif 
uniform float time; 
uniform vec2 mouse; 
uniform vec2 resolution; 
void main( void )  
{ 
	vec2 p = ( gl_FragCoord.xy / resolution.xy ) * 2.0 - 1.0; 
	vec3 c = vec3( 0.0 ); 
	float glowFactor = mix( 0.15, 0.35, 0. ); 
	c += vec3(0.0, 0.02, 0.10) * ( glowFactor * abs( 1.0 / p.x )); 
	gl_FragColor = vec4( c, 1.0 ); 
}
affichage de polygones

Code : Tout sélectionner

float circle(vec2 p, float radius) {
  return length(p) - radius;
}

float rect(vec2 p, vec2 size) {  
  vec2 d = abs(p) - size;
  return min(max(d.x, d.y), 0.0) + length(max(d,0.0));
}

float roundRect(vec2 p, vec2 size, float radius) {
  vec2 d = abs(p) - size;
  return min(max(d.x, d.y), 0.0) + length(max(d,0.0))- radius;
}
float ring(vec2 p, float radius, float width) {
  return abs(length(p) - radius * 0.5) - width;
}
float hexagon(vec2 p, float radius) {
    vec2 q = abs(p);
    return max(abs(q.y), q.x * 0.866025 + q.y * 0.5) - radius;
}
float triangle(vec2 p, float size) {
    vec2 q = abs(p);
    return max(q.x * 0.866025 + p.y * 0.5, -p.y * 0.5) - size * 0.5;
}
float ellipse(vec2 p, vec2 r, float s) {
    return (length(p / r) - s);
}
float capsule(vec2 p, vec2 a, vec2 b, float r) {
    vec2 pa = p - a, ba = b - a;
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
    return length( pa - ba*h ) - r;
}
//http://thndl.com/square-shaped-shaders.html
float polygon(vec2 p, int vertices, float size) {
    float a = atan(p.x, p.y) + 3.14*sin(time);
    float b = 3.141592*2. / float(vertices);
    return cos(floor(0.5 + a / b) * b - a) * length(p) - size;
}
void main() {
    vec2 st = gl_FragCoord.xy/resolution.xy;

    float d = circle(st - vec2(0.2), 0.1);
    d = min(d, rect(st - vec2(0.5, 0.2), vec2(0.1, 0.08)));
    d = min(d, roundRect(st - vec2(0.8, 0.2), vec2(0.08, 0.06), 0.02));
    d = min(d, ring(st - vec2(0.2, 0.5), 0.18, 0.02));
    d = min(d, hexagon(st - vec2(0.5, 0.5), 0.1));
    d = min(d, triangle(st - vec2(0.8, 0.5), 0.1));
    d = min(d, ellipse(st - vec2(0.2, 0.8), vec2(0.9, 1.2), 0.1));
    d = min(d, capsule(st - vec2(0.5, 0.8), vec2(-0.05, -0.05), vec2(0.05, 0.05), 0.05));
    d = min(d, polygon(st - vec2(0.8, 0.8), 5, 0.1));
    vec3 color = vec3(smoothedge(d));
    gl_FragColor = vec4(color, 1.0);
	//https://thebookofshaders.com/edit.php?log=160414041142
}
code un peut plus complex

Code : Tout sélectionner

/*--------------------------------------------------------------------------------------
License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
----------------------------------------------------------------------------------------
^This means do anything you want with this code. Because we are programmers, not lawyers.
-Otavio Good

https://www.shadertoy.com/view/XljGDz
*/

// Number of times the fractal repeats
#define RECURSION_LEVELS 3
// Animation splits the sphere in different directions
// This ended up running a significantly slower fps and not looking very different. :(
//#define SPLIT_ANIM

#ifdef GL_ES
precision mediump float;
#endif

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

float localTime = 0.0;
float marchCount;

float PI=3.14159265;

vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
float saturate(float a) { return clamp(a, 0.0, 1.0); }

vec3 RotateX(vec3 v, float rad)
{
  float cos = cos(rad);
  float sin = sin(rad);
  return vec3(v.x, cos * v.y + sin * v.z, -sin * v.y + cos * v.z);
}
vec3 RotateY(vec3 v, float rad)
{
  float cos = cos(rad);
  float sin = sin(rad);
  return vec3(cos * v.x - sin * v.z, v.y, sin * v.x + cos * v.z);
}
vec3 RotateZ(vec3 v, float rad)
{
  float cos = cos(rad);
  float sin = sin(rad);
  return vec3(cos * v.x + sin * v.y, -sin * v.x + cos * v.y, v.z);
}


/*vec3 GetEnvColor(vec3 rayDir, vec3 sunDir)
{
	vec3 tex = texture(iChannel0, rayDir).xyz;
	tex = tex * tex;	// gamma correct
    return tex;
}*/

// This is a procedural environment map with a giant overhead softbox,
// 4 lights in a horizontal circle, and a bottom-to-top fade.
vec3 GetEnvColor2(vec3 rayDir, vec3 sunDir)
{
    // fade bottom to top so it looks like the softbox is casting light on a floor
    // and it's bouncing back
    vec3 final = vec3(1.0) * dot(-rayDir, sunDir) * 0.5 + 0.5;
    final *= 0.125;
    // overhead softbox, stretched to a rectangle
    if ((rayDir.y > abs(rayDir.x)*1.0) && (rayDir.y > abs(rayDir.z*0.25))) final = vec3(2.0)*rayDir.y;
    // fade the softbox at the edges with a rounded rectangle.
    float roundBox = length(max(abs(rayDir.xz/max(0.0,rayDir.y))-vec2(0.9, 4.0),0.0))-0.1;
    final += vec3(0.8)* pow(saturate(1.0 - roundBox*0.5), 6.0);
    // purple lights from side
    final += vec3(8.0,6.0,7.0) * saturate(0.001/(1.0 - abs(rayDir.x)));
    // yellow lights from side
    final += vec3(8.0,7.0,6.0) * saturate(0.001/(1.0 - abs(rayDir.z)));
    return vec3(final);
}

/*vec3 GetEnvColorReflection(vec3 rayDir, vec3 sunDir, float ambient)
{
	vec3 tex = texture(iChannel0, rayDir).xyz;
	tex = tex * tex;
    vec3 texBack = texture(iChannel0, rayDir).xyz;
    vec3 texDark = pow(texBack, vec3(50.0)).zzz;	// fake hdr texture
    texBack += texDark*0.5 * ambient;
    return texBack*texBack*texBack;
}*/

vec3 camPos = vec3(0.0), camFacing;
vec3 camLookat=vec3(0,0.0,0);

// polynomial smooth min (k = 0.1);
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);
}

vec2 matMin(vec2 a, vec2 b)
{
	if (a.x < b.x) return a;
	else return b;
}

float spinTime;
vec3 diagN = normalize(vec3(-1.0));
float cut = 0.77;
float inner = 0.333;
float outness = 1.414;
float finWidth;
float teeth;
float globalTeeth;

vec2 sphereIter(vec3 p, float radius, float subA)
{
    finWidth = 0.1;
    teeth = globalTeeth;
    float blender = 0.25;
    vec2 final = vec2(1000000.0, 0.0);
    for (int i = 0; i < RECURSION_LEVELS; i++)
    {
#ifdef SPLIT_ANIM
        // rotate top and bottom of sphere opposite directions
        p = RotateY(p, spinTime*sign(p.y)*0.05/blender);
#endif
        // main sphere
        float d = length(p) - radius*outness;
#ifdef SPLIT_ANIM
        // subtract out disc at the place where rotation happens so we don't have artifacts
        d = max(d, -(max(length(p) - radius*outness + 0.1, abs(p.y) - finWidth*0.25)));
#endif

        // calc new position at 8 vertices of cube, scaled
        vec3 corners = abs(p) + diagN * radius;
        float lenCorners = length(corners);
        // subtract out main sphere hole, mirrored on all axises
        float subtracter = lenCorners - radius * subA;
        // make mirrored fins that go through all vertices of the cube
        vec3 ap = abs(-p) * 0.7071;	// 1/sqrt(2) to keep distance field normalized
        subtracter = max(subtracter, -(abs(ap.x-ap.y) - finWidth));
        subtracter = max(subtracter, -(abs(ap.y-ap.z) - finWidth));
        subtracter = max(subtracter, -(abs(ap.z-ap.x) - finWidth));
        // subtract sphere from fins so they don't intersect the inner spheres.
        // also animate them so they are like teeth
        subtracter = min(subtracter, lenCorners - radius * subA + teeth);
        // smoothly subtract out that whole complex shape
        d = -smin(-d, subtracter, blender);
        //vec2 sphereDist = sphereB(abs(p) + diagN * radius, radius * inner, cut);	// recurse
        // do a material-min with the last iteration
        final = matMin(final, vec2(d, float(i)));

#ifndef SPLIT_ANIM
        corners = RotateY(corners, spinTime*0.25/blender);
#endif
        // Simple rotate 90 degrees on X axis to keep things fresh
        p = vec3(corners.x, corners.z, -corners.y);
        // Scale things for the next iteration / recursion-like-thing
        radius *= inner;
        teeth *= inner;
        finWidth *= inner;
        blender *= inner;
    }
    // Bring in the final smallest-sized sphere
    float d = length(p) - radius*outness;
    final = matMin(final, vec2(d, 6.0));
    return final;
}

vec2 DistanceToObject(vec3 p)
{
    vec2 distMat = sphereIter(p, 5.2 / outness, cut);
    return distMat;
}

// dirVec MUST BE NORMALIZED FIRST!!!!
float SphereIntersect(vec3 pos, vec3 dirVecPLZNormalizeMeFirst, vec3 spherePos, float rad)
{
    vec3 radialVec = pos - spherePos;
    float b = dot(radialVec, dirVecPLZNormalizeMeFirst);
    float c = dot(radialVec, radialVec) - rad * rad;
    float h = b * b - c;
    if (h < 0.0) return -1.0;
    return -b - sqrt(h);
}

void main()
{
    localTime = time - 0.0;
	// ---------------- First, set up the camera rays for ray marching ----------------
	vec2 uv = gl_FragCoord.xy/resolution.xy * 2.0 - 1.0;
    float zoom = 1.7;
    uv /= zoom;

	// Camera up vector.
	vec3 camUp=vec3(0,1,0);

	// Camera lookat.
	camLookat=vec3(0,0.0,0);

    // debugging camera
    float mx=mouse.x/resolution.x*PI*2.0-0.7 + localTime*3.1415 * 0.0625*0.666;
	float my=-mouse.y/resolution.y*10.0 - sin(localTime * 0.31)*0.5;//*PI/2.01;
	camPos += vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*(12.2);

	// Camera setup.
	vec3 camVec=normalize(camLookat - camPos);
	vec3 sideNorm=normalize(cross(camUp, camVec));
	vec3 upNorm=cross(camVec, sideNorm);
	vec3 worldFacing=(camPos + camVec);
	vec3 worldPix = worldFacing + uv.x * sideNorm * (resolution.x/resolution.y) + uv.y * upNorm;
	vec3 rayVec = normalize(worldPix - camPos);

	// ----------------------------------- Animate ------------------------------------
    localTime = time*0.5;
    // This is a wave function like a triangle wave, but with flat tops and bottoms.
    // period is 1.0
    float rampStep = min(3.0,max(1.0, abs((fract(localTime)-0.5)*1.0)*8.0))*0.5-0.5;
    rampStep = smoothstep(0.0, 1.0, rampStep);
    // lopsided triangle wave - goes up for 3 time units, down for 1.
    float step31 = (max(0.0, (fract(localTime+0.125)-0.25)) - min(0.0,(fract(localTime+0.125)-0.25))*3.0)*0.333;

    spinTime = step31 + localTime;
    //globalTeeth = 0.0 + max(0.0, sin(localTime*3.0))*0.9;
    globalTeeth = rampStep*0.99;
    cut = max(0.48, min(0.77, localTime));
	// --------------------------------------------------------------------------------
	vec2 distAndMat = vec2(0.5, 0.0);
	float t = 0.0;
	//float inc = 0.02;
	float maxDepth = 24.0;
	vec3 pos = vec3(0,0,0);
    marchCount = 0.0;
    // intersect with sphere first as optimization so we don't ray march more than is needed.
    float hit = SphereIntersect(camPos, rayVec, vec3(0.0), 5.6);
    if (hit >= 0.0)
    {
        t = hit;
        // ray marching time
        for (int i = 0; i < 290; i++)	// This is the count of the max times the ray actually marches.
        {
            pos = camPos + rayVec * t;
            // *******************************************************
            // This is _the_ function that defines the "distance field".
            // It's really what makes the scene geometry.
            // *******************************************************
            distAndMat = DistanceToObject(pos);
            // adjust by constant because deformations mess up distance function.
            t += distAndMat.x * 0.7;
            //if (t > maxDepth) break;
            if ((t > maxDepth) || (abs(distAndMat.x) < 0.0025)) break;
            marchCount+= 1.0;
        }
    }
    else
    {
        t = maxDepth + 1.0;
        distAndMat.x = 1000000.0;
    }
    // --------------------------------------------------------------------------------
	// Now that we have done our ray marching, let's put some color on this geometry.

	vec3 sunDir = normalize(vec3(3.93, 10.82, -1.5));
	vec3 finalColor = vec3(0.0);

	// If a ray actually hit the object, let's light it.
	//if (abs(distAndMat.x) < 0.75)
    if (t <= maxDepth)
	{
        // calculate the normal from the distance field. The distance field is a volume, so if you
        // sample the current point and neighboring points, you can use the difference to get
        // the normal.
        vec3 smallVec = vec3(0.005, 0, 0);
        vec3 normalU = vec3(distAndMat.x - DistanceToObject(pos - smallVec.xyy).x,
                           distAndMat.x - DistanceToObject(pos - smallVec.yxy).x,
                           distAndMat.x - DistanceToObject(pos - smallVec.yyx).x);

        vec3 normal = normalize(normalU);

        // calculate 2 ambient occlusion values. One for global stuff and one
        // for local stuff
        float ambientS = 1.0;
        ambientS *= saturate(DistanceToObject(pos + normal * 0.1).x*10.0);
        ambientS *= saturate(DistanceToObject(pos + normal * 0.2).x*5.0);
        ambientS *= saturate(DistanceToObject(pos + normal * 0.4).x*2.5);
        ambientS *= saturate(DistanceToObject(pos + normal * 0.8).x*1.25);
        float ambient = ambientS * saturate(DistanceToObject(pos + normal * 1.6).x*1.25*0.5);
        ambient *= saturate(DistanceToObject(pos + normal * 3.2).x*1.25*0.25);
        ambient *= saturate(DistanceToObject(pos + normal * 6.4).x*1.25*0.125);
        ambient = max(0.035, pow(ambient, 0.3));	// tone down ambient with a pow and min clamp it.
        ambient = saturate(ambient);

        // calculate the reflection vector for highlights
        vec3 ref = reflect(rayVec, normal);
        ref = normalize(ref);

        // Trace a ray for the reflection
        float sunShadow = 1.0;
        float iter = 0.1;
        vec3 nudgePos = pos + normal*0.02;	// don't start tracing too close or inside the object
		for (int i = 0; i < 40; i++)
        {
            float tempDist = DistanceToObject(nudgePos + ref * iter).x;
	        sunShadow *= saturate(tempDist*50.0);
            if (tempDist <= 0.0) break;
            //iter *= 1.5;	// constant is more reliable than distance-based
            iter += max(0.00, tempDist)*1.0;
            if (iter > 4.2) break;
        }
        sunShadow = saturate(sunShadow);

        // ------ Calculate texture color ------
        vec3 texColor;
        texColor = vec3(1.0);// vec3(0.65, 0.5, 0.4)*0.1;
        texColor = vec3(0.85, 0.945 - distAndMat.y * 0.15, 0.93 + distAndMat.y * 0.35)*0.951;
        if (distAndMat.y == 6.0) texColor = vec3(0.91, 0.1, 0.41)*10.5;
        //texColor *= mix(vec3(0.3), vec3(1.0), tex3d(pos*0.5, normal).xxx);
        texColor = max(texColor, vec3(0.0));
        texColor *= 0.25;

        // ------ Calculate lighting color ------
        // Start with sun color, standard lighting equation, and shadow
        vec3 lightColor = vec3(0.0);// sunCol * saturate(dot(sunDir, normal)) * sunShadow*14.0;
        // sky color, hemisphere light equation approximation, ambient occlusion
        lightColor += vec3(0.1,0.35,0.95) * (normal.y * 0.5 + 0.5) * ambient * 0.2;
        // ground color - another hemisphere light
        lightColor += vec3(1.0) * ((-normal.y) * 0.5 + 0.5) * ambient * 0.2;


        // finally, apply the light to the texture.
        finalColor = texColor * lightColor;
        //if (distAndMat.y == ceil(mod(localTime, 4.0))) finalColor += vec3(0.0, 0.41, 0.72)*0.925;

        // reflection environment map - this is most of the light
        vec3 refColor = GetEnvColor2(ref, sunDir)*sunShadow;
        finalColor += refColor * 0.35 * ambient;// * sunCol * sunShadow * 9.0 * texColor.g;

        // fog
		finalColor = mix(vec3(1.0, 0.41, 0.41) + vec3(1.0), finalColor, exp(-t*0.0007));
        // visualize length of gradient of distance field to check distance field correctness
        //finalColor = vec3(0.5) * (length(normalU) / smallVec.x);
	}
    else
    {
	    finalColor = GetEnvColor2(rayVec, sunDir);// + vec3(0.1, 0.1, 0.1);
    }
    //finalColor += marchCount * vec3(1.0, 0.3, 0.91) * 0.001;

    // vignette?
    //finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5));
    //finalColor *= 1.95;

	// output the final color with sqrt for "gamma correction"
	gl_FragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
}

Avatar de l’utilisateur
threedslider
Messages : 452
Inscription : dim. 01/juil./2018 22:38

Re: Shader pour OpenGL

Message par threedslider »

@manababel impressionnant ! 8O Merci beaucoup !

Je vais apprendre ça c'est trop super ce truc :mrgreen:

@brossden : dsl de ne pas avoir répondu, je pense que tu sais ce que je voulais savoir d'après manababel, il m'a aidé à comprendre les shaders, Merci :wink:
Répondre