Reshuffled

This commit is contained in:
2021-04-19 21:30:34 +10:00
parent cc94f7c775
commit ff8b84b542
45 changed files with 218 additions and 140 deletions

53
src/display/camera.c Normal file
View File

@ -0,0 +1,53 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "camera.h"
camera_t * cameraCreate() {
camera_t *camera = malloc(sizeof(camera_t));
if(!camera) return NULL;
return camera;
}
void cameraDispose(camera_t *camera) {
free(camera);
}
void cameraLookAt(camera_t *camera,
float x, float y, float z, float targetX, float targetY, float targetZ
) {
glm_lookat(
(vec3){ x, y, z },
(vec3){ targetX, targetY, targetZ },
(vec3){ 0, 1, 0 },
camera->view
);
}
void cameraLook(camera_t *camera,
float x, float y, float z,
float pitch, float yaw, float roll
) {
glm_look(
(vec3){ x, y, z },
(vec3){ pitch, yaw, roll },
(vec3){ 0, 1, 0 },
camera->view
);
}
void cameraPerspective(camera_t *camera,
float fov, float aspect, float near, float far
) {
glm_perspective(fov, aspect, near, far, camera->projection);
}
void cameraOrtho(camera_t *camera,
float left, float right, float bottom, float top, float near, float far
) {
glm_ortho(left, right, bottom, top, near, far, camera->projection);
}

90
src/display/camera.h Normal file
View File

@ -0,0 +1,90 @@
// Copyright (c) 2021 Dominic Msters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <cglm/cglm.h>
#include <malloc.h>
/** The math for the camera is stored here. */
typedef struct {
/** View Matrix (Where the camera looks) */
mat4 view;
/** Projection Matrix (How the camera looks) */
mat4 projection;
} camera_t;
/**
* Create a new camera instance.
*
* @return A new camera instance.
*/
camera_t * cameraCreate();
/**
* Cleanup a previously created camera
*
* @param camera Camera instance to dispose.
*/
void cameraDispose(camera_t *camera);
/**
* Make a camera look at a position in world space while itself being positioned
* within world space.
*
* @param camera The camera to position.
* @param x The X position in world space of the camera.
* @param y The Y position in world space of the camera.
* @param z The Z position in world space of the camera.
* @param targetX The Target X position in world space of the camera.
* @param targetY The Target Y position in world space of the camera.
* @param targetZ The Target Z position in world space of the camera.
*/
void cameraLookAt(camera_t *camera,
float x, float y, float z, float targetX, float targetY, float targetZ
);
/**
* Make a camera look in a direction based on a rotation direction.
*
* @param camera The camera to position.
* @param x The X position in world space of the camera.
* @param y The Y position in world space of the camera.
* @param z The Z position in world space of the camera.
* @param pitch The pitch of the camera.
* @param yaw The yaw of the camera.
* @param roll The roll of the camera.
*/
void cameraLook(camera_t *camera,
float x, float y, float z,
float pitch, float yaw, float roll
);
/**
* Make a camera's projection be a 3D Perspective view.
*
* @param camera The camera to project.
* @param fov The field of view of the camera.
* @param aspect The aspect ratio of the camera (w / h)
* @param near The near plane clip.
* @param far the far plane clip.
*/
void cameraPerspective(camera_t *camera,
float fov, float aspect, float near, float far
);
/**
* Defines an orthorgonal camera matrix.
*
* @param camera Camera to position.
* @param left The left side of the viewport.
* @param right The right side of the viewport.
* @param bottom The bottom side of the viewport.
* @param near The near plane clip.
* @param far the far plane clip.
*/
void cameraOrtho(camera_t *camera,
float left, float right, float bottom, float top, float near, float far
);

126
src/display/primitive.c Normal file
View File

