Shader.java 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package me.hammerle.snuviengine.api;
  2. import java.io.IOException;
  3. import java.net.URL;
  4. import java.util.ArrayList;
  5. import java.util.Scanner;
  6. import static org.lwjgl.opengl.GL11.GL_NO_ERROR;
  7. import static org.lwjgl.opengl.GL11.glGetError;
  8. import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
  9. import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER;
  10. import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
  11. import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER;
  12. import static org.lwjgl.opengl.GL20.glAttachShader;
  13. import static org.lwjgl.opengl.GL20.glCompileShader;
  14. import static org.lwjgl.opengl.GL20.glCreateProgram;
  15. import static org.lwjgl.opengl.GL20.glCreateShader;
  16. import static org.lwjgl.opengl.GL20.glDeleteShader;
  17. import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
  18. import static org.lwjgl.opengl.GL20.glGetProgrami;
  19. import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
  20. import static org.lwjgl.opengl.GL20.glGetShaderi;
  21. import static org.lwjgl.opengl.GL20.glLinkProgram;
  22. import static org.lwjgl.opengl.GL20.glShaderSource;
  23. public class Shader {
  24. public static int createShaderProgram(String vertex, String fragment) {
  25. int vertexShader = readAndCompileShader(vertex, GL_VERTEX_SHADER);
  26. if(vertexShader == -1) {
  27. return -1;
  28. }
  29. int fragmentShader = readAndCompileShader(fragment, GL_FRAGMENT_SHADER);
  30. if(fragmentShader == -1) {
  31. return -1;
  32. }
  33. return createShaderProgram(vertexShader, fragmentShader);
  34. }
  35. private static int readAndCompileShader(String file, int shaderType) {
  36. String[] shaderSource = readFile(file);
  37. if(shaderSource == null) {
  38. return -1;
  39. }
  40. return compileShader(file, shaderSource, shaderType);
  41. }
  42. private static String[] readFile(String name) {
  43. URL url = Renderer.class.getClassLoader().getResource("me/hammerle/snuviengine/shader/" + name);
  44. if(url == null) {
  45. printError("failed reading shader '%s'", name);
  46. return null;
  47. }
  48. return readUrl(url);
  49. }
  50. private static String[] readUrl(URL url) {
  51. try(Scanner scanner = new Scanner(url.openStream())) {
  52. return readScanner(scanner);
  53. } catch(IOException ex) {
  54. printError("failed reading shader '%s'", url);
  55. return null;
  56. }
  57. }
  58. private static String[] readScanner(Scanner scanner) {
  59. ArrayList<String> strings = new ArrayList<>();
  60. while(scanner.hasNext()) {
  61. strings.add(scanner.nextLine() + "\n");
  62. }
  63. return strings.toArray(new String[strings.size()]);
  64. }
  65. private static int compileShader(String name, String[] shaderSource, int shaderType) {
  66. int shader = glCreateShader(shaderType);
  67. glShaderSource(shader, shaderSource);
  68. glCompileShader(shader);
  69. if(checkForShaderError(name, shader)) {
  70. return -1;
  71. }
  72. return shader;
  73. }
  74. private static boolean checkForShaderError(String name, int shader) {
  75. int error = glGetError();
  76. if(error != GL_NO_ERROR) {
  77. printError("failed compiling shader '%s' with error code: %d", name, error);
  78. return true;
  79. }
  80. int compiled = glGetShaderi(shader, GL_COMPILE_STATUS);
  81. if(compiled != 1) {
  82. printError("failed compiling shader '%s': %s", name, glGetShaderInfoLog(shader));
  83. return true;
  84. }
  85. return false;
  86. }
  87. private static void printError(String format, Object... o) {
  88. System.out.println(String.format(format, o));
  89. }
  90. private static int createShaderProgram(int vertexShader, int fragmentShader) {
  91. int program = glCreateProgram();
  92. glAttachShader(program, vertexShader);
  93. glAttachShader(program, fragmentShader);
  94. glLinkProgram(program);
  95. if(checkForLinkingError(program)) {
  96. return -1;
  97. }
  98. return program;
  99. }
  100. private static boolean checkForLinkingError(int program) {
  101. int error = glGetError();
  102. if(error != GL_NO_ERROR) {
  103. printError("failed linking shaders with error code: %d", error);
  104. return true;
  105. }
  106. int compiled = glGetProgrami(program, GL_LINK_STATUS);
  107. if(compiled != 1) {
  108. printError("failed linking shaders: %s", glGetProgramInfoLog(program));
  109. return true;
  110. }
  111. return false;
  112. }
  113. }