ifndef                  _SHADERS_ASM
_SHADERS_ASM            equ     1

; ------------------------------------------------------
; Structure
SHADER_ARG              struct
Arg1                    real4   ?
Arg2                    real4   ?
Arg3                    real4   ?
Arg4                    real4   ?
SHADER_ARG              ends

; ------------------------------------------------------
; Includes
                        include Extensions.asm
                        include Files.asm

; ------------------------------------------------------
; Variables
glGenProgramsARB        PFNGLGENPROGRAMSARBPROC 0
glBindProgramARB        PFNGLBINDPROGRAMARBPROC 0
glProgramStringARB      PFNGLPROGRAMSTRINGARBPROC 0
glProgramLocalParameter4fARB PFNGLPROGRAMLOCALPARAMETER4FARBPROC 0
glProgramLocalParameter4fvARB PFNGLPROGRAMLOCALPARAMETER4FVARBPROC 0
glDeleteProgramsARB     PFNGLDELETEPROGRAMSARBPROC 0
glGetUniformLocationARB PFNGLGETUNIFORMLOCATIONARBPROC 0

_Shader_Err_Format      db      "%s:",13,10,"%s", 0

                        .data?
_Shader_Err_String      db      2048 dup (?)
_Shader_Name            db      MAX_PATH dup (?)

                        .code

; ------------------------------------------------------
; Name: Init_Shaders_Context
; Desc: Obtain shaders interaction procedures
Init_Shaders_Context    proc
                        invoke  wglGetProcAddress, CSTR("glGenProgramsARB")
                        mov     glGenProgramsARB, eax
                        invoke  wglGetProcAddress, CSTR("glBindProgramARB")
                        mov     glBindProgramARB, eax
                        invoke  wglGetProcAddress, CSTR("glProgramStringARB")
                        mov     glProgramStringARB, eax
                        invoke  wglGetProcAddress, CSTR("glProgramLocalParameter4fARB")
                        mov     glProgramLocalParameter4fARB, eax
                        invoke  wglGetProcAddress, CSTR("glProgramLocalParameter4fvARB")
                        mov     glProgramLocalParameter4fvARB, eax
                        invoke  wglGetProcAddress, CSTR("glDeleteProgramsARB")
                        mov     glDeleteProgramsARB, eax
                        .if     glGenProgramsARB != NULL && glBindProgramARB != NULL && glProgramStringARB != NULL && \
                                glProgramLocalParameter4fARB != NULL && glProgramLocalParameter4fvARB != NULL && \
                                glDeleteProgramsARB != NULL
                                mov     eax, TRUE
                                ret
                        .endif
                        mov     eax, FALSE
                        ret
Init_Shaders_Context    endp

; ------------------------------------------------------
; Name: Destroy_Shader
; Desc: Remove a shader from memory
Destroy_Shader          proc    ShaderID:dword
                        .if     ShaderID != NULL
                                invoke  glDeleteProgramsARB, 1, addr ShaderID
                        .endif
                        ret
Destroy_Shader          endp

; ------------------------------------------------------
; Name: Get_Shader_Error
; Desc: Report any assembling error
Get_Shader_Error        proc    uses ebx
                        invoke  glGetString, GL_PROGRAM_ERROR_STRING_ARB
                        mov     ebx, eax
                        invoke  lstrlen, eax
                        .if     eax == 0
                                push    offset _Shader_Name
                                push    CSTR("Can't open shader file: %s")
                                push    offset _Shader_Err_String
                                invoke  sprintf
                                add     esp, 3 * 4
                                mov     eax, offset _Shader_Err_String
                        .else
                                push    ebx
                                push    offset _Shader_Name
                                push    offset _Shader_Err_Format
                                push    offset _Shader_Err_String
                                invoke  sprintf
                                add     esp, 4 * 4
                                mov     eax, offset _Shader_Err_String
                        .endif
                        ret
Get_Shader_Error        endp

; ------------------------------------------------------
; Name: Load_Pixel_Shader
; Desc: Create a pixel shader
Load_Pixel_Shader       proc    ShaderFileName:dword, ShaderID:dword
                        local   Shader_Len:dword
                        local   Shader_Mem:dword

                        invoke  glEnable, GL_FRAGMENT_PROGRAM_ARB
                        invoke  glGenProgramsARB, 1, ShaderID
                        mov     eax, [ShaderID]
                        .if     dword ptr [eax] != 0
                                invoke  glBindProgramARB, GL_FRAGMENT_PROGRAM_ARB, dword ptr [eax]
                                invoke  Load_File, ShaderFileName, addr Shader_Len
                                mov     Shader_Mem, eax
                                .if     eax == NULL
                                        mov     eax, [ShaderID]
                                        invoke  Destroy_Shader, dword ptr [eax]
                                        invoke  glDisable, GL_FRAGMENT_PROGRAM_ARB
                                        xor     eax, eax
                                        ret
                                .endif
                                invoke  glProgramStringARB, GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, Shader_Len, Shader_Mem
                                invoke  glGetError
                                push    eax
                                push    ShaderFileName
                                push    CSTR("%s")
                                push    offset _Shader_Name
                                invoke  sprintf
                                add     esp, 3 * 4
                                invoke  Free_File, Shader_Mem
                                pop     eax
                                .if     eax != GL_NO_ERROR
                                        mov     eax, [ShaderID]
                                        invoke  Destroy_Shader, dword ptr [eax]
                                        invoke  glDisable, GL_FRAGMENT_PROGRAM_ARB
                                        xor     eax, eax
                                        ret
                                .endif
                        .endif
                        invoke  glDisable, GL_FRAGMENT_PROGRAM_ARB
                        mov     eax, TRUE
                        ret