@ -0,0 +1,126 @@
#include "primitive.h"
primitive_t * primitiveCreate(int32_t verticeCount, int32_t indiceCount) {
primitive_t *primitive = malloc(sizeof(primitive_t));
primitive->verticeCount = verticeCount;
primitive->indiceCount = indiceCount;
// size_t sizeIndices = sizeof(uint32_t) * verticeCount;
size_t sizePositions = sizeof(float) * verticeCount * PRIMITIVE_POSITIONS_PER_VERTICE;
size_t sizeCoordinates = sizeof(float) * verticeCount * PRIMITIVE_COORDINATES_PER_VERTICE;
size_t sizeIndices = sizeof(indice_t) * indiceCount;
// Create some buffers, one for the vertex data, one for the indices
GLuint *buffer = malloc(sizeof(GLuint) * 2);
glGenBuffers(2, buffer);
primitive->vertexBuffer = buffer[0];
primitive->indexBuffer = buffer[1];
free(buffer);
//Buffer an empty set of data then buffer each component
glBindBuffer(GL_ARRAY_BUFFER, primitive->vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, primitive->indexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizePositions+sizeCoordinates, 0, GL_DYNAMIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, 0, GL_DYNAMIC_DRAW);
size_t offset = 0;
// Setup the attrib pointers
glVertexAttribPointer(0, PRIMITIVE_POSITIONS_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(0);
offset += sizePositions;
glVertexAttribPointer(1, PRIMITIVE_COORDINATES_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(1);
return primitive;
}
void primitiveBufferVertices(primitive_t *primitive,
int32_t position, int32_t count, vertice_t *vertices
) {
// Memory
size_t lengthPositions, lengthCoordinates, offsetPositions, offsetCoordinates;
float *positions, *coordinates;
int32_t i;
// Setup the size of the memory that the positions and coordinates will use
lengthPositions = sizeof(float) * PRIMITIVE_POSITIONS_PER_VERTICE * count;
offsetPositions = sizeof(float) * PRIMITIVE_POSITIONS_PER_VERTICE * position;
lengthCoordinates = sizeof(float) * PRIMITIVE_COORDINATES_PER_VERTICE * count;
offsetCoordinates = (
(sizeof(float) * PRIMITIVE_POSITIONS_PER_VERTICE * primitive->verticeCount)+
(sizeof(float) * PRIMITIVE_COORDINATES_PER_VERTICE * position)
);
// Create some memory
positions = malloc(lengthPositions);
coordinates = malloc(lengthCoordinates);
// Now copy the positions and coordinates from the vertices into the buffer
for(i = 0; i < count; i++) {
positions[i * PRIMITIVE_POSITIONS_PER_VERTICE] = vertices[i].x;
positions[i * PRIMITIVE_POSITIONS_PER_VERTICE + 1] = vertices[i].y;
positions[i * PRIMITIVE_POSITIONS_PER_VERTICE + 2] = vertices[i].z;
coordinates[i * PRIMITIVE_COORDINATES_PER_VERTICE] = vertices[i].u;
coordinates[i * PRIMITIVE_COORDINATES_PER_VERTICE + 1] = vertices[i].v;
}
// Buffer the data into the GPU
glBindBuffer(GL_ARRAY_BUFFER, primitive->vertexBuffer);
glBufferSubData(GL_ARRAY_BUFFER, offsetPositions, lengthPositions, positions);
glBufferSubData(GL_ARRAY_BUFFER, offsetCoordinates, lengthCoordinates, coordinates);
// Free the vertices.
free(positions);
free(coordinates);
}
void primitiveBufferIndices(primitive_t *primitive,
int32_t position, int32_t count, indice_t *indices
) {
size_t length, offset;
offset = position * sizeof(indice_t);
length = count * sizeof(indice_t);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, primitive->indexBuffer);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, length, indices);
}
void primitiveDraw(primitive_t *primitive, int32_t start, int32_t count) {
// Re-Bind the buffers
glBindBuffer(GL_ARRAY_BUFFER, primitive->vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, primitive->indexBuffer);
// Re-Calculate the attrib pointers.
size_t offset = 0;
glVertexAttribPointer(0, PRIMITIVE_POSITIONS_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(0);
offset += sizeof(float) * primitive->verticeCount * PRIMITIVE_POSITIONS_PER_VERTICE;
glVertexAttribPointer(1, PRIMITIVE_COORDINATES_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(1);
// Render the elements.
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(
sizeof(indice_t)*start
));
}
void primitiveDispose(primitive_t *primitive) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &primitive->vertexBuffer);
glDeleteBuffers(1, &primitive->indexBuffer);
free(primitive);
}

