big rendering overhaul (cleaning and api abstraction)
This commit is contained in:
parent
b7cb37c06a
commit
5059802d09
@ -114,8 +114,7 @@ set(TWN_NONOPT_SOURCE_FILES
|
|||||||
src/rendering/twn_triangles.c
|
src/rendering/twn_triangles.c
|
||||||
src/rendering/twn_billboards.c
|
src/rendering/twn_billboards.c
|
||||||
src/rendering/twn_circles.c
|
src/rendering/twn_circles.c
|
||||||
src/rendering/twn_skybox.c
|
src/rendering/twn_skybox.c)
|
||||||
src/rendering/twn_fog.c)
|
|
||||||
|
|
||||||
set(TWN_SOURCE_FILES
|
set(TWN_SOURCE_FILES
|
||||||
$<IF:$<BOOL:${TWN_USE_AMALGAM}>,src/twn_amalgam.c src/twn_stb.c,${TWN_NONOPT_SOURCE_FILES}>
|
$<IF:$<BOOL:${TWN_USE_AMALGAM}>,src/twn_amalgam.c src/twn_stb.c,${TWN_NONOPT_SOURCE_FILES}>
|
||||||
|
@ -222,7 +222,10 @@ static void ingame_tick(State *state) {
|
|||||||
draw_terrain(scn);
|
draw_terrain(scn);
|
||||||
|
|
||||||
draw_skybox("/assets/miramar/miramar_*.tga");
|
draw_skybox("/assets/miramar/miramar_*.tga");
|
||||||
draw_fog(0.9f, 1.0f, 0.05f, (Color){ 140, 147, 160, 255 });
|
|
||||||
|
ctx.fog_color = (Color){ 140, 147, 160, 255 };
|
||||||
|
ctx.fog_start = 0.9f;
|
||||||
|
ctx.fog_density = 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,6 +23,10 @@ typedef struct Context {
|
|||||||
/* TODO: actually set it */
|
/* TODO: actually set it */
|
||||||
float frame_duration;
|
float frame_duration;
|
||||||
|
|
||||||
|
/* it is disabled by having fog_density approximately equal to zero */
|
||||||
|
float fog_start, fog_end, fog_density;
|
||||||
|
Color fog_color;
|
||||||
|
|
||||||
/* resolution is set from config and dictates both logical and drawing space, as they're related */
|
/* resolution is set from config and dictates both logical and drawing space, as they're related */
|
||||||
/* even if scaling is done, game logic should never change over that */
|
/* even if scaling is done, game logic should never change over that */
|
||||||
Vec2 resolution;
|
Vec2 resolution;
|
||||||
|
@ -88,12 +88,6 @@ TWN_API DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 p
|
|||||||
/* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */
|
/* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */
|
||||||
TWN_API void draw_skybox(const char *textures);
|
TWN_API void draw_skybox(const char *textures);
|
||||||
|
|
||||||
/* only one for setting is supported for a frame, any call overwrites previous */
|
|
||||||
TWN_API void draw_fog(float start, /* optional, default: 0.0 */
|
|
||||||
float end, /* optional, default: 1.0 */
|
|
||||||
float density, /* optional, default: 0.0 */
|
|
||||||
Color color); /* optional, default: all 255 */
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef TWN_NOT_C
|
#ifndef TWN_NOT_C
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ typedef enum TextureMode {
|
|||||||
TEXTURE_MODE_OPAQUE, /* all pixels are solid */
|
TEXTURE_MODE_OPAQUE, /* all pixels are solid */
|
||||||
TEXTURE_MODE_SEETHROUGH, /* some pixels are alpha zero */
|
TEXTURE_MODE_SEETHROUGH, /* some pixels are alpha zero */
|
||||||
TEXTURE_MODE_GHOSTLY, /* arbitrary alpha values */
|
TEXTURE_MODE_GHOSTLY, /* arbitrary alpha values */
|
||||||
|
TEXTURE_MODE_COUNT,
|
||||||
TEXTURE_MODE_UNKNOWN = -1, /* a sentinel */
|
TEXTURE_MODE_UNKNOWN = -1, /* a sentinel */
|
||||||
} TextureMode;
|
} TextureMode;
|
||||||
|
|
||||||
|
@ -213,18 +213,6 @@
|
|||||||
{ "name": "textures", "type": "char *", "default": {} }
|
{ "name": "textures", "type": "char *", "default": {} }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
"draw_fog": {
|
|
||||||
"module": "draw",
|
|
||||||
"symbol": "fog",
|
|
||||||
"header": "twn_draw.h",
|
|
||||||
"params": [
|
|
||||||
{ "name": "start", "type": "float", "default": 0 },
|
|
||||||
{ "name": "end", "type": "float", "default": 1 },
|
|
||||||
{ "name": "density", "type": "float", "default": 0 },
|
|
||||||
{ "name": "color", "type": "Color", "default": { "r": 255, "g": 255, "b": 255, "a": 255 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"types": {
|
"types": {
|
||||||
@ -269,6 +257,10 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{ "name": "frame_number", "type": "float" },
|
{ "name": "frame_number", "type": "float" },
|
||||||
{ "name": "frame_duration", "type": "float" },
|
{ "name": "frame_duration", "type": "float" },
|
||||||
|
{ "name": "fog_start", "type": "float" },
|
||||||
|
{ "name": "fog_end", "type": "float" },
|
||||||
|
{ "name": "fog_density", "type": "float" },
|
||||||
|
{ "name": "fog_color", "type": "Color" },
|
||||||
{ "name": "resolution", "type": "Vec2" },
|
{ "name": "resolution", "type": "Vec2" },
|
||||||
{ "name": "mouse_position", "type": "Vec2" },
|
{ "name": "mouse_position", "type": "Vec2" },
|
||||||
{ "name": "mouse_movement", "type": "Vec2" },
|
{ "name": "mouse_movement", "type": "Vec2" },
|
||||||
|
@ -133,7 +133,7 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
|||||||
|
|
||||||
command.vertices = (AttributeArrayPointer) {
|
command.vertices = (AttributeArrayPointer) {
|
||||||
.arity = 3,
|
.arity = 3,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = offsetof(ElementIndexedBillboard, v1),
|
.stride = offsetof(ElementIndexedBillboard, v1),
|
||||||
.offset = offsetof(ElementIndexedBillboard, v0),
|
.offset = offsetof(ElementIndexedBillboard, v0),
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -141,7 +141,7 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
|||||||
|
|
||||||
command.texcoords = (AttributeArrayPointer) {
|
command.texcoords = (AttributeArrayPointer) {
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = offsetof(ElementIndexedBillboard, v1),
|
.stride = offsetof(ElementIndexedBillboard, v1),
|
||||||
.offset = offsetof(ElementIndexedBillboard, uv0),
|
.offset = offsetof(ElementIndexedBillboard, uv0),
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -149,7 +149,7 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
|||||||
|
|
||||||
command.colors = (AttributeArrayPointer) {
|
command.colors = (AttributeArrayPointer) {
|
||||||
.arity = 4,
|
.arity = 4,
|
||||||
.type = GL_UNSIGNED_BYTE,
|
.type = TWN_UNSIGNED_BYTE,
|
||||||
.stride = offsetof(ElementIndexedBillboard, v1),
|
.stride = offsetof(ElementIndexedBillboard, v1),
|
||||||
.offset = offsetof(ElementIndexedBillboard, c0),
|
.offset = offsetof(ElementIndexedBillboard, c0),
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -159,14 +159,19 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
|||||||
command.texture_key = texture_key;
|
command.texture_key = texture_key;
|
||||||
|
|
||||||
command.element_buffer = get_quad_element_buffer();
|
command.element_buffer = get_quad_element_buffer();
|
||||||
command.element_count = 6 * (GLsizei)primitives_len;
|
command.element_count = 6 * (uint32_t)primitives_len;
|
||||||
command.range_end = 6 * (GLsizei)primitives_len;
|
command.range_end = 6 * (uint32_t)primitives_len;
|
||||||
|
|
||||||
/* TODO: support alpha blended case, with distance sort */
|
/* TODO: support alpha blended case, with distance sort */
|
||||||
TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
|
TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
|
||||||
if (mode == TEXTURE_MODE_GHOSTLY)
|
if (mode == TEXTURE_MODE_GHOSTLY)
|
||||||
mode = TEXTURE_MODE_SEETHROUGH;
|
mode = TEXTURE_MODE_SEETHROUGH;
|
||||||
use_texture_mode(mode);
|
|
||||||
|
command.texture_mode = mode;
|
||||||
|
command.pipeline = PIPELINE_SPACE;
|
||||||
|
|
||||||
|
command.depth_range_high = depth_range_high;
|
||||||
|
command.depth_range_low = depth_range_low;
|
||||||
|
|
||||||
DeferredCommand final_command = {
|
DeferredCommand final_command = {
|
||||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||||
|
@ -99,7 +99,7 @@ void render_circle(const CirclePrimitive *circle) {
|
|||||||
|
|
||||||
command.vertices = (AttributeArrayPointer) {
|
command.vertices = (AttributeArrayPointer) {
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = sizeof (Vec2),
|
.stride = sizeof (Vec2),
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -112,7 +112,11 @@ void render_circle(const CirclePrimitive *circle) {
|
|||||||
command.element_count = (num_vertices - 2) * 3;
|
command.element_count = (num_vertices - 2) * 3;
|
||||||
command.range_end = (num_vertices - 2) * 3;
|
command.range_end = (num_vertices - 2) * 3;
|
||||||
|
|
||||||
use_texture_mode(circle->color.a == 255 ? TEXTURE_MODE_OPAQUE : TEXTURE_MODE_GHOSTLY);
|
command.texture_mode = circle->color.a == 255 ? TEXTURE_MODE_OPAQUE : TEXTURE_MODE_GHOSTLY;
|
||||||
|
command.pipeline = PIPELINE_2D;
|
||||||
|
|
||||||
|
command.depth_range_high = depth_range_high;
|
||||||
|
command.depth_range_low = depth_range_low;
|
||||||
|
|
||||||
DeferredCommand final_command = {
|
DeferredCommand final_command = {
|
||||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
PIPELINE_NO,
|
PIPELINE_NO,
|
||||||
PIPELINE_SPACE,
|
PIPELINE_SPACE,
|
||||||
PIPELINE_2D,
|
PIPELINE_2D, /* TODO: rename to PIPELINE_PLANE? */
|
||||||
} Pipeline;
|
} Pipeline;
|
||||||
|
|
||||||
|
|
||||||
@ -30,25 +30,27 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
AttributeArrayPointer vertices;
|
AttributeArrayPointer vertices;
|
||||||
AttributeArrayPointer texcoords;
|
AttributeArrayPointer texcoords;
|
||||||
|
|
||||||
bool constant_colored;
|
|
||||||
union {
|
union {
|
||||||
AttributeArrayPointer colors;
|
AttributeArrayPointer colors;
|
||||||
Color color;
|
Color color;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool textured, texture_repeat, uses_gpu_key;
|
double depth_range_low, depth_range_high;
|
||||||
|
|
||||||
|
Pipeline pipeline;
|
||||||
|
TextureMode texture_mode;
|
||||||
|
|
||||||
TextureKey texture_key;
|
TextureKey texture_key;
|
||||||
GPUTexture gpu_texture;
|
GPUTexture gpu_texture;
|
||||||
|
|
||||||
|
/* could be either `element_count` with supplied `element_buffer`, or this, but not both */
|
||||||
|
uint32_t primitive_count;
|
||||||
uint32_t element_buffer;
|
uint32_t element_buffer;
|
||||||
uint32_t element_count;
|
uint32_t element_count;
|
||||||
uint32_t range_start, range_end;
|
uint32_t range_start, range_end;
|
||||||
|
|
||||||
/* could be either `element_count` with supplied `element_buffer`, or this, but not both */
|
bool constant_colored;
|
||||||
uint32_t primitive_count;
|
bool textured, texture_repeat, uses_gpu_key;
|
||||||
|
|
||||||
double depth_range_low, depth_range_high;
|
|
||||||
} DeferredCommandDraw;
|
} DeferredCommandDraw;
|
||||||
|
|
||||||
|
|
||||||
@ -65,47 +67,17 @@ typedef struct {
|
|||||||
} DeferredCommandClear;
|
} DeferredCommandClear;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Pipeline pipeline;
|
|
||||||
} DeferredCommandUsePipeline;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TextureMode mode;
|
|
||||||
} DeferredCommandUseTextureMode;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
double low, high;
|
|
||||||
} DeferredCommandDepthRange;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float start, end, density;
|
|
||||||
Color color;
|
|
||||||
} DeferredCommandApplyFog;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum DeferredCommandType {
|
enum DeferredCommandType {
|
||||||
DEFERRED_COMMAND_TYPE_DRAW,
|
DEFERRED_COMMAND_TYPE_DRAW,
|
||||||
DEFERRED_COMMAND_TYPE_DRAW_SKYBOX,
|
DEFERRED_COMMAND_TYPE_DRAW_SKYBOX,
|
||||||
DEFERRED_COMMAND_TYPE_CLEAR,
|
DEFERRED_COMMAND_TYPE_CLEAR,
|
||||||
DEFERRED_COMMAND_TYPE_USE_PIPIELINE,
|
|
||||||
DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE,
|
|
||||||
DEFERRED_COMMAND_TYPE_DEPTH_RANGE,
|
|
||||||
DEFERRED_COMMAND_TYPE_APPLY_FOG,
|
|
||||||
DEFERRED_COMMAND_TYPE_POP_FOG,
|
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
DeferredCommandDraw draw;
|
DeferredCommandDraw draw;
|
||||||
DeferredCommandDrawSkybox draw_skybox;
|
DeferredCommandDrawSkybox draw_skybox;
|
||||||
DeferredCommandClear clear;
|
DeferredCommandClear clear;
|
||||||
DeferredCommandUsePipeline use_pipeline;
|
|
||||||
DeferredCommandUseTextureMode use_texture_mode;
|
|
||||||
DeferredCommandDepthRange depth_range;
|
|
||||||
DeferredCommandApplyFog apply_fog;
|
|
||||||
};
|
};
|
||||||
} DeferredCommand;
|
} DeferredCommand;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "twn_engine_context_c.h"
|
#include "twn_engine_context_c.h"
|
||||||
#include "twn_camera_c.h"
|
#include "twn_camera_c.h"
|
||||||
#include "twn_types.h"
|
#include "twn_types.h"
|
||||||
#include "twn_util_c.h"
|
|
||||||
#include "twn_vec.h"
|
#include "twn_vec.h"
|
||||||
#include "twn_deferred_commands.h"
|
#include "twn_deferred_commands.h"
|
||||||
|
|
||||||
@ -11,15 +10,19 @@
|
|||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <math.h>
|
||||||
#include <tgmath.h>
|
#include <tgmath.h>
|
||||||
|
|
||||||
|
|
||||||
DeferredCommand *deferred_commands;
|
DeferredCommand *deferred_commands;
|
||||||
|
|
||||||
/* TODO: have a default initialized one */
|
/* TODO: have a default initialized one */
|
||||||
|
/* TODO: with buffered render, don't we use camera of wrong frame right now ? */
|
||||||
Matrix4 camera_projection_matrix;
|
Matrix4 camera_projection_matrix;
|
||||||
Matrix4 camera_look_at_matrix;
|
Matrix4 camera_look_at_matrix;
|
||||||
|
|
||||||
|
double depth_range_low, depth_range_high;
|
||||||
|
|
||||||
|
|
||||||
void render_queue_clear(void) {
|
void render_queue_clear(void) {
|
||||||
text_cache_reset_arena(&ctx.text_cache);
|
text_cache_reset_arena(&ctx.text_cache);
|
||||||
@ -205,8 +208,6 @@ TWN_API void draw_quad(char const *texture,
|
|||||||
|
|
||||||
|
|
||||||
static void render_2d(void) {
|
static void render_2d(void) {
|
||||||
use_2d_pipeline();
|
|
||||||
|
|
||||||
const size_t render_queue_len = arrlenu(ctx.render_queue_2d);
|
const size_t render_queue_len = arrlenu(ctx.render_queue_2d);
|
||||||
|
|
||||||
struct Render2DInvocation {
|
struct Render2DInvocation {
|
||||||
@ -362,9 +363,6 @@ static void render_space(void) {
|
|||||||
/* nothing to do, abort */
|
/* nothing to do, abort */
|
||||||
/* as space pipeline isn't used we can have fewer changes and initialization costs */
|
/* as space pipeline isn't used we can have fewer changes and initialization costs */
|
||||||
if (hmlenu(ctx.uncolored_mesh_batches) != 0 || hmlenu(ctx.billboard_batches) != 0) {
|
if (hmlenu(ctx.uncolored_mesh_batches) != 0 || hmlenu(ctx.billboard_batches) != 0) {
|
||||||
use_space_pipeline();
|
|
||||||
apply_fog();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < hmlenu(ctx.uncolored_mesh_batches); ++i) {
|
for (size_t i = 0; i < hmlenu(ctx.uncolored_mesh_batches); ++i) {
|
||||||
finally_draw_uncolored_space_traingle_batch(&ctx.uncolored_mesh_batches[i].value,
|
finally_draw_uncolored_space_traingle_batch(&ctx.uncolored_mesh_batches[i].value,
|
||||||
ctx.uncolored_mesh_batches[i].key);
|
ctx.uncolored_mesh_batches[i].key);
|
||||||
@ -373,8 +371,6 @@ static void render_space(void) {
|
|||||||
for (size_t i = 0; i < hmlenu(ctx.billboard_batches); ++i) {
|
for (size_t i = 0; i < hmlenu(ctx.billboard_batches); ++i) {
|
||||||
finally_draw_billboard_batch(&ctx.billboard_batches[i].value, ctx.billboard_batches[i].key);
|
finally_draw_billboard_batch(&ctx.billboard_batches[i].value, ctx.billboard_batches[i].key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_fog();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render_skybox(); /* after everything else, as to use depth buffer for early z rejection */
|
render_skybox(); /* after everything else, as to use depth buffer for early z rejection */
|
||||||
@ -439,15 +435,8 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position,
|
|||||||
|
|
||||||
|
|
||||||
void set_depth_range(double low, double high) {
|
void set_depth_range(double low, double high) {
|
||||||
DeferredCommand const command = {
|
depth_range_low = low;
|
||||||
.type = DEFERRED_COMMAND_TYPE_DEPTH_RANGE,
|
depth_range_high = high;
|
||||||
.depth_range = {
|
|
||||||
.low = low,
|
|
||||||
.high = high
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
arrpush(deferred_commands, command);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -468,44 +457,9 @@ void clear_draw_buffer(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void use_texture_mode(TextureMode mode) {
|
|
||||||
DeferredCommand const command = {
|
|
||||||
.type = DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE,
|
|
||||||
.use_texture_mode = { mode }
|
|
||||||
};
|
|
||||||
|
|
||||||
arrpush(deferred_commands, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void use_2d_pipeline(void) {
|
|
||||||
DeferredCommand const command = {
|
|
||||||
.type = DEFERRED_COMMAND_TYPE_USE_PIPIELINE,
|
|
||||||
.use_pipeline = { PIPELINE_2D }
|
|
||||||
};
|
|
||||||
|
|
||||||
arrpush(deferred_commands, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void use_space_pipeline(void) {
|
|
||||||
DeferredCommand const command = {
|
|
||||||
.type = DEFERRED_COMMAND_TYPE_USE_PIPIELINE,
|
|
||||||
.use_pipeline = { PIPELINE_SPACE }
|
|
||||||
};
|
|
||||||
|
|
||||||
arrpush(deferred_commands, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void issue_deferred_draw_commands(void) {
|
void issue_deferred_draw_commands(void) {
|
||||||
for (size_t i = 0; i < arrlenu(deferred_commands); ++i) {
|
for (size_t i = 0; i < arrlenu(deferred_commands); ++i) {
|
||||||
switch (deferred_commands[i].type) {
|
switch (deferred_commands[i].type) {
|
||||||
case DEFERRED_COMMAND_TYPE_DEPTH_RANGE: {
|
|
||||||
finally_set_depth_range(deferred_commands[i].depth_range);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DEFERRED_COMMAND_TYPE_CLEAR: {
|
case DEFERRED_COMMAND_TYPE_CLEAR: {
|
||||||
finally_clear_draw_buffer(deferred_commands[i].clear);
|
finally_clear_draw_buffer(deferred_commands[i].clear);
|
||||||
break;
|
break;
|
||||||
@ -521,37 +475,6 @@ void issue_deferred_draw_commands(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DEFERRED_COMMAND_TYPE_USE_PIPIELINE: {
|
|
||||||
switch (deferred_commands[i].use_pipeline.pipeline) {
|
|
||||||
case PIPELINE_2D:
|
|
||||||
finally_use_2d_pipeline();
|
|
||||||
break;
|
|
||||||
case PIPELINE_SPACE:
|
|
||||||
finally_use_space_pipeline();
|
|
||||||
break;
|
|
||||||
case PIPELINE_NO:
|
|
||||||
default:
|
|
||||||
SDL_assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DEFERRED_COMMAND_TYPE_USE_TEXTURE_MODE: {
|
|
||||||
finally_use_texture_mode(deferred_commands[i].use_texture_mode.mode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DEFERRED_COMMAND_TYPE_APPLY_FOG: {
|
|
||||||
finally_apply_fog(deferred_commands[i].apply_fog);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DEFERRED_COMMAND_TYPE_POP_FOG: {
|
|
||||||
finally_pop_fog();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SDL_assert(false);
|
SDL_assert(false);
|
||||||
}
|
}
|
||||||
|
@ -12,27 +12,35 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <stb_truetype.h>
|
#include <stb_truetype.h>
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
|
||||||
#include <GLES2/gl2.h>
|
|
||||||
#else
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
extern Matrix4 camera_projection_matrix;
|
extern Matrix4 camera_projection_matrix;
|
||||||
extern Matrix4 camera_look_at_matrix;
|
extern Matrix4 camera_look_at_matrix;
|
||||||
|
|
||||||
|
extern double depth_range_low, depth_range_high;
|
||||||
|
|
||||||
#define QUAD_ELEMENT_BUFFER_LENGTH (65536 / 6)
|
#define QUAD_ELEMENT_BUFFER_LENGTH (65536 / 6)
|
||||||
#define CIRCLE_VERTICES_MAX 2048
|
#define CIRCLE_VERTICES_MAX 2048
|
||||||
|
|
||||||
|
/* TODO: limit to only most necessary */
|
||||||
|
enum {
|
||||||
|
TWN_FLOAT,
|
||||||
|
TWN_INT,
|
||||||
|
TWN_SHORT,
|
||||||
|
TWN_UNSIGNED_SHORT,
|
||||||
|
TWN_UNSIGNED_INT,
|
||||||
|
TWN_BYTE,
|
||||||
|
TWN_UNSIGNED_BYTE,
|
||||||
|
};
|
||||||
|
|
||||||
typedef GLuint VertexBuffer;
|
|
||||||
|
typedef uint32_t VertexBuffer;
|
||||||
|
|
||||||
typedef struct VertexBufferBuilder {
|
typedef struct VertexBufferBuilder {
|
||||||
size_t bytes_left;
|
size_t bytes_left;
|
||||||
|
size_t size;
|
||||||
void *mapping;
|
void *mapping;
|
||||||
|
void *base;
|
||||||
} VertexBufferBuilder;
|
} VertexBufferBuilder;
|
||||||
|
|
||||||
|
|
||||||
@ -209,6 +217,8 @@ typedef struct ElementIndexedBillboard {
|
|||||||
} ElementIndexedBillboard;
|
} ElementIndexedBillboard;
|
||||||
|
|
||||||
|
|
||||||
|
bool render_init(void);
|
||||||
|
|
||||||
/* renders the background, then the primitives in all render queues */
|
/* renders the background, then the primitives in all render queues */
|
||||||
void render(void);
|
void render(void);
|
||||||
|
|
||||||
@ -250,6 +260,8 @@ void text_cache_reset_arena(TextCache *cache);
|
|||||||
|
|
||||||
VertexBuffer create_vertex_buffer(void);
|
VertexBuffer create_vertex_buffer(void);
|
||||||
|
|
||||||
|
void restart_scratch_vertex_arrays(void);
|
||||||
|
|
||||||
VertexBuffer get_scratch_vertex_array(void);
|
VertexBuffer get_scratch_vertex_array(void);
|
||||||
|
|
||||||
void delete_vertex_buffer(VertexBuffer buffer);
|
void delete_vertex_buffer(VertexBuffer buffer);
|
||||||
@ -274,7 +286,6 @@ void finally_clear_draw_buffer(DeferredCommandClear command);
|
|||||||
void swap_buffers(void);
|
void swap_buffers(void);
|
||||||
|
|
||||||
void set_depth_range(double low, double high);
|
void set_depth_range(double low, double high);
|
||||||
void finally_set_depth_range(DeferredCommandDepthRange command);
|
|
||||||
|
|
||||||
VertexBuffer get_quad_element_buffer(void);
|
VertexBuffer get_quad_element_buffer(void);
|
||||||
|
|
||||||
@ -284,15 +295,6 @@ void render_circle(const CirclePrimitive *circle);
|
|||||||
|
|
||||||
void render_rectangle(const RectPrimitive *rectangle);
|
void render_rectangle(const RectPrimitive *rectangle);
|
||||||
|
|
||||||
void use_space_pipeline(void);
|
|
||||||
void finally_use_space_pipeline(void);
|
|
||||||
|
|
||||||
void use_2d_pipeline(void);
|
|
||||||
void finally_use_2d_pipeline(void);
|
|
||||||
|
|
||||||
void use_texture_mode(TextureMode mode);
|
|
||||||
void finally_use_texture_mode(TextureMode mode);
|
|
||||||
|
|
||||||
void finally_render_quads(Primitive2D const primitives[],
|
void finally_render_quads(Primitive2D const primitives[],
|
||||||
struct QuadBatch batch,
|
struct QuadBatch batch,
|
||||||
VertexBuffer buffer);
|
VertexBuffer buffer);
|
||||||
@ -325,11 +327,6 @@ void finally_draw_text(FontData const *font_data,
|
|||||||
void render_skybox(void);
|
void render_skybox(void);
|
||||||
void finally_render_skybox(DeferredCommandDrawSkybox);
|
void finally_render_skybox(DeferredCommandDrawSkybox);
|
||||||
|
|
||||||
void apply_fog(void);
|
|
||||||
void finally_apply_fog(DeferredCommandApplyFog);
|
|
||||||
void pop_fog(void);
|
|
||||||
void finally_pop_fog(void);
|
|
||||||
|
|
||||||
void start_render_frame(void);
|
void start_render_frame(void);
|
||||||
void end_render_frame(void);
|
void end_render_frame(void);
|
||||||
|
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
#include "twn_draw.h"
|
|
||||||
#include "twn_draw_c.h"
|
|
||||||
|
|
||||||
#include <stb_ds.h>
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
static float start_cache, end_cache, density_cache;
|
|
||||||
static Color color_cache;
|
|
||||||
static bool fog_used = false;
|
|
||||||
|
|
||||||
|
|
||||||
void draw_fog(float start, float end, float density, Color color) {
|
|
||||||
start_cache = start;
|
|
||||||
end_cache = end;
|
|
||||||
density_cache = density;
|
|
||||||
color_cache = color;
|
|
||||||
fog_used = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void apply_fog(void) {
|
|
||||||
if (!fog_used)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DeferredCommand command = {
|
|
||||||
.type = DEFERRED_COMMAND_TYPE_APPLY_FOG,
|
|
||||||
.apply_fog = (DeferredCommandApplyFog){
|
|
||||||
.start = start_cache,
|
|
||||||
.end = end_cache,
|
|
||||||
.density = density_cache,
|
|
||||||
.color = color_cache
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
arrpush(deferred_commands, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void pop_fog(void) {
|
|
||||||
if (!fog_used)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DeferredCommand command = {
|
|
||||||
.type = DEFERRED_COMMAND_TYPE_POP_FOG,
|
|
||||||
};
|
|
||||||
|
|
||||||
arrpush(deferred_commands, command);
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
#include "twn_gpu_texture_c.h"
|
|
||||||
#include "twn_util_c.h"
|
|
||||||
|
|
||||||
|
|
||||||
GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps) {
|
|
||||||
GLuint texture;
|
|
||||||
glGenTextures(1, &texture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, (GLboolean)generate_mipmaps);
|
|
||||||
|
|
||||||
if (filter == TEXTURE_FILTER_NEAREAST) {
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
} else if (filter == TEXTURE_FILTER_LINEAR) {
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
|
||||||
#if !defined(EMSCRIPTEN)
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void delete_gpu_texture(GPUTexture texture) {
|
|
||||||
glDeleteTextures(1, &texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int width, int height) {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
|
||||||
|
|
||||||
int format_internal, format;
|
|
||||||
if (channels == 4) {
|
|
||||||
format_internal = GL_RGBA8;
|
|
||||||
format = GL_RGBA;
|
|
||||||
} else if (channels == 3) {
|
|
||||||
format_internal = GL_RGBA8;
|
|
||||||
format = GL_RGB;
|
|
||||||
} else if (channels == 1) {
|
|
||||||
format_internal = GL_ALPHA;
|
|
||||||
format = GL_ALPHA;
|
|
||||||
} else {
|
|
||||||
CRY("upload_gpu_texture", "Unsupported channel count");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D,
|
|
||||||
0,
|
|
||||||
format_internal,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
0,
|
|
||||||
format,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
pixels);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void bind_gpu_texture(GPUTexture texture) {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
|
||||||
}
|
|
@ -4,7 +4,6 @@
|
|||||||
#include "twn_engine_context_c.h"
|
#include "twn_engine_context_c.h"
|
||||||
#include "twn_types.h"
|
#include "twn_types.h"
|
||||||
#include "twn_deferred_commands.h"
|
#include "twn_deferred_commands.h"
|
||||||
#include "twn_gl_any_rendering_c.h"
|
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
@ -14,8 +13,49 @@ static TextureMode texture_mode_last_used = TEXTURE_MODE_UNKNOWN;
|
|||||||
static Pipeline pipeline_last_used = PIPELINE_NO;
|
static Pipeline pipeline_last_used = PIPELINE_NO;
|
||||||
|
|
||||||
|
|
||||||
|
static void APIENTRY opengl_log(GLenum source,
|
||||||
|
GLenum type,
|
||||||
|
GLuint id,
|
||||||
|
GLenum severity,
|
||||||
|
GLsizei length,
|
||||||
|
const GLchar* message,
|
||||||
|
const void* userParam)
|
||||||
|
{
|
||||||
|
(void)source;
|
||||||
|
(void)type;
|
||||||
|
(void)id;
|
||||||
|
(void)severity;
|
||||||
|
(void)userParam;
|
||||||
|
|
||||||
|
log_info("OpenGL: %.*s\n", length, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool render_init(void) {
|
||||||
|
if (gladLoadGL() == 0) {
|
||||||
|
CRY("Init", "GLAD failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info("OpenGL context: %s\n", glGetString(GL_VERSION));
|
||||||
|
|
||||||
|
glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
|
||||||
|
glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||||
|
glHint(GL_FOG_HINT, GL_FASTEST);
|
||||||
|
|
||||||
|
/* hook up opengl debugging callback */
|
||||||
|
if (ctx.game.debug) {
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
glDebugMessageCallback(opengl_log, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void start_render_frame(void) {
|
void start_render_frame(void) {
|
||||||
clear_draw_buffer();
|
clear_draw_buffer();
|
||||||
|
pipeline_last_used = PIPELINE_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -38,10 +78,13 @@ void end_render_frame(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void finally_use_space_pipeline(void) {
|
static void finally_use_space_pipeline(void) {
|
||||||
if (pipeline_last_used == PIPELINE_SPACE)
|
if (pipeline_last_used == PIPELINE_SPACE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
depth_range_high = 1.0;
|
||||||
|
depth_range_low = 0.0;
|
||||||
|
|
||||||
static GLuint list = 0;
|
static GLuint list = 0;
|
||||||
if (!list) {
|
if (!list) {
|
||||||
list = glGenLists(1);
|
list = glGenLists(1);
|
||||||
@ -54,9 +97,9 @@ void finally_use_space_pipeline(void) {
|
|||||||
glDisable(GL_DEPTH_CLAMP);
|
glDisable(GL_DEPTH_CLAMP);
|
||||||
|
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glDepthRange(0, 1);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
/* solid white, no modulation */
|
/* solid white, no modulation */
|
||||||
glColor4ub(255, 255, 255, 255);
|
glColor4ub(255, 255, 255, 255);
|
||||||
@ -76,7 +119,7 @@ void finally_use_space_pipeline(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void finally_use_2d_pipeline(void) {
|
static void finally_use_2d_pipeline(void) {
|
||||||
if (pipeline_last_used == PIPELINE_SPACE) {
|
if (pipeline_last_used == PIPELINE_SPACE) {
|
||||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
glFlush();
|
glFlush();
|
||||||
@ -111,6 +154,7 @@ void finally_use_2d_pipeline(void) {
|
|||||||
glOrtho(0, (double)ctx.base_render_width, (double)ctx.base_render_height, 0, 0, 1);
|
glOrtho(0, (double)ctx.base_render_width, (double)ctx.base_render_height, 0, 0, 1);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
/* TODO: 2d camera */
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
texture_mode_last_used = -1;
|
texture_mode_last_used = -1;
|
||||||
@ -118,7 +162,7 @@ void finally_use_2d_pipeline(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void finally_use_texture_mode(TextureMode mode) {
|
static void finally_use_texture_mode(TextureMode mode) {
|
||||||
if (texture_mode_last_used == mode)
|
if (texture_mode_last_used == mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -248,6 +292,9 @@ void finally_render_skybox(DeferredCommandDrawSkybox command) {
|
|||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadMatrixf(&camera_look_at_matrix_solipsist.row[0].x);
|
glLoadMatrixf(&camera_look_at_matrix_solipsist.row[0].x);
|
||||||
|
|
||||||
|
glDepthRange(0.0f, 1.0f);
|
||||||
|
glDisable(GL_FOG);
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
glEnable(GL_TEXTURE_CUBE_MAP);
|
glEnable(GL_TEXTURE_CUBE_MAP);
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
|
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
|
||||||
@ -370,38 +417,6 @@ void finally_render_skybox(DeferredCommandDrawSkybox command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void finally_apply_fog(DeferredCommandApplyFog command) {
|
|
||||||
if (command.density < 0.0f || command.density > 1.0f)
|
|
||||||
log_warn("Invalid fog density given, should be in range [0..1]");
|
|
||||||
|
|
||||||
/* TODO: cache it for constant parameters, which is a common case */
|
|
||||||
|
|
||||||
glEnable(GL_FOG);
|
|
||||||
|
|
||||||
glFogf(GL_FOG_DENSITY, command.density);
|
|
||||||
glFogf(GL_FOG_START, command.start);
|
|
||||||
glFogf(GL_FOG_END, command.end);
|
|
||||||
|
|
||||||
float color_conv[4];
|
|
||||||
color_conv[0] = (float)command.color.r / UINT8_MAX;
|
|
||||||
color_conv[1] = (float)command.color.g / UINT8_MAX;
|
|
||||||
color_conv[2] = (float)command.color.b / UINT8_MAX;
|
|
||||||
color_conv[3] = (float)command.color.a / UINT8_MAX;
|
|
||||||
|
|
||||||
glFogfv(GL_FOG_COLOR, color_conv);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void finally_pop_fog(void) {
|
|
||||||
glDisable(GL_FOG);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void finally_set_depth_range(DeferredCommandDepthRange command) {
|
|
||||||
glDepthRange(command.low, command.high);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void finally_clear_draw_buffer(DeferredCommandClear command) {
|
void finally_clear_draw_buffer(DeferredCommandClear command) {
|
||||||
glClearColor((1.0f / 255) * command.color.r,
|
glClearColor((1.0f / 255) * command.color.r,
|
||||||
(1.0f / 255) * command.color.g,
|
(1.0f / 255) * command.color.g,
|
||||||
@ -418,18 +433,64 @@ void finally_clear_draw_buffer(DeferredCommandClear command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GLsizei to_gl_type_enum(int value) {
|
||||||
|
switch (value) {
|
||||||
|
case TWN_FLOAT: return GL_FLOAT;
|
||||||
|
case TWN_INT: return GL_INT;
|
||||||
|
case TWN_SHORT: return GL_SHORT;
|
||||||
|
case TWN_UNSIGNED_SHORT: return GL_UNSIGNED_SHORT;
|
||||||
|
case TWN_UNSIGNED_BYTE: return GL_UNSIGNED_BYTE;
|
||||||
|
case TWN_BYTE: return GL_BYTE;
|
||||||
|
default:
|
||||||
|
CRY("to_gl_type_enum", "Unknown primitive type");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void finally_draw_command(DeferredCommandDraw command) {
|
void finally_draw_command(DeferredCommandDraw command) {
|
||||||
/* TODO: don't assume a single vertex array ? */
|
/* TODO: don't assume a single vertex array ? */
|
||||||
SDL_assert(command.vertices.arity != 0);
|
SDL_assert(command.vertices.arity != 0);
|
||||||
SDL_assert(command.vertices.buffer);
|
SDL_assert(command.vertices.buffer);
|
||||||
SDL_assert((command.element_buffer && command.element_count != 0) || command.primitive_count != 0);
|
SDL_assert((command.element_buffer && command.element_count != 0) || command.primitive_count != 0);
|
||||||
|
|
||||||
|
/* TODO: cache previous setting, don't recommit */
|
||||||
|
glDepthRange(command.depth_range_low, command.depth_range_high);
|
||||||
|
|
||||||
|
/* TODO: cache it for constant parameters, which is a common case */
|
||||||
|
if (fabsf(0.0f - ctx.game_copy.fog_density) >= 0.00001f) {
|
||||||
|
glEnable(GL_FOG);
|
||||||
|
|
||||||
|
/* clamp to valid range */
|
||||||
|
ctx.game_copy.fog_density = clampf(ctx.game_copy.fog_density, 0.0, 1.0);
|
||||||
|
|
||||||
|
glFogf(GL_FOG_DENSITY, ctx.game_copy.fog_density);
|
||||||
|
glFogf(GL_FOG_START, ctx.game_copy.fog_start);
|
||||||
|
glFogf(GL_FOG_END, ctx.game_copy.fog_end);
|
||||||
|
|
||||||
|
float color_conv[4];
|
||||||
|
color_conv[0] = (float)ctx.game_copy.fog_color.r / UINT8_MAX;
|
||||||
|
color_conv[1] = (float)ctx.game_copy.fog_color.g / UINT8_MAX;
|
||||||
|
color_conv[2] = (float)ctx.game_copy.fog_color.b / UINT8_MAX;
|
||||||
|
color_conv[3] = (float)ctx.game_copy.fog_color.a / UINT8_MAX;
|
||||||
|
|
||||||
|
glFogfv(GL_FOG_COLOR, color_conv);
|
||||||
|
} else
|
||||||
|
glDisable(GL_FOG);
|
||||||
|
|
||||||
|
if (command.pipeline == PIPELINE_SPACE)
|
||||||
|
finally_use_space_pipeline();
|
||||||
|
else
|
||||||
|
finally_use_2d_pipeline();
|
||||||
|
|
||||||
|
finally_use_texture_mode(command.texture_mode);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, command.vertices.buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, command.vertices.buffer);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, command.element_buffer);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, command.element_buffer);
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glVertexPointer(command.vertices.arity,
|
glVertexPointer(command.vertices.arity,
|
||||||
command.vertices.type,
|
to_gl_type_enum(command.vertices.type),
|
||||||
command.vertices.stride,
|
command.vertices.stride,
|
||||||
(void *)command.vertices.offset);
|
(void *)command.vertices.offset);
|
||||||
|
|
||||||
@ -439,7 +500,7 @@ void finally_draw_command(DeferredCommandDraw command) {
|
|||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
glClientActiveTexture(GL_TEXTURE0);
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
glTexCoordPointer(command.texcoords.arity,
|
glTexCoordPointer(command.texcoords.arity,
|
||||||
command.texcoords.type,
|
to_gl_type_enum(command.texcoords.type),
|
||||||
command.texcoords.stride,
|
command.texcoords.stride,
|
||||||
(void *)command.texcoords.offset);
|
(void *)command.texcoords.offset);
|
||||||
}
|
}
|
||||||
@ -449,7 +510,7 @@ void finally_draw_command(DeferredCommandDraw command) {
|
|||||||
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
glColorPointer(command.colors.arity,
|
glColorPointer(command.colors.arity,
|
||||||
command.colors.type,
|
to_gl_type_enum(command.colors.type),
|
||||||
command.colors.stride,
|
command.colors.stride,
|
||||||
(void *)command.colors.offset);
|
(void *)command.colors.offset);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "twn_gl_any_rendering_c.h"
|
|
||||||
#include "twn_draw_c.h"
|
|
||||||
#include "twn_engine_context_c.h"
|
#include "twn_engine_context_c.h"
|
||||||
|
#include "twn_util_c.h"
|
||||||
|
#include "twn_draw_c.h"
|
||||||
|
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
|
|
||||||
@ -120,3 +120,85 @@ GLuint get_scratch_vertex_array(void) {
|
|||||||
(*used)++;
|
(*used)++;
|
||||||
return (*current_scratch_vertex_array)[*used - 1];
|
return (*current_scratch_vertex_array)[*used - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps) {
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
#if !defined(EMSCRIPTEN)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, (GLboolean)generate_mipmaps);
|
||||||
|
#else
|
||||||
|
if (generate_mipmaps)
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (filter == TEXTURE_FILTER_NEAREAST) {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
} else if (filter == TEXTURE_FILTER_LINEAR) {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
#if !defined(EMSCRIPTEN)
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void delete_gpu_texture(GPUTexture texture) {
|
||||||
|
glDeleteTextures(1, &texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int width, int height) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
int format_internal, format;
|
||||||
|
if (channels == 4) {
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
format_internal = GL_RGBA;
|
||||||
|
#else
|
||||||
|
format_internal = GL_RGBA8;
|
||||||
|
#endif
|
||||||
|
format = GL_RGBA;
|
||||||
|
} else if (channels == 3) {
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
format_internal = GL_RGBA;
|
||||||
|
#else
|
||||||
|
format_internal = GL_RGBA8;
|
||||||
|
#endif
|
||||||
|
format = GL_RGB;
|
||||||
|
} else if (channels == 1) {
|
||||||
|
format_internal = GL_ALPHA;
|
||||||
|
format = GL_ALPHA;
|
||||||
|
} else {
|
||||||
|
CRY("upload_gpu_texture", "Unsupported channel count");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
format_internal,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
0,
|
||||||
|
format,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
pixels);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bind_gpu_texture(GPUTexture texture) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
#ifndef TWN_GL_ANY_RENDERING_C_H
|
|
||||||
#define TWN_GL_ANY_RENDERING_C_H
|
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
|
||||||
#include <GLES2/gl2.h>
|
|
||||||
#else
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
void restart_scratch_vertex_arrays(void);
|
|
||||||
|
|
||||||
GLuint get_scratch_vertex_array(void);
|
|
||||||
|
|
||||||
#endif
|
|
@ -2,8 +2,9 @@
|
|||||||
#define TWN_GPU_TEXTURE_C_H
|
#define TWN_GPU_TEXTURE_C_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef GLuint GPUTexture;
|
typedef uint32_t GPUTexture;
|
||||||
|
|
||||||
typedef enum TextureFilter {
|
typedef enum TextureFilter {
|
||||||
TEXTURE_FILTER_NEAREAST,
|
TEXTURE_FILTER_NEAREAST,
|
||||||
|
@ -11,7 +11,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
|||||||
{
|
{
|
||||||
DeferredCommandDraw command = {0};
|
DeferredCommandDraw command = {0};
|
||||||
|
|
||||||
GLsizei off = 0, voff = 0, uvoff = 0, coff = 0;
|
uint32_t off = 0, voff = 0, uvoff = 0, coff = 0;
|
||||||
|
|
||||||
if (!batch.constant_colored && batch.textured) {
|
if (!batch.constant_colored && batch.textured) {
|
||||||
off = offsetof(ElementIndexedQuad, v1);
|
off = offsetof(ElementIndexedQuad, v1);
|
||||||
@ -33,7 +33,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
|||||||
|
|
||||||
command.vertices = (AttributeArrayPointer) {
|
command.vertices = (AttributeArrayPointer) {
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = off,
|
.stride = off,
|
||||||
.offset = voff,
|
.offset = voff,
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -42,7 +42,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
|||||||
if (batch.textured)
|
if (batch.textured)
|
||||||
command.texcoords = (AttributeArrayPointer) {
|
command.texcoords = (AttributeArrayPointer) {
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = off,
|
.stride = off,
|
||||||
.offset = uvoff,
|
.offset = uvoff,
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -51,7 +51,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
|||||||
if (!batch.constant_colored) {
|
if (!batch.constant_colored) {
|
||||||
command.colors = (AttributeArrayPointer) {
|
command.colors = (AttributeArrayPointer) {
|
||||||
.arity = 4,
|
.arity = 4,
|
||||||
.type = GL_UNSIGNED_BYTE,
|
.type = TWN_UNSIGNED_BYTE,
|
||||||
.stride = off,
|
.stride = off,
|
||||||
.offset = coff,
|
.offset = coff,
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -68,10 +68,14 @@ void finally_render_quads(const Primitive2D primitives[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
command.element_buffer = get_quad_element_buffer();
|
command.element_buffer = get_quad_element_buffer();
|
||||||
command.element_count = 6 * (GLsizei)batch.size;
|
command.element_count = 6 * (uint32_t)batch.size;
|
||||||
command.range_end = 6 * (GLsizei)batch.size;
|
command.range_end = 6 * (uint32_t)batch.size;
|
||||||
|
|
||||||
use_texture_mode(batch.mode);
|
command.texture_mode = batch.mode;
|
||||||
|
command.pipeline = PIPELINE_2D;
|
||||||
|
|
||||||
|
command.depth_range_high = depth_range_high;
|
||||||
|
command.depth_range_low = depth_range_low;
|
||||||
|
|
||||||
DeferredCommand final_command = {
|
DeferredCommand final_command = {
|
||||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||||
|
@ -70,8 +70,6 @@ void render_rect_batch(const Primitive2D primitives[],
|
|||||||
/* single vertex array is used for every batch with NULL glBufferData() trick at the end */
|
/* single vertex array is used for every batch with NULL glBufferData() trick at the end */
|
||||||
VertexBuffer const vertex_array = get_scratch_vertex_array();
|
VertexBuffer const vertex_array = get_scratch_vertex_array();
|
||||||
|
|
||||||
use_texture_mode(batch.mode);
|
|
||||||
|
|
||||||
/* vertex population over a vertex buffer builder interface */
|
/* vertex population over a vertex buffer builder interface */
|
||||||
{
|
{
|
||||||
VertexBufferBuilder payload = build_vertex_buffer(vertex_array, get_quad_payload_size(batch) * batch.size);
|
VertexBufferBuilder payload = build_vertex_buffer(vertex_array, get_quad_payload_size(batch) * batch.size);
|
||||||
|
@ -21,8 +21,6 @@ void render_skybox(void) {
|
|||||||
if (!paths_in_use)
|
if (!paths_in_use)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
use_space_pipeline();
|
|
||||||
|
|
||||||
/* note: ownership of 'paths_in_use' goes there */
|
/* note: ownership of 'paths_in_use' goes there */
|
||||||
DeferredCommand command = {
|
DeferredCommand command = {
|
||||||
.type = DEFERRED_COMMAND_TYPE_DRAW_SKYBOX,
|
.type = DEFERRED_COMMAND_TYPE_DRAW_SKYBOX,
|
||||||
|
@ -351,7 +351,7 @@ void finally_draw_text(FontData const *font_data,
|
|||||||
|
|
||||||
command.vertices = (AttributeArrayPointer) {
|
command.vertices = (AttributeArrayPointer) {
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = offsetof(ElementIndexedQuadWithoutColor, v1),
|
.stride = offsetof(ElementIndexedQuadWithoutColor, v1),
|
||||||
.offset = offsetof(ElementIndexedQuadWithoutColor, v0),
|
.offset = offsetof(ElementIndexedQuadWithoutColor, v0),
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -359,7 +359,7 @@ void finally_draw_text(FontData const *font_data,
|
|||||||
|
|
||||||
command.texcoords = (AttributeArrayPointer) {
|
command.texcoords = (AttributeArrayPointer) {
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = offsetof(ElementIndexedQuadWithoutColor, v1),
|
.stride = offsetof(ElementIndexedQuadWithoutColor, v1),
|
||||||
.offset = offsetof(ElementIndexedQuadWithoutColor, uv0),
|
.offset = offsetof(ElementIndexedQuadWithoutColor, uv0),
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -373,10 +373,14 @@ void finally_draw_text(FontData const *font_data,
|
|||||||
command.textured = true;
|
command.textured = true;
|
||||||
|
|
||||||
command.element_buffer = get_quad_element_buffer();
|
command.element_buffer = get_quad_element_buffer();
|
||||||
command.element_count = 6 * (GLsizei)len;
|
command.element_count = 6 * (uint32_t)len;
|
||||||
command.range_end = 6 * (GLsizei)len;
|
command.range_end = 6 * (uint32_t)len;
|
||||||
|
|
||||||
use_texture_mode(TEXTURE_MODE_GHOSTLY);
|
command.texture_mode = TEXTURE_MODE_GHOSTLY;
|
||||||
|
command.pipeline = PIPELINE_2D;
|
||||||
|
|
||||||
|
command.depth_range_high = depth_range_high;
|
||||||
|
command.depth_range_low = depth_range_low;
|
||||||
|
|
||||||
DeferredCommand final_command = {
|
DeferredCommand final_command = {
|
||||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||||
|
@ -87,7 +87,7 @@ void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
|||||||
|
|
||||||
command.vertices = (AttributeArrayPointer) {
|
command.vertices = (AttributeArrayPointer) {
|
||||||
.arity = 3,
|
.arity = 3,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = offsetof(UncoloredSpaceTriangle, v1),
|
.stride = offsetof(UncoloredSpaceTriangle, v1),
|
||||||
.offset = offsetof(UncoloredSpaceTriangle, v0),
|
.offset = offsetof(UncoloredSpaceTriangle, v0),
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -95,7 +95,7 @@ void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
|||||||
|
|
||||||
command.texcoords = (AttributeArrayPointer) {
|
command.texcoords = (AttributeArrayPointer) {
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.type = GL_FLOAT,
|
.type = TWN_FLOAT,
|
||||||
.stride = offsetof(UncoloredSpaceTriangle, v1),
|
.stride = offsetof(UncoloredSpaceTriangle, v1),
|
||||||
.offset = offsetof(UncoloredSpaceTriangle, uv0),
|
.offset = offsetof(UncoloredSpaceTriangle, uv0),
|
||||||
.buffer = buffer
|
.buffer = buffer
|
||||||
@ -104,13 +104,18 @@ void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
|||||||
command.textured = true;
|
command.textured = true;
|
||||||
command.texture_key = texture_key;
|
command.texture_key = texture_key;
|
||||||
|
|
||||||
command.primitive_count = (GLsizei)(3 * primitives_len);
|
command.primitive_count = (uint32_t)(3 * primitives_len);
|
||||||
|
|
||||||
/* TODO: support alpha blended case, with distance sort */
|
/* TODO: support alpha blended case, with distance sort */
|
||||||
TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
|
TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
|
||||||
if (mode == TEXTURE_MODE_GHOSTLY)
|
if (mode == TEXTURE_MODE_GHOSTLY)
|
||||||
mode = TEXTURE_MODE_SEETHROUGH;
|
mode = TEXTURE_MODE_SEETHROUGH;
|
||||||
use_texture_mode(mode);
|
|
||||||
|
command.texture_mode = mode;
|
||||||
|
command.pipeline = PIPELINE_SPACE;
|
||||||
|
|
||||||
|
command.depth_range_high = depth_range_high;
|
||||||
|
command.depth_range_low = depth_range_low;
|
||||||
|
|
||||||
DeferredCommand final_command = {
|
DeferredCommand final_command = {
|
||||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include "rendering/twn_circles.c"
|
#include "rendering/twn_circles.c"
|
||||||
#include "rendering/twn_draw.c"
|
#include "rendering/twn_draw.c"
|
||||||
#include "rendering/twn_fog.c"
|
|
||||||
#include "rendering/twn_skybox.c"
|
#include "rendering/twn_skybox.c"
|
||||||
#include "rendering/twn_sprites.c"
|
#include "rendering/twn_sprites.c"
|
||||||
#include "rendering/twn_rects.c"
|
#include "rendering/twn_rects.c"
|
||||||
|
@ -12,13 +12,6 @@
|
|||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
#include <toml.h>
|
#include <toml.h>
|
||||||
|
|
||||||
/* TODO: should not be used here directly */
|
|
||||||
#ifdef EMSCRIPTEN
|
|
||||||
#include <GLES2/gl2.h>
|
|
||||||
#else
|
|
||||||
#include <glad/glad.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
@ -100,28 +93,6 @@ static void poll_events(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef EMSCRIPTEN
|
|
||||||
|
|
||||||
static void APIENTRY opengl_log(GLenum source,
|
|
||||||
GLenum type,
|
|
||||||
GLuint id,
|
|
||||||
GLenum severity,
|
|
||||||
GLsizei length,
|
|
||||||
const GLchar* message,
|
|
||||||
const void* userParam)
|
|
||||||
{
|
|
||||||
(void)source;
|
|
||||||
(void)type;
|
|
||||||
(void)id;
|
|
||||||
(void)severity;
|
|
||||||
(void)userParam;
|
|
||||||
|
|
||||||
log_info("OpenGL: %.*s\n", length, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static void preserve_persistent_ctx_fields(void) {
|
static void preserve_persistent_ctx_fields(void) {
|
||||||
ctx.game.udata = ctx.game_copy.udata;
|
ctx.game.udata = ctx.game_copy.udata;
|
||||||
}
|
}
|
||||||
@ -539,25 +510,13 @@ static bool initialize(void) {
|
|||||||
if (SDL_GL_SetSwapInterval(-1))
|
if (SDL_GL_SetSwapInterval(-1))
|
||||||
SDL_GL_SetSwapInterval(1);
|
SDL_GL_SetSwapInterval(1);
|
||||||
|
|
||||||
#ifndef EMSCRIPTEN
|
if (!render_init())
|
||||||
if (gladLoadGL() == 0) {
|
|
||||||
CRY("Init", "GLAD failed");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
log_info("OpenGL context: %s\n", glGetString(GL_VERSION));
|
|
||||||
|
|
||||||
#ifndef EMSCRIPTEN
|
|
||||||
glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
|
|
||||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
|
||||||
glHint(GL_FOG_HINT, GL_FASTEST);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* might need this to have multiple windows */
|
/* might need this to have multiple windows */
|
||||||
ctx.window_id = SDL_GetWindowID(ctx.window);
|
ctx.window_id = SDL_GetWindowID(ctx.window);
|
||||||
|
|
||||||
glViewport(0, 0, (GLsizei)ctx.base_render_width, (GLsizei)ctx.base_render_height);
|
setup_viewport(0, 0, (int)ctx.base_render_width, (int)ctx.base_render_height);
|
||||||
|
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
// SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h);
|
// SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h);
|
||||||
@ -596,14 +555,6 @@ static bool initialize(void) {
|
|||||||
/* you could change this at runtime if you wanted */
|
/* you could change this at runtime if you wanted */
|
||||||
ctx.update_multiplicity = 1;
|
ctx.update_multiplicity = 1;
|
||||||
|
|
||||||
#ifndef EMSCRIPTEN
|
|
||||||
/* hook up opengl debugging callback */
|
|
||||||
if (ctx.game.debug) {
|
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
|
||||||
glDebugMessageCallback(opengl_log, NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* random seeding */
|
/* random seeding */
|
||||||
/* SDL_GetPerformanceCounter returns some platform-dependent number. */
|
/* SDL_GetPerformanceCounter returns some platform-dependent number. */
|
||||||
/* it should vary between game instances. i checked! random enough for me. */
|
/* it should vary between game instances. i checked! random enough for me. */
|
||||||
@ -718,6 +669,9 @@ static bool initialize(void) {
|
|||||||
ctx.render_double_buffered = true;
|
ctx.render_double_buffered = true;
|
||||||
ctx.window_mouse_resident = true;
|
ctx.window_mouse_resident = true;
|
||||||
|
|
||||||
|
ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */
|
||||||
|
ctx.game.fog_end = 1.0f;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "twn_loop.h"
|
#include "twn_loop.h"
|
||||||
|
|
||||||
|
#ifndef EMSCRIPTEN
|
||||||
#define SDL_MAIN_HANDLED
|
#define SDL_MAIN_HANDLED
|
||||||
|
#endif
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user