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_billboards.c
|
||||
src/rendering/twn_circles.c
|
||||
src/rendering/twn_skybox.c
|
||||
src/rendering/twn_fog.c)
|
||||
src/rendering/twn_skybox.c)
|
||||
|
||||
set(TWN_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_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 */
|
||||
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 */
|
||||
/* even if scaling is done, game logic should never change over that */
|
||||
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' */
|
||||
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
|
||||
|
||||
|
@ -9,6 +9,7 @@ typedef enum TextureMode {
|
||||
TEXTURE_MODE_OPAQUE, /* all pixels are solid */
|
||||
TEXTURE_MODE_SEETHROUGH, /* some pixels are alpha zero */
|
||||
TEXTURE_MODE_GHOSTLY, /* arbitrary alpha values */
|
||||
TEXTURE_MODE_COUNT,
|
||||
TEXTURE_MODE_UNKNOWN = -1, /* a sentinel */
|
||||
} TextureMode;
|
||||
|
||||
|
@ -213,18 +213,6 @@
|
||||
{ "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": {
|
||||
@ -269,6 +257,10 @@
|
||||
"fields": [
|
||||
{ "name": "frame_number", "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": "mouse_position", "type": "Vec2" },
|
||||
{ "name": "mouse_movement", "type": "Vec2" },
|
||||
|
@ -133,7 +133,7 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
||||
|
||||
command.vertices = (AttributeArrayPointer) {
|
||||
.arity = 3,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = offsetof(ElementIndexedBillboard, v1),
|
||||
.offset = offsetof(ElementIndexedBillboard, v0),
|
||||
.buffer = buffer
|
||||
@ -141,7 +141,7 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
||||
|
||||
command.texcoords = (AttributeArrayPointer) {
|
||||
.arity = 2,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = offsetof(ElementIndexedBillboard, v1),
|
||||
.offset = offsetof(ElementIndexedBillboard, uv0),
|
||||
.buffer = buffer
|
||||
@ -149,7 +149,7 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
||||
|
||||
command.colors = (AttributeArrayPointer) {
|
||||
.arity = 4,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.type = TWN_UNSIGNED_BYTE,
|
||||
.stride = offsetof(ElementIndexedBillboard, v1),
|
||||
.offset = offsetof(ElementIndexedBillboard, c0),
|
||||
.buffer = buffer
|
||||
@ -159,14 +159,19 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
|
||||
command.texture_key = texture_key;
|
||||
|
||||
command.element_buffer = get_quad_element_buffer();
|
||||
command.element_count = 6 * (GLsizei)primitives_len;
|
||||
command.range_end = 6 * (GLsizei)primitives_len;
|
||||
command.element_count = 6 * (uint32_t)primitives_len;
|
||||
command.range_end = 6 * (uint32_t)primitives_len;
|
||||
|
||||
/* TODO: support alpha blended case, with distance sort */
|
||||
TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
|
||||
if (mode == TEXTURE_MODE_GHOSTLY)
|
||||
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 = {
|
||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||
|
@ -99,7 +99,7 @@ void render_circle(const CirclePrimitive *circle) {
|
||||
|
||||
command.vertices = (AttributeArrayPointer) {
|
||||
.arity = 2,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = sizeof (Vec2),
|
||||
.offset = 0,
|
||||
.buffer = buffer
|
||||
@ -112,7 +112,11 @@ void render_circle(const CirclePrimitive *circle) {
|
||||
command.element_count = (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 = {
|
||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||
|
@ -12,7 +12,7 @@
|
||||
typedef enum {
|
||||
PIPELINE_NO,
|
||||
PIPELINE_SPACE,
|
||||
PIPELINE_2D,
|
||||
PIPELINE_2D, /* TODO: rename to PIPELINE_PLANE? */
|
||||
} Pipeline;
|
||||
|
||||
|
||||
@ -30,25 +30,27 @@ typedef struct {
|
||||
typedef struct {
|
||||
AttributeArrayPointer vertices;
|
||||
AttributeArrayPointer texcoords;
|
||||
|
||||
bool constant_colored;
|
||||
union {
|
||||
AttributeArrayPointer colors;
|
||||
AttributeArrayPointer colors;
|
||||
Color color;
|
||||
};
|
||||
|
||||
bool textured, texture_repeat, uses_gpu_key;
|
||||
double depth_range_low, depth_range_high;
|
||||
|
||||
Pipeline pipeline;
|
||||
TextureMode texture_mode;
|
||||
|
||||
TextureKey texture_key;
|
||||
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_count;
|
||||
uint32_t range_start, range_end;
|
||||
|
||||
/* could be either `element_count` with supplied `element_buffer`, or this, but not both */
|
||||
uint32_t primitive_count;
|
||||
|
||||
double depth_range_low, depth_range_high;
|
||||
bool constant_colored;
|
||||
bool textured, texture_repeat, uses_gpu_key;
|
||||
} DeferredCommandDraw;
|
||||
|
||||
|
||||
@ -65,47 +67,17 @@ typedef struct {
|
||||
} 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 {
|
||||
enum DeferredCommandType {
|
||||
DEFERRED_COMMAND_TYPE_DRAW,
|
||||
DEFERRED_COMMAND_TYPE_DRAW_SKYBOX,
|
||||
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;
|
||||
|
||||
union {
|
||||
DeferredCommandDraw draw;
|
||||
DeferredCommandDrawSkybox draw_skybox;
|
||||
DeferredCommandClear clear;
|
||||
DeferredCommandUsePipeline use_pipeline;
|
||||
DeferredCommandUseTextureMode use_texture_mode;
|
||||
DeferredCommandDepthRange depth_range;
|
||||
DeferredCommandApplyFog apply_fog;
|
||||
};
|
||||
} DeferredCommand;
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "twn_engine_context_c.h"
|
||||
#include "twn_camera_c.h"
|
||||
#include "twn_types.h"
|
||||
#include "twn_util_c.h"
|
||||
#include "twn_vec.h"
|
||||
#include "twn_deferred_commands.h"
|
||||
|
||||
@ -11,15 +10,19 @@
|
||||
#include <stb_ds.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <math.h>
|
||||
#include <tgmath.h>
|
||||
|
||||
|
||||
DeferredCommand *deferred_commands;
|
||||
|
||||
/* 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_look_at_matrix;
|
||||
|
||||
double depth_range_low, depth_range_high;
|
||||
|
||||
|
||||
void render_queue_clear(void) {
|
||||
text_cache_reset_arena(&ctx.text_cache);
|
||||
@ -205,8 +208,6 @@ TWN_API void draw_quad(char const *texture,
|
||||
|
||||
|
||||
static void render_2d(void) {
|
||||
use_2d_pipeline();
|
||||
|
||||
const size_t render_queue_len = arrlenu(ctx.render_queue_2d);
|
||||
|
||||
struct Render2DInvocation {
|
||||
@ -362,9 +363,6 @@ static void render_space(void) {
|
||||
/* nothing to do, abort */
|
||||
/* 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) {
|
||||
use_space_pipeline();
|
||||
apply_fog();
|
||||
|
||||
for (size_t i = 0; i < hmlenu(ctx.uncolored_mesh_batches); ++i) {
|
||||
finally_draw_uncolored_space_traingle_batch(&ctx.uncolored_mesh_batches[i].value,
|
||||
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) {
|
||||
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 */
|
||||
@ -439,15 +435,8 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position,
|
||||
|
||||
|
||||
void set_depth_range(double low, double high) {
|
||||
DeferredCommand const command = {
|
||||
.type = DEFERRED_COMMAND_TYPE_DEPTH_RANGE,
|
||||
.depth_range = {
|
||||
.low = low,
|
||||
.high = high
|
||||
}
|
||||
};
|
||||
|
||||
arrpush(deferred_commands, command);
|
||||
depth_range_low = low;
|
||||
depth_range_high = high;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
for (size_t i = 0; i < arrlenu(deferred_commands); ++i) {
|
||||
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: {
|
||||
finally_clear_draw_buffer(deferred_commands[i].clear);
|
||||
break;
|
||||
@ -521,37 +475,6 @@ void issue_deferred_draw_commands(void) {
|
||||
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:
|
||||
SDL_assert(false);
|
||||
}
|
||||
|
@ -12,27 +12,35 @@
|
||||
#include <SDL2/SDL.h>
|
||||
#include <stb_truetype.h>
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <GLES2/gl2.h>
|
||||
#else
|
||||
#include <glad/glad.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern Matrix4 camera_projection_matrix;
|
||||
extern Matrix4 camera_look_at_matrix;
|
||||
|
||||
extern double depth_range_low, depth_range_high;
|
||||
|
||||
#define QUAD_ELEMENT_BUFFER_LENGTH (65536 / 6)
|
||||
#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 {
|
||||
size_t bytes_left;
|
||||
size_t size;
|
||||
void *mapping;
|
||||
void *base;
|
||||
} VertexBufferBuilder;
|
||||
|
||||
|
||||
@ -209,6 +217,8 @@ typedef struct ElementIndexedBillboard {
|
||||
} ElementIndexedBillboard;
|
||||
|
||||
|
||||
bool render_init(void);
|
||||
|
||||
/* renders the background, then the primitives in all render queues */
|
||||
void render(void);
|
||||
|
||||
@ -250,6 +260,8 @@ void text_cache_reset_arena(TextCache *cache);
|
||||
|
||||
VertexBuffer create_vertex_buffer(void);
|
||||
|
||||
void restart_scratch_vertex_arrays(void);
|
||||
|
||||
VertexBuffer get_scratch_vertex_array(void);
|
||||
|
||||
void delete_vertex_buffer(VertexBuffer buffer);
|
||||
@ -274,7 +286,6 @@ void finally_clear_draw_buffer(DeferredCommandClear command);
|
||||
void swap_buffers(void);
|
||||
|
||||
void set_depth_range(double low, double high);
|
||||
void finally_set_depth_range(DeferredCommandDepthRange command);
|
||||
|
||||
VertexBuffer get_quad_element_buffer(void);
|
||||
|
||||
@ -284,15 +295,6 @@ void render_circle(const CirclePrimitive *circle);
|
||||
|
||||
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[],
|
||||
struct QuadBatch batch,
|
||||
VertexBuffer buffer);
|
||||
@ -325,11 +327,6 @@ void finally_draw_text(FontData const *font_data,
|
||||
void render_skybox(void);
|
||||
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 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_types.h"
|
||||
#include "twn_deferred_commands.h"
|
||||
#include "twn_gl_any_rendering_c.h"
|
||||
|
||||
#include <glad/glad.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 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) {
|
||||
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)
|
||||
return;
|
||||
|
||||
depth_range_high = 1.0;
|
||||
depth_range_low = 0.0;
|
||||
|
||||
static GLuint list = 0;
|
||||
if (!list) {
|
||||
list = glGenLists(1);
|
||||
@ -54,9 +97,9 @@ void finally_use_space_pipeline(void) {
|
||||
glDisable(GL_DEPTH_CLAMP);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glDepthRange(0, 1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
/* solid white, no modulation */
|
||||
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) {
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
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);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
/* TODO: 2d camera */
|
||||
glLoadIdentity();
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
@ -248,6 +292,9 @@ void finally_render_skybox(DeferredCommandDrawSkybox command) {
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadMatrixf(&camera_look_at_matrix_solipsist.row[0].x);
|
||||
|
||||
glDepthRange(0.0f, 1.0f);
|
||||
glDisable(GL_FOG);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_TEXTURE_CUBE_MAP);
|
||||
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) {
|
||||
glClearColor((1.0f / 255) * command.color.r,
|
||||
(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) {
|
||||
/* TODO: don't assume a single vertex array ? */
|
||||
SDL_assert(command.vertices.arity != 0);
|
||||
SDL_assert(command.vertices.buffer);
|
||||
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_ELEMENT_ARRAY_BUFFER, command.element_buffer);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(command.vertices.arity,
|
||||
command.vertices.type,
|
||||
to_gl_type_enum(command.vertices.type),
|
||||
command.vertices.stride,
|
||||
(void *)command.vertices.offset);
|
||||
|
||||
@ -439,7 +500,7 @@ void finally_draw_command(DeferredCommandDraw command) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(command.texcoords.arity,
|
||||
command.texcoords.type,
|
||||
to_gl_type_enum(command.texcoords.type),
|
||||
command.texcoords.stride,
|
||||
(void *)command.texcoords.offset);
|
||||
}
|
||||
@ -449,7 +510,7 @@ void finally_draw_command(DeferredCommandDraw command) {
|
||||
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(command.colors.arity,
|
||||
command.colors.type,
|
||||
to_gl_type_enum(command.colors.type),
|
||||
command.colors.stride,
|
||||
(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_util_c.h"
|
||||
#include "twn_draw_c.h"
|
||||
|
||||
#include <stb_ds.h>
|
||||
|
||||
@ -120,3 +120,85 @@ GLuint get_scratch_vertex_array(void) {
|
||||
(*used)++;
|
||||
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
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef GLuint GPUTexture;
|
||||
typedef uint32_t GPUTexture;
|
||||
|
||||
typedef enum TextureFilter {
|
||||
TEXTURE_FILTER_NEAREAST,
|
||||
|
@ -11,7 +11,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
||||
{
|
||||
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) {
|
||||
off = offsetof(ElementIndexedQuad, v1);
|
||||
@ -33,7 +33,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
||||
|
||||
command.vertices = (AttributeArrayPointer) {
|
||||
.arity = 2,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = off,
|
||||
.offset = voff,
|
||||
.buffer = buffer
|
||||
@ -42,7 +42,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
||||
if (batch.textured)
|
||||
command.texcoords = (AttributeArrayPointer) {
|
||||
.arity = 2,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = off,
|
||||
.offset = uvoff,
|
||||
.buffer = buffer
|
||||
@ -51,7 +51,7 @@ void finally_render_quads(const Primitive2D primitives[],
|
||||
if (!batch.constant_colored) {
|
||||
command.colors = (AttributeArrayPointer) {
|
||||
.arity = 4,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.type = TWN_UNSIGNED_BYTE,
|
||||
.stride = off,
|
||||
.offset = coff,
|
||||
.buffer = buffer
|
||||
@ -68,10 +68,14 @@ void finally_render_quads(const Primitive2D primitives[],
|
||||
}
|
||||
|
||||
command.element_buffer = get_quad_element_buffer();
|
||||
command.element_count = 6 * (GLsizei)batch.size;
|
||||
command.range_end = 6 * (GLsizei)batch.size;
|
||||
command.element_count = 6 * (uint32_t)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 = {
|
||||
.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 */
|
||||
VertexBuffer const vertex_array = get_scratch_vertex_array();
|
||||
|
||||
use_texture_mode(batch.mode);
|
||||
|
||||
/* vertex population over a vertex buffer builder interface */
|
||||
{
|
||||
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)
|
||||
return;
|
||||
|
||||
use_space_pipeline();
|
||||
|
||||
/* note: ownership of 'paths_in_use' goes there */
|
||||
DeferredCommand command = {
|
||||
.type = DEFERRED_COMMAND_TYPE_DRAW_SKYBOX,
|
||||
|
@ -351,7 +351,7 @@ void finally_draw_text(FontData const *font_data,
|
||||
|
||||
command.vertices = (AttributeArrayPointer) {
|
||||
.arity = 2,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = offsetof(ElementIndexedQuadWithoutColor, v1),
|
||||
.offset = offsetof(ElementIndexedQuadWithoutColor, v0),
|
||||
.buffer = buffer
|
||||
@ -359,7 +359,7 @@ void finally_draw_text(FontData const *font_data,
|
||||
|
||||
command.texcoords = (AttributeArrayPointer) {
|
||||
.arity = 2,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = offsetof(ElementIndexedQuadWithoutColor, v1),
|
||||
.offset = offsetof(ElementIndexedQuadWithoutColor, uv0),
|
||||
.buffer = buffer
|
||||
@ -373,10 +373,14 @@ void finally_draw_text(FontData const *font_data,
|
||||
command.textured = true;
|
||||
|
||||
command.element_buffer = get_quad_element_buffer();
|
||||
command.element_count = 6 * (GLsizei)len;
|
||||
command.range_end = 6 * (GLsizei)len;
|
||||
command.element_count = 6 * (uint32_t)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 = {
|
||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||
|
@ -87,7 +87,7 @@ void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
||||
|
||||
command.vertices = (AttributeArrayPointer) {
|
||||
.arity = 3,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = offsetof(UncoloredSpaceTriangle, v1),
|
||||
.offset = offsetof(UncoloredSpaceTriangle, v0),
|
||||
.buffer = buffer
|
||||
@ -95,7 +95,7 @@ void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
||||
|
||||
command.texcoords = (AttributeArrayPointer) {
|
||||
.arity = 2,
|
||||
.type = GL_FLOAT,
|
||||
.type = TWN_FLOAT,
|
||||
.stride = offsetof(UncoloredSpaceTriangle, v1),
|
||||
.offset = offsetof(UncoloredSpaceTriangle, uv0),
|
||||
.buffer = buffer
|
||||
@ -104,13 +104,18 @@ void finally_draw_uncolored_space_traingle_batch(const MeshBatch *batch,
|
||||
command.textured = true;
|
||||
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 */
|
||||
TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
|
||||
if (mode == TEXTURE_MODE_GHOSTLY)
|
||||
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 = {
|
||||
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include "rendering/twn_circles.c"
|
||||
#include "rendering/twn_draw.c"
|
||||
#include "rendering/twn_fog.c"
|
||||
#include "rendering/twn_skybox.c"
|
||||
#include "rendering/twn_sprites.c"
|
||||
#include "rendering/twn_rects.c"
|
||||
|
@ -12,13 +12,6 @@
|
||||
#include <stb_ds.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 <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) {
|
||||
ctx.game.udata = ctx.game_copy.udata;
|
||||
}
|
||||
@ -539,25 +510,13 @@ static bool initialize(void) {
|
||||
if (SDL_GL_SetSwapInterval(-1))
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
if (gladLoadGL() == 0) {
|
||||
CRY("Init", "GLAD failed");
|
||||
if (!render_init())
|
||||
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 */
|
||||
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: */
|
||||
// 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 */
|
||||
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 */
|
||||
/* SDL_GetPerformanceCounter returns some platform-dependent number. */
|
||||
/* 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.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;
|
||||
|
||||
fail:
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "twn_loop.h"
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
#define SDL_MAIN_HANDLED
|
||||
#endif
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user