69
src/display/primitive.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#include <stdint.h>
#include <glad/glad.h>
#include <malloc.h>
#define PRIMITIVE_POSITIONS_PER_VERTICE 3
#define PRIMITIVE_COORDINATES_PER_VERTICE 2
/** Structure containing information about a primitive */
typedef struct {
int32_t verticeCount;
int32_t indiceCount;
GLuint vertexBuffer;
GLuint indexBuffer;
} primitive_t;
/** Structure containing vertice position information */
typedef struct {
float x, y, z;
float u, v;
} vertice_t;
/** Indice that references a specific vertice */
typedef unsigned int indice_t;
/**
* Creates a new primitive.
* @param verticeCount How many vertices can the primitive hold.
* @param indiceCount How many indices can the primitive hold.
* @return The newly created primitive ready to be buffered to.
*/
primitive_t * primitiveCreate(int32_t verticeCount, int32_t indiceCount);
/**
* Buffer Vertices to a primitive for use in rendering.
* @param primitive The primitive to buffer vertices into.
* @param position The position (index) to overwrite the vertices of.
* @param count The count of vertices to buffer.
* @param vertices Array of vertices to buffer into the primitive.
*/
void primitiveBufferVertices(primitive_t *primitive,
int32_t position, int32_t count, vertice_t *vertices
);
/**
* Buffer Indices to a primitive for use in rendering.
* @param primitive The primitive to buffer indices into.
* @param position The position (index) to overwrite the indices of.
* @param count The count of indices to buffer.
* @param indices Array of indices to buffer into the primitive.
*/
void primitiveBufferIndices(primitive_t *primitive,
int32_t position, int32_t count, indice_t *indices
);
/**
* Draw a primitive. Primitives are drawn by their indices.
* @param primitive Primitive to draw.
* @param start Start indice (index) to draw.
* @param count Count of indices to draw.
*/
void primitiveDraw(primitive_t *primitive, int32_t start, int32_t count);
/**
* Cleanup a previously created primitive.
* @param primitive Primitive to cleanup.
*/
void primitiveDispose(primitive_t *primitive);

View File

@ -0,0 +1,112 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "cube.h"
void cubeBuffer(primitive_t *prim,
float x, float y, float z,
float w, float h, float d,
int32_t verticeStart, int32_t indiceStart
) {
vertice_t *vertices = malloc(sizeof(vertice_t) * CUBE_VERTICE_COUNT);
indice_t *indices = malloc(sizeof(indice_t) * CUBE_INDICE_COUNT);
vertices[0].x = x, vertices[0].y = y, vertices[0].z = z;
vertices[0].u = 0, vertices[0].v = 0;
vertices[1].x = x+w, vertices[1].y = y, vertices[1].z = z;
vertices[1].u = 1, vertices[1].v = 0;
vertices[2].x = x, vertices[2].y = y+h, vertices[2].z = z;
vertices[2].u = 0, vertices[2].v = 1;
vertices[3].x = x+w, vertices[3].y = y+h, vertices[3].z = z;
vertices[3].u = 1, vertices[3].v = 1;
vertices[4].x = x, vertices[4].y = y, vertices[4].z = z+d;
vertices[4].u = 0, vertices[4].v = 0;
vertices[5].x = x+w, vertices[5].y = y, vertices[5].z = z+d;
vertices[5].u = 1, vertices[5].v = 0;
vertices[6].x = x, vertices[6].y = y+h, vertices[6].z = z+d;
vertices[6].u = 0, vertices[6].v = 1;
vertices[7].x = x+w, vertices[7].y = y+h, vertices[7].z = z+d;
vertices[7].u = 1, vertices[7].v = 1;
// Back
indices[ 0] = (indice_t)(verticeStart + 0);
indices[ 1] = (indice_t)(verticeStart + 1);
indices[ 2] = (indice_t)(verticeStart + 3);
indices[ 3] = (indice_t)(verticeStart + 0);
indices[ 4] = (indice_t)(verticeStart + 2);
indices[ 5] = (indice_t)(verticeStart + 3);
// Right
indices[ 6] = (indice_t)(verticeStart + 1);
indices[ 7] = (indice_t)(verticeStart + 5);
indices[ 8] = (indice_t)(verticeStart + 7);
indices[ 9] = (indice_t)(verticeStart + 1);
indices[10] = (indice_t)(verticeStart + 3);
indices[11] = (indice_t)(verticeStart + 7);
// Left
indices[12] = (indice_t)(verticeStart + 4);
indices[13] = (indice_t)(verticeStart + 0);
indices[14] = (indice_t)(verticeStart + 2);
indices[15] = (indice_t)(verticeStart + 4);
indices[16] = (indice_t)(verticeStart + 6);
indices[17] = (indice_t)(verticeStart + 2);
// Front
indices[18] = (indice_t)(verticeStart + 5);
indices[19] = (indice_t)(verticeStart + 4);
indices[20] = (indice_t)(verticeStart + 6);
indices[21] = (indice_t)(verticeStart + 5);
indices[22] = (indice_t)(verticeStart + 7);
indices[23] = (indice_t)(verticeStart + 6);
// Top
indices[24] = (indice_t)(verticeStart + 7);
indices[25] = (indice_t)(verticeStart + 2);
indices[26] = (indice_t)(verticeStart + 6);
indices[27] = (indice_t)(verticeStart + 7);
indices[28] = (indice_t)(verticeStart + 3);
indices[29] = (indice_t)(verticeStart + 2);
// Bottom
indices[30] = (indice_t)(verticeStart + 1);
indices[31] = (indice_t)(verticeStart + 0);
indices[32] = (indice_t)(verticeStart + 4);
indices[33] = (indice_t)(verticeStart + 1);
indices[34] = (indice_t)(verticeStart + 4);
indices[35] = (indice_t)(verticeStart + 5);
primitiveBufferVertices(prim, verticeStart, CUBE_VERTICE_COUNT, vertices);
primitiveBufferIndices(prim, indiceStart, CUBE_INDICE_COUNT, indices);
free(vertices);
free(indices);
}
primitive_t * cubeCreate(float w, float h, float d) {
primitive_t *cube = primitiveCreate(CUBE_VERTICE_COUNT, CUBE_INDICE_COUNT);
cubeBuffer(cube,
-w/2, -h/2, -d/2,
w, h, d,
0, 0
);
return cube;
}

