Dawn/src/display/shader.c

163 lines
4.8 KiB
C

/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "shader.h"
void shaderCompile(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 NULL;
}
// 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 NULL;
}
// 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 NULL;
}
// 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);
// Fetch the uniforms.
return shader;
}
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) {
glUniformMatrix4fv(shader->uniView, 1, GL_FALSE, camera->view[0]);
glUniformMatrix4fv(shader->uniProj, 1, GL_FALSE, camera->projection[0]);
}
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 shaderUsePosition(shader_t *shader,
float x, float y, float z,
float pitch, float yaw, float roll
) {
mat4 MATRIX_POSITION;
vec3 axis;
// Identify mat.
glm_mat4_identity(MATRIX_POSITION);
//Position
axis[0] = x, axis[1] = y, axis[2] = z;
glm_translate_make(MATRIX_POSITION, axis);
// Rotation (YZX order)
axis[0] = 0, axis[1] = 1, axis[2] = 0;
glm_rotate(MATRIX_POSITION, yaw, axis);
axis[1] = 0, axis[2] = 1;
glm_rotate(MATRIX_POSITION, roll, axis);
axis[0] = 1, axis[2] = 0;
glm_rotate(MATRIX_POSITION, pitch, axis);
//Send to the shader.
glUniformMatrix4fv(shader->uniModl, 1, GL_FALSE, MATRIX_POSITION[0]);
}
void shaderUsePositionAndScale(shader_t *shader,
float x, float y, float z,
float pitch, float yaw, float roll,
float scaleX, float scaleY, float scaleZ
) {
mat4 MATRIX_POSITION;
vec3 axis;
// Identify mat.
glm_mat4_identity(MATRIX_POSITION);
//Position
axis[0] = x, axis[1] = y, axis[2] = z;
glm_translate_make(MATRIX_POSITION, axis);
// Rotation (YZX order)
axis[0] = 0, axis[1] = 1, axis[2] = 0;
glm_rotate(MATRIX_POSITION, yaw, axis);
axis[1] = 0, axis[2] = 1;
glm_rotate(MATRIX_POSITION, roll, axis);
axis[0] = 1, axis[2] = 0;
glm_rotate(MATRIX_POSITION, pitch, axis);
// Scale
axis[0] = scaleX, axis[1] = scaleY, axis[2] = scaleZ;
glm_scale(MATRIX_POSITION, axis);
glUniformMatrix4fv(shader->uniModl, 1, GL_FALSE, MATRIX_POSITION[0]);
}