; ------------------------------------------------------
; GLSL Shader Toon
; Copyright (c) 2005-2016, Franck Charlet
; All rights reserved.
; ------------------------------------------------------
; buildblock RELEASE
;       CAPT %5\Release.bat
; buildblockend
; buildblock DEBUG
;       CAPT %5\Debug.bat
; buildblockend

; ------------------------------------------------------
; Constants
SCREEN_WIDTH            equ     800
SCREEN_HEIGHT           equ     600
SCREEN_BPP              equ     32

; ------------------------------------------------------
; Includes
                        include ..\Common_Src\FrameWork.asm
                        include ..\Common_Src\BMP.asm
                        include ..\Common_Src\Textures.asm
                        include ..\Common_Src\GLSL.asm

; ------------------------------------------------------
; Variables
RotX                    real4   0.0
RotXSpeed               real4   40.0
RotY                    real4   0.0
RotYSpeed               real4   30.0
RotZ                    real4   0.0
RotZSpeed               real4   20.0

Texture1                BMP     <>
Texture1_Id             dd      0

GLSL_Object_Id          dd      0
PShader_Id              dd      0
VShader_Id              dd      0

pmodel                  LPGLMmaterial 0
Array                   GLMArray <>

Light_Direction         dd      -4.0, 4.0, 4.0