View File

@ -0,0 +1,40 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include <malloc.h>
#include "../primitive.h"
#define CUBE_VERTICE_COUNT 8
#define CUBE_INDICE_COUNT 36
/**
* Buffer the vertices and indices of a cube onto a primitive.
* @param primitive Primitive to buffer to.
* @param x X position of the cube.
* @param y Y position of the cube.
* @param z Z position of the cube.
* @param w Width of cube.
* @param h Height of cube.
* @param d Depth of cube.
* @param verticeStart The position of the vertex buffer to buffer into.
* @param indiceStart The position of the index buffer to buffer into.
*/
void cubeBuffer(primitive_t *primitive,
float x, float y, float z,
float w, float h, float d,
int32_t verticeStart, int32_t indiceStart
);
/**
* Creates a cube primitive of given size.
* @param w Width of cube.
* @param h Height of cube.
* @param d Depth of cube.
* @return Primitive of the cube.
*/
primitive_t * cubeCreate(float w, float h, float d);

View File

@ -0,0 +1,58 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "quad.h"
void quadBuffer(primitive_t *primitive, float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1,
int32_t verticeStart, int32_t indiceStart
) {
vertice_t *vertices = malloc(sizeof(vertice_t) * QUAD_VERTICE_COUNT);
indice_t *indices = malloc(sizeof(indice_t) * QUAD_INDICE_COUNT);
vertices[0].x = x0, vertices[0].y = y0, vertices[0].z = z;
vertices[0].u = u0, vertices[0].v = v0;
vertices[1].x = x1, vertices[1].y = y0, vertices[1].z = z;
vertices[1].u = u1, vertices[1].v = v0;
vertices[2].x = x0, vertices[2].y = y1, vertices[2].z = z;
vertices[2].u = u0, vertices[2].v = v1;
vertices[3].x = x1, vertices[3].y = y1, vertices[3].z = z;
vertices[3].u = u1, vertices[3].v = v1;
indices[0] = (indice_t)(verticeStart + 0);
indices[1] = (indice_t)(verticeStart + 1);
indices[2] = (indice_t)(verticeStart + 2);
indices[3] = (indice_t)(verticeStart + 1);
indices[4] = (indice_t)(verticeStart + 2);
indices[5] = (indice_t)(verticeStart + 3);
primitiveBufferVertices(primitive,verticeStart,QUAD_VERTICE_COUNT,vertices);
primitiveBufferIndices( primitive,indiceStart, QUAD_INDICE_COUNT, indices );
free(vertices);
free(indices);
}
primitive_t * quadCreate(float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1
) {
primitive_t *primitive = primitiveCreate(4, 6);
quadBuffer(primitive, z,
x0, y0, u0, v0,
x1, y1, u1, v1,
0, 0
);
return primitive;
}

