186 lines
5.3 KiB
C
186 lines
5.3 KiB
C
/**
|
|
* 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
|
|
) {
|
|
int32_t isSuccess, maxLength, i, texture;
|
|
char *error;
|
|
GLuint shaderVertex, shaderFragment, shaderProgram;
|
|
GLint size; // size of the variable
|
|
GLsizei length; // name length
|
|
|
|
GLchar const* filesVertex[] = { vertexShaderSource };
|
|
GLchar const* filesFragment[] = { fragmentShaderSource };
|
|
|
|
// Load the vertex shader first
|
|
shaderVertex = glCreateShader(GL_VERTEX_SHADER);
|
|
glShaderSource(shaderVertex, 1, filesVertex, 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, filesFragment, 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;
|
|
|
|
// Extract uniforms
|
|
glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &shader->uniformCount);
|
|
|
|
texture = 0;
|
|
for(i = 0; i < shader->uniformCount; i++) {
|
|
shader->uniformNames[i] = (
|
|
shader->uniformBuffer + (i * SHADER_UNIFORM_NAME_MAX)
|
|
);
|
|
|
|
glGetActiveUniform(
|
|
shaderProgram, (GLuint)i, SHADER_UNIFORM_NAME_MAX,
|
|
&length, &size, shader->types + i, shader->uniformNames[i]
|
|
);
|
|
|
|
// TODO: Reset uniforms to zero.
|
|
if(shader->types[i] == GL_SAMPLER_2D) shader->textureSlots[i] = texture++;
|
|
}
|
|
|
|
// Bind the shader
|
|
shaderUse(shader);
|
|
}
|
|
|
|
shaderuniform_t shaderGetUniform(shader_t *shader, char *name) {
|
|
int32_t i;
|
|
for(i = 0; i < shader->uniformCount; i++) {
|
|
if(strcmp(shader->uniformNames[i], name) == 0) return i;
|
|
}
|
|
return (shaderuniform_t)-1;
|
|
}
|
|
|
|
void shaderDispose(shader_t *shader) {
|
|
glDeleteProgram(shader->shaderProgram);
|
|
glDeleteShader(shader->shaderVertex);
|
|
glDeleteShader(shader->shaderFrag);
|
|
}
|
|
|
|
void shaderUse(shader_t *shader) {
|
|
glUseProgram(shader->shaderProgram);
|
|
}
|
|
|
|
void shaderUseTexture(
|
|
shader_t *shader, shaderuniform_t uniform, texture_t *texture
|
|
) {
|
|
int32_t i = shader->textureSlots[(int32_t)uniform];
|
|
// TODO: I need to be able to get the texture ID
|
|
glActiveTexture(GL_TEXTURE0 + i);
|
|
glBindTexture(GL_TEXTURE_2D, texture->id);
|
|
glUniform1i(uniform, i);
|
|
}
|
|
|
|
void shaderUseMatrix(
|
|
shader_t *shader, shaderuniform_t uniform, matrix_t *matrix
|
|
) {
|
|
glUniformMatrix4fv(uniform, 1, GL_FALSE, matrix->internalMatrix[0]);
|
|
}
|
|
|
|
void shaderUseColor(shader_t *shader, shaderuniform_t uniform, pixel_t color) {
|
|
glUniform4f(uniform,
|
|
(float)color.r / 255.0f,
|
|
(float)color.g / 255.0f,
|
|
(float)color.b / 255.0f,
|
|
(float)color.a / 255.0f
|
|
);
|
|
}
|
|
|
|
void shaderUsePosition(
|
|
shader_t *shader, shaderuniform_t uniform,
|
|
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, uniform, &matrix);
|
|
}
|
|
|
|
void shaderUsePositionAndScale(
|
|
shader_t *shader, shaderuniform_t uniform,
|
|
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, uniform, &matrix);
|
|
}
|
|
|
|
void shaderUseCamera(
|
|
shader_t *shader,
|
|
shaderuniform_t uniformView, shaderuniform_t uniformProjection,
|
|
camera_t *camera
|
|
) {
|
|
shaderUseMatrix(shader, uniformView, &camera->view);
|
|
shaderUseMatrix(shader, uniformProjection, &camera->projection);
|
|
} |