; ------------------------------------------------------
; Name: Initialize()
; Desc: Perform the various initializations
Initialize              proc

                        invoke  glClearDepth, CDBL(1.0)
                        invoke  glHint, GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST
                        invoke  glClearColor, 0, 0, 0, CFLT(1.0)
                        invoke  glEnable, GL_NORMALIZE
                        invoke  glEnable, GL_CULL_FACE
                        invoke  glEnable, GL_DEPTH_TEST

                        ; Init the context (needs opengl 2.0)
                        invoke  Init_GLSL_Context
                        .if     eax == FALSE
                                invoke  Set_Error_Msg, CSTR("The driver of this gfxcard doesn't handle GLSL")
                                mov     eax, FALSE
                                ret
                        .endif

                        ; -----------------------
                        ; Create the shaders container
                        invoke  Create_GLSL_Object
                        mov     GLSL_Object_Id, eax
                        .if     eax == FALSE
                                invoke  Set_Error_Msg, CSTR("Can't create GLSL container")
                                mov     eax, FALSE
                                ret
                        .endif

                        ; Load, compile and attach the pixel shader
                        invoke  Load_GLSL_Pixel_Shader, GLSL_Object_Id, CSTR("..\..\Media\ps_toon.glsl"), addr PShader_Id
                        .if     eax == FALSE
                                invoke  Get_GLSL_Error, PShader_Id
                                invoke  Set_Error_Msg, eax
                                mov     eax, FALSE
                                ret
                        .endif

                        ; Load, compile and attach the vertex shader
                        invoke  Load_GLSL_Vertex_Shader, GLSL_Object_Id, CSTR("..\..\Media\vx_toon.glsl"), addr VShader_Id
                        .if     eax == FALSE
                                invoke  Get_GLSL_Error, VShader_Id
                                invoke  Set_Error_Msg, eax
                                mov     eax, FALSE
                                ret
                        .endif

                        ; Link the shaders together in the container
                        invoke  Link_GLSL_Object, GLSL_Object_Id
                        .if     eax == FALSE
                                invoke  Get_GLSL_Error, GLSL_Object_Id
                                invoke  Set_Error_Msg, eax
                                mov     eax, FALSE
                                ret
                        .endif
                        ; -----------------------

                        invoke  Load_BMP, CSTR("..\..\Media\band.bmp"), addr Texture1, -1
                        .if     eax == FALSE
                                invoke  Set_Error_Msg, CSTR("Can't load texture file")
                                mov     eax, FALSE
                                ret
                        .endif
                        
                        invoke  Init_Textures_Context
                        
                        invoke  Create_2D_Texture, Texture1.Datas, Texture1._Width, TRUE, GL_RGBA, GL_RGBA
                        mov     Texture1_Id, eax
                        .if     eax == FALSE
                                invoke  Set_Error_Msg, CSTR("Can't create texture")
                                mov     eax, FALSE
                                ret
                        .endif

                        ; ----------------------------------
                        ; Object is coming from: http://modelsbank.3dm3.com
                        ; Converted from 3ds with PoseRay (http://mysite.verizon.net/sfg0000/)
                        invoke  glmReadOBJ, CSTR("..\..\Media\tie-fighter.obj")
                        mov     pmodel, eax
                        .if     eax == FALSE
                                invoke  Set_Error_Msg, CSTR("Can't load model file")
                                mov     eax, FALSE
                                ret
                        .endif
                        
                        ; Prepare it for rendering
                        invoke  glmUnitize, pmodel
                        invoke  glmFacetNormals, pmodel
                        invoke  glmVertexNormals, pmodel, CFLT(90.0)
                        invoke  glmCreateVertexArray, pmodel, GLM_SMOOTH or GLM_MATERIAL, addr Array

                        mov     eax, TRUE
                        ret
Initialize              endp

; ------------------------------------------------------
; Name: Deinitialize()
; Desc: Free allocated resources
Deinitialize            proc
                        invoke  glmDestroyVertexArray, addr Array
                        invoke  glmDelete, pmodel

                        invoke  Destroy_Texture, Texture1_Id
                        invoke  Unload_BMP, addr Texture1
                        invoke  Destroy_GLSL_Object, GLSL_Object_Id
                        ret
Deinitialize            endp

; ------------------------------------------------------
; Name: Update()
; Desc: Update the scene
Update                  proc    FrameRate:real4

                        ; Update scene here

                        fld     RotXSpeed
                        fmul    FrameRate
                        fadd    RotX
                        fstp    RotX

                        fld     RotYSpeed
                        fmul    FrameRate
                        fadd    RotY
                        fstp    RotY

                        fld     RotZSpeed
                        fmul    FrameRate
                        fadd    RotZ
                        fstp    RotZ

                        invoke  DInput_Get_Key, DIK_ESCAPE
                        test    eax, eax
                        jz      Esc_Pressed
                        invoke  Terminate_Application
Esc_Pressed:            ret
Update                  endp

; ------------------------------------------------------
; Name: Draw()
; Desc: Draw the scene
Draw                    proc
                        invoke  glClear, GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT

                        ; Draw scene here
                        invoke  glPushMatrix
                                invoke  glTranslatef, CFLT(0.0), CFLT(0.0), CFLT(-4.0)
                                invoke  glRotatef, RotX, CFLT(0.0), CFLT(1.0), CFLT(0.0)
                                invoke  glRotatef, RotY, CFLT(1.0), CFLT(0.0), CFLT(0.0)
                                invoke  glRotatef, RotZ, CFLT(0.0), CFLT(0.0), CFLT(1.0)

                                invoke  glEnable, GL_TEXTURE_2D
                                invoke  glBindTexture, GL_TEXTURE_2D, Texture1_Id
                                invoke  glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
                                invoke  glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
                                invoke  glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE
                                invoke  glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE
                                
                                ; Use these shaders to render the object
                                invoke  Enable_GLSL_Object, GLSL_Object_Id

                                ; Update the parameters
                                invoke  Set_GLSL_Float_Var_3, GLSL_Object_Id, CSTR("light_direction"), 1, addr Light_Direction

                                lea     esi, Array

                                invoke  glEnable, GL_COLOR_MATERIAL
                                invoke  glEnable, GL_VERTEX_ARRAY
                                invoke  glEnable, GL_TEXTURE_COORD_ARRAY
                                invoke  glEnable, GL_NORMAL_ARRAY
                                invoke  glEnable, GL_COLOR_ARRAY

                                invoke  glVertexPointer, 3, GL_FLOAT, 0, [esi + GLMArray.Triangles]
                                invoke  glColorPointer, 3, GL_FLOAT, 0, [esi + GLMArray.Colors]
                                invoke  glTexCoordPointer, 2, GL_FLOAT, 0, [esi + GLMArray.Textures]
                                invoke  glNormalPointer, GL_FLOAT, 0, [esi + GLMArray.Normals]
                                invoke  glDrawArrays, GL_TRIANGLES, 0, [esi + GLMArray.Nbr_Triangles]

                                invoke  glDisable, GL_COLOR_ARRAY
                                invoke  glDisable, GL_NORMAL_ARRAY
                                invoke  glDisable, GL_TEXTURE_COORD_ARRAY
                                invoke  glDisable, GL_VERTEX_ARRAY
                                invoke  glDisable, GL_COLOR_MATERIAL

                                invoke  glDisable, GL_TEXTURE_2D

                                ; Stop rendering with the shaders
                                invoke  Disable_GLSL_Object

                        invoke  glPopMatrix
                        ret
Draw                    endp

end start