View File

@ -0,0 +1,52 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include "../primitive.h"
#define QUAD_VERTICE_COUNT 4
#define QUAD_INDICE_COUNT 6
/**
* Buffers the vertices of a quad onto a primitive.
*
* @param primitive The primitive to buffer to.
* @param z The Z axis coordinate of the quad.
* @param x0 The X lower coordinate.
* @param y0 The Y lower coordinate.
* @param u0 The X lower texture coordinate.
* @param v0 The Y lower texture coordinate.
* @param x1 The X higher coordinate.
* @param y1 The Y higher coordinate.
* @param u1 The X higher texture coordinate.
* @param v1 The Y higher texture coordinate.
* @param verticeStart Start vertice to buffer to.
* @param indiceStart Start indice to buffer to.
*/
void quadBuffer(primitive_t *primitive, float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1,
int32_t verticeStart, int32_t indiceStart
);
/**
* Creates a new quad primitive.
*
* @param z The Z axis coordinate of the quad.
* @param x0 The X lower coordinate.
* @param y0 The Y lower coordinate.
* @param u0 The X lower texture coordinate.
* @param v0 The Y lower texture coordinate.
* @param x1 The X higher coordinate.
* @param y1 The Y higher coordinate.
* @param u1 The X higher texture coordinate.
* @param v1 The Y higher texture coordinate.
* @return The quad primitive.
*/
primitive_t * quadCreate(float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1
);

44
src/display/render.c Normal file
View File

@ -0,0 +1,44 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "render.h"
render_t * renderInit(char *name) {
// Initialize the renderer
render_t *render = malloc(sizeof(render_t));
if(!render) return NULL;
// render->width = WINDOW_WIDTH_DEFAULT;
// render->height = WINDOW_HEIGHT_DEFAULT;
// Enable GL things.
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
// Setup the alpha blend function.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
return render;
}
void renderFrame(render_t *render) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
bool renderDispose(render_t *render) {
// Free up the renderer
free(render);
return true;
}
void renderSetResolution(render_t *render, uint32_t width, uint32_t height) {
render->width = width;
render->height = height;
glViewport(0, 0, width, height);
}

58
src/display/render.h Normal file
View File

@ -0,0 +1,58 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <malloc.h>
#include <glad/glad.h>
#include <cglm/call.h>
#include "primitive.h"
/**
* Contains information about the current render state, can be used for querying
* how the renderer is currently set up.
*/
typedef struct {
/** Resolution (in pixels) */
int32_t width, height;
} render_t;
/**
* Initialize the renderer.
*
* @param name String of the windows' name.
* @return Rendering Context information.
*/
render_t * renderInit(char *name);
/**
* Render a single frame of the render loop. The renderer is not (currently)
* responsible for render looping.
*
* @param render The renderer to loop for.
*/
void renderFrame(render_t *render);
/**
* Cleanup a render context.
*
* @param render Renderer to cleanup.
* @return True or False if Successful/Not.
*/
bool renderDispose(render_t *render);
/**
* Set the internal display resolution.
*
* @param render Renderer to set resolution for.
* @param width Width (in pixels) of the viewport.
* @param height Height (in pixels) of the viewport.
*/
void renderSetResolution(render_t *render, uint32_t width, uint32_t height);

141
src/display/shader.c Normal file
View File

