iuno
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Libs
|
||||
target_link_libraries(${DUSK_TARGET_NAME}
|
||||
PUBLIC
|
||||
archive_static
|
||||
m
|
||||
spng_static
|
||||
cglm
|
||||
)
|
||||
|
||||
# Includes
|
||||
target_include_directories(${DUSK_TARGET_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
asset.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(assert)
|
||||
add_subdirectory(display)
|
||||
add_subdirectory(overworld)
|
||||
|
||||
# Assets
|
||||
copytool("textures/8x8.png")
|
||||
@@ -1,10 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
assertgl.c
|
||||
)
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assert/assertgl.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
void assertNotGLErrorCheck(const char_t *file, const int32_t line) {
|
||||
assertNotNull(file, "File is an invlaid string");
|
||||
assertTrue(line > 0, "assertNotGLErrorCheck: line is invalid");
|
||||
|
||||
char_t *buffer;
|
||||
GLenum errorCode;
|
||||
int32_t errorCount = 0;
|
||||
|
||||
while((errorCode = glGetError()) != GL_NO_ERROR) {
|
||||
if(errorCount == 0) {
|
||||
buffer = memoryAllocate(sizeof(char_t) * 4096);
|
||||
sprintf(buffer, "assertNotGLErrorCheck: %s:%d\n", file, line);
|
||||
}
|
||||
|
||||
errorCount++;
|
||||
|
||||
switch (errorCode) {
|
||||
case GL_INVALID_ENUM:
|
||||
sprintf(buffer, "%s\nINVALID_ENUM", buffer);
|
||||
break;
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
sprintf(buffer, "%s\nINVALID_ENUM", buffer);
|
||||
break;
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
sprintf(buffer, "%s\nINVALID_OPERATION", buffer);
|
||||
break;
|
||||
|
||||
// case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
// sprintf(buffer, "%s\nINVALID_FRAMEBUFFER_OPERATION", buffer);
|
||||
// break;
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
sprintf(buffer, "%s\nOUT_OF_MEMORY", buffer);
|
||||
break;
|
||||
|
||||
case GL_STACK_UNDERFLOW:
|
||||
sprintf(buffer, "%s\nSTACK_UNDERFLOW", buffer);
|
||||
break;
|
||||
|
||||
case GL_STACK_OVERFLOW:
|
||||
sprintf(buffer, "%s\nSTACK_OVERFLOW", buffer);
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(buffer, "%s\nUNKNOWN_ERROR", buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buffer, "%s (%i)\n", buffer, errorCode);
|
||||
}
|
||||
|
||||
if(errorCount > 0) {
|
||||
assertUnreachable(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
|
||||
/**
|
||||
* Asserts that there are no OpenGL errors.
|
||||
*
|
||||
* @param file The file the assertion is being made in.
|
||||
* @param line The line the assertion is being made in.
|
||||
*/
|
||||
void assertNotGLErrorCheck(const char_t *file, const int32_t line);
|
||||
|
||||
/**
|
||||
* Asserts that there are no OpenGL errors.
|
||||
*/
|
||||
#define assertNoGLError() assertNotGLErrorCheck(__FILE__, __LINE__)
|
||||
@@ -1,223 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "asset.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/math.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
asset_t ASSET;
|
||||
|
||||
void assetInit() {
|
||||
const char_t *assetFilename = "dusk.tar";
|
||||
char_t assetPath[FILENAME_MAX];
|
||||
const char_t* scanLocations[] = {
|
||||
EXECUTABLE_DIRECTORY
|
||||
};
|
||||
|
||||
memoryZero(&ASSET, sizeof(asset_t));
|
||||
|
||||
// Try and find the asset file.
|
||||
for(int32_t i = 0; i < sizeof(scanLocations) / sizeof(char_t*); i++) {
|
||||
sprintf(assetPath, "%s/%s", scanLocations[i], assetFilename);
|
||||
|
||||
FILE *file = fopen(assetPath, "rb");
|
||||
if(file == NULL) continue;
|
||||
|
||||
// File found.
|
||||
ASSET.file = file;
|
||||
}
|
||||
|
||||
// Ensure we found it.
|
||||
assertNotNull(ASSET.file, "Failed to find asset file!");
|
||||
}
|
||||
|
||||
void assetOpen(const char_t *path) {
|
||||
assertNotNull(path, "Path is not valid!");
|
||||
assertStrLen(path, FILENAME_MAX, "Path is too long!");
|
||||
assertStrLenMin(path, 1, "Path is empty!");
|
||||
|
||||
// Make sure things are clean
|
||||
assertNull(ASSET.archive, "Archive is not NULL!");
|
||||
assertNull(ASSET.entry, "Entry is not NULL!");
|
||||
assertNotNull(ASSET.file, "File is NULL!");
|
||||
|
||||
// Store path
|
||||
strcpy(ASSET.path, path);
|
||||
|
||||
// Prepare data
|
||||
ASSET.archive = archive_read_new();
|
||||
assertNotNull(ASSET.archive, "Failed to init archive reader");
|
||||
|
||||
// Set up the reader
|
||||
// archive_read_support_filter_bzip2(ASSET_ARCHIVE);
|
||||
archive_read_support_format_tar(ASSET.archive);
|
||||
|
||||
// Set the archive reader callbacks
|
||||
archive_read_set_open_callback(ASSET.archive, &assetArchiveOpen);
|
||||
archive_read_set_read_callback(ASSET.archive, &assetArchiveRead);
|
||||
archive_read_set_seek_callback(ASSET.archive, &assetArchiveSeek);
|
||||
archive_read_set_close_callback(ASSET.archive, &assetArchiveClose);
|
||||
archive_read_set_callback_data(ASSET.archive, ASSET.buffer);// TODO: Not needed?
|
||||
|
||||
// Open the archive
|
||||
int32_t ret = archive_read_open1(ASSET.archive);
|
||||
assertTrue(ret == ARCHIVE_OK, "Failed to open archive!");
|
||||
|
||||
// Iterate over each file.
|
||||
while(archive_read_next_header(ASSET.archive, &ASSET.entry) == ARCHIVE_OK) {
|
||||
// What file is at this position?
|
||||
const char_t *headerFile = (char_t*)archive_entry_pathname(ASSET.entry);
|
||||
|
||||
// Compare if this is the file we are looking for, if it is just exit the
|
||||
// function
|
||||
if(strcmp(headerFile, ASSET.path) == 0) return;
|
||||
|
||||
// It is not, skip it.
|
||||
int32_t ret = archive_read_data_skip(ASSET.archive);
|
||||
assertTrue(ret == ARCHIVE_OK, "Failed to skip data!");
|
||||
}
|
||||
|
||||
// If we get here we did not find the find in the archive.
|
||||
assertUnreachable("Failed to find file!");
|
||||
}
|
||||
|
||||
size_t assetGetSize() {
|
||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
||||
assertTrue(archive_entry_size_is_set(ASSET.entry), "Entry size is not set!");
|
||||
return archive_entry_size(ASSET.entry);
|
||||
}
|
||||
|
||||
size_t assetRead(
|
||||
uint8_t *buffer,
|
||||
const size_t bufferSize
|
||||
) {
|
||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
||||
assertNotNull(buffer, "Buffer is NULL!");
|
||||
assertTrue(bufferSize > 0, "Buffer size must be greater than 0!");
|
||||
|
||||
ssize_t read = archive_read_data(ASSET.archive, buffer, bufferSize);
|
||||
if(read == ARCHIVE_FATAL) {
|
||||
assertUnreachable(archive_error_string(ASSET.archive));
|
||||
return -1;
|
||||
}
|
||||
|
||||
assertTrue(read != ARCHIVE_RETRY, "Failed to read data (RETRY)!");
|
||||
assertTrue(read != ARCHIVE_WARN, "Failed to read data (WARN)!");
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
size_t assetReadUntil(
|
||||
uint8_t *buffer,
|
||||
const char_t c,
|
||||
const size_t maxLength
|
||||
) {
|
||||
if(buffer == NULL) {
|
||||
assertTrue(
|
||||
maxLength == -1, "If no buffer is provided, maxLength must be -1."
|
||||
);
|
||||
uint8_t tBuffer[1];
|
||||
size_t read = 0;
|
||||
while(assetRead(tBuffer, 1) == 1 && (char_t)tBuffer[0] != c) read++;
|
||||
return read;
|
||||
}
|
||||
|
||||
size_t read = 0;
|
||||
while(read < maxLength) {
|
||||
// TODO: Read more than 1 char at a time.
|
||||
read += assetRead(buffer + read, 1);
|
||||
if((char_t)buffer[read-1] == c) return read - 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void assetSkip(const size_t length) {
|
||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
||||
|
||||
// Asset archive does not support skipping, so we have to read and discard.
|
||||
uint8_t buffer[ASSET_BUFFER_SIZE];
|
||||
size_t remaining = length;
|
||||
do {
|
||||
size_t toRead = mathMin(remaining, ASSET_BUFFER_SIZE);
|
||||
size_t read = assetRead(buffer, toRead);
|
||||
assertTrue(read == toRead, "Failed to skip data! (overskip?)");
|
||||
remaining -= read;
|
||||
} while(remaining > 0);
|
||||
}
|
||||
|
||||
void assetClose() {
|
||||
if(ASSET.archive == NULL) return;
|
||||
|
||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
||||
|
||||
int32_t ret = archive_read_free(ASSET.archive);
|
||||
assertTrue(ret == ARCHIVE_OK, "Failed to close archive!");
|
||||
|
||||
assertNull(ASSET.archive, "Archive is not NULL? Cleanup incorrect.");
|
||||
}
|
||||
|
||||
void assetDispose() {
|
||||
assertNull(ASSET.archive, "Asset disposing but asset is currently open?");
|
||||
assertNull(ASSET.entry, "Asset disposing but entry is currently open?");
|
||||
assertNotNull(ASSET.file, "Asset disposing but file is NULL?");
|
||||
|
||||
fclose(ASSET.file);
|
||||
memoryZero(&ASSET, sizeof(asset_t));
|
||||
}
|
||||
|
||||
// Libarchive callbacks
|
||||
|
||||
ssize_t assetArchiveRead(
|
||||
struct archive *archive,
|
||||
void *data,
|
||||
const void **buffer
|
||||
) {
|
||||
assertNotNull(archive, "Archive is NULL!");
|
||||
assertNotNull(data, "Data is NULL!");
|
||||
assertNotNull(buffer, "Buffer is NULL!");
|
||||
|
||||
*buffer = data;
|
||||
size_t read = fread(data, 1, ASSET_BUFFER_SIZE, ASSET.file);
|
||||
if(ferror(ASSET.file)) return ARCHIVE_FATAL;
|
||||
return read;
|
||||
}
|
||||
|
||||
int64_t assetArchiveSeek(
|
||||
struct archive *archive,
|
||||
void *data,
|
||||
int64_t offset,
|
||||
int32_t whence
|
||||
) {
|
||||
assertNotNull(archive, "Archive is NULL!");
|
||||
assertNotNull(data, "Data is NULL!");
|
||||
assertTrue(offset > 0, "Offset must be greater than 0!");
|
||||
assertNotNull(ASSET.file, "File is NULL!");
|
||||
int32_t ret = fseek(ASSET.file, offset, whence);
|
||||
assertTrue(ret == 0, "Failed to seek!");
|
||||
return ftell(ASSET.file);
|
||||
}
|
||||
|
||||
int32_t assetArchiveOpen(struct archive *a, void *data) {
|
||||
int32_t ret = fseek(ASSET.file, 0, SEEK_SET);
|
||||
assertTrue(ret == 0, "Failed to seek to start of file!");
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
int32_t assetArchiveClose(struct archive *a, void *data) {
|
||||
assertNotNull(ASSET.file, "File is NULL!");
|
||||
|
||||
ASSET.archive = NULL;
|
||||
ASSET.entry = NULL;
|
||||
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
|
||||
#define ASSET_BUFFER_SIZE 32768
|
||||
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
struct archive *archive;
|
||||
struct archive_entry *entry;
|
||||
uint8_t buffer[ASSET_BUFFER_SIZE];
|
||||
|
||||
// ?
|
||||
char_t path[FILENAME_MAX];
|
||||
} asset_t;
|
||||
|
||||
extern asset_t ASSET;
|
||||
|
||||
/**
|
||||
* Initializes the asset manager.
|
||||
*/
|
||||
void assetInit();
|
||||
|
||||
/**
|
||||
* Opens an asset by its filename (within the asset archive). Asset paths should
|
||||
* always use the unix forward slash '/' as a path separator.
|
||||
*
|
||||
* @param path The path to the asset within the archive.
|
||||
*/
|
||||
void assetOpen(const char *path);
|
||||
|
||||
/**
|
||||
* Returns the size of the asset.
|
||||
*
|
||||
* @return The size of the asset.
|
||||
*/
|
||||
size_t assetGetSize();
|
||||
|
||||
/**
|
||||
* Reads the asset into the buffer.
|
||||
*
|
||||
* @param buffer The buffer to read the asset into.
|
||||
* @param bufferSize The size of the buffer.
|
||||
* @return The amount of data read.
|
||||
*/
|
||||
size_t assetRead(uint8_t *buffer, const size_t bufferSize);
|
||||
|
||||
/**
|
||||
* Reads ahead in the buffer until either the end of the buffer, or the
|
||||
* specified character is found. Return value will be -1 if the character was
|
||||
* not found.
|
||||
*
|
||||
* Buffer can be NULL if you just want to skip ahead.
|
||||
*
|
||||
* Returned value will be either the amount of data read into the buffer, which
|
||||
* excludes the extra 1 character that was read from the asset. If the character
|
||||
* was not found, -1 will be returned.
|
||||
*
|
||||
* @param buffer Buffer to read into.
|
||||
* @param c Character to read until.
|
||||
* @param maxLength Maximum length to read.
|
||||
* @return -1 if the character was not found, otherwise the amount of data read.
|
||||
*/
|
||||
size_t assetReadUntil(uint8_t *buffer, const char c, const size_t maxLength);
|
||||
|
||||
/**
|
||||
* Skips ahead in the buffer by the specified length.
|
||||
*
|
||||
* @param length The length to skip ahead by.
|
||||
*/
|
||||
void assetSkip(const size_t length);
|
||||
|
||||
/**
|
||||
* Closes the asset.
|
||||
*/
|
||||
void assetClose();
|
||||
|
||||
/**
|
||||
* Destroys and cleans up the asset manager.
|
||||
*/
|
||||
void assetDispose();
|
||||
|
||||
/**
|
||||
* Internal read method provided to libarchive api.
|
||||
*
|
||||
* @param archive The archive to read from.
|
||||
* @param data The data to read into.
|
||||
* @param buffer The buffer to read from.
|
||||
* @return The amount of data read.
|
||||
*/
|
||||
ssize_t assetArchiveRead(
|
||||
struct archive *archive,
|
||||
void *data,
|
||||
const void **buffer
|
||||
);
|
||||
|
||||
/**
|
||||
* Internal seek method provided to libarchive api.
|
||||
*
|
||||
* @param archive The archive to seek in.
|
||||
* @param data The data to seek in.
|
||||
* @param offset Offset bytes to seek.
|
||||
* @param whence Relative to whence to seek.
|
||||
* @return The new position.
|
||||
*/
|
||||
int64_t assetArchiveSeek(
|
||||
struct archive *archive,
|
||||
void *data,
|
||||
int64_t offset,
|
||||
int32_t whence
|
||||
);
|
||||
|
||||
/**
|
||||
* Internal open method provided to libarchive api.
|
||||
*
|
||||
* @param archive The archive to open.
|
||||
* @param data The data to open.
|
||||
* @return The result of the open.
|
||||
*/
|
||||
int32_t assetArchiveOpen(struct archive *a, void *data);
|
||||
|
||||
/**
|
||||
* Internal close method provided to libarchive api.
|
||||
*
|
||||
* @param archive The archive to close.
|
||||
* @param data The data to close.
|
||||
* @return The result of the close.
|
||||
*/
|
||||
int32_t assetArchiveClose(struct archive *a, void *data);
|
||||
@@ -1,16 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
render.c
|
||||
quad.c
|
||||
texture.c
|
||||
tilesetgl.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(shader)
|
||||
@@ -1,130 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include "assert/assert.h"
|
||||
#include "assert/assertgl.h"
|
||||
#include "display/window.h"
|
||||
|
||||
framebuffer_t FRAMEBUFFER;
|
||||
|
||||
void frameBufferInit(const int32_t width, const int32_t height) {
|
||||
assertTrue(width > 0, "Width must be greater than 0");
|
||||
assertTrue(height > 0, "Height must be greater than 0");
|
||||
|
||||
FRAMEBUFFER.id = -1;
|
||||
FRAMEBUFFER.width = -1;
|
||||
FRAMEBUFFER.height = -1;
|
||||
FRAMEBUFFER.texture = -1;
|
||||
|
||||
frameBufferSetSize(width, height);
|
||||
}
|
||||
|
||||
void frameBufferSetSize(const int32_t width, const int32_t height) {
|
||||
assertTrue(width > 0, "Width must be greater than 0");
|
||||
assertTrue(height > 0, "Height must be greater than 0");
|
||||
|
||||
if(FRAMEBUFFER.width == width && FRAMEBUFFER.height == height) return;
|
||||
|
||||
FRAMEBUFFER.width = width;
|
||||
FRAMEBUFFER.height = height;
|
||||
|
||||
frameBufferUnbind();
|
||||
|
||||
// Delete old texture and depth buffer
|
||||
if(FRAMEBUFFER.texture != -1) {
|
||||
glDeleteTextures(1, &FRAMEBUFFER.texture);
|
||||
assertNoGLError();
|
||||
FRAMEBUFFER.texture = -1;
|
||||
}
|
||||
|
||||
if(FRAMEBUFFER.id != -1) {
|
||||
glDeleteFramebuffers(1, &FRAMEBUFFER.id);
|
||||
assertNoGLError();
|
||||
FRAMEBUFFER.id = -1;
|
||||
}
|
||||
|
||||
// Generate framebuffer
|
||||
glGenFramebuffers(1, &FRAMEBUFFER.id);
|
||||
assertNoGLError();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FRAMEBUFFER.id);
|
||||
assertNoGLError();
|
||||
|
||||
// Create new texture
|
||||
glGenTextures(1, &FRAMEBUFFER.texture);
|
||||
assertNoGLError();
|
||||
glBindTexture(GL_TEXTURE_2D, FRAMEBUFFER.texture);
|
||||
assertNoGLError();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
assertNoGLError();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
assertNoGLError();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
assertNoGLError();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
assertNoGLError();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
assertNoGLError();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FRAMEBUFFER.texture, 0);
|
||||
assertNoGLError();
|
||||
|
||||
// Check framebuffer completeness
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
assertNoGLError();
|
||||
assertTrue(status == GL_FRAMEBUFFER_COMPLETE, "Framebuffer is not complete");
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void frameBufferBind() {
|
||||
if(FRAMEBUFFER.id == -1) return;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FRAMEBUFFER.id);
|
||||
assertNoGLError();
|
||||
|
||||
glViewport(0, 0, FRAMEBUFFER.width, FRAMEBUFFER.height);
|
||||
assertNoGLError();
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
assertNoGLError();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void frameBufferTextureBind(const GLuint slot) {
|
||||
if(FRAMEBUFFER.texture == -1) return;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + slot);
|
||||
assertNoGLError();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, FRAMEBUFFER.texture);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void frameBufferUnbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
assertNoGLError();
|
||||
|
||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
assertNoGLError();
|
||||
|
||||
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
|
||||
assertNoGLError();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void frameBufferDispose() {
|
||||
glDeleteFramebuffers(1, &FRAMEBUFFER.id);
|
||||
glDeleteTextures(1, &FRAMEBUFFER.texture);
|
||||
|
||||
FRAMEBUFFER.id = -1;
|
||||
FRAMEBUFFER.texture = -1;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
|
||||
typedef struct {
|
||||
GLuint id;
|
||||
GLuint texture;
|
||||
int width;
|
||||
int height;
|
||||
} framebuffer_t;
|
||||
|
||||
extern framebuffer_t FRAMEBUFFER;
|
||||
|
||||
/**
|
||||
* Initializes the framebuffer.
|
||||
*
|
||||
* @param width The width of the framebuffer.
|
||||
* @param height The height of the framebuffer.
|
||||
*/
|
||||
void frameBufferInit(const int32_t width, const int32_t height);
|
||||
|
||||
/**
|
||||
* Sets the size of the framebuffer.
|
||||
*
|
||||
* @param width The width of the framebuffer.
|
||||
* @param height The height of the framebuffer.
|
||||
*/
|
||||
void frameBufferSetSize(const int32_t width, const int32_t height);
|
||||
|
||||
/**
|
||||
* Binds the framebuffer.
|
||||
*/
|
||||
void frameBufferBind();
|
||||
|
||||
/**
|
||||
* Unbinds the framebuffer.
|
||||
*/
|
||||
void frameBufferUnbind();
|
||||
|
||||
/**
|
||||
* Binds the framebuffer texture to a slot.
|
||||
*
|
||||
* @param slot The slot to bind the texture to.
|
||||
*/
|
||||
void frameBufferTextureBind(const GLuint slot);
|
||||
|
||||
/**
|
||||
* Unbinds the framebuffer.
|
||||
*/
|
||||
void frameBufferDispose();
|
||||
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assert/assertgl.h"
|
||||
#include "quad.h"
|
||||
|
||||
duskquad_t QUAD;
|
||||
|
||||
void quadInit() {
|
||||
// Create the single quad.
|
||||
const float quadPositions[] = {
|
||||
0.0f, 0.0f, 0.0f, // Bottom-left corner
|
||||
1.0f, 0.0f, 0.0f, // Bottom-right corner
|
||||
1.0f, 1.0f, 0.0f, // Top-right corner
|
||||
0.0f, 1.0f, 0.0f // Top-left corner
|
||||
};
|
||||
|
||||
const float quadUVs[] = {
|
||||
0.0f, 0.0f,
|
||||
1.0f, 0.0f,
|
||||
1.0f, 1.0f,
|
||||
0.0f, 1.0f
|
||||
};
|
||||
|
||||
const uint32_t quadIndices[] = {
|
||||
0, 1, 2,
|
||||
2, 3, 0,
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &QUAD.quadVAO);
|
||||
assertNoGLError();
|
||||
|
||||
glBindVertexArray(QUAD.quadVAO);
|
||||
assertNoGLError();
|
||||
|
||||
// Positions
|
||||
glGenBuffers(1, &QUAD.quadVBO);
|
||||
assertNoGLError();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, QUAD.quadVBO);
|
||||
assertNoGLError();
|
||||
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER, sizeof(quadPositions), quadPositions, GL_STATIC_DRAW
|
||||
);
|
||||
assertNoGLError();
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
assertNoGLError();
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
assertNoGLError();
|
||||
|
||||
// UVs
|
||||
glGenBuffers(1, &QUAD.quadUVVBO);
|
||||
assertNoGLError();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, QUAD.quadUVVBO);
|
||||
assertNoGLError();
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadUVs), quadUVs, GL_STATIC_DRAW);
|
||||
assertNoGLError();
|
||||
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
|
||||
assertNoGLError();
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
assertNoGLError();
|
||||
|
||||
// Indices
|
||||
glGenBuffers(1, &QUAD.quadEBO);
|
||||
assertNoGLError();
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, QUAD.quadEBO);
|
||||
assertNoGLError();
|
||||
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW
|
||||
);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void quadRender(const int32_t count) {
|
||||
glBindVertexArray(QUAD.quadVAO);
|
||||
assertNoGLError();
|
||||
|
||||
glDrawElementsInstanced(
|
||||
GL_TRIANGLES, 6,
|
||||
GL_UNSIGNED_INT, 0,
|
||||
count
|
||||
);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void quadDispose() {
|
||||
glDeleteBuffers(1, &QUAD.quadVBO);
|
||||
assertNoGLError();
|
||||
|
||||
glDeleteBuffers(1, &QUAD.quadEBO);
|
||||
assertNoGLError();
|
||||
|
||||
glDeleteVertexArrays(1, &QUAD.quadVAO);
|
||||
assertNoGLError();
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
|
||||
typedef struct {
|
||||
GLuint quadVBO;
|
||||
GLuint quadUVVBO;
|
||||
GLuint quadVAO;
|
||||
GLuint quadEBO;
|
||||
} duskquad_t;
|
||||
|
||||
extern duskquad_t QUAD;
|
||||
|
||||
/**
|
||||
* Initializes the quad.
|
||||
*/
|
||||
void quadInit();
|
||||
|
||||
/**
|
||||
* Renders quads.
|
||||
*
|
||||
* @param count The number of quads to render.
|
||||
*/
|
||||
void quadRender(const int32_t count);
|
||||
|
||||
/**
|
||||
* Disposes of the quad.
|
||||
*/
|
||||
void quadDispose();
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assert/assertgl.h"
|
||||
#include "util/memory.h"
|
||||
#include "render.h"
|
||||
#include "display/scene.h"
|
||||
#include "display/shader/shadermanager.h"
|
||||
#include "display/quad.h"
|
||||
#include "display/window.h"
|
||||
#include "display/tilesetgl.h"
|
||||
|
||||
render_t RENDER;
|
||||
|
||||
void renderInit() {
|
||||
memoryZero(&RENDER, sizeof(render_t));
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
assertNoGLError();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
assertNoGLError();
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
assertNoGLError();
|
||||
|
||||
shaderManagerInit();
|
||||
quadInit();
|
||||
}
|
||||
|
||||
void renderUpdate() {
|
||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
assertNoGLError();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
assertNoGLError();
|
||||
|
||||
// Update rendering data
|
||||
shaderManagerUpdate();
|
||||
tilesetGLBind();
|
||||
|
||||
// Hand off to the scene to do its rendering.
|
||||
sceneRender();
|
||||
}
|
||||
|
||||
void renderDispose() {
|
||||
quadDispose();
|
||||
shaderManagerDispose();
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
|
||||
typedef struct {
|
||||
int32_t nothing;
|
||||
} render_t;
|
||||
|
||||
extern render_t RENDER;
|
||||
|
||||
/**
|
||||
* Initializes the render system.
|
||||
*/
|
||||
void renderInit();
|
||||
|
||||
/**
|
||||
* Updates the render system.
|
||||
*/
|
||||
void renderUpdate();
|
||||
|
||||
/**
|
||||
* Renders the overworld scene.
|
||||
*/
|
||||
void renderOverworld();
|
||||
|
||||
/**
|
||||
* Disposes of the render system.
|
||||
*/
|
||||
void renderDispose();
|
||||
@@ -1,18 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
shadermanager.c
|
||||
shader.c
|
||||
shaderbuffer.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(entityshader)
|
||||
add_subdirectory(mapshader)
|
||||
add_subdirectory(fragments)
|
||||
@@ -1,13 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
transforms.c
|
||||
entities.c
|
||||
mapshaderdata.c
|
||||
tilesetshaderdata.c
|
||||
)
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entities.h"
|
||||
#include "overworld/overworld.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
shaderbuffer_t ENTITIES_BUFFER;
|
||||
entitiesdata_t ENTITIES_DATA;
|
||||
|
||||
void entitiesInit() {
|
||||
memoryZero(&ENTITIES_DATA, sizeof(entitiesdata_t));
|
||||
shaderBufferInit(&ENTITIES_BUFFER, sizeof(entitiesdata_t));
|
||||
}
|
||||
|
||||
void entitiesUpdate() {
|
||||
for(uint8_t i = 0; i < OVERWORLD.entityCount; i++) {
|
||||
// Pack the entity data into the buffer
|
||||
entity_t *src = &OVERWORLD.entities[i];
|
||||
entitiesdataent_t *dst = &ENTITIES_DATA.entities[i];
|
||||
|
||||
// Copy position data.
|
||||
memoryCopyRangeSafe(
|
||||
&dst->position,
|
||||
&src->x,
|
||||
&src->frame + sizeof(uint8_t),
|
||||
sizeof(uint8_t) * 5
|
||||
);
|
||||
}
|
||||
|
||||
shaderBufferBind(&ENTITIES_BUFFER);
|
||||
shaderBufferSetData(&ENTITIES_BUFFER, &ENTITIES_DATA);
|
||||
}
|
||||
|
||||
void entitiesDispose() {
|
||||
shaderBufferDispose(&ENTITIES_BUFFER);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../../../../dusk/overworld/overworlddefs.h"
|
||||
#include "../fragments/packed.glsl"
|
||||
#include "../fragments/quad.glsl"
|
||||
#include "../data/tilesets.glsl"
|
||||
|
||||
struct Entity {
|
||||
uvec4 position;
|
||||
};
|
||||
|
||||
layout(std140) uniform b_Entities {
|
||||
Entity entities[OVERWORLD_ENTITY_COUNT_MAX];
|
||||
};
|
||||
|
||||
vec2 entityGetSize() {
|
||||
return vec2(float(OVERWORLD_ENTITY_WIDTH), float(OVERWORLD_ENTITY_HEIGHT));
|
||||
}
|
||||
|
||||
vec2 entityGetVertice(uint instanceIndex, uint indiceIndex) {
|
||||
// Get base quad vertice
|
||||
vec2 vert = quadGetVertice(indiceIndex);
|
||||
|
||||
uint x = packedGetU8(0u, entities[instanceIndex].position);
|
||||
uint y = packedGetU8(1u, entities[instanceIndex].position);
|
||||
int subX = packedGetI8(2u, entities[instanceIndex].position);
|
||||
int subY = packedGetI8(3u, entities[instanceIndex].position);
|
||||
|
||||
vert.x += float(x);
|
||||
vert.y += float(y);
|
||||
|
||||
vert *= entityGetSize();
|
||||
|
||||
vert.x += float(subX);
|
||||
vert.y += float(subY);
|
||||
|
||||
return vert;
|
||||
}
|
||||
|
||||
vec2 entityGetUV(uint instanceIndex, uint indiceIndex) {
|
||||
uint frame = packedGetU8(4u, entities[instanceIndex].position);
|
||||
vec4 tilesetUVs = tilesetGetUVsByIndex(uint(TILESET_SLOT_ENTITIES), frame);
|
||||
vec2 uv = quadGetTextureCoordinate(indiceIndex, tilesetUVs);
|
||||
return uv;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/shaderbuffer.h"
|
||||
#include "overworld/overworld.h"
|
||||
|
||||
#define ENTITIES_BLOCK_NAME "b_Entities"
|
||||
|
||||
typedef struct {
|
||||
uvec4_t position;
|
||||
} entitiesdataent_t;
|
||||
|
||||
typedef struct {
|
||||
entitiesdataent_t entities[OVERWORLD_ENTITY_COUNT_MAX];
|
||||
} entitiesdata_t;
|
||||
|
||||
extern shaderbuffer_t ENTITIES_BUFFER;
|
||||
extern entitiesdata_t ENTITIES_DATA;
|
||||
|
||||
/**
|
||||
* Initializes the entities buffer and data.
|
||||
*/
|
||||
void entitiesInit();
|
||||
|
||||
/**
|
||||
* Updates the entities buffer with the current data.
|
||||
*/
|
||||
void entitiesUpdate();
|
||||
|
||||
/**
|
||||
* Destroys the entities buffer.
|
||||
*/
|
||||
void entitiesDispose();
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../../../../dusk/overworld/overworlddefs.h"
|
||||
#include "../fragments/packed.glsl"
|
||||
#include "../fragments/quad.glsl"
|
||||
|
||||
#define MAP_TILE_PACKED_SIZE 16
|
||||
|
||||
layout(std140) uniform b_Map {
|
||||
uvec4 mapTileIds[OVERWORLD_TILE_COUNT_MAX / MAP_TILE_PACKED_SIZE];
|
||||
uvec4 mapSize;
|
||||
};
|
||||
|
||||
vec2 mapTileGetSize() {
|
||||
return vec2(float(OVERWORLD_TILE_WIDTH), float(OVERWORLD_TILE_HEIGHT));
|
||||
}
|
||||
|
||||
vec2 mapGetVertice(uint instanceIndex, uint indiceIndex) {
|
||||
vec2 quad = quadGetVertice(indiceIndex);
|
||||
|
||||
uint mapWidth = packedGetU8(0u, mapSize);
|
||||
uint mapHeight = packedGetU8(1u, mapSize);
|
||||
uint mapLayerCount = packedGetU8(2u, mapSize);
|
||||
|
||||
// Get x and y within layer
|
||||
uint x = instanceIndex % mapWidth;
|
||||
uint y = (instanceIndex / mapWidth) % mapHeight;
|
||||
|
||||
// Get quad position, consider layer count
|
||||
quad += vec2(x, y);
|
||||
quad *= mapTileGetSize();
|
||||
|
||||
return quad;
|
||||
}
|
||||
|
||||
uint mapGetLayer(uint instanceIndex) {
|
||||
uint mapWidth = packedGetU8(0u, mapSize);
|
||||
uint mapHeight = packedGetU8(1u, mapSize);
|
||||
return instanceIndex / (mapWidth * mapHeight);
|
||||
}
|
||||
|
||||
uint mapGetTileId(uint instanceIndex) {
|
||||
uvec4 v4 = mapTileIds[packedArrayGetU8IndexFromUVEC4Array(instanceIndex)];
|
||||
return packedArrayGetU8FromUVEC4ArrayValue(instanceIndex, v4);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "mapshaderdata.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
shaderbuffer_t MAP_SHADER_DATA_BUFFER;
|
||||
mapshaderdata_t MAP_SHADER_DATA_DATA;
|
||||
|
||||
void mapShaderDataInit() {
|
||||
memoryZero(&MAP_SHADER_DATA_DATA, sizeof(mapshaderdata_t));
|
||||
shaderBufferInit(&MAP_SHADER_DATA_BUFFER, sizeof(mapshaderdata_t));
|
||||
|
||||
assertTrue(
|
||||
sizeof(MAP_SHADER_DATA_DATA.tileIds) == sizeof(OVERWORLD.map.tileIds),
|
||||
"Map shader tile data and Overworld tile data are not the same size."
|
||||
);
|
||||
}
|
||||
|
||||
void mapShaderDataUpdate() {
|
||||
// Copy tile ids.
|
||||
memoryCopyRangeSafe(
|
||||
MAP_SHADER_DATA_DATA.tileIds,
|
||||
OVERWORLD.map.tileIds,
|
||||
&OVERWORLD.map.tileIds[
|
||||
OVERWORLD.map.width * OVERWORLD.map.height * OVERWORLD.map.layerCount
|
||||
],
|
||||
sizeof(MAP_SHADER_DATA_DATA.tileIds)
|
||||
);
|
||||
|
||||
// Copy map size.
|
||||
memoryCopyRangeSafe(
|
||||
&MAP_SHADER_DATA_DATA.mapSize,
|
||||
&OVERWORLD.map.width,
|
||||
&OVERWORLD.map.layerCount + sizeof(uint8_t),
|
||||
sizeof(uint8_t) * 3
|
||||
);
|
||||
|
||||
shaderBufferBind(&MAP_SHADER_DATA_BUFFER);
|
||||
shaderBufferSetData(&MAP_SHADER_DATA_BUFFER, &MAP_SHADER_DATA_DATA);
|
||||
}
|
||||
|
||||
void mapShaderDataDispose() {
|
||||
shaderBufferDispose(&MAP_SHADER_DATA_BUFFER);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma ocne
|
||||
#include "display/shader/shaderbuffer.h"
|
||||
#include "overworld/overworld.h"
|
||||
|
||||
#define MAP_BLOCK_NAME "b_Map"
|
||||
#define MAP_TILE_PACK_SIZE sizeof(uvec4_t) / sizeof(tileid_t)
|
||||
|
||||
typedef struct {
|
||||
uvec4_t tileIds[OVERWORLD_TILE_COUNT_MAX / MAP_TILE_PACK_SIZE];
|
||||
uvec4_t mapSize;
|
||||
} mapshaderdata_t;
|
||||
|
||||
extern shaderbuffer_t MAP_SHADER_DATA_BUFFER;
|
||||
extern mapshaderdata_t MAP_SHADER_DATA_DATA;
|
||||
|
||||
/**
|
||||
* Initializes the map buffer and data.
|
||||
*/
|
||||
void mapShaderDataInit();
|
||||
|
||||
/**
|
||||
* Updates the map buffer with the current data.
|
||||
*/
|
||||
void mapShaderDataUpdate();
|
||||
|
||||
/**
|
||||
* Destroys the map buffer.
|
||||
*/
|
||||
void mapShaderDataDispose();
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../../../../dusk/display/tilesetdefs.h"
|
||||
#include "../fragments/packed.glsl"
|
||||
|
||||
struct Tileset {
|
||||
uvec4 tileset;
|
||||
};
|
||||
|
||||
layout(std140) uniform b_Tilesets {
|
||||
Tileset tilesets[TILESET_SLOT_COUNT];
|
||||
};
|
||||
|
||||
uniform sampler2D u_TilesetTextures[TILESET_SLOT_COUNT];
|
||||
|
||||
uint tilesetGetColumns(uint tilesetIndex) {
|
||||
return packedGetU32(0u, tilesets[tilesetIndex].tileset);
|
||||
}
|
||||
|
||||
uint tilesetGetRows(uint tilesetIndex) {
|
||||
return packedGetU32(1u, tilesets[tilesetIndex].tileset);
|
||||
}
|
||||
|
||||
uint tilesetGetWidth(uint tilesetIndex) {
|
||||
return packedGetU32(2u, tilesets[tilesetIndex].tileset);
|
||||
}
|
||||
|
||||
uint tilesetGetHeight(uint tilesetIndex) {
|
||||
return packedGetU32(3u, tilesets[tilesetIndex].tileset);
|
||||
}
|
||||
|
||||
vec4 tilesetGetUVs(uint tilesetIndex, uint col, uint row) {
|
||||
Tileset tileset = tilesets[tilesetIndex];
|
||||
float segWidth = 1.0 / float(tilesetGetColumns(tilesetIndex));
|
||||
float segHeight = 1.0 / float(tilesetGetRows(tilesetIndex));
|
||||
float x = float(col) * segWidth;
|
||||
float y = float(row) * segHeight;
|
||||
return vec4(x, y, x + segWidth, y + segHeight);
|
||||
}
|
||||
|
||||
vec4 tilesetGetUVsByIndex(uint tilesetIndex, uint index) {
|
||||
Tileset tileset = tilesets[tilesetIndex];
|
||||
uint col = index % tilesetGetColumns(tilesetIndex);
|
||||
uint row = index / tilesetGetColumns(tilesetIndex);
|
||||
return tilesetGetUVs(tilesetIndex, col, row);
|
||||
}
|
||||
|
||||
vec4 tilesetGetColor(uint tilesetIndex, vec2 coord) {
|
||||
switch(tilesetIndex) {
|
||||
case 0u:
|
||||
return texture(u_TilesetTextures[0], coord);
|
||||
case 1u:
|
||||
return texture(u_TilesetTextures[1], coord);
|
||||
case 2u:
|
||||
return texture(u_TilesetTextures[2], coord);
|
||||
case 3u:
|
||||
return texture(u_TilesetTextures[3], coord);
|
||||
default:
|
||||
return vec4(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "tilesetshaderdata.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "display/shader/shader.h"
|
||||
|
||||
shaderbuffer_t TILESET_SHADER_DATA_BUFFER;
|
||||
tilesetshaderdata_t TILESET_SHADER_DATA_DATA;
|
||||
GLuint TILESET_SHADER_DATA_TEXTURES[TILESET_SLOT_COUNT];
|
||||
|
||||
void tilesetShaderDataInit() {
|
||||
memoryZero(&TILESET_SHADER_DATA_DATA, sizeof(tilesetshaderdata_t));
|
||||
shaderBufferInit(&TILESET_SHADER_DATA_BUFFER, sizeof(tilesetshaderdata_t));
|
||||
|
||||
assertTrue(
|
||||
sizeof(tilesetshaderdata_t) == sizeof(uvec4_t) * TILESET_SLOT_COUNT,
|
||||
"Tileset Shader Data size mismatch"
|
||||
);
|
||||
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
TILESET_SHADER_DATA_TEXTURES[i] = i;
|
||||
} while(++i < TILESET_SLOT_COUNT);
|
||||
}
|
||||
|
||||
void tilesetShaderDataUpdate() {
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
tilesetid_t id = TILESET_SLOTS[i];
|
||||
if(id == TILESET_NULL) continue;
|
||||
tileset_t *tileset = &TILESETS[id];
|
||||
texture_t *texture = &TILESET_GL_TEXTURES[i];
|
||||
tilesetshaderdatatileset_t *dest = &TILESET_SHADER_DATA_DATA.tilesets[i];
|
||||
|
||||
dest->columns = tileset->columns;
|
||||
dest->rows = tileset->rows;
|
||||
dest->width = texture->width;
|
||||
dest->height = texture->height;
|
||||
} while(++i < TILESET_SLOT_COUNT);
|
||||
|
||||
shaderBufferBind(&TILESET_SHADER_DATA_BUFFER);
|
||||
shaderBufferSetData(&TILESET_SHADER_DATA_BUFFER, &TILESET_SHADER_DATA_DATA);
|
||||
}
|
||||
|
||||
void tilesetShaderTexturesBind(const GLuint uniform) {
|
||||
shaderSetTextures(uniform, TILESET_SHADER_DATA_TEXTURES, TILESET_SLOT_COUNT);
|
||||
}
|
||||
|
||||
void tilesetShaderDataDispose() {
|
||||
shaderBufferDispose(&TILESET_SHADER_DATA_BUFFER);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/shaderbuffer.h"
|
||||
#include "display/tilesetgl.h"
|
||||
|
||||
#define TILESET_SHADER_DATA_BLOCK_NAME "b_Tilesets"
|
||||
#define TILESET_UNIFORM_TEXTURES_NAME "u_TilesetTextures"
|
||||
|
||||
typedef struct {
|
||||
uint32_t columns;
|
||||
uint32_t rows;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} tilesetshaderdatatileset_t;
|
||||
|
||||
typedef struct {
|
||||
tilesetshaderdatatileset_t tilesets[TILESET_SLOT_COUNT];
|
||||
} tilesetshaderdata_t;
|
||||
|
||||
extern shaderbuffer_t TILESET_SHADER_DATA_BUFFER;
|
||||
extern tilesetshaderdata_t TILESET_SHADER_DATA_DATA;
|
||||
extern GLuint TILESET_SHADER_DATA_TEXTURES[];
|
||||
|
||||
/**
|
||||
* Initializes the tileset buffer and data.
|
||||
*/
|
||||
void tilesetShaderDataInit();
|
||||
|
||||
/**
|
||||
* Updates the tileset buffer with the current data.
|
||||
*/
|
||||
void tilesetShaderDataUpdate();
|
||||
|
||||
/**
|
||||
* Binds the tileset textures to the given uniform.
|
||||
*
|
||||
* @param uniform The uniform to bind the textures to.
|
||||
*/
|
||||
void tilesetShaderTexturesBind(const GLuint uniform);
|
||||
|
||||
/**
|
||||
* Destroys the tileset buffer.
|
||||
*/
|
||||
void tilesetShaderDataDispose();
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "transforms.h"
|
||||
#include "display/window.h"
|
||||
|
||||
shaderbuffer_t TRANSFORMS_BUFFER;
|
||||
transformsdata_t TRANSFORMS_DATA;
|
||||
|
||||
void transformsInit() {
|
||||
memset(&TRANSFORMS_DATA, 0, sizeof(transformsdata_t));
|
||||
shaderBufferInit(&TRANSFORMS_BUFFER, sizeof(transformsdata_t));
|
||||
|
||||
glm_mat4_identity(TRANSFORMS_DATA.projection);
|
||||
glm_mat4_identity(TRANSFORMS_DATA.view);
|
||||
|
||||
TRANSFORMS_DATA.resolution[0] = WINDOW_WIDTH;
|
||||
TRANSFORMS_DATA.resolution[1] = WINDOW_HEIGHT;
|
||||
}
|
||||
|
||||
void transformsUpdate() {
|
||||
TRANSFORMS_DATA.resolution[0] = WINDOW_WIDTH;
|
||||
TRANSFORMS_DATA.resolution[1] = WINDOW_HEIGHT;
|
||||
|
||||
glm_perspective(
|
||||
glm_rad(45.0f),
|
||||
TRANSFORMS_DATA.resolution[0] / TRANSFORMS_DATA.resolution[1],
|
||||
0.5f,
|
||||
1000.0f,
|
||||
TRANSFORMS_DATA.projection
|
||||
);
|
||||
|
||||
glm_lookat(
|
||||
(vec3){ 0, 0, 300 },
|
||||
(vec3){ 0, 32, 0 },
|
||||
(vec3){ 0, 1, 0 },
|
||||
TRANSFORMS_DATA.view
|
||||
);
|
||||
|
||||
shaderBufferBind(&TRANSFORMS_BUFFER);
|
||||
shaderBufferSetData(&TRANSFORMS_BUFFER, &TRANSFORMS_DATA);
|
||||
}
|
||||
|
||||
void transformsDispose() {
|
||||
shaderBufferDispose(&TRANSFORMS_BUFFER);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../../../../dusk/display/displaydefs.h"
|
||||
|
||||
struct Transform {
|
||||
mat4 projection;
|
||||
mat4 view;
|
||||
vec2 resolution;
|
||||
};
|
||||
|
||||
layout(std140) uniform b_Transforms {
|
||||
Transform transforms;
|
||||
};
|
||||
|
||||
vec2 transformDisplayGetSize() {
|
||||
return vec2(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
}
|
||||
|
||||
float transformDisplayGetAspectRatio() {
|
||||
return (float(SCREEN_WIDTH) / float(SCREEN_HEIGHT));
|
||||
}
|
||||
|
||||
vec2 transformResolutionGetSize() {
|
||||
return transforms.resolution;
|
||||
}
|
||||
|
||||
float transformResolutionGetAspectRatio() {
|
||||
return (transforms.resolution.x / transforms.resolution.y);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/shaderbuffer.h"
|
||||
|
||||
#define TRANSFORMS_BLOCK_NAME "b_Transforms"
|
||||
|
||||
typedef struct {
|
||||
mat4 projection;
|
||||
mat4 view;
|
||||
vec2 resolution;
|
||||
} transformsdata_t;
|
||||
|
||||
extern shaderbuffer_t TRANSFORMS_BUFFER;
|
||||
extern transformsdata_t TRANSFORMS_DATA;
|
||||
|
||||
/**
|
||||
* Initializes the transforms buffer and data.
|
||||
*/
|
||||
void transformsInit();
|
||||
|
||||
/**
|
||||
* Updates the transforms buffer with the current data.
|
||||
*/
|
||||
void transformsUpdate();
|
||||
|
||||
/**
|
||||
* Destroys the transforms buffer.
|
||||
*/
|
||||
void transformsDispose();
|
||||
@@ -1,14 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Shaders
|
||||
glsltool(entity_vert.glsl)
|
||||
glsltool(entity_frag.glsl)
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
entityshader.c
|
||||
)
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../fragments/header.glsl"
|
||||
#include "../data/entities.glsl"
|
||||
#include "../data/tilesets.glsl"
|
||||
|
||||
// Inputs from vertex shader
|
||||
in vec2 v_TextureCoord;
|
||||
|
||||
// Frag pixel color
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
vec4 tColor = tilesetGetColor(uint(TILESET_SLOT_ENTITIES), v_TextureCoord);
|
||||
if(tColor.a == 0.0) discard;
|
||||
if(tColor.r == 0.0) discard;
|
||||
FragColor = vec4(1, 1, 1, 1) * tColor;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../fragments/header.glsl"
|
||||
#include "../data/transforms.glsl"
|
||||
#include "../data/entities.glsl"
|
||||
|
||||
// Outputs to fragment shader
|
||||
out vec2 v_TextureCoord;
|
||||
|
||||
void main() {
|
||||
uint instanceIndex = uint(gl_InstanceID);
|
||||
uint indiceIndex = quadGetIndiceIndex(gl_VertexID);
|
||||
|
||||
vec2 vert = entityGetVertice(instanceIndex, indiceIndex);
|
||||
vec2 uv = entityGetUV(instanceIndex, indiceIndex);
|
||||
|
||||
gl_Position = transforms.projection * transforms.view * vec4(vert, 0.0, 1.0);
|
||||
v_TextureCoord = uv;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assert/assert.h"
|
||||
#include "assert/assertgl.h"
|
||||
#include "util/memory.h"
|
||||
#include "entityshader.h"
|
||||
#include "entity_vert.glsl.h"
|
||||
#include "entity_frag.glsl.h"
|
||||
#include "display/shader/data/transforms.h"
|
||||
#include "display/shader/data/entities.h"
|
||||
#include "display/shader/data/tilesetshaderdata.h"
|
||||
|
||||
entityshader_t ENTITY_SHADER;
|
||||
|
||||
void entityShaderInit() {
|
||||
memoryZero(&ENTITY_SHADER, sizeof(entityshader_t));
|
||||
|
||||
shaderInit(
|
||||
&ENTITY_SHADER.shader,
|
||||
entity_vertShaderSource,
|
||||
entity_fragShaderSource
|
||||
);
|
||||
|
||||
// Uniform buffers
|
||||
ENTITY_SHADER.transformsBlock = shaderGetBlock(
|
||||
&ENTITY_SHADER.shader,
|
||||
TRANSFORMS_BLOCK_NAME
|
||||
);
|
||||
|
||||
ENTITY_SHADER.entitiesBlock = shaderGetBlock(
|
||||
&ENTITY_SHADER.shader,
|
||||
ENTITIES_BLOCK_NAME
|
||||
);
|
||||
|
||||
ENTITY_SHADER.tilesetsBlock = shaderGetBlock(
|
||||
&ENTITY_SHADER.shader,
|
||||
TILESET_SHADER_DATA_BLOCK_NAME
|
||||
);
|
||||
|
||||
// Uniforms
|
||||
ENTITY_SHADER.tilesetTexturesUniform = shaderGetUniform(
|
||||
&ENTITY_SHADER.shader,
|
||||
TILESET_UNIFORM_TEXTURES_NAME
|
||||
);
|
||||
}
|
||||
|
||||
void entityShaderUse() {
|
||||
shaderUse(&ENTITY_SHADER.shader);
|
||||
shaderBufferBindToBlock(&TRANSFORMS_BUFFER, ENTITY_SHADER.transformsBlock);
|
||||
shaderBufferBindToBlock(&ENTITIES_BUFFER, ENTITY_SHADER.entitiesBlock);
|
||||
shaderBufferBindToBlock(
|
||||
&TILESET_SHADER_DATA_BUFFER, ENTITY_SHADER.tilesetsBlock
|
||||
);
|
||||
tilesetShaderTexturesBind(ENTITY_SHADER.tilesetTexturesUniform);
|
||||
}
|
||||
|
||||
void entityShaderDispose() {
|
||||
shaderDispose(&ENTITY_SHADER.shader);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/shader.h"
|
||||
|
||||
typedef struct {
|
||||
shader_t shader;
|
||||
|
||||
GLuint entitiesBlock;
|
||||
GLuint transformsBlock;
|
||||
GLuint tilesetsBlock;
|
||||
|
||||
GLuint tilesetTexturesUniform;
|
||||
} entityshader_t;
|
||||
|
||||
extern entityshader_t ENTITY_SHADER;
|
||||
|
||||
/**
|
||||
* Initializes the entity shader.
|
||||
*/
|
||||
void entityShaderInit();
|
||||
|
||||
/**
|
||||
* Uses the entity shader.
|
||||
*/
|
||||
void entityShaderUse();
|
||||
|
||||
/**
|
||||
* Disposes of the entity shader.
|
||||
*/
|
||||
void entityShaderDispose();
|
||||
@@ -1,9 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
)
|
||||
@@ -1,6 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#version 330 core
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#define PACKED_U8_PER_UI 4
|
||||
#define PACKED_U8_PER_UVEC4 PACKED_U8_PER_UI * 4
|
||||
|
||||
uint packedGetU8(uint position, uvec4 data) {
|
||||
uint subData = data[position / 4u];
|
||||
return (subData >> (position * 8u)) & 0xFFu;
|
||||
}
|
||||
|
||||
uint packedGetU32(uint position, uvec4 data) {
|
||||
return data[position];
|
||||
}
|
||||
|
||||
int packedGetI8(uint position, uvec4 data) {
|
||||
uint subData = data[position / 4u];
|
||||
|
||||
int shift = int(position * 8u);
|
||||
return int(subData << (24 - shift)) >> 24;
|
||||
}
|
||||
|
||||
uint packedArrayGetU8IndexFromUVEC4Array(uint u8ArrayIndex) {
|
||||
// Given a uint8_t array is uploaded, this will return the index to get the
|
||||
// appropriate uvec4 from a uvec4 array that will be at the right index.
|
||||
return u8ArrayIndex / uint(PACKED_U8_PER_UVEC4);
|
||||
}
|
||||
|
||||
uint packedArrayGetU8FromUVEC4ArrayValue(uint u8ArrayIndex, uvec4 data) {
|
||||
// Given a value from a uint8_t array, this will return the value at the
|
||||
// appropriate index. You must first get the uvec4 from the array using
|
||||
// packedArrayGetU8IndexFromUVEC4Array.
|
||||
uint subIndex = (u8ArrayIndex % uint(PACKED_U8_PER_UVEC4)) / uint(PACKED_U8_PER_UI);
|
||||
uint shiftAmount = (u8ArrayIndex % uint(PACKED_U8_PER_UI)) * 8u;
|
||||
uint value = (data[subIndex] >> shiftAmount) & 0xFFu;
|
||||
return value;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
uint quadGetIndiceIndex(uint vertexId) {
|
||||
return vertexId % 6u;
|
||||
}
|
||||
|
||||
uint quadGetIndiceIndex(int vertexId) {
|
||||
return quadGetIndiceIndex(uint(vertexId));
|
||||
}
|
||||
|
||||
vec2 quadGetVertice(uint indiceIndex) {
|
||||
vec2 vert = vec2(0, 0);
|
||||
|
||||
/*if(indiceIndex == 0u || indiceIndex == 4u) {
|
||||
// vert = vec2(0, 0);
|
||||
} else*/ if(indiceIndex == 1u) {
|
||||
vert = vec2(1, 0);
|
||||
} else if(indiceIndex == 2u || indiceIndex == 5u) {
|
||||
vert = vec2(1, 1);
|
||||
} else if(indiceIndex == 3u) {
|
||||
vert = vec2(0, 1);
|
||||
}
|
||||
|
||||
return vert;
|
||||
}
|
||||
|
||||
vec2 quadGetTextureCoordinate(uint indiceIndex) {
|
||||
vec2 vert = quadGetVertice(indiceIndex);
|
||||
return vert;
|
||||
}
|
||||
|
||||
vec2 quadGetTextureCoordinate(uint indiceIndex, vec4 uv) {
|
||||
vec2 vert = quadGetVertice(indiceIndex);
|
||||
vert.y = 1.0 - vert.y;
|
||||
return vec2(uv.x + (uv.z - uv.x) * vert.x, uv.y + (uv.w - uv.y) * vert.y);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Shaders
|
||||
glsltool(map_vert.glsl)
|
||||
glsltool(map_frag.glsl)
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
mapshader.c
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../fragments/header.glsl"
|
||||
#include "../data/map.glsl"
|
||||
|
||||
// Inputs from vertex shader
|
||||
in vec2 v_TextureCoord;
|
||||
flat in uint v_InstanceIndex;
|
||||
flat in uint v_IndiceIndex;
|
||||
|
||||
// Frag pixel color
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
uint layer = mapGetLayer(v_InstanceIndex);
|
||||
uint tileId = mapGetTileId(v_InstanceIndex);
|
||||
|
||||
if(tileId == 0u) {
|
||||
FragColor = vec4(1, 0, 0, 1);
|
||||
} else if(tileId == 1u) {
|
||||
FragColor = vec4(0, 1, 0, 1);
|
||||
} else {
|
||||
FragColor = vec4(0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright (c) 2025 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "../fragments/header.glsl"
|
||||
#include "../data/transforms.glsl"
|
||||
#include "../data/map.glsl"
|
||||
|
||||
// Outputs to fragment shader
|
||||
out vec2 v_TextureCoord;
|
||||
flat out uint v_InstanceIndex;
|
||||
flat out uint v_IndiceIndex;
|
||||
|
||||
void main() {
|
||||
uint instanceIndex = uint(gl_InstanceID);
|
||||
uint indiceIndex = quadGetIndiceIndex(gl_VertexID);
|
||||
|
||||
uint layer = mapGetLayer(instanceIndex);
|
||||
vec2 vert = mapGetVertice(instanceIndex, indiceIndex);
|
||||
vec2 uv = quadGetTextureCoordinate(indiceIndex);
|
||||
|
||||
gl_Position = transforms.projection * transforms.view * vec4(vert, float(layer) * 64.0, 1.0);
|
||||
|
||||
v_TextureCoord = uv;
|
||||
v_InstanceIndex = instanceIndex;
|
||||
v_IndiceIndex = indiceIndex;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "mapshader.h"
|
||||
#include "util/memory.h"
|
||||
#include "display/shader/data/mapshaderdata.h"
|
||||
#include "display/shader/data/transforms.h"
|
||||
#include "map_vert.glsl.h"
|
||||
#include "map_frag.glsl.h"
|
||||
|
||||
mapshader_t MAP_SHADER;
|
||||
|
||||
void mapShaderInit() {
|
||||
memoryZero(&MAP_SHADER, sizeof(mapshader_t));
|
||||
|
||||
shaderInit(
|
||||
&MAP_SHADER.shader,
|
||||
map_vertShaderSource,
|
||||
map_fragShaderSource
|
||||
);
|
||||
|
||||
// Uniform blocks
|
||||
MAP_SHADER.mapBlock = shaderGetBlock(
|
||||
&MAP_SHADER.shader,
|
||||
MAP_BLOCK_NAME
|
||||
);
|
||||
|
||||
MAP_SHADER.transformsBlock = shaderGetBlock(
|
||||
&MAP_SHADER.shader,
|
||||
TRANSFORMS_BLOCK_NAME
|
||||
);
|
||||
}
|
||||
|
||||
void mapShaderUse() {
|
||||
shaderUse(&MAP_SHADER.shader);
|
||||
shaderBufferBindToBlock(&MAP_SHADER_DATA_BUFFER, MAP_SHADER.mapBlock);
|
||||
shaderBufferBindToBlock(&TRANSFORMS_BUFFER, MAP_SHADER.transformsBlock);
|
||||
}
|
||||
|
||||
void mapShaderDispose() {
|
||||
shaderDispose(&MAP_SHADER.shader);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/shader.h"
|
||||
|
||||
typedef struct {
|
||||
shader_t shader;
|
||||
GLuint mapBlock;
|
||||
GLuint transformsBlock;
|
||||
} mapshader_t;
|
||||
|
||||
extern mapshader_t MAP_SHADER;
|
||||
|
||||
/**
|
||||
* Initializes the map shader.
|
||||
*/
|
||||
void mapShaderInit();
|
||||
|
||||
/**
|
||||
* Uses the map shader.
|
||||
*/
|
||||
void mapShaderUse();
|
||||
|
||||
/**
|
||||
* Destroys the map shader.
|
||||
*/
|
||||
void mapShaderDispose();
|
||||
@@ -1,146 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "shader.h"
|
||||
#include "assert/assert.h"
|
||||
#include "assert/assertgl.h"
|
||||
|
||||
void shaderInit(
|
||||
shader_t *shader,
|
||||
const char *vertexSource,
|
||||
const char *fragmentSource
|
||||
) {
|
||||
assertNotNull(shader, "shader must not be NULL");
|
||||
assertNotNull(vertexSource, "vertexSource must not be NULL");
|
||||
assertNotNull(fragmentSource, "fragmentSource must not be NULL");
|
||||
|
||||
int32_t success;
|
||||
char infoLog[SHADER_LOG_LENGTH];
|
||||
|
||||
// Create vertex shader
|
||||
shader->vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
assertNoGLError();
|
||||
|
||||
glShaderSource(shader->vertexShader, 1, &vertexSource, NULL);
|
||||
assertNoGLError();
|
||||
|
||||
glCompileShader(shader->vertexShader);
|
||||
assertNoGLError();
|
||||
|
||||
glGetShaderiv(shader->vertexShader, GL_COMPILE_STATUS, &success);
|
||||
assertNoGLError();
|
||||
|
||||
if(!success) {
|
||||
glGetShaderInfoLog(
|
||||
shader->vertexShader, SHADER_LOG_LENGTH, NULL, infoLog
|
||||
);
|
||||
assertNoGLError();
|
||||
assertUnreachable(infoLog);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create fragment shader
|
||||
shader->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
assertNoGLError();
|
||||
|
||||
glShaderSource(shader->fragmentShader, 1, &fragmentSource, NULL);
|
||||
assertNoGLError();
|
||||
|
||||
glCompileShader(shader->fragmentShader);
|
||||
assertNoGLError();
|
||||
|
||||
glGetShaderiv(shader->fragmentShader, GL_COMPILE_STATUS, &success);
|
||||
assertNoGLError();
|
||||
|
||||
if(!success) {
|
||||
glGetShaderInfoLog(
|
||||
shader->fragmentShader, SHADER_LOG_LENGTH, NULL, infoLog
|
||||
);
|
||||
assertNoGLError();
|
||||
assertUnreachable(infoLog);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create shader program
|
||||
shader->shaderProgram = glCreateProgram();
|
||||
assertNoGLError();
|
||||
|
||||
glAttachShader(shader->shaderProgram, shader->vertexShader);
|
||||
assertNoGLError();
|
||||
|
||||
glAttachShader(shader->shaderProgram, shader->fragmentShader);
|
||||
assertNoGLError();
|
||||
|
||||
glLinkProgram(shader->shaderProgram);
|
||||
assertNoGLError();
|
||||
|
||||
glGetProgramiv(shader->shaderProgram, GL_LINK_STATUS, &success);
|
||||
assertNoGLError();
|
||||
|
||||
if(!success) {
|
||||
glGetProgramInfoLog(shader->shaderProgram, SHADER_LOG_LENGTH, NULL, infoLog);
|
||||
assertNoGLError();
|
||||
assertUnreachable(infoLog);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void shaderUse(const shader_t *shader) {
|
||||
assertNotNull(shader, "shader must not be NULL");
|
||||
|
||||
glUseProgram(shader->shaderProgram);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
GLuint shaderGetUniform(const shader_t *shader, const char_t *name) {
|
||||
assertNotNull(shader, "shader must not be NULL");
|
||||
assertNotNull(name, "name must not be NULL");
|
||||
|
||||
GLuint uniform = glGetUniformLocation(shader->shaderProgram, name);
|
||||
assertNoGLError();
|
||||
|
||||
return uniform;
|
||||
}
|
||||
|
||||
GLuint shaderGetBlock(const shader_t *shader, const char *name) {
|
||||
assertNotNull(shader, "shader must not be NULL");
|
||||
assertNotNull(name, "name must not be NULL");
|
||||
|
||||
GLuint blockIndex = glGetUniformBlockIndex(shader->shaderProgram, name);
|
||||
assertNoGLError();
|
||||
|
||||
// TODO: I really don't think this should be here at all.
|
||||
glUniformBlockBinding(shader->shaderProgram, blockIndex, blockIndex);
|
||||
assertNoGLError();
|
||||
|
||||
return blockIndex;
|
||||
}
|
||||
|
||||
void shaderSetTextures(
|
||||
const GLuint uniform,
|
||||
const GLuint *textures,
|
||||
const uint8_t count
|
||||
) {
|
||||
assertNotNull(textures, "textures must not be NULL");
|
||||
assertTrue(count > 0, "count must be greater than 0");
|
||||
|
||||
glUniform1iv(uniform, count, textures);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void shaderDispose(shader_t *shader) {
|
||||
assertNotNull(shader, "shader must not be NULL");
|
||||
|
||||
glDeleteProgram(shader->shaderProgram);
|
||||
assertNoGLError();
|
||||
|
||||
glDeleteShader(shader->vertexShader);
|
||||
assertNoGLError();
|
||||
|
||||
glDeleteShader(shader->fragmentShader);
|
||||
assertNoGLError();
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
|
||||
#define SHADER_LOG_LENGTH 512
|
||||
|
||||
typedef struct {
|
||||
GLuint shaderProgram;
|
||||
GLuint vertexShader;
|
||||
GLuint fragmentShader;
|
||||
} shader_t;
|
||||
|
||||
/**
|
||||
* Initializes a shader.
|
||||
*
|
||||
* @param shader The shader to initialize.
|
||||
* @param vertexSource The vertex shader source.
|
||||
* @param fragmentSource The fragment shader source.
|
||||
*/
|
||||
void shaderInit(
|
||||
shader_t *shader,
|
||||
const char_t *vertexSource,
|
||||
const char_t *fragmentSource
|
||||
);
|
||||
|
||||
/**
|
||||
* Uses a shader.
|
||||
*
|
||||
* @param shader The shader to use.
|
||||
*/
|
||||
void shaderUse(const shader_t *shader);
|
||||
|
||||
/**
|
||||
* Gets a uniform from a shader.
|
||||
*
|
||||
* @param shader The shader to get the uniform from.
|
||||
* @param name The name of the uniform.
|
||||
* @return The uniform.
|
||||
*/
|
||||
GLuint shaderGetUniform(const shader_t *shader, const char_t *name);
|
||||
|
||||
/**
|
||||
* Gets a block id from a shader.
|
||||
*
|
||||
* @param shader The shader to get the block from.
|
||||
* @param name The name of the block.
|
||||
* @return The block index/identifier.
|
||||
*/
|
||||
GLuint shaderGetBlock(const shader_t *shader, const char_t *name);
|
||||
|
||||
/**
|
||||
* Sets texture uniforms to a shader.
|
||||
*
|
||||
* @param uniform The uniform to set.
|
||||
* @param textures The textures to set.
|
||||
* @param count The number of textures to set.
|
||||
*/
|
||||
void shaderSetTextures(
|
||||
const GLuint uniform,
|
||||
const GLuint *textures,
|
||||
const uint8_t count
|
||||
);
|
||||
|
||||
/**
|
||||
* Disposes of a shader.
|
||||
*
|
||||
* @param shader The shader to dispose of.
|
||||
*/
|
||||
void shaderDispose(shader_t *shader);
|
||||
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assert/assert.h"
|
||||
#include "shaderbuffer.h"
|
||||
#include "assert/assertgl.h"
|
||||
|
||||
void shaderBufferInit(shaderbuffer_t *shaderBuffer, const size_t size) {
|
||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||
assertTrue(size > 0, "size must be greater than 0.");
|
||||
|
||||
shaderBuffer->size = size;
|
||||
|
||||
glGenBuffers(1, &shaderBuffer->id);
|
||||
assertNoGLError();
|
||||
|
||||
shaderBufferBind(shaderBuffer);
|
||||
|
||||
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
void shaderBufferBind(shaderbuffer_t *shaderBuffer) {
|
||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, shaderBuffer->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void shaderBufferSetData(shaderbuffer_t *shaderBuffer, const void *data) {
|
||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||
assertNotNull(data, "data cannot be NULL.");
|
||||
|
||||
glBufferData(GL_UNIFORM_BUFFER, shaderBuffer->size, data, GL_STATIC_DRAW);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void shaderBufferBindToBlock(
|
||||
shaderbuffer_t *shaderBuffer,
|
||||
const GLuint blockIndex
|
||||
) {
|
||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, blockIndex, shaderBuffer->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void shaderBufferDispose(shaderbuffer_t *shaderBuffer) {
|
||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
||||
glDeleteBuffers(1, &shaderBuffer->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
|
||||
typedef struct {
|
||||
GLuint id;
|
||||
size_t size;
|
||||
} shaderbuffer_t;
|
||||
|
||||
/**
|
||||
* Initializes a shader buffer.
|
||||
*
|
||||
* @param shaderBuffer The shader buffer to initialize.
|
||||
* @param size The size of the buffer.
|
||||
*/
|
||||
void shaderBufferInit(
|
||||
shaderbuffer_t *shaderBuffer,
|
||||
const size_t size
|
||||
);
|
||||
|
||||
/**
|
||||
* Binds a shader buffer.
|
||||
*
|
||||
* @param shaderBuffer The shader buffer to bind.
|
||||
*/
|
||||
void shaderBufferBind(shaderbuffer_t *shaderBuffer);
|
||||
|
||||
/**
|
||||
* Sets the data of a shader buffer.
|
||||
*
|
||||
* @param shaderBuffer The shader buffer to set the data of.
|
||||
* @param data The data to set.
|
||||
*/
|
||||
void shaderBufferSetData(
|
||||
shaderbuffer_t *shaderBuffer,
|
||||
const void *data
|
||||
);
|
||||
|
||||
/**
|
||||
* Binds a shader buffer to a block.
|
||||
*
|
||||
* @param shaderBuffer The shader buffer to bind.
|
||||
* @param blockIndex The block index to bind to.
|
||||
*/
|
||||
void shaderBufferBindToBlock(
|
||||
shaderbuffer_t *shaderBuffer,
|
||||
const GLuint blockIndex
|
||||
);
|
||||
|
||||
/**
|
||||
* Disposes of a shader buffer.
|
||||
*
|
||||
* @param shaderBuffer The shader buffer to dispose of.
|
||||
*/
|
||||
void shaderBufferDispose(shaderbuffer_t *shaderBuffer);
|
||||
@@ -1,109 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "shadermanager.h"
|
||||
#include "assert/assert.h"
|
||||
#include "display/shader/data/transforms.h"
|
||||
#include "display/shader/data/entities.h"
|
||||
#include "display/shader/data/mapshaderdata.h"
|
||||
#include "display/shader/data/tilesetshaderdata.h"
|
||||
#include "display/shader/entityshader/entityshader.h"
|
||||
#include "display/shader/mapshader/mapshader.h"
|
||||
|
||||
shadermanagerdatacallback_t SHADER_MANAGER_DATA_CALLBACKS[] = {
|
||||
{ transformsInit, transformsUpdate, transformsDispose },
|
||||
{ entitiesInit, entitiesUpdate, entitiesDispose },
|
||||
{ mapShaderDataInit, mapShaderDataUpdate, mapShaderDataDispose },
|
||||
{ tilesetShaderDataInit, tilesetShaderDataUpdate, tilesetShaderDataDispose }
|
||||
};
|
||||
|
||||
|
||||
shadermanagershadercallback_t SHADER_MANAGER_SHADER_CALLBACKS[] = {
|
||||
{ entityShaderInit, entityShaderDispose },
|
||||
{ mapShaderInit, mapShaderDispose }
|
||||
};
|
||||
|
||||
void shaderManagerInit() {
|
||||
size_t i;
|
||||
assertTrue(
|
||||
SHADER_MANAGER_SHADER_CALLBACKS_SIZE > 0,
|
||||
"No Shader Callbacks Defined"
|
||||
);
|
||||
assertTrue(
|
||||
SHADER_MANAGER_DATA_CALLBACKS_SIZE > 0,
|
||||
"No Data Callbacks Defined"
|
||||
);
|
||||
|
||||
// Init Shader Datas (before the shaders)
|
||||
i = 0;
|
||||
do {
|
||||
assertNotNull(
|
||||
SHADER_MANAGER_DATA_CALLBACKS[i].init,
|
||||
"Data Callback is NULL"
|
||||
);
|
||||
SHADER_MANAGER_DATA_CALLBACKS[i++].init();
|
||||
} while(i < SHADER_MANAGER_DATA_CALLBACKS_SIZE);
|
||||
|
||||
// Init the shaders
|
||||
i = 0;
|
||||
do {
|
||||
assertNotNull(
|
||||
SHADER_MANAGER_SHADER_CALLBACKS[i].init,
|
||||
"Shader Callback is NULL"
|
||||
);
|
||||
SHADER_MANAGER_SHADER_CALLBACKS[i++].init();
|
||||
} while(i < SHADER_MANAGER_SHADER_CALLBACKS_SIZE);
|
||||
}
|
||||
|
||||
void shaderManagerUpdate() {
|
||||
assertTrue(
|
||||
SHADER_MANAGER_DATA_CALLBACKS_SIZE > 0,
|
||||
"No Data Callbacks Defined"
|
||||
);
|
||||
|
||||
|
||||
// Update all the data
|
||||
size_t i = 0;
|
||||
do {
|
||||
assertNotNull(
|
||||
SHADER_MANAGER_DATA_CALLBACKS[i].update,
|
||||
"Data Callback is NULL"
|
||||
);
|
||||
SHADER_MANAGER_DATA_CALLBACKS[i++].update();
|
||||
} while(i < SHADER_MANAGER_DATA_CALLBACKS_SIZE);
|
||||
}
|
||||
|
||||
void shaderManagerDispose() {
|
||||
assertTrue(
|
||||
SHADER_MANAGER_SHADER_CALLBACKS_SIZE > 0,
|
||||
"No Shader Callbacks Defined"
|
||||
);
|
||||
assertTrue(
|
||||
SHADER_MANAGER_DATA_CALLBACKS_SIZE > 0,
|
||||
"No Data Callbacks Defined"
|
||||
);
|
||||
|
||||
// Cleanup the shaders
|
||||
size_t i = 0;
|
||||
do {
|
||||
assertNotNull(
|
||||
SHADER_MANAGER_SHADER_CALLBACKS[i].dispose,
|
||||
"Shader Callback is NULL"
|
||||
);
|
||||
SHADER_MANAGER_SHADER_CALLBACKS[i++].dispose();
|
||||
} while(i < SHADER_MANAGER_SHADER_CALLBACKS_SIZE);
|
||||
|
||||
// Cleanup the data
|
||||
i = 0;
|
||||
do {
|
||||
assertNotNull(
|
||||
SHADER_MANAGER_DATA_CALLBACKS[i].dispose,
|
||||
"Data Callback is NULL"
|
||||
);
|
||||
SHADER_MANAGER_DATA_CALLBACKS[i++].dispose();
|
||||
} while(i < SHADER_MANAGER_DATA_CALLBACKS_SIZE);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef struct {
|
||||
void (*init)();
|
||||
void (*update)();
|
||||
void (*dispose)();
|
||||
} shadermanagerdatacallback_t;
|
||||
|
||||
typedef struct {
|
||||
void (*init)();
|
||||
void (*dispose)();
|
||||
} shadermanagershadercallback_t;
|
||||
|
||||
extern shadermanagerdatacallback_t SHADER_MANAGER_DATA_CALLBACKS[];
|
||||
extern shadermanagershadercallback_t SHADER_MANAGER_SHADER_CALLBACKS[];
|
||||
|
||||
#define SHADER_MANAGER_DATA_CALLBACKS_SIZE ( \
|
||||
sizeof(SHADER_MANAGER_DATA_CALLBACKS) / sizeof(shadermanagerdatacallback_t) \
|
||||
)
|
||||
|
||||
#define SHADER_MANAGER_SHADER_CALLBACKS_SIZE ( \
|
||||
sizeof(SHADER_MANAGER_SHADER_CALLBACKS) / \
|
||||
sizeof(shadermanagershadercallback_t) \
|
||||
)
|
||||
|
||||
/**
|
||||
* Initializes the Shader Manager
|
||||
*/
|
||||
void shaderManagerInit();
|
||||
|
||||
/**
|
||||
* Updates the Shader Manager
|
||||
*/
|
||||
void shaderManagerUpdate();
|
||||
|
||||
/**
|
||||
* Disposes of the Shader Manager
|
||||
*/
|
||||
void shaderManagerDispose();
|
||||
@@ -1,103 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "texture.h"
|
||||
#include "assert/assert.h"
|
||||
#include "assert/assertgl.h"
|
||||
#include "asset.h"
|
||||
#include "util/math.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
#define TEXTURE_BUFFER_SIZE 32768
|
||||
|
||||
int32_t TEXTURE_ACTIVE_COUNT;
|
||||
|
||||
void textureLoad(
|
||||
texture_t *texture,
|
||||
const char_t *path
|
||||
) {
|
||||
assertNotNull(texture, "Texture is null.");
|
||||
assertNotNull(path, "Path is null.");
|
||||
|
||||
// Open asset
|
||||
assetOpen(path);
|
||||
|
||||
// Setup spng
|
||||
spng_ctx *ctx = spng_ctx_new(0);
|
||||
spng_set_png_stream(ctx, &textureSPNGBuffer, NULL);
|
||||
|
||||
// Get image info
|
||||
struct spng_ihdr ihdr;
|
||||
spng_get_ihdr(ctx, &ihdr);
|
||||
texture->width = ihdr.width;
|
||||
texture->height = ihdr.height;
|
||||
|
||||
// Decode the image. I can probably stream this in the future.
|
||||
size_t dataSize = ihdr.width * ihdr.height * 4;// 4 for RGBA
|
||||
uint8_t *data = (uint8_t *)memoryAllocate(dataSize);
|
||||
assertNotNull(data, "Failed to allocate memory for texture data.");
|
||||
spng_decode_image(ctx, data, dataSize, SPNG_FMT_RGBA8, 0);
|
||||
|
||||
// Finish decoding
|
||||
spng_ctx_free(ctx);
|
||||
assetClose();
|
||||
|
||||
// Create texture
|
||||
glGenTextures(1, &texture->id);
|
||||
assertNoGLError();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||
assertNoGLError();
|
||||
|
||||
// Buffer then cleanup
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA,
|
||||
texture->width, texture->height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, data
|
||||
);
|
||||
assertNoGLError();
|
||||
memoryFree(data);
|
||||
|
||||
// Setup texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
assertNoGLError();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
assertNoGLError();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void textureBind(
|
||||
const texture_t *texture,
|
||||
const GLuint slot
|
||||
) {
|
||||
assertNotNull(texture, "Texture is null.");
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + slot);
|
||||
assertNoGLError();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
void textureDispose(texture_t *texture) {
|
||||
glDeleteTextures(1, &texture->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
int32_t textureSPNGBuffer(
|
||||
spng_ctx *ctx,
|
||||
void *user,
|
||||
void *destination,
|
||||
size_t length
|
||||
) {
|
||||
size_t read = assetRead(destination, length);
|
||||
if(read == 0) return SPNG_IO_EOF;
|
||||
return SPNG_OK;
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskgl.h"
|
||||
#include <spng.h>
|
||||
|
||||
extern int32_t TEXTURE_ACTIVE_COUNT;
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
GLuint id;
|
||||
} texture_t;
|
||||
|
||||
/**
|
||||
* Initializes a texture to be read to be used.
|
||||
*
|
||||
* @param texture Texture to initialize.
|
||||
* @param path Path of the file to load.
|
||||
*/
|
||||
void textureLoad(
|
||||
texture_t *texture,
|
||||
const char_t *path
|
||||
);
|
||||
|
||||
/**
|
||||
* Binds the texture to the given slot (for use by the shaders).
|
||||
*
|
||||
* @param texture Texture to bind.
|
||||
* @param slot Slot to bind to.
|
||||
*/
|
||||
void textureBind(
|
||||
const texture_t *texture,
|
||||
const GLuint slot
|
||||
);
|
||||
|
||||
/**
|
||||
* Unloads a previously initialized texture.
|
||||
*
|
||||
* @param texture Texture to destroy.
|
||||
*/
|
||||
void textureDispose(texture_t *texture);
|
||||
|
||||
/**
|
||||
* Callback function for libspng to read from the asset.
|
||||
*
|
||||
* @param ctx The spng context.
|
||||
* @param user User data.
|
||||
* @param destination Destination buffer.
|
||||
* @param length Length of the buffer.
|
||||
* @return The amount of data read.
|
||||
*/
|
||||
int32_t textureSPNGBuffer(
|
||||
spng_ctx *ctx,
|
||||
void *user,
|
||||
void *destination,
|
||||
size_t length
|
||||
);
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "tilesetgl.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
const char* TILESET_GL_TEXTURES_PATHS[TILESET_COUNT] = {
|
||||
NULL,
|
||||
"textures/8x8.png"
|
||||
};
|
||||
|
||||
texture_t TILESET_GL_TEXTURES[TILESET_SLOT_COUNT];
|
||||
|
||||
void tilesetGLBind() {
|
||||
uint8_t i;
|
||||
do {
|
||||
if(TILESET_SLOTS[i] == TILESET_NULL) continue;
|
||||
textureBind(TILESET_GL_TEXTURES + i, i);
|
||||
} while(++i < TILESET_SLOT_COUNT);
|
||||
}
|
||||
|
||||
void tilesetBind(const tilesetid_t id, const uint8_t slot) {
|
||||
assertTrue(slot < TILESET_SLOT_COUNT, "Invalid slot");
|
||||
assertTrue(id < TILESET_COUNT, "Invalid tileset id");
|
||||
|
||||
TILESET_SLOTS[slot] = id;
|
||||
textureLoad(TILESET_GL_TEXTURES + slot, TILESET_GL_TEXTURES_PATHS[id]);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "texture.h"
|
||||
#include "display/tileset.h"
|
||||
|
||||
extern const char* TILESET_GL_TEXTURES_PATHS[];
|
||||
extern texture_t TILESET_GL_TEXTURES[];
|
||||
|
||||
/**
|
||||
* Binds the tileset to the OpenGL context.
|
||||
*/
|
||||
void tilesetGLBind();
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
#include "duskglimpl.h"
|
||||
|
||||
#include <libgen.h>
|
||||
#include <cglm/cglm.h>
|
||||
#include <float.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
|
||||
extern char_t EXECUTABLE_PATH[];
|
||||
extern char_t EXECUTABLE_DIRECTORY[];
|
||||
|
||||
typedef uint32_t uvec4_t[4];
|
||||
@@ -1,12 +0,0 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
overworld.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "overworld/overworld.h"
|
||||
#include "display/quad.h"
|
||||
#include "display/shader/entityshader/entityshader.h"
|
||||
#include "display/shader/mapshader/mapshader.h"
|
||||
|
||||
void overworldRender() {
|
||||
mapShaderUse();
|
||||
quadRender(
|
||||
OVERWORLD.map.width * OVERWORLD.map.height * OVERWORLD.map.layerCount
|
||||
);
|
||||
|
||||
entityShaderUse();
|
||||
quadRender(OVERWORLD.entityCount);
|
||||
}
|
||||
Reference in New Issue
Block a user