/** * Copyright (c) 2021 Dominic Msters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "shader.h" void shaderInit(shader_t *shader, char *vertexShaderSource, char* fragmentShaderSource ) { int isSuccess, maxLength; char *error; GLuint shaderVertex, shaderFragment, shaderProgram; // Load the vertex shader first shaderVertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(shaderVertex, 1, &vertexShaderSource, 0); glCompileShader(shaderVertex); // Validate glGetShaderiv(shaderVertex, GL_COMPILE_STATUS, &isSuccess); if(!isSuccess) { glGetShaderiv(shaderVertex, GL_INFO_LOG_LENGTH, &maxLength); error = malloc(maxLength); glGetShaderInfoLog(shaderVertex, maxLength, &maxLength, error); printf("Failed to compile vertex shader %s\n", error); free(error); return; } // Now load the Frag shader shaderFragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(shaderFragment, 1, &fragmentShaderSource, 0); glCompileShader(shaderFragment); glGetShaderiv(shaderFragment, GL_COMPILE_STATUS, &isSuccess); if(!isSuccess) { glGetShaderiv(shaderFragment, GL_INFO_LOG_LENGTH, &maxLength); error = malloc(maxLength); glGetShaderInfoLog(shaderFragment, maxLength, &maxLength, error); printf("Failed to compile fragment shader %s\n", error); free(error); glDeleteShader(shaderVertex); return; } // Now create the shader program. shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, shaderVertex); glAttachShader(shaderProgram, shaderFragment); //Bind, Verify & Use the shader program glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &isSuccess); if(!isSuccess) { glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &maxLength); error = malloc(maxLength); glGetProgramInfoLog(shaderProgram, maxLength, &maxLength, error); printf("Failed to load shader program %s\n", error); free(error); glDeleteShader(shaderVertex); glDeleteShader(shaderFragment); return; } // Everything is okay, let's create the encapsulated shader. shader->shaderVertex = shaderVertex; shader->shaderFrag = shaderFragment; shader->shaderProgram = shaderProgram; shader->uniProj = glGetUniformLocation(shader->shaderProgram,SHADER_UNI_PROJ); shader->uniView = glGetUniformLocation(shader->shaderProgram,SHADER_UNI_VIEW); shader->uniText = glGetUniformLocation(shader->shaderProgram,SHADER_UNI_TEXT); shader->uniModl = glGetUniformLocation(shader->shaderProgram,SHADER_UNI_MODL); // Bind the shader shaderUse(shader); // Reset position shaderUsePosition(shader, 0, 0, 0, 0, 0, 0); } void shaderDispose(shader_t *shader) { glDeleteProgram(shader->shaderProgram); glDeleteShader(shader->shaderVertex); glDeleteShader(shader->shaderFrag); } void shaderUse(shader_t *shader) { glUseProgram(shader->shaderProgram); } void shaderUseCamera(shader_t *shader, camera_t *camera) { shaderUseMatrix(shader, shader->uniView, &camera->view); shaderUseMatrix(shader, shader->uniProj, &camera->projection); } void shaderUseTexture(shader_t *shader, texture_t *texture) { // OpenGL requires us to set the active texure. glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture->id); glUniform1i(shader->uniText, 0); } void shaderUseMatrix(shader_t *shader,shaderuniform_t uniform,matrix_t *matrix){ glUniformMatrix4fv(uniform, 1, GL_FALSE, matrix->internalMatrix[0]); } void shaderUsePosition(shader_t *shader, float x, float y, float z, float pitch, float yaw, float roll ) { matrix_t matrix; matrixIdentity(&matrix); matrixTranslate(&matrix, x, y, z); // Rotation (YZX order) matrixRotate(&matrix, yaw, 0, 1, 0); matrixRotate(&matrix, roll, 0, 0, 1); matrixRotate(&matrix, pitch, 1, 0, 0); shaderUseMatrix(shader, shader->uniModl, &matrix); } void shaderUsePositionAndScale(shader_t *shader, float x, float y, float z, float pitch, float yaw, float roll, float scaleX, float scaleY, float scaleZ ) { matrix_t matrix; matrixIdentity(&matrix); matrixTranslate(&matrix, x, y, z); // Rotation (YZX order) matrixRotate(&matrix, yaw, 0, 1, 0); matrixRotate(&matrix, roll, 0, 0, 1); matrixRotate(&matrix, pitch, 1, 0, 0); matrixScale(&matrix, scaleX, scaleY, scaleZ); shaderUseMatrix(shader, shader->uniModl, &matrix); }