@ -0,0 +1,141 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "shader.h"
shader_t * shaderCompile(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_t *shader = malloc(sizeof(shader_t));
if(shader == NULL) {
glDeleteProgram(shaderProgram);
glDeleteShader(shaderVertex);
glDeleteShader(shaderFragment);
return NULL;
}
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;
}
bool shaderDipose(shader_t *shader) {
glDeleteProgram(shader->shaderProgram);
glDeleteShader(shader->shaderVertex);
glDeleteShader(shader->shaderFrag);
free(shader);
return true;
}
void shaderUse(shader_t *shader) {
glUseProgram(shader->shaderProgram);
}
void shaderUseCamera(shader_t *shader, camera_t *camera) {
glUniformMatrix4fv(shader->uniView, 1, GL_FALSE, (float*)camera->view);
glUniformMatrix4fv(shader->uniProj, 1, GL_FALSE, (float*)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 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(MATRIX_POSITION, axis);
//Rotation, we do each axis individually
axis[0] = 1, axis[1] = 0, axis[2] = 0;
glm_rotate(MATRIX_POSITION, pitch, axis);
axis[0] = 0, axis[1] = 1;
glm_rotate(MATRIX_POSITION, yaw, axis);
axis[1] = 0, axis[2] = 1;
glm_rotate(MATRIX_POSITION, roll, axis);
//Send to the shader.
glUniformMatrix4fv(shader->uniModl, 1, GL_FALSE, (float*)MATRIX_POSITION);
}

90
src/display/shader.h Normal file
View File

@ -0,0 +1,90 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include <glad/glad.h>
#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include "camera.h"
#include "texture.h"
#define SHADER_UNI_VIEW "u_View"
#define SHADER_UNI_PROJ "u_Proj"
#define SHADER_UNI_TEXT "u_Text"
#define SHADER_UNI_MODL "u_Modl"
/**
* Structure containing information about an OpenGL Shader. For simplicity sake
* we demand certain uninforms to be present on the shader target.
*/
typedef struct {
/** Pointer to an uploaded vertex shader program */
GLuint shaderVertex;
/** Pointer to an uploaded fragment shader program */
GLuint shaderFrag;
/** Pointer to an uploaded shader program linked */
GLuint shaderProgram;
/** Matrix for the view matrix */
GLint uniView;
/** Matrix for the projection matrix */
GLint uniProj;
/** Uniform for the current texture */
GLint uniText;
/** Uniform for the current model world position */
GLint uniModl;
} shader_t;
/**
* Create a shader from vertex and fragment shader code.
*
* @param vertexShaderSource The raw vertex shader code.
* @param fragmentShaderSource The raw fragment shader code.
* @return Pointer to the loaded shader.
*/
shader_t * shaderCompile(char *vertexShaderSource, char* fragmentShaderSource);
/**
* Cleanup and unload a previously loaded shader.
*
* @param shader The shader to unload
* @return True if successfully disposed.
*/
bool shaderDipose(shader_t *shader);
/**
* Attaches the supplied shader as the current shader.
* @param shader The shader to attach
*/
void shaderUse(shader_t *shader);
/**
* Attaches a camera to the shader.
* @param shader Shader to attach to.
* @param camera Camera to attach.
*/
void shaderUseCamera(shader_t *shader, camera_t *camera);
/**
* Attaches a texture to the shader.
* @param shader Shader to attach to.
* @param texture Texture to attach.
*/
void shaderUseTexture(shader_t *shader, texture_t *texture);
void shaderUsePosition(shader_t *shader,
float x, float y, float z,
float pitch, float yaw, float roll
);

59
src/display/spritebatch.c Normal file
View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "spritebatch.h"
spritebatch_t * spriteBatchCreate(int32_t maxSprites) {
spritebatch_t *batch = malloc(sizeof(spritebatch_t));
if(batch == NULL) return NULL;
batch->maxSprites = maxSprites;
batch->currentSprite = 0;
batch->primitive = primitiveCreate(
maxSprites*QUAD_VERTICE_COUNT, maxSprites*QUAD_INDICE_COUNT
);
if(batch == NULL) {
free(batch);
return NULL;
}
return batch;
}
void spriteBatchQuad(spritebatch_t *spriteBatch, int32_t index,
float x, float y, float z, float width, float height,
float u0, float v0, float u1, float v1
) {
if(index == -1) {
index = spriteBatch->currentSprite++;
} else {
spriteBatch->currentSprite = mathMax(index, spriteBatch->currentSprite);
}
quadBuffer(spriteBatch->primitive, z,
x, y, u0, v0,
x+width, y+height, u1, v1,
index*QUAD_VERTICE_COUNT, index*QUAD_INDICE_COUNT
);
}
void spriteBatchFlush(spritebatch_t *spriteBatch) {
spriteBatch->currentSprite = 0;
}
void spriteBatchDraw(spritebatch_t *spriteBatch, int32_t index, int32_t count) {
if(count == -1) count = spriteBatch->currentSprite;
primitiveDraw(spriteBatch->primitive,
index*QUAD_INDICE_COUNT, count*QUAD_INDICE_COUNT
);
}
void spriteBatchDispose(spritebatch_t *spriteBatch) {
primitiveDispose(spriteBatch->primitive);
free(spriteBatch);
}

70
src/display/spritebatch.h Normal file
View File

@ -0,0 +1,70 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include "primitive.h"
#include "primitives/quad.h"
#include "../util/math.h"
typedef struct {
/** Maximum sprites the batch can hold. */
int32_t maxSprites;
/** The current/next sprite index. */
int32_t currentSprite;
/** Internal primitive */
primitive_t *primitive;
} spritebatch_t;
/**
* Creates a new Sprite Batch made of standard quads.
*
* @param maxSprites The maxiumum number of sprites the batch can hold.
* @returns A new quad Sprite Batch.
*/
spritebatch_t * spriteBatchCreate(int32_t maxSprites);
/**
* Renders a sprite onto a given Sprite Batch.
*
* @param spriteBatch The sprite batch to render to.
* @param index The index within the sprite batch. Set to -1 to select "next".
* @param x X coordinate of the sprite.
* @param y Y coordinate of the sprite.
* @param width Width of the sprite.
* @param height Height of the sprite.
* @param u0 Texture U coordinate (min).
* @param v0 Texture V coordinate (min).
* @param u1 Texture U coordinate (max).
* @param v1 Texture V coordinate (max).
*/
void spriteBatchQuad(spritebatch_t *spriteBatch, int32_t index,
float x, float y, float z, float width, float height,
float u0, float v0, float u1, float v1
);
/**
* Flushes a sprite batch to reset the indexes.
* @param spriteBatch The batch.
*/
void spriteBatchFlush(spritebatch_t *spriteBatch);
/**
* Draws the Sprite Batch.
*
* @param spriteBatch The sprite batch to render.
* @param start Start index to render from.
* @param count Count of sprites to render. Set to -1 to render to the current.
*/
void spriteBatchDraw(spritebatch_t *spriteBatch, int32_t start, int32_t count);
/**
* Disposes a previously created Sprite Batch.
*
* @param spriteBatch The sprite batch to dispose.
*/
void spriteBatchDispose(spritebatch_t *spriteBatch);

61
src/display/texture.c Normal file
View File

@ -0,0 +1,61 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "texture.h"
texture_t * textureCreate(int32_t width, int32_t height, pixel_t *pixels) {
texture_t *texture = malloc(sizeof(texture_t));
if(texture == NULL) return NULL;
texture->width = width;
texture->height = height;
// Generate a texture ID and bind.
glGenTextures(1, &texture->id);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->id);
// Setup our preferred texture params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Start by buffering all transparent black pixels.
if(pixels == NULL) {
pixels = calloc(width * height, sizeof(pixel_t));
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixels
);
free(pixels);
} else {
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixels
);
}
return texture;
}
void textureBufferPixels(texture_t *texture,
int32_t x, int32_t y, int32_t width, int32_t height, pixel_t *pixels
) {
glBindTexture(GL_TEXTURE_2D, texture->id);
glTexSubImage2D(GL_TEXTURE_2D, 0,
x, y, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, pixels
);
}
void textureDispose(texture_t *texture) {
glDeleteTextures(1, &texture->id);
free(texture);
}

