Objetc border (outline) NO SHADERS

Everything related to 3D programming
User avatar
minimy
Enthusiast
Enthusiast
Posts: 619
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Objetc border (outline) NO SHADERS

Post by minimy »

Hi again, I'm back with a trick to fix how to make the edge (outline) on our 3D objects, it's not a fancy solution but it's simple and it works.

1) You only need to put 2 objects, the first one with your textures and all the shaders and more.
2) The second is the edge scaled a litle more big, with inverted culling to invert the normals and project the edge.

I guess it goes without saying that you should move the two objects and if they are animated, animate both objects at once.

This is a sample. For me it's enought. Now you have the ball to make a shader hehe :lol:
Where is my medal? :mrgreen:
And my cup? heep! :lol:

Code: Select all

;{ GLOBALES
  Global.b sal
  Global.l contador
  Global.b pantallaCompleta
;}

  ;{ FUENTES
  Global  fontLit= LoadFont(#PB_Any,"Arial",9)
  ;}
  
  ;{ SISTEMA 3D
  Procedure   spr2DText(spr, txt.s, ink.l=$ff00ffff)
    Protected n,y=2,tl= CountString(txt,#CR$)
    Protected tx.s
    StartDrawing(SpriteOutput(spr))
    DrawingMode(#PB_2DDrawing_AlphaChannel)
      Box(0,0,OutputWidth(),OutputHeight(),$00000000)
    DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Transparent)
      Box(0,0,OutputWidth(),OutputHeight(),$aa000000)
      DrawingFont(FontID(fontLit))
      For n=1 To tl+1
        tx= StringField(txt,n,#CR$)
        DrawText(5,y,tx,ink)
        y+16
      Next n
      DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Outlined)
      Box(0,0,OutputWidth(),OutputHeight(),ink)
    StopDrawing()
  EndProcedure
  Procedure   eventosWindows()
    Repeat
      event= WindowEvent()
      Select event
        Case #PB_Event_Gadget
          EventGadget=  EventGadget()
          EventType=    EventType()
          
        Case #PB_Event_CloseWindow
          sal= 1
      EndSelect
    Until event= 0
  EndProcedure
  Procedure   eventos3D(camara, speed.f=1, mouseSpd.f=0.05)
    Protected.f KeyX,KeyY, MouseX,MouseY
    If KeyboardPushed(#PB_Key_Escape)
      sal=1
    EndIf
    
    If KeyboardPushed(#PB_Key_A)
      KeyX= -speed
    ElseIf KeyboardPushed(#PB_Key_D)
      KeyX= speed
    Else
      KeyX= 0
    EndIf
    
    If KeyboardPushed(#PB_Key_W)
      KeyY= -speed
    ElseIf KeyboardPushed(#PB_Key_S)
      KeyY= speed
    Else
      KeyY= 0
    EndIf
    
    If KeyboardPushed(#PB_Key_LeftShift)
      keyY * 10
      keyX * 10
    EndIf

    MouseX = -MouseDeltaX() * mouseSpd
    MouseY = -MouseDeltaY() * mouseSpd
    
    RotateCamera(camara, MouseY, MouseX, 0, #PB_Relative)
    MoveCamera (camara, KeyX, 0, KeyY)
  EndProcedure
  Procedure   iniDX(title.s="ToniEngine3D", width=800,height=600, fullscreen.b=#False, AA.i=#PB_AntialiasingMode_None, shadowmode= #PB_Shadow_Modulative, shadowres=4096, param=#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
    Protected.b screenTestOK
    InitEngine3D()
      InitSprite()
      InitKeyboard()
      InitMouse()
      AntialiasingMode(AA)
      
      If width=0 And height=0
        ExamineDesktops()
        width=  DesktopWidth(0)
        height= DesktopHeight(0)
        pantallaCompleta= 0
        param= #PB_Window_BorderLess
      EndIf
      
      If fullscreen
        pantallaCompleta= 1
        If ExamineScreenModes()
          While NextScreenMode()
;             Debug Str(ScreenModeWidth())+"x"+Str(ScreenModeHeight())+"x"+Str(ScreenModeDepth())+"@"+Str(ScreenModeRefreshRate())+"Hz"
            If ScreenModeWidth()=width And ScreenModeHeight()=height And ScreenModeDepth()=32
              screenTestOK= 1
            EndIf
          Wend
        EndIf
        If screenTestOK= 0
          width=1280:height=720
        EndIf
        OpenScreen(width,height,32,title,#PB_Screen_NoSynchronization)
      Else
        OpenWindow(0, 0, 0, width, height, title, param)
          SetWindowColor(0,$444444)
          OpenWindowedScreen(WindowID(0), 0, 0, (width * DesktopResolutionX()), (height * DesktopResolutionY()),0,0,0,#PB_Screen_NoSynchronization)
      EndIf
      KeyboardMode(#PB_Keyboard_International)
      Add3DArchive("Data/Textures", #PB_3DArchive_FileSystem)
      Add3DArchive("Data/Model", #PB_3DArchive_FileSystem)
      Parse3DScripts()

      Protected.b s= 100
      If shadowmode= #PB_Shadow_TextureAdditive Or shadowmode= #PB_Shadow_TextureModulative
        WorldShadows(shadowmode, -1, RGB(s,s,s), shadowres)
      Else  
        WorldShadows(shadowmode, -1, RGB(s,s,s))
    EndIf
  EndProcedure
  
;   iniDX("Base 3D",1280,800,#True) ;pantalla completa
  iniDX("Base 3D",960,540,#False,#PB_AntialiasingMode_None,#PB_Shadow_Additive, 256) ;modo ventana
;   iniDX("Base 3D",0,0,#False,#PB_AntialiasingMode_None,#PB_Shadow_Modulative, 512) ; pantalla completa en veentana
  sprInfo=  CreateSprite(#PB_Any,100,200,#PB_Sprite_AlphaBlending)
  ;}
  
  Procedure   creaSuelo(size=50, col1.l=$0,col2.l=$aaaaaa, res=256)
  Protected.i suelo_tx3D, suelo_mate, suelo_mesh, suelo
    suelo_tx3D=   CreateTexture(#PB_Any,res,res)
    StartDrawing(TextureOutput(suelo_tx3D))
      Box(0,0,OutputWidth(),OutputHeight(),col1)
      Box(2,2,OutputWidth()-4,OutputHeight()-4,col2)
    StopDrawing()
    
    suelo_mesh=   CreatePlane(#PB_Any,size,size,1,1,1,1)
    suelo_mate=   CreateMaterial(#PB_Any,TextureID(suelo_tx3D))
                  ScaleMaterial(suelo_mate,1/size,1/size)
    suelo=        CreateEntity(#PB_Any, MeshID(suelo_mesh), MaterialID(suelo_mate))
  ProcedureReturn suelo
  EndProcedure
  
  ;{ DECORADO 3D
  creaSuelo()
  
  cubo_mesh=    CreateCube(#PB_Any,1)
  cubo_mate=    CreateMaterial(#PB_Any, #Null,$0000ff)
  cubo_enti=    CreateEntity(#PB_Any, MeshID(cubo_mesh), MaterialID(cubo_mate),0,1,0)
  
  ; el borde
  borde=    CreateMaterial(#PB_Any, #Null,$000000)
  MaterialCullingMode(borde,#PB_Material_AntiClockWiseCull)
  cuboBorde=    CreateEntity(#PB_Any, MeshID(cubo_mesh), MaterialID(borde),0,1,0)
  ScaleEntity(cuboBorde,1.1,1.1,1.1)
  ;}
  
  ;{ CÁMARA Y LUZ
  luz=          CreateLight(#PB_Any,$ffffff,30,50,0,#PB_Light_Point)
  
  
  camara=       CreateCamera(#PB_Any,0,0,100,100)
                MoveCamera(camara,3,5,7)
                CameraRange(camara, 0.1,1000)
                CameraLookAt(camara,0,0,0)
  ;}
                
  ;{ BUCLE PRINCIPAL
  Repeat
    ;{ PROCESO EVENTOS
    If pantallaCompleta= 0
      eventosWindows()
    EndIf
    ;}
    
    ExamineKeyboard()
    ExamineMouse()
    eventos3D(camara, 0.1)
    
    ElapsedTime = RenderWorld()
    
    ;{ HUD
    If contador % 25 = 0
      txt.s= "DEBUGGER"+ #CR$+
             "FPS: "+Str(Engine3DStatus(#PB_Engine3D_CurrentFPS)) +#CR$+
             Str(ScreenWidth())+" x "+Str(ScreenHeight()) +#CR$+
;              "X: "+StrF(CameraX(camara),2)+#CR$+"Y: "+StrF(CameraY(camara),2)+#CR$+"Z: "+StrF(CameraZ(camara),2); +#CR$+
;              "X: "+StrF(land\playX) +#CR$+
;              "Z: "+StrF(land\playZ) +#CR$+
;              "CAY: "+StrF(cya,2); +#CR$+
      spr2DText(sprInfo,txt, $ff00ffff)
    EndIf
    DisplayTransparentSprite(sprInfo,ScreenWidth()-110,10)
    ;}
    
    
    RotateEntity(cubo_enti,0,1,0,#PB_Relative)
    RotateEntity(cuboBorde,0,1,0,#PB_Relative)
    
    FlipBuffers()
    contador +1
    Delay(1)
  Until sal=1
  ;}
If translation=Error: reply="Sorry, Im Spanish": Endif
User avatar
minimy
Enthusiast
Enthusiast
Posts: 619
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Objetc border (outline) NO SHADERS

Post by minimy »

Another example improved with textures and lightning off for better effect, with more objects. (more cups later...) :mrgreen:

Code: Select all

;{ GLOBALES
  Global.b sal
  Global.l contador
  Global.b pantallaCompleta
;}

  ;{ FUENTES
  Global  fontLit= LoadFont(#PB_Any,"Arial",9)
  ;}
  
  ;{ SISTEMA 3D
  Procedure   spr2DText(spr, txt.s, ink.l=$ff00ffff)
    Protected n,y=2,tl= CountString(txt,#CR$)
    Protected tx.s
    StartDrawing(SpriteOutput(spr))
    DrawingMode(#PB_2DDrawing_AlphaChannel)
      Box(0,0,OutputWidth(),OutputHeight(),$00000000)
    DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Transparent)
      Box(0,0,OutputWidth(),OutputHeight(),$aa000000)
      DrawingFont(FontID(fontLit))
      For n=1 To tl+1
        tx= StringField(txt,n,#CR$)
        DrawText(5,y,tx,ink)
        y+16
      Next n
      DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Outlined)
      Box(0,0,OutputWidth(),OutputHeight(),ink)
    StopDrawing()
  EndProcedure
  Procedure   eventosWindows()
    Repeat
      event= WindowEvent()
      Select event
        Case #PB_Event_Gadget
          EventGadget=  EventGadget()
          EventType=    EventType()
          
        Case #PB_Event_CloseWindow
          sal= 1
      EndSelect
    Until event= 0
  EndProcedure
  Procedure   eventos3D(camara, speed.f=1, mouseSpd.f=0.05)
    Protected.f KeyX,KeyY, MouseX,MouseY
    If KeyboardPushed(#PB_Key_Escape)
      sal=1
    EndIf
    
    If KeyboardPushed(#PB_Key_C)
      SetClipboardText( StrD(CameraX(camara),2)+","+StrD(CameraY(camara),2)+","+StrD(CameraZ(camara),2) )
    EndIf
    
    If KeyboardPushed(#PB_Key_A)
      KeyX= -speed
    ElseIf KeyboardPushed(#PB_Key_D)
      KeyX= speed
    Else
      KeyX= 0
    EndIf
    
    If KeyboardPushed(#PB_Key_W)
      KeyY= -speed
    ElseIf KeyboardPushed(#PB_Key_S)
      KeyY= speed
    Else
      KeyY= 0
    EndIf
    
    If KeyboardPushed(#PB_Key_LeftShift)
      keyY * 10
      keyX * 10
    EndIf

    MouseX = -MouseDeltaX() * mouseSpd
    MouseY = -MouseDeltaY() * mouseSpd
    
    RotateCamera(camara, MouseY, MouseX, 0, #PB_Relative)
    MoveCamera (camara, KeyX, 0, KeyY)
  EndProcedure
  Procedure   iniDX(title.s="ToniEngine3D", width=800,height=600, fullscreen.b=#False, AA.i=#PB_AntialiasingMode_None, shadowmode= #PB_Shadow_Modulative, shadowres=4096, param=#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
    Protected.b screenTestOK
    InitEngine3D()
      InitSprite()
      InitKeyboard()
      InitMouse()
      AntialiasingMode(AA)
      
      If width=0 And height=0
        ExamineDesktops()
        width=  DesktopWidth(0)
        height= DesktopHeight(0)
        pantallaCompleta= 0
        param= #PB_Window_BorderLess
      EndIf
      
      If fullscreen
        pantallaCompleta= 1
        If ExamineScreenModes()
          While NextScreenMode()
;             Debug Str(ScreenModeWidth())+"x"+Str(ScreenModeHeight())+"x"+Str(ScreenModeDepth())+"@"+Str(ScreenModeRefreshRate())+"Hz"
            If ScreenModeWidth()=width And ScreenModeHeight()=height And ScreenModeDepth()=32
              screenTestOK= 1
            EndIf
          Wend
        EndIf
        If screenTestOK= 0
          width=1280:height=720
        EndIf
        OpenScreen(width,height,32,title,#PB_Screen_NoSynchronization)
      Else
        OpenWindow(0, 0, 0, width, height, title, param)
          SetWindowColor(0,$444444)
          OpenWindowedScreen(WindowID(0), 0, 0, (width * DesktopResolutionX()), (height * DesktopResolutionY()),0,0,0,#PB_Screen_NoSynchronization)
      EndIf
      KeyboardMode(#PB_Keyboard_International)
      Add3DArchive("Data/Textures", #PB_3DArchive_FileSystem)
      Add3DArchive("Data/Model", #PB_3DArchive_FileSystem)
      Parse3DScripts()

      Protected.b s= 100
      If shadowmode= #PB_Shadow_TextureAdditive Or shadowmode= #PB_Shadow_TextureModulative
        WorldShadows(shadowmode, -1, RGB(s,s,s), shadowres)
      Else  
        WorldShadows(shadowmode, -1, RGB(s,s,s))
    EndIf
  EndProcedure
  
  iniDX("Base 3D",960,540,#False,#PB_AntialiasingMode_None,#PB_Shadow_Additive, 256) ;modo ventana
  sprInfo=  CreateSprite(#PB_Any,100,200,#PB_Sprite_AlphaBlending)
  ;}
  
  Procedure   creaSuelo(size=50, col1.l=$0,col2.l=$aaaaaa, res=256)
  Protected.i suelo_tx3D, suelo_mate, suelo_mesh, suelo
    suelo_tx3D=   CreateTexture(#PB_Any,res,res)
    StartDrawing(TextureOutput(suelo_tx3D))
      Box(0,0,OutputWidth(),OutputHeight(),col1)
      Box(2,2,OutputWidth()-4,OutputHeight()-4,col2)
    StopDrawing()
    
    suelo_mesh=   CreatePlane(#PB_Any,size,size,1,1,1,1)
    suelo_mate=   CreateMaterial(#PB_Any,TextureID(suelo_tx3D))
                  ScaleMaterial(suelo_mate,1/size,1/size)
    suelo=        CreateEntity(#PB_Any, MeshID(suelo_mesh), MaterialID(suelo_mate))
  ProcedureReturn suelo
  EndProcedure
  
  ;{ DECORADO 3D
  creaSuelo()
  
  torus_mesh=   CreateTorus(#PB_Any,0.5,0.2)
  
  cubo_mesh=    CreateCube(#PB_Any,1)
  cubo_mate=    CreateMaterial(#PB_Any, #Null,$0000ff)
  
  cubo_enti=    CreateEntity(#PB_Any, MeshID(cubo_mesh), MaterialID(cubo_mate),0,1,0)
  torus_enti=   CreateEntity(#PB_Any, MeshID(torus_mesh), MaterialID(cubo_mate),3,1,0)
  
  ;borde
  borde_color=  $000000
  borde_tex=CreateTexture(#PB_Any,32,32) : StartDrawing(TextureOutput(borde_tex)) : Box(0,0,OutputWidth(),OutputHeight(),borde_color) : StopDrawing()
  borde=    CreateMaterial(#PB_Any, TextureID(borde_tex))
  MaterialCullingMode(borde,#PB_Material_AntiClockWiseCull)
  DisableMaterialLighting(borde,1)
  
  
  cuboBorde=    CreateEntity(#PB_Any, MeshID(cubo_mesh), MaterialID(borde),0,1,0)
  ScaleEntity(cuboBorde,1.1,1.1,1.1)
  
  torusBorde=    CreateEntity(#PB_Any, MeshID(torus_mesh), MaterialID(borde),3,1,0)
  ScaleEntity(torusBorde,1.1,1.1,1.1)
  
  
  ;}
  
  ;{ CÁMARA Y LUZ
  luz=          CreateLight(#PB_Any,$ffffff,30,50,0,#PB_Light_Point)
  
  
  camara=       CreateCamera(#PB_Any,0,0,100,100)
                MoveCamera(camara,4.47,1.04,2.93)
                CameraRange(camara, 0.1,1000)
                CameraLookAt(camara,1.5,1,0)
                CameraBackColor(camara,$440000)
  ;}
                
  ;{ BUCLE PRINCIPAL
  Repeat
    ;{ PROCESO EVENTOS
    If pantallaCompleta= 0
      eventosWindows()
    EndIf
    ;}
    
    ExamineKeyboard()
    ExamineMouse()
    eventos3D(camara, 0.1)
    
    ElapsedTime = RenderWorld()
    
    ;{ HUD
    If contador % 25 = 0
      txt.s= "DEBUGGER"+ #CR$+
             "FPS: "+Str(Engine3DStatus(#PB_Engine3D_CurrentFPS)) +#CR$+
             Str(ScreenWidth())+" x "+Str(ScreenHeight()) +#CR$+
      spr2DText(sprInfo,txt, $ff00ffff)
    EndIf
    DisplayTransparentSprite(sprInfo,ScreenWidth()-110,10)
    ;}
    
    
    RotateEntity(cubo_enti,0.5,1,0,#PB_Relative)
    RotateEntity(cuboBorde,0.5,1,0,#PB_Relative)
    
    RotateEntity(torus_enti,-0.5,1,0,#PB_Relative)
    RotateEntity(torusBorde,-0.5,1,0,#PB_Relative)
    
    FlipBuffers()
    contador +1
    Delay(1)
  Until sal=1
  ;}
If translation=Error: reply="Sorry, Im Spanish": Endif
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 386
Joined: Thu Jul 09, 2015 9:07 am

Re: Objetc border (outline) NO SHADERS

Post by pf shadoko »

good work

in the following example, instead of enlarging the entity, I use a shader to thicken it
otherwise I use the same method: create a 2nd entity with AntiClockWiseCull
note you can adjust the thickness and color of the border

Code: Select all

InitEngine3D():InitSprite():InitKeyboard():InitMouse()

ExamineDesktops()
OpenWindow(0, 0,0, DesktopWidth(0)*0.8,DesktopHeight(0)*0.8, "CreateShader - [Esc] quit",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0), WindowHeight(0), 0, 0, 0)

Add3DArchive(#PB_Compiler_Home + "Examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home+"Examples/3D/Data/Packs/Sinbad.zip", #PB_3DArchive_Zip)
Parse3DScripts()

CreateCamera(0, 0, 0, 100, 100):MoveCamera(0,0,3,15):CameraLookAt(0,0,0,0)
CreateLight(0,$ffffff, -10000, 10000, 0)
AmbientColor($111111*3)
CameraBackColor(0,$444488)

mesh=LoadMesh(#PB_Any, "Sinbad.mesh")
CreateEntity(0, MeshID(mesh), #PB_Material_None)

vert_pg.s="%%#version 130%%uniform mat4 P24;//+24%uniform vec4 P31;//+31%uniform float border;//0.1%%varying float ofogf;%%void main()%{%gl_Position=P24*(gl_Vertex+vec4(gl_Normal*border,0));%ofogf=P31.z>0?min(abs(gl_Position.z)*P31.w,1):0;%}%%%"
frag_pg.s="%%#version 130%%uniform vec4 P69;//+69 0%uniform vec4 P30;//+30%varying float ofogf;%%void main()%{%gl_FragColor=mix(P69,P30,ofogf);%}%%"
CreateShader(0,vert_pg,frag_pg)
CreateShaderMaterial(1,0)
MaterialCullingMode(1,#PB_Material_AntiClockWiseCull)

; border color:
SetMaterialColor(1,#PB_Material_DiffuseColor,$ff)
; border width:
MaterialShaderParameter(1,0,"border",1,0.05,0,0,0)

CreateEntity(1, MeshID(mesh), MaterialID(1))
AttachEntityObject(0,"",EntityID(1))

Define.f MouseX,Mousey,depx,depz,dist

Repeat
	While WindowEvent():Wend
	ExamineKeyboard()
	ExamineMouse()
	RotateEntity(0,0.2,0.2,0.2, #PB_Relative)
	RenderWorld()
	FlipBuffers()    
Until KeyboardReleased(#PB_Key_Escape) Or MouseButton(3)
User avatar
minimy
Enthusiast
Enthusiast
Posts: 619
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: Objetc border (outline) NO SHADERS

Post by minimy »

Hi pf_shadoko, I knew that if someone was able to do the shader, it must be your hehe. :D
You are a 3D master. The shader is more effective. The medal is for you! :lol:
Thank you so much for sharing it.
I'm curious to look forward to your new demo. Because all your demos are amazing.
If translation=Error: reply="Sorry, Im Spanish": Endif
Post Reply