shader.nim 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import
  2. pure/os,
  3. tri_engine/gfx/gl/gl
  4. type
  5. TShader* = object
  6. id*: GL_handle
  7. TShaderType* {.pure.} = enum
  8. frag = GL_FRAGMENT_SHADER,
  9. vert = GL_VERTEX_SHADER
  10. E_Shader* = object of Exception
  11. E_UnknownShaderType* = object of E_Shader
  12. converter pathToShaderType*(s: string): TShaderType =
  13. case s.splitFile().ext:
  14. of ".vs":
  15. return TShaderType.vert
  16. of ".fs":
  17. return TShaderType.frag
  18. else:
  19. raise newException(E_UnknownShaderType, "Can't determine shader type from file extension: " & s)
  20. proc setSrc*(shader: TShader, src: string) =
  21. var s = src.cstring
  22. ?glShaderSource(shader.id, 1, cast[cstringarray](s.addr), nil)
  23. proc newShader*(id: GL_handle): TShader =
  24. if id.int != 0 and not (?glIsShader(id)).bool:
  25. raise newException(E_GL, "Invalid shader ID: " & $id)
  26. result.id = id
  27. proc shaderInfoLog*(o: TShader): string =
  28. var log {.global.}: array[0..1024, char]
  29. var logLen: GLsizei
  30. ?glGetShaderInfoLog(o.id.GLuint, log.len.GLsizei, addr logLen, cast[cstring](log.addr))
  31. cast[string](log.addr).substr(0, logLen)
  32. proc compile*(shader: TShader, path="") =
  33. ?glCompileShader(shader.id)
  34. var compileStatus = 0.GLint
  35. ?glGetShaderIv(shader.id, GL_COMPILE_STATUS, compileStatus.addr)
  36. if compileStatus == 0:
  37. raise newException(E_GL, if path.len == 0:
  38. shaderInfoLog(shader)
  39. else:
  40. path & ":\n" & shaderInfoLog(shader)
  41. )
  42. proc newShaderFromSrc*(src: string, `type`: TShaderType): TShader =
  43. result.id = ?glCreateShader(`type`.GLenum)
  44. result.setSrc(src)
  45. result.compile()
  46. proc newShaderFromFile*(path: string): TShader =
  47. newShaderFromSrc(readFile(path), path)
  48. type
  49. TProgram* = object
  50. id*: GL_handle
  51. shaders: seq[TShader]
  52. proc attach*(o: TProgram, shader: TShader) =
  53. ?glAttachShader(o.id, shader.id)
  54. proc infoLog*(o: TProgram): string =
  55. var log {.global.}: array[0..1024, char]
  56. var logLen: GLsizei
  57. ?glGetProgramInfoLog(o.id.GLuint, log.len.GLsizei, addr logLen, cast[cstring](log.addr))
  58. cast[string](log.addr).substr(0, logLen)
  59. proc link*(o: TProgram) =
  60. ?glLinkProgram(o.id)
  61. var linkStatus = 0.GLint
  62. ?glGetProgramIv(o.id, GL_LINK_STATUS, linkStatus.addr)
  63. if linkStatus == 0:
  64. raise newException(E_GL, o.infoLog())
  65. proc validate*(o: TProgram) =
  66. ?glValidateProgram(o.id)
  67. var validateStatus = 0.GLint
  68. ?glGetProgramIv(o.id, GL_VALIDATE_STATUS, validateStatus.addr)
  69. if validateStatus == 0:
  70. raise newException(E_GL, o.infoLog())
  71. proc newProgram*(shaders: seq[TShader]): TProgram =
  72. result.id = ?glCreateProgram()
  73. if result.id.int == 0:
  74. return
  75. for shader in shaders:
  76. if shader.id.int == 0:
  77. return
  78. ?result.attach(shader)
  79. result.shaders = shaders
  80. result.link()
  81. result.validate()
  82. proc use*(o: TProgram) =
  83. ?glUseProgram(o.id)