57
src/display/texture.h Normal file
View File

@ -0,0 +1,57 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include <glad/glad.h>
#include <malloc.h>
#include <memory.h>
/**
* Structure detailing information about a texture.
* Because we plan to upload the pixels of a texture into the GPU, we don't
* store the pixels in memory because we don't need to!
*/
typedef struct {
int32_t width;
int32_t height;
GLuint id;
} texture_t;
/** Information about a single pixel. */
typedef struct {
uint8_t r, g, b, a ;
} pixel_t;
/**
* Creates a new texture that can be written in to.
*
* @param width Width of the texture (in pixels).
* @param height Height of the texture (in pixels).
* @param pixels Default pixel array, set to NULL to set all pixel data to 0.
* @return The newly created texture instance.
*/
texture_t * textureCreate(int32_t width, int32_t height, pixel_t *pixels);
/**
* Buffer pixel data onto the GPU. Pixel buffering is rather costly so avoid
* doing this too often.
*
* @param texture Texture to buffer in to.
* @param x X coordinate in texture space to render to.
* @param y Y coordinate in texture space to render to.
* @param width Width of the pixel region you're buffering.
* @param height Height of the pixel region you're buffering.
* @param pixels Array of pixels to buffer onto the GPU.
*/
void textureBufferPixels(texture_t *texture,
int32_t x, int32_t y, int32_t width, int32_t height, pixel_t *pixels
);
/**
* Clean a previously created texture.
* @param texture Texture to clean up.
*/
void textureDispose(texture_t *texture);

