big rendering overhaul (cleaning and api abstraction)
This commit is contained in:
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user