Create empty texture idea, change function scopes
Some functions which should not be exposed in the API have been switched to INTERNAL scope. We have a notion of an empty texture in World Traveller that we can pass in situations where we just want to render a solid colour with no associated texture. The alternative to this was creating a separate shader for rendering primitives but would require at some point to expose the AssetManager to the renderer or the user on behalf has to manually switch shaders before rendering (non-intuitive).
This commit is contained in:
parent
86b4d1e206
commit
d0b4c99787
@ -49,8 +49,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="data\shaders\default.vert.glsl" />
|
<None Include="data\shaders\default.vert.glsl" />
|
||||||
<None Include="data\shaders\default.frag.glsl" />
|
<None Include="data\shaders\default.frag.glsl" />
|
||||||
<None Include="data\shaders\sprite.vert.glsl" />
|
|
||||||
<None Include="data\shaders\sprite.frag.glsl" />
|
<None Include="data\shaders\sprite.frag.glsl" />
|
||||||
|
<None Include="data\shaders\sprite.vert.glsl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\include\Dengine\Common.h">
|
<ClInclude Include="src\include\Dengine\Common.h">
|
||||||
|
Binary file not shown.
@ -63,7 +63,7 @@ const i32 asset_loadTextureImage(AssetManager *assetManager,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture tex = genTexture(CAST(GLuint)(imgWidth), CAST(GLuint)(imgHeight),
|
Texture tex = texture_gen(CAST(GLuint)(imgWidth), CAST(GLuint)(imgHeight),
|
||||||
CAST(GLint)(bytesPerPixel), image);
|
CAST(GLint)(bytesPerPixel), image);
|
||||||
glCheckError();
|
glCheckError();
|
||||||
stbi_image_free(image);
|
stbi_image_free(image);
|
||||||
@ -111,6 +111,30 @@ INTERNAL GLuint createShaderFromPath(const char *const path, GLuint shadertype)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INTERNAL i32 shaderLoadProgram(Shader *const shader, const GLuint vertexShader,
|
||||||
|
const GLuint fragmentShader)
|
||||||
|
{
|
||||||
|
shader->id = glCreateProgram();
|
||||||
|
glAttachShader(shader->id, vertexShader);
|
||||||
|
glAttachShader(shader->id, fragmentShader);
|
||||||
|
glLinkProgram(shader->id);
|
||||||
|
|
||||||
|
glDeleteShader(fragmentShader);
|
||||||
|
glDeleteShader(vertexShader);
|
||||||
|
|
||||||
|
GLint success;
|
||||||
|
GLchar infoLog[512];
|
||||||
|
glGetProgramiv(shader->id, GL_LINK_STATUS, &success);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
glGetProgramInfoLog(shader->id, 512, NULL, infoLog);
|
||||||
|
printf("glLinkProgram failed: %s\n", infoLog);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const i32 asset_loadShaderFiles(AssetManager *assetManager,
|
const i32 asset_loadShaderFiles(AssetManager *assetManager,
|
||||||
const char *const vertexPath,
|
const char *const vertexPath,
|
||||||
const char *const fragmentPath,
|
const char *const fragmentPath,
|
||||||
@ -121,7 +145,7 @@ const i32 asset_loadShaderFiles(AssetManager *assetManager,
|
|||||||
createShaderFromPath(fragmentPath, GL_FRAGMENT_SHADER);
|
createShaderFromPath(fragmentPath, GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
Shader shader;
|
Shader shader;
|
||||||
i32 result = shader_loadProgram(&shader, vertexShader, fragmentShader);
|
i32 result = shaderLoadProgram(&shader, vertexShader, fragmentShader);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -295,13 +319,13 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
|||||||
V2(CAST(f32)(glyphIndex * font->maxSize.w), CAST(f32) row);
|
V2(CAST(f32)(glyphIndex * font->maxSize.w), CAST(f32) row);
|
||||||
#if 1
|
#if 1
|
||||||
fontAtlas->texRect[atlasIndex++] =
|
fontAtlas->texRect[atlasIndex++] =
|
||||||
getRect(origin, V2(CAST(f32) font->maxSize.w,
|
math_getRect(origin, V2(CAST(f32) font->maxSize.w,
|
||||||
CAST(f32) font->maxSize.h));
|
CAST(f32) font->maxSize.h));
|
||||||
#else
|
#else
|
||||||
v2i fontSize =
|
v2i fontSize =
|
||||||
font->charMetrics[activeGlyph.codepoint - 32].trueSize;
|
font->charMetrics[activeGlyph.codepoint - 32].trueSize;
|
||||||
fontAtlas->texRect[atlasIndex++] =
|
fontAtlas->texRect[atlasIndex++] = math_getRect(
|
||||||
getRect(origin, V2(CAST(f32)fontSize.x, CAST(f32)fontSize.y));
|
origin, V2(CAST(f32) fontSize.x, CAST(f32) fontSize.y));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +372,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture tex = genTexture(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4,
|
Texture tex = texture_gen(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4,
|
||||||
CAST(u8 *) fontBitmap);
|
CAST(u8 *) fontBitmap);
|
||||||
assetManager->textures[texlist_font] = tex;
|
assetManager->textures[texlist_font] = tex;
|
||||||
|
|
||||||
|
221
src/Renderer.c
221
src/Renderer.c
@ -18,6 +18,125 @@ INTERNAL void updateBufferObject(Renderer *const renderer,
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INTERNAL RenderQuad createTexQuad(Renderer *renderer, v4 quadRect, v4 texRect,
|
||||||
|
Texture *tex)
|
||||||
|
{
|
||||||
|
// NOTE(doyle): Draws a series of triangles (three-sided polygons) using
|
||||||
|
// vertices v0, v1, v2, then v2, v1, v3 (note the order)
|
||||||
|
RenderQuad result = {0};
|
||||||
|
|
||||||
|
/* Convert screen coordinates to normalised device coordinates */
|
||||||
|
v4 quadRectNdc = quadRect;
|
||||||
|
quadRectNdc.e[0] *= renderer->vertexNdcFactor.w;
|
||||||
|
quadRectNdc.e[1] *= renderer->vertexNdcFactor.h;
|
||||||
|
quadRectNdc.e[2] *= renderer->vertexNdcFactor.w;
|
||||||
|
quadRectNdc.e[3] *= renderer->vertexNdcFactor.h;
|
||||||
|
|
||||||
|
/* Convert texture coordinates to normalised texture coordinates */
|
||||||
|
v4 texRectNdc = texRect;
|
||||||
|
if (tex)
|
||||||
|
{
|
||||||
|
v2 texNdcFactor = V2(1.0f / tex->width, 1.0f / tex->height);
|
||||||
|
texRectNdc.e[0] *= texNdcFactor.w;
|
||||||
|
texRectNdc.e[1] *= texNdcFactor.h;
|
||||||
|
texRectNdc.e[2] *= texNdcFactor.w;
|
||||||
|
texRectNdc.e[3] *= texNdcFactor.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form the quad */
|
||||||
|
result.vertex[0] = V4(quadRectNdc.x, quadRectNdc.y, texRectNdc.x,
|
||||||
|
texRectNdc.y); // Top left
|
||||||
|
result.vertex[1] = V4(quadRectNdc.x, quadRectNdc.w, texRectNdc.x,
|
||||||
|
texRectNdc.w); // Bottom left
|
||||||
|
result.vertex[2] = V4(quadRectNdc.z, quadRectNdc.y, texRectNdc.z,
|
||||||
|
texRectNdc.y); // Top right
|
||||||
|
result.vertex[3] = V4(quadRectNdc.z, quadRectNdc.w, texRectNdc.z,
|
||||||
|
texRectNdc.w); // Bottom right
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL inline RenderQuad createQuad(Renderer *renderer, v4 quadRect)
|
||||||
|
{
|
||||||
|
v4 texRect = V4(0, 0, 0, 0);
|
||||||
|
RenderQuad result =
|
||||||
|
createTexQuad(renderer, quadRect, texRect, NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL inline RenderQuad
|
||||||
|
createDefaultTexQuad(Renderer *renderer, v4 texRect, Texture *tex)
|
||||||
|
{
|
||||||
|
RenderQuad result = {0};
|
||||||
|
v4 defaultQuad = V4(0.0f, renderer->size.h, renderer->size.w, 0.0f);
|
||||||
|
result = createTexQuad(renderer, defaultQuad, texRect, tex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL void renderObject(Renderer *renderer, v2 pos, v2 size, f32 rotate,
|
||||||
|
v4 color, Texture *tex)
|
||||||
|
{
|
||||||
|
mat4 transMatrix = mat4_translate(pos.x, pos.y, 0.0f);
|
||||||
|
// NOTE(doyle): Rotate from the center of the object, not its' origin (i.e.
|
||||||
|
// top left)
|
||||||
|
mat4 rotateMatrix = mat4_translate((size.x * 0.5f), (size.y * 0.5f), 0.0f);
|
||||||
|
rotateMatrix = mat4_mul(rotateMatrix, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f));
|
||||||
|
rotateMatrix = mat4_mul(rotateMatrix, mat4_translate((size.x * -0.5f), (size.y * -0.5f), 0.0f));
|
||||||
|
|
||||||
|
// NOTE(doyle): We draw everything as a unit square in OGL. Scale it to size
|
||||||
|
// TODO(doyle): We should have a notion of hitbox size and texture size
|
||||||
|
// we're going to render so we can draw textures that may be bigger than the
|
||||||
|
// entity, (slightly) but keep a consistent bounding box
|
||||||
|
mat4 scaleMatrix = mat4_scale(size.x, size.y, 1.0f);
|
||||||
|
mat4 model = mat4_mul(transMatrix, mat4_mul(rotateMatrix, scaleMatrix));
|
||||||
|
|
||||||
|
/* Load transformation matrix */
|
||||||
|
shader_use(renderer->shader);
|
||||||
|
shader_uniformSetMat4fv(renderer->shader, "model", model);
|
||||||
|
glCheckError();
|
||||||
|
|
||||||
|
/* Set color modulation value */
|
||||||
|
shader_uniformSetVec4f(renderer->shader, "spriteColor", color);
|
||||||
|
|
||||||
|
/* Send draw calls */
|
||||||
|
#if RENDER_BOUNDING_BOX
|
||||||
|
glBindVertexArray(renderer->vao);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, renderer->numVertexesInVbo);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (tex)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex->id);
|
||||||
|
shader_uniformSet1i(renderer->shader, "tex", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(renderer->vao);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, renderer->numVertexesInVbo);
|
||||||
|
|
||||||
|
#ifdef DENGINE_DEBUG
|
||||||
|
debug_callCountIncrement(debugcallcount_drawArrays);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Unbind */
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glCheckError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderer_rect(Renderer *const renderer, v4 cameraBounds, v2 pos, v2 size,
|
||||||
|
f32 rotate, Texture *tex, v4 texRect, v4 color)
|
||||||
|
{
|
||||||
|
v4 quadRect = math_getRect(pos, size);
|
||||||
|
RenderQuad quad = createTexQuad(renderer, quadRect, texRect, tex);
|
||||||
|
updateBufferObject(renderer, &quad, 1);
|
||||||
|
|
||||||
|
// NOTE(doyle): Get the origin of cameraBounds in world space, bottom left
|
||||||
|
v2 offsetFromCamOrigin = V2(cameraBounds.x, cameraBounds.w);
|
||||||
|
v2 rectRelativeToCamera = v2_sub(pos, offsetFromCamOrigin);
|
||||||
|
renderObject(renderer, rectRelativeToCamera, size, rotate, color, tex);
|
||||||
|
}
|
||||||
|
|
||||||
void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
||||||
Font *const font, const char *const string, v2 pos,
|
Font *const font, const char *const string, v2 pos,
|
||||||
f32 rotate, v4 color)
|
f32 rotate, v4 color)
|
||||||
@ -48,15 +167,15 @@ void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
|||||||
for (i32 i = 0; i < strLen; i++)
|
for (i32 i = 0; i < strLen; i++)
|
||||||
{
|
{
|
||||||
// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint
|
// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint
|
||||||
// to
|
// to its actual atlas index, i.e. we skip the first 31 glyphs
|
||||||
// its actual atlas index, i.e. we skip the first 31 glyphs
|
|
||||||
i32 codepoint = string[i];
|
i32 codepoint = string[i];
|
||||||
i32 relativeIndex = codepoint - font->codepointRange.x;
|
i32 relativeIndex = codepoint - font->codepointRange.x;
|
||||||
CharMetrics charMetric = font->charMetrics[relativeIndex];
|
CharMetrics charMetric = font->charMetrics[relativeIndex];
|
||||||
pos.y = baseline - (scale * charMetric.offset.y);
|
pos.y = baseline - (scale * charMetric.offset.y);
|
||||||
|
|
||||||
const v4 charRectOnScreen = getRect(
|
const v4 charRectOnScreen =
|
||||||
pos, V2(scale * CAST(f32) font->maxSize.w, scale * CAST(f32) font->maxSize.h));
|
math_getRect(pos, V2(scale * CAST(f32) font->maxSize.w,
|
||||||
|
scale * CAST(f32) font->maxSize.h));
|
||||||
|
|
||||||
pos.x += scale * charMetric.advance;
|
pos.x += scale * charMetric.advance;
|
||||||
|
|
||||||
@ -64,8 +183,8 @@ void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
|||||||
v4 charTexRect = font->atlas->texRect[relativeIndex];
|
v4 charTexRect = font->atlas->texRect[relativeIndex];
|
||||||
renderer_flipTexCoord(&charTexRect, FALSE, TRUE);
|
renderer_flipTexCoord(&charTexRect, FALSE, TRUE);
|
||||||
|
|
||||||
RenderQuad charQuad = renderer_createQuad(
|
RenderQuad charQuad = createTexQuad(renderer, charRectOnScreen,
|
||||||
renderer, charRectOnScreen, charTexRect, font->tex);
|
charTexRect, font->tex);
|
||||||
stringQuads[quadIndex++] = charQuad;
|
stringQuads[quadIndex++] = charQuad;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +192,7 @@ void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
|||||||
// relative to the window size, hence we also render at the origin since
|
// relative to the window size, hence we also render at the origin since
|
||||||
// we're rendering a window sized buffer
|
// we're rendering a window sized buffer
|
||||||
updateBufferObject(renderer, stringQuads, quadIndex);
|
updateBufferObject(renderer, stringQuads, quadIndex);
|
||||||
renderer_object(renderer, V2(0.0f, 0.0f), renderer->size, rotate, color,
|
renderObject(renderer, V2(0.0f, 0.0f), renderer->size, rotate, color,
|
||||||
font->tex);
|
font->tex);
|
||||||
PLATFORM_MEM_FREE(stringQuads, strLen * sizeof(RenderQuad));
|
PLATFORM_MEM_FREE(stringQuads, strLen * sizeof(RenderQuad));
|
||||||
}
|
}
|
||||||
@ -110,97 +229,13 @@ void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
|
|||||||
renderer_flipTexCoord(&texRect, TRUE, FALSE);
|
renderer_flipTexCoord(&texRect, TRUE, FALSE);
|
||||||
}
|
}
|
||||||
RenderQuad entityQuad =
|
RenderQuad entityQuad =
|
||||||
renderer_createDefaultQuad(renderer, texRect, entity->tex);
|
createDefaultTexQuad(renderer, texRect, entity->tex);
|
||||||
updateBufferObject(renderer, &entityQuad, 1);
|
updateBufferObject(renderer, &entityQuad, 1);
|
||||||
|
|
||||||
// NOTE(doyle): The camera origin is 0,0 in world positions
|
|
||||||
v2 offsetFromCamOrigin = V2(cameraBounds.x, cameraBounds.w);
|
v2 offsetFromCamOrigin = V2(cameraBounds.x, cameraBounds.w);
|
||||||
v2 entityRelativeToCamera = v2_sub(entity->pos, offsetFromCamOrigin);
|
v2 entityRelativeToCamera = v2_sub(entity->pos, offsetFromCamOrigin);
|
||||||
|
|
||||||
renderer_object(renderer, entityRelativeToCamera, entity->size, rotate,
|
renderObject(renderer, entityRelativeToCamera, entity->size, rotate,
|
||||||
color, entity->tex);
|
color, entity->tex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v4 color,
|
|
||||||
Texture *tex)
|
|
||||||
{
|
|
||||||
shader_use(renderer->shader);
|
|
||||||
mat4 transMatrix = mat4_translate(pos.x, pos.y, 0.0f);
|
|
||||||
|
|
||||||
// NOTE(doyle): Rotate from the center of the object, not its' origin (i.e.
|
|
||||||
// top left)
|
|
||||||
mat4 rotateMatrix = mat4_translate((size.x * 0.5f), (size.y * 0.5f), 0.0f);
|
|
||||||
rotateMatrix = mat4_mul(rotateMatrix, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f));
|
|
||||||
rotateMatrix = mat4_mul(rotateMatrix, mat4_translate((size.x * -0.5f), (size.y * -0.5f), 0.0f));
|
|
||||||
|
|
||||||
// NOTE(doyle): We draw everything as a unit square in OGL. Scale it to size
|
|
||||||
// TODO(doyle): We should have a notion of hitbox size and texture size
|
|
||||||
// we're going to render so we can draw textures that may be bigger than the
|
|
||||||
// entity, (slightly) but keep a consistent bounding box
|
|
||||||
mat4 scaleMatrix = mat4_scale(size.x, size.y, 1.0f);
|
|
||||||
|
|
||||||
mat4 model = mat4_mul(transMatrix, mat4_mul(rotateMatrix, scaleMatrix));
|
|
||||||
shader_uniformSetMat4fv(renderer->shader, "model", model);
|
|
||||||
glCheckError();
|
|
||||||
|
|
||||||
shader_uniformSetVec4f(renderer->shader, "spriteColor", color);
|
|
||||||
|
|
||||||
#if RENDER_BOUNDING_BOX
|
|
||||||
glBindVertexArray(renderer->vao);
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, renderer->numVertexesInVbo);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
if (tex)
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex->id);
|
|
||||||
shader_uniformSet1i(renderer->shader, "tex", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindVertexArray(renderer->vao);
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, renderer->numVertexesInVbo);
|
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
|
||||||
debug_callCountIncrement(debugcallcount_drawArrays);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glBindVertexArray(0);
|
|
||||||
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
glCheckError();
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderQuad renderer_createQuad(Renderer *renderer, v4 quadRect, v4 texRect,
|
|
||||||
Texture *tex)
|
|
||||||
{
|
|
||||||
// NOTE(doyle): Draws a series of triangles (three-sided polygons) using
|
|
||||||
// vertices v0, v1, v2, then v2, v1, v3 (note the order)
|
|
||||||
RenderQuad result = {0};
|
|
||||||
|
|
||||||
v4 quadRectNdc = quadRect;
|
|
||||||
quadRectNdc.e[0] *= renderer->vertexNdcFactor.w;
|
|
||||||
quadRectNdc.e[1] *= renderer->vertexNdcFactor.h;
|
|
||||||
quadRectNdc.e[2] *= renderer->vertexNdcFactor.w;
|
|
||||||
quadRectNdc.e[3] *= renderer->vertexNdcFactor.h;
|
|
||||||
|
|
||||||
v2 texNdcFactor = V2(1.0f / tex->width, 1.0f / tex->height);
|
|
||||||
v4 texRectNdc = texRect;
|
|
||||||
texRectNdc.e[0] *= texNdcFactor.w;
|
|
||||||
texRectNdc.e[1] *= texNdcFactor.h;
|
|
||||||
texRectNdc.e[2] *= texNdcFactor.w;
|
|
||||||
texRectNdc.e[3] *= texNdcFactor.h;
|
|
||||||
|
|
||||||
result.vertex[0] = V4(quadRectNdc.x, quadRectNdc.y, texRectNdc.x,
|
|
||||||
texRectNdc.y); // Top left
|
|
||||||
result.vertex[1] = V4(quadRectNdc.x, quadRectNdc.w, texRectNdc.x,
|
|
||||||
texRectNdc.w); // Bottom left
|
|
||||||
result.vertex[2] = V4(quadRectNdc.z, quadRectNdc.y, texRectNdc.z,
|
|
||||||
texRectNdc.y); // Top right
|
|
||||||
result.vertex[3] = V4(quadRectNdc.z, quadRectNdc.w, texRectNdc.z,
|
|
||||||
texRectNdc.w); // Bottom right
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
24
src/Shader.c
24
src/Shader.c
@ -1,29 +1,5 @@
|
|||||||
#include "Dengine/Shader.h"
|
#include "Dengine/Shader.h"
|
||||||
|
|
||||||
const i32 shader_loadProgram(Shader *const shader, const GLuint vertexShader,
|
|
||||||
const GLuint fragmentShader)
|
|
||||||
{
|
|
||||||
shader->id = glCreateProgram();
|
|
||||||
glAttachShader(shader->id, vertexShader);
|
|
||||||
glAttachShader(shader->id, fragmentShader);
|
|
||||||
glLinkProgram(shader->id);
|
|
||||||
|
|
||||||
glDeleteShader(fragmentShader);
|
|
||||||
glDeleteShader(vertexShader);
|
|
||||||
|
|
||||||
GLint success;
|
|
||||||
GLchar infoLog[512];
|
|
||||||
glGetProgramiv(shader->id, GL_LINK_STATUS, &success);
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
glGetProgramInfoLog(shader->id, 512, NULL, infoLog);
|
|
||||||
printf("glLinkProgram failed: %s\n", infoLog);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shader_uniformSet1i(Shader *const shader, const GLchar *name,
|
void shader_uniformSet1i(Shader *const shader, const GLchar *name,
|
||||||
const GLuint data)
|
const GLuint data)
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,7 @@ INTERNAL GLint getGLFormat(i32 bytesPerPixel, b32 srgb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture genTexture(const GLuint width, const GLuint height,
|
Texture texture_gen(const GLuint width, const GLuint height,
|
||||||
const GLint bytesPerPixel, const u8 *const image)
|
const GLint bytesPerPixel, const u8 *const image)
|
||||||
{
|
{
|
||||||
// TODO(doyle): Let us set the parameters gl params as well
|
// TODO(doyle): Let us set the parameters gl params as well
|
||||||
|
@ -92,6 +92,12 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
|||||||
{
|
{
|
||||||
AssetManager *assetManager = &state->assetManager;
|
AssetManager *assetManager = &state->assetManager;
|
||||||
/* Initialise assets */
|
/* Initialise assets */
|
||||||
|
/* Create empty 1x1 4bpp black texture */
|
||||||
|
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
|
||||||
|
Texture emptyTex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap));
|
||||||
|
assetManager->textures[texlist_empty] = emptyTex;
|
||||||
|
|
||||||
|
/* Load textures */
|
||||||
asset_loadTextureImage(assetManager,
|
asset_loadTextureImage(assetManager,
|
||||||
"data/textures/WorldTraveller/TerraSprite1024.png",
|
"data/textures/WorldTraveller/TerraSprite1024.png",
|
||||||
texlist_hero);
|
texlist_hero);
|
||||||
@ -105,10 +111,13 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
|||||||
const i32 texSize = 1024;
|
const i32 texSize = 1024;
|
||||||
v2 texOrigin = V2(0, CAST(f32)(texSize - 128));
|
v2 texOrigin = V2(0, CAST(f32)(texSize - 128));
|
||||||
terrainAtlas->texRect[terraincoords_ground] =
|
terrainAtlas->texRect[terraincoords_ground] =
|
||||||
V4(texOrigin.x, texOrigin.y, texOrigin.x + atlasTileSize, texOrigin.y - atlasTileSize);
|
V4(texOrigin.x, texOrigin.y, texOrigin.x + atlasTileSize,
|
||||||
|
texOrigin.y - atlasTileSize);
|
||||||
|
|
||||||
|
/* Load shaders */
|
||||||
asset_loadShaderFiles(assetManager, "data/shaders/sprite.vert.glsl",
|
asset_loadShaderFiles(assetManager, "data/shaders/sprite.vert.glsl",
|
||||||
"data/shaders/sprite.frag.glsl", shaderlist_sprite);
|
"data/shaders/sprite.frag.glsl",
|
||||||
|
shaderlist_sprite);
|
||||||
|
|
||||||
asset_loadTTFont(assetManager, "C:/Windows/Fonts/Arialbd.ttf");
|
asset_loadTTFont(assetManager, "C:/Windows/Fonts/Arialbd.ttf");
|
||||||
glCheckError();
|
glCheckError();
|
||||||
@ -135,7 +144,8 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
|||||||
|
|
||||||
v2 worldDimensionInTilesf = V2(CAST(f32) worldDimensionInTiles.x,
|
v2 worldDimensionInTilesf = V2(CAST(f32) worldDimensionInTiles.x,
|
||||||
CAST(f32) worldDimensionInTiles.y);
|
CAST(f32) worldDimensionInTiles.y);
|
||||||
world->bounds = getRect(V2(0, 0), v2_scale(worldDimensionInTilesf,
|
world->bounds =
|
||||||
|
math_getRect(V2(0, 0), v2_scale(worldDimensionInTilesf,
|
||||||
CAST(f32) state->tileSize));
|
CAST(f32) state->tileSize));
|
||||||
|
|
||||||
TexAtlas *const atlas =
|
TexAtlas *const atlas =
|
||||||
@ -403,7 +413,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Recalculate rendering bounds */
|
/* Recalculate rendering bounds */
|
||||||
v4 cameraBounds = getRect(world->cameraPos, renderer->size);
|
v4 cameraBounds = math_getRect(world->cameraPos, renderer->size);
|
||||||
// NOTE(doyle): Lock camera if it passes the bounds of the world
|
// NOTE(doyle): Lock camera if it passes the bounds of the world
|
||||||
if (cameraBounds.x <= world->bounds.x)
|
if (cameraBounds.x <= world->bounds.x)
|
||||||
{
|
{
|
||||||
@ -441,12 +451,9 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
|||||||
|
|
||||||
renderer_entity(&state->renderer, cameraBounds, entity, dt, rotate,
|
renderer_entity(&state->renderer, cameraBounds, entity, dt, rotate,
|
||||||
V4(1, 1, 1, 1));
|
V4(1, 1, 1, 1));
|
||||||
// TODO(doyle): Clean up lines
|
|
||||||
// Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }
|
|
||||||
|
|
||||||
/* Game logic */
|
/* Game logic */
|
||||||
if (entity->type == entitytype_hero) continue;
|
if (entity->type == entitytype_mob)
|
||||||
else if (entity->type == entitytype_mob)
|
|
||||||
{
|
{
|
||||||
// TODO(doyle): Currently calculated in pixels, how about meaningful
|
// TODO(doyle): Currently calculated in pixels, how about meaningful
|
||||||
// game units?
|
// game units?
|
||||||
@ -468,6 +475,11 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
|||||||
renderer_staticString(&state->renderer, font, battleStr, strPos,
|
renderer_staticString(&state->renderer, font, battleStr, strPos,
|
||||||
0, color);
|
0, color);
|
||||||
#endif
|
#endif
|
||||||
|
Texture *emptyTex =
|
||||||
|
asset_getTexture(assetManager, texlist_empty);
|
||||||
|
renderer_rect(renderer, cameraBounds, hero->pos,
|
||||||
|
V2(distance, 100.0f), 0, emptyTex, V4(0, 1, 1, 0),
|
||||||
|
V4(1, 0, 0, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
enum TexList
|
enum TexList
|
||||||
{
|
{
|
||||||
|
texlist_empty,
|
||||||
texlist_hero,
|
texlist_hero,
|
||||||
texlist_terrain,
|
texlist_terrain,
|
||||||
texlist_font,
|
texlist_font,
|
||||||
|
@ -54,7 +54,7 @@ typedef struct Entity
|
|||||||
|
|
||||||
INTERNAL inline v4 getEntityScreenRect(Entity entity)
|
INTERNAL inline v4 getEntityScreenRect(Entity entity)
|
||||||
{
|
{
|
||||||
v4 result = getRect(entity.pos, entity.size);
|
v4 result = math_getRect(entity.pos, entity.size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ INTERNAL inline v4 mat4_mul_v4(const mat4 a, const v4 b)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL inline v4 getRect(v2 origin, v2 size)
|
INTERNAL inline v4 math_getRect(v2 origin, v2 size)
|
||||||
{
|
{
|
||||||
v2 upperLeftBound = v2_add(origin, V2(0.0f, size.y));
|
v2 upperLeftBound = v2_add(origin, V2(0.0f, size.y));
|
||||||
v2 lowerRightBound = v2_add(origin, V2(size.x, 0.0f));
|
v2 lowerRightBound = v2_add(origin, V2(size.x, 0.0f));
|
||||||
@ -280,7 +280,7 @@ INTERNAL inline v4 getRect(v2 origin, v2 size)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL inline v2 getRectSize(v4 rect)
|
INTERNAL inline v2 math_getRectSize(v4 rect)
|
||||||
{
|
{
|
||||||
f32 width = ABS(rect.x - rect.z);
|
f32 width = ABS(rect.x - rect.z);
|
||||||
f32 height = ABS(rect.y - rect.w);
|
f32 height = ABS(rect.y - rect.w);
|
||||||
|
@ -19,6 +19,12 @@ typedef struct RenderQuad
|
|||||||
v4 vertex[4];
|
v4 vertex[4];
|
||||||
} RenderQuad;
|
} RenderQuad;
|
||||||
|
|
||||||
|
// TODO(doyle): Clean up lines
|
||||||
|
// Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }
|
||||||
|
|
||||||
|
void renderer_rect(Renderer *const renderer, v4 cameraBounds, v2 pos, v2 size,
|
||||||
|
f32 rotate, Texture *tex, v4 texRect, v4 color);
|
||||||
|
|
||||||
void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
||||||
Font *const font, const char *const string, v2 pos,
|
Font *const font, const char *const string, v2 pos,
|
||||||
f32 rotate, v4 color);
|
f32 rotate, v4 color);
|
||||||
@ -34,12 +40,6 @@ inline void renderer_staticString(Renderer *const renderer, Font *const font,
|
|||||||
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
|
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
|
||||||
f32 dt, f32 rotate, v4 color);
|
f32 dt, f32 rotate, v4 color);
|
||||||
|
|
||||||
void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v4 color,
|
|
||||||
Texture *tex);
|
|
||||||
|
|
||||||
RenderQuad renderer_createQuad(Renderer *renderer, v4 quadRect, v4 texRect,
|
|
||||||
Texture *tex);
|
|
||||||
|
|
||||||
INTERNAL inline void renderer_flipTexCoord(v4 *texCoords, b32 flipX, b32 flipY)
|
INTERNAL inline void renderer_flipTexCoord(v4 *texCoords, b32 flipX, b32 flipY)
|
||||||
{
|
{
|
||||||
if (flipX)
|
if (flipX)
|
||||||
@ -56,14 +56,4 @@ INTERNAL inline void renderer_flipTexCoord(v4 *texCoords, b32 flipX, b32 flipY)
|
|||||||
texCoords->w = tmp.y;
|
texCoords->w = tmp.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL inline RenderQuad renderer_createDefaultQuad(Renderer *renderer,
|
|
||||||
v4 texRect, Texture *tex)
|
|
||||||
{
|
|
||||||
RenderQuad result = {0};
|
|
||||||
v4 defaultQuad = V4(0.0f, renderer->size.h, renderer->size.w, 0.0f);
|
|
||||||
result = renderer_createQuad(renderer, defaultQuad, texRect, tex);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,10 +9,6 @@ typedef struct Shader
|
|||||||
GLuint id;
|
GLuint id;
|
||||||
} Shader;
|
} Shader;
|
||||||
|
|
||||||
const i32 shader_loadProgram(Shader *const shader,
|
|
||||||
const GLuint vertexShader,
|
|
||||||
const GLuint fragmentShader);
|
|
||||||
|
|
||||||
void shader_uniformSet1i(Shader *const shader, const GLchar *name,
|
void shader_uniformSet1i(Shader *const shader, const GLchar *name,
|
||||||
const GLuint data);
|
const GLuint data);
|
||||||
void shader_uniformSetMat4fv(Shader *const shader, const GLchar *name,
|
void shader_uniformSetMat4fv(Shader *const shader, const GLchar *name,
|
||||||
|
@ -32,7 +32,7 @@ typedef struct Texture
|
|||||||
} Texture;
|
} Texture;
|
||||||
|
|
||||||
// Generates texture from image data
|
// Generates texture from image data
|
||||||
Texture genTexture(const GLuint width, const GLuint height,
|
Texture texture_gen(const GLuint width, const GLuint height,
|
||||||
const GLint bytesPerPixel, const u8 *const image);
|
const GLint bytesPerPixel, const u8 *const image);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user