66
src/display/tileset.c Normal file
View File

@ -0,0 +1,66 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "tileset.h"
tileset_t * tilesetCreate(
int32_t columns, int32_t rows,
int32_t width, int32_t height,
int32_t gapX, int32_t gapY,
int32_t borderX, int32_t borderY
) {
tileset_t *tileset;
float divX, divY, tdivX;
int32_t x, y, i;
tileset = malloc(sizeof(tileset_t));
if(tileset == NULL) return NULL;
tileset->count = rows * columns;
tileset->divisions = malloc(sizeof(tilesetdiv_t) * tileset->count);
if(tileset->divisions == NULL) {
free(tileset);
return NULL;
}
tileset->columns = columns;
tileset->rows = rows;
// Calculate division sizes (pixels)
divX = (width - (borderX * 2) - (gapX * (columns - 1))) / columns;
divY = (height - (borderY * 2) - (gapY * (rows - 1))) / rows;
// Calculate the division sizes (units)
divX = divX / width;
divY = divY / height;
// Calculate the divisions
i = -1;
for(y = 0; y < rows; y++) {
for(x = 0; x < columns; x++) {
tileset->divisions[++i].x0 = borderX + (divX * x) + (gapX * x);
tileset->divisions[i].y0 = borderY + (divY * y) + (gapY * y);
tileset->divisions[i].x1 = tileset->divisions[i].x0 + divX;
tileset->divisions[i].y1 = tileset->divisions[i].y0 + divY;
}
}
return tileset;
}
tilesetdiv_t tilesetGetDivision(tileset_t *tileset,
int32_t column, int32_t row
) {
return tileset->divisions[
(column % tileset->columns) + (row * tileset->columns)
];
}
void tilesetDispose(tileset_t *tileset) {
free(tileset->divisions);
free(tileset);
}

65
src/display/tileset.h Normal file
View File

@ -0,0 +1,65 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include <malloc.h>
/** Division of a texture */
typedef struct {
float x0, y0, x1, y1;
} tilesetdiv_t;
/** Definition of a Tileset */
typedef struct {
/** Count of X/Y divisions */
int32_t columns, rows;
/** Count of divisions (unused) */
int32_t count;
/** Division information */
tilesetdiv_t *divisions;
} tileset_t;
/**
* Create a tileset. Tilesets will be pre-divided to save performance later.
*
* @param columns Count of columns.
* @param rows Count of rows.
* @param width Width of the tileset.
* @param height Height of the tileset.
* @param gapX Space between each column.
* @param gapY Space between each row.
* @param borderX Space around the edge of the tileset.
* @param borderY Space around the edge of the tileset.
* @returns The tileset.
*/
tileset_t * tilesetCreate(
int32_t columns, int32_t rows,
int32_t width, int32_t height,
int32_t gapX, int32_t gapY,
int32_t borderX, int32_t borderY
);
/**
* Retreive the division for a given tileset coordinate.
*
* @param tileset Tileset to retreive from.
* @param column X axis of the tileset.
* @param row Y axis of the tileset.
* @returns The Tileset division.
*/
tilesetdiv_t tilesetGetDivision(tileset_t *tileset,
int32_t column, int32_t row
);
/**
* Cleans a previously created tileset
*
* @param tileset Cleanup the tileset.
*/
void tilesetDispose(tileset_t *tileset);