Load_Pixel_Shader       endp

; ------------------------------------------------------
; Name: Load_Vertex_Shader
; Desc: Create a vertex shader
Load_Vertex_Shader      proc    ShaderFileName:dword, ShaderID:dword
                        local   Shader_Len:dword
                        local   Shader_Mem:dword

                        invoke  glEnable, GL_VERTEX_PROGRAM_ARB
                        invoke  glGenProgramsARB, 1, ShaderID
                        mov     eax, [ShaderID]
                        .if     dword ptr [eax] != 0
                                invoke  glBindProgramARB, GL_VERTEX_PROGRAM_ARB, dword ptr [eax]
                                invoke  Load_File, ShaderFileName, addr Shader_Len
                                mov     Shader_Mem, eax
                                .if     eax == NULL
                                        mov     eax, [ShaderID]
                                        invoke  Destroy_Shader, dword ptr [eax]
                                        invoke  glDisable, GL_VERTEX_PROGRAM_ARB
                                        xor     eax, eax
                                        ret
                                .endif
                                invoke  glProgramStringARB, GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, Shader_Len, Shader_Mem
                                invoke  glGetError
                                push    eax
                                push    ShaderFileName
                                push    CSTR("%s")
                                push    offset _Shader_Name
                                invoke  sprintf
                                add     esp, 3 * 4
                                invoke  Free_File, Shader_Mem
                                pop     eax
                                .if     eax != GL_NO_ERROR
                                        mov     eax, [ShaderID]
                                        invoke  Destroy_Shader, dword ptr [eax]
                                        invoke  glDisable, GL_VERTEX_PROGRAM_ARB
                                        xor     eax, eax
                                        ret
                                .endif
                        .endif
                        invoke  glDisable, GL_VERTEX_PROGRAM_ARB
                        mov     eax, TRUE
                        ret
Load_Vertex_Shader      endp

; ------------------------------------------------------
; Name: Set_Pixel_Shader_Param
; Desc: Send a parameter to a pixel shader
Set_Pixel_Shader_Param  proc    ParamNbr:dword, Arg:dword
                        invoke  glProgramLocalParameter4fvARB, GL_FRAGMENT_PROGRAM_ARB, ParamNbr, Arg
                        ret
Set_Pixel_Shader_Param  endp

; ------------------------------------------------------
; Name: Set_Vertex_Shader_Param
; Desc: Send a parameter to a vertex shader
Set_Vertex_Shader_Param proc    ParamNbr:dword, Arg:dword
                        invoke  glProgramLocalParameter4fvARB, GL_VERTEX_PROGRAM_ARB, ParamNbr, Arg
                        ret
Set_Vertex_Shader_Param endp

; ------------------------------------------------------
; Name: Enable_Pixel_Shader
; Desc: Enable rendering with a pixel shader
Enable_Pixel_Shader     proc    ShaderID:dword
                        invoke  glBindProgramARB, GL_FRAGMENT_PROGRAM_ARB, ShaderID
                        invoke  glEnable, GL_FRAGMENT_PROGRAM_ARB
                        ret
Enable_Pixel_Shader     endp

; ------------------------------------------------------
; Name: Enable_Vertex_Shader
; Desc: Enable rendering with a vertex shader
Enable_Vertex_Shader    proc    ShaderID:dword
                        invoke  glBindProgramARB, GL_VERTEX_PROGRAM_ARB, ShaderID
                        invoke  glEnable, GL_VERTEX_PROGRAM_ARB
                        ret
Enable_Vertex_Shader    endp

; ------------------------------------------------------
; Name: Disable_Pixel_Shader
; Desc: Disable pixel shader rendering
Disable_Pixel_Shader    proc
                        invoke  glDisable, GL_FRAGMENT_PROGRAM_ARB
                        ret
Disable_Pixel_Shader    endp

; ------------------------------------------------------
; Name: Disable_Vertex_Shader
; Desc: Disable vertex shader rendering
Disable_Vertex_Shader   proc
                        invoke  glDisable, GL_VERTEX_PROGRAM_ARB
                        ret
Disable_Vertex_Shader   endp

; ------------------------------------------------------
; Name: Set_GLSL_Uniform_Var
; Desc: Set the value of an uniform variable
Set_GLSL_Uniform_Var    proc    ShaderID:dword, VarName:dword
                        invoke  glDisable, GL_VERTEX_PROGRAM_ARB
                        ret
Set_GLSL_Uniform_Var    